IDA汇编命令分析以及函数调⽤过程
dll的⽂件,⼊⼝函数DllEntryPoint:
.text:000000018000525C ; BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
.text:000000018000525C public DllEntryPoint
.text:000000018000525C DllEntryPoint proc near ; DATA XREF: .pdata:0000000180009474o
.text:000000018000525C
.text:000000018000525C arg_0 = qword ptr 8
.text:000000018000525C arg_8 = qword ptr 10h
.text:000000018000525C
.text:000000018000525C mov [rsp+arg_0], rbx
.text:0000000180005261 mov [rsp+arg_8], rsi
.text:0000000180005266 push rdi
.text:0000000180005267 sub rsp, 20h
.text:000000018000526B mov rdi, r8
.text:000000018000526E mov ebx, edx
.text:0000000180005270 mov rsi, rcx
.text:0000000180005273 cmp edx, 1
.text:0000000180005276 jnz short loc_18000527D
.text:0000000180005278 call sub_180005688
.text:000000018000527D
.text:000000018000527D loc_18000527D: ; CODE XREF: DllEntryPoint+1Aj
.text:000000018000527D mov r8, rdi ; lpvReserved
.
text:0000000180005280 mov edx, ebx ; fdwReason
.text:0000000180005282 mov rcx, rsi ; hinstDLL
.text:0000000180005285 mov rbx, [rsp+28h+arg_0]
.text:000000018000528A mov rsi, [rsp+28h+arg_8]
.text:000000018000528F add rsp, 20h
.text:0000000180005293 pop rdi
.text:0000000180005294 jmp __DllMainCRTStartup
.text:0000000180005294 DllEntryPoint endp
arg_0 = qword ptr 8:声明arg_0变量等于从地址rbp:8处取出⼀个四字宽度的值,地址rbp:8指向⼀个4字(8个字节)的值,且取别名为arg_0,以后要⽤到时,直接使⽤别名。C语⾔相当于*(rbp+8)赋给了arg_0。
esp:32位栈指针寄存器(extended stack pointer),该指针指向系统栈最上⾯栈的顶部。
ebp:32位基址指针寄存器(extended base pointer),该指针指向系统栈(整个系统)中最上⾯栈帧(⼀个函数)的底部。
函数栈帧:esp和ebp之间内存空间为当前栈帧,ebp表⽰当前栈帧底部,esb表⽰当前栈帧顶部。
eip:指令寄存器(extended instruction pointer),该指针指向下⼀条待执⾏的指令地址。
。
rsp:64位的栈顶指针,相较于rbp处于低地址
rbp:64位的栈底指针,相较于rsp处于⾼地址
rbx:64位通⽤寄存器,64位基地址
汇编判断指令rsi:⽤来向函数参数的指针,源
rdi:⽤来向函数参数的指针,⽬的
ebx:⽤来向函数参数的指针
call:将当前相对地址(IP)压⼊栈中,调⽤CALL后的⼦程序。
lea:全称为load effective address,从存储器读数据到寄存器,实质是将存储器的有效地址写⼊到⽬的操作数,C语⾔的&
将源操作数(即存储单元的有效地址偏移地址)传送到⽬的操作数(运⾏时执⾏)
左边的是⽬的操作数,保存操作结果,该指令⽬的操作数只能是8个通⽤寄存器之⼀
右边的是源操作数,该指令的源操作数只能是⼀个存储单元,表达存储单元有多种寻址⽅式(Intel汇编格式)
jae: ⼤于等于转移
ja:前者⼤于后者转移,⽤于⽆符号⽐较(jump if above)
jl:条件跳转指令,⽤于有符号数 ⼩于跳转,jump less。还有类似jg ⼤于跳转jump grater
xor: 异或,相同为0,不同为1。
xor <op1> <op2>
op1异或op2 后 结果放⼊op1
xor eax, eax 与 mov eax, 0作⽤相同,只是所占字节不同⽽已,前⾯为2字节,后⾯为5字节
1.它⼀般⽤来判断两个值是否相等
⽐如:
xor rcx, rsp
判断rcx与rsp是否相等,相等则rcx为0,不等,则为1
2.它⼀般⽤来给⼀个值清0
⽐如:
xor edx, edx
将edx赋值为0
jz: jump if zero(结果为0,则设置ZF零标志位为1,并跳转)
jnz:jump if not zero
test:逻辑与运算指令,根据结果设置标志寄存器ZF,结果本⾝不保存。运算结果为0时,ZF零标志置1,否则清0
test ax,bx与test bx,ax效果⼀样。
它⼀般⽤来判断寄存器值是否为0
⽐如:
test ax, ax
jz short loc_1400012C8
判断ax是否为0,为0,则跳转到⼦函数loc_1400012C8处执⾏
cmp:⽐较指令, cmp的功能相当于减法指令,不保存结果。cmp指令执⾏后,将对标志寄存器产⽣影响。其他相关指令通过识别这些被影响的标志寄存器
位来得知⽐较结果。
⽐如:
mov ax,8
mov bx,3
cmp ax,bx
执⾏后:
ax=8,ZF=0,PF=1,SF=0,CF=0,OF=0.
通过cmp指令执⾏后,相关标志位的值就可以看出⽐较的结果。
cmp ax,bx的逻辑含义是⽐较ax,bx中的值。
如果执⾏后:
ZF=1则AX=BX
ZF=0则AX!=BX
CF=1则AX<BX
CF=0则AX>=BX
CF=0&ZF=0则AX>BX
CF=1|ZF=1则AX<=BX
⽐如:
mov eax, 10
mov ebx, 10
cmp eax, ebx
相减求出结果,若为0,则ZF置1,反之结果为1,则ZF清0
jz SOME_WHERE ;检查ZF,为1就跳
jnz SOME_WHERE ;检查ZF,为0就跳
db:以表达式的值的字节形式初始化代码空间,只能位于CODE段之内,否则会发⽣错误。
格式:[标号:] db 表达式
表达式中可包含符号,字符串或表达式等项。各项之间以逗号隔开,字符串⽤引号括起来。括号内的标号时可选的,如果使⽤了标号,则标号的值将时表达式表中第⼀个字节的地址。
retn:段内转移⼦程序返回。
movzx:零扩展传送
setb:将其后寄存器位置1
neg:求其后寄存器的补码
lock:使CPU产⽣⼀个LOCK#信号,确保在多处理器系统或多线程竞争的环境下互斥的使⽤这个内存地址,当指令执⾏完毕时,锁定动作消失。
cmpxchg:⽐较交换指令,第⼀个操作数先与al/ax/eax⽐较;若相等则ZF置1,且第⼆个操作数覆盖第⼀个操作数。反之,ZF清0,第⼀个操作数覆盖al/ax/eax。在80486以上的CPU中⽀持。
.text:004092D9 lock cmpxchg [esi], ecx
jmp short opr:段内直接短跳转转移
因为偏移量需向前或向后跳转,因此它时⼀个有符号的数值。这种转移格式只允许在-128~+127字节范围内转移。
.text:004092DF jz short loc_4092EC
offset:取偏移地址。(编译时执⾏)
mov reg,offset xxx ⽐ lea reg,xxx 的指令长度少⼀个字节,且快⼀个时钟,因此,应优先选⽤ mov offset 指令
栈:汇编内把⼀段内存空间定义为⼀个栈,栈总是先进后出。
进栈指令Push:
push reg/mem/seg
sp<---sp-2
ss<---reg/mem/seg
先使堆栈指令sp减2,随后把⼀个字操作数存⼊堆栈顶部。其操作单元只能是字,进栈时低字节存放在低地址,⾼字节存放在⾼地址,sp相应的向低地址移动两个字节单元。
出栈指令:
pop reg/seg/mem; reg/seg/mem<--ss:[sp],sp<-sp+2
出栈指令把栈顶的⼀个字传送⾄指定的⽬的操作数,然后堆栈指针sp加2。其操作单元只能是字,字从栈顶弹出时,低地址字节送低字节,⾼地址字节送⾼字节。
POP SS堆栈可以⽤来临时存放数据,以便随时恢复它们。也常⽤于⼦程序见传递参数。
注意⼏点:
1.因为堆栈指针sp总是指向已经存⼊数据的栈顶(不是空单元),所以push指令是将(SP)减2,后
将内容压栈(即先修改SP是指指向空单元,后压⼊数据),⽽POP是先从栈顶弹出⼀个字,后将堆栈指针SP加
2.
2.PUSH CS是合法的,但是POP CS是不合法的。
3.因为SP总是指向栈顶,⽽⽤PUSH和POP指令存取数时都是在栈顶进⾏的,所以堆栈是先进后出或叫后进先出的。栈底在⾼地址,堆栈是从⾼地址向低地址延伸的,所有栈底就是最初的栈顶。
4.⽤PUSH指令和POP指令时只能按字访问堆栈,不能按字节访问堆栈。
5.PUSH和POP指令都不影响标志。
.text:00404200 var_1B4 = dword ptr -1B4h
字单元赋值给变量var_1B4,它的值是ebp-1B4h。表⽰被调函数的局部变量地址。
.text:00404730 arg_0 = dword ptr 8
表⽰调⽤函数传⼊被调函数的参数值。都是以ebp为基址进⾏偏移。
.text:00404736 mov eax, ___security_cookie
___security_cookie该值是⼀个全局变量,其在编译阶段就被编译器所创建,随后写⼊.data区,保存在PE中;___security_cookie⽤来与局部变量与ebp之间的⼀个地址(它是在函数执⾏返回地址前的⼀个四字节地址,只要它被修改了,说明栈溢出了。可以先于返回地址被发现。。。)进⾏对⽐,确认该值是否与当时push到栈中的值是否⼀致,若不⼀致说明,栈溢出覆盖修改了这个值,那么就需要终⽌程序执⾏了。
___security_cookie详细可参考。
.text:00404746 loc_404746: ; CODE XREF: sub_404730:loc_4047C3↓j
代码交叉引⽤,其中loc_404746是被引⽤者,引⽤者为loc_4047C3,向下箭头↓表⽰引⽤者位置在下⾯。
箭头↓后⾯的j表⽰调⽤类型为jump。在IDA中,指令转交控制权的⽅式叫做流(flow):
有三种基本流:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论