常見函數調用約定(x86、x64、arm、arm64)
我學習逆向,整理的一些常見的函數調用約定反彙編筆記。由於我是新手,肯定有一些疏漏不完善的,我遇到了會實時更新的。
更新時間:2018年2月18日
常見函數調用約定(x86、x64、arm、arm64)
X86 函數調用約定
X86 有三種常用調用約定,cdecl(C規範)/stdcall(WinAPI默認)/fastcall 函數調用約定。
cdecl 函數調用約定
參數從右往左依次入棧,調用者實現棧平衡,返回值存放在 EAX 中。
20: int cdecl_sum = cdecl_add(1, 2, 3, 4, 5, 6, 7);00401138 push 70040113A push 60040113C push 50040113E push 400401140 push 300401142 push 200401144 push 100401146 call @ILT+5(_cdecl_add) (0040100a)0040114B add esp,1Ch # 棧平衡0040114E mov dword ptr [ebp-4],eax # 返回值3: int __cdecl cdecl_add(int a, int b, int c, int d, int e, int f, int g)4: {00401030 push ebp00401031 mov ebp,esp00401033 sub esp,44h00401036 push ebx00401037 push esi00401038 push edi00401039 lea edi,[ebp-44h]0040103C mov ecx,11h00401041 mov eax,0CCCCCCCCh00401046 rep stos dword ptr [edi]5: int sum = a+b+c+d+e+f+g;00401048 mov eax,dword ptr [ebp+8]0040104B add eax,dword ptr [ebp+0Ch]0040104E add eax,dword ptr [ebp+10h]00401051 add eax,dword ptr [ebp+14h]00401054 add eax,dword ptr [ebp+18h]00401057 add eax,dword ptr [ebp+1Ch]0040105A add eax,dword ptr [ebp+20h]0040105D mov dword ptr [ebp-4],eax6: return sum;00401060 mov eax,dword ptr [ebp-4] # 存放返回值7: }00401063 pop edi00401064 pop esi00401065 pop ebx00401066 mov esp,ebp00401068 pop ebp00401069 ret
stdcall 函數調用約定
參數從右往左依次入棧,被調用者實現棧平衡,返回值存放在 EAX 中。
21: int stdcall_sum = stdcall_add(1, 2, 3, 4, 5, 6, 7);00401151 push 700401153 push 600401155 push 500401157 push 400401159 push 30040115B push 20040115D push 10040115F call @ILT+15(_stdcall_add@28) (00401014)00401164 mov dword ptr [ebp-8],eax # 返回值9: int __stdcall stdcall_add(int a, int b, int c, int d, int e, int f, int g)10: {00401080 push ebp00401081 mov ebp,esp00401083 sub esp,44h00401086 push ebx00401087 push esi00401088 push edi00401089 lea edi,[ebp-44h]0040108C mov ecx,11h00401091 mov eax,0CCCCCCCCh00401096 rep stos dword ptr [edi]11: int sum = a+b+c+d+e+f+g;00401098 mov eax,dword ptr [ebp+8]0040109B add eax,dword ptr [ebp+0Ch]0040109E add eax,dword ptr [ebp+10h]004010A1 add eax,dword ptr [ebp+14h]004010A4 add eax,dword ptr [ebp+18h]004010A7 add eax,dword ptr [ebp+1Ch]004010AA add eax,dword ptr [ebp+20h]004010AD mov dword ptr [ebp-4],eax12: return sum;004010B0 mov eax,dword ptr [ebp-4] # 存放返回值13: }004010B3 pop edi004010B4 pop esi004010B5 pop ebx004010B6 mov esp,ebp004010B8 pop ebp004010B9 ret 1Ch # 棧平衡(等價於先 add esp, 1Ch 再 ret)
X64 函數調用約定
X64隻有一種 fastcall 函數調用約定
fastcall 函數調用約定
參數1、參數2、參數3、參數4分別保存在 RCX、RDX、R8D、R9D ,剩下的參數從右往左依次入棧,被調用者實現棧平衡,返回值存放在 RAX 中。
# 該代碼是 msvc 2017 x64 生成的彙編代碼 int fastcall_sum = fastcall_add(1, 2, 3, 4, 5, 6, 7);00007FF6577A366E mov dword ptr [rsp+30h],700007FF6577A3676 mov dword ptr [rsp+28h],6 00007FF6577A367E mov dword ptr [rsp+20h],5 00007FF6577A3686 mov r9d,4 00007FF6577A368C mov r8d,3 00007FF6577A3692 mov edx,2 00007FF6577A3697 mov ecx,1 00007FF6577A369C call fastcall_add (07FF6577A11C2h) 00007FF6577A36A1 mov dword ptr [fastcall_sum],eax # 返回值int __fastcall fastcall_add(int a, int b, int c, int d, int e, int f, int g){00007FF6D22D1790 mov dword ptr [rsp+20h],r9d 00007FF6D22D1795 mov dword ptr [rsp+18h],r8d 00007FF6D22D179A mov dword ptr [rsp+10h],edx 00007FF6D22D179E mov dword ptr [rsp+8],ecx 00007FF6D22D17A2 push rbp 00007FF6D22D17A3 push rdi 00007FF6D22D17A4 sub rsp,0E8h 00007FF6D22D17AB mov rbp,rsp 00007FF6D22D17AE mov rdi,rsp 00007FF6D22D17B1 mov ecx,3Ah 00007FF6D22D17B6 mov eax,0CCCCCCCCh 00007FF6D22D17BB rep stos dword ptr [rdi] 00007FF6D22D17BD mov ecx,dword ptr [rsp+108h] int sum = a + b + c + d + e + f + g;00007FF6D22D17C4 mov eax,dword ptr [b] 00007FF6D22D17CA mov ecx,dword ptr [a] 00007FF6D22D17D0 add ecx,eax 00007FF6D22D17D2 mov eax,ecx 00007FF6D22D17D4 add eax,dword ptr [c] 00007FF6D22D17DA add eax,dword ptr [d] 00007FF6D22D17E0 add eax,dword ptr [e] 00007FF6D22D17E6 add eax,dword ptr [f] 00007FF6D22D17EC add eax,dword ptr [g] 00007FF6D22D17F2 mov dword ptr [sum],eax return sum;00007FF6D22D17F5 mov eax,dword ptr [sum] # 存放返回值}00007FF6D22D17F8 lea rsp,[rbp+0E8h] 00007FF6D22D17FF pop rdi 00007FF6D22D1800 pop rbp 00007FF6D22D1801 ret # 沒做棧平衡
X64
參數1、參數2、參數3分別保存在RDX、R8D、R9D中,this指針存放RCX中,剩下的參數從右往左依次入棧,被調用者實現棧平衡,返回值存放在 RAX 中。
# 該代碼是 msvc 2017 x64 生成的彙編代碼 int sum = calc.thiscall_add(1, 2, 3, 4, 5, 6, 7);00007FF602E6190F mov dword ptr [rsp+38h],7 00007FF602E61917 mov dword ptr [rsp+30h],6 00007FF602E6191F mov dword ptr [rsp+28h],5 00007FF602E61927 mov dword ptr [rsp+20h],4 00007FF602E6192F mov r9d,3 00007FF602E61935 mov r8d,2 00007FF602E6193B mov edx,1 00007FF602E61940 lea rcx,[calc] # this指針00007FF602E61944 call Calc::thiscall_add (07FF602E610A0h) 00007FF602E61949 mov dword ptr [sum],eax # 返回值int Calc::thiscall_add(int a, int b, int c, int d, int e, int f, int g){00007FF602E61770 mov dword ptr [rsp+20h],r9d 00007FF602E61775 mov dword ptr [rsp+18h],r8d 00007FF602E6177A mov dword ptr [rsp+10h],edx 00007FF602E6177E mov qword ptr [rsp+8],rcx 00007FF602E61783 push rbp 00007FF602E61784 push rdi 00007FF602E61785 sub rsp,0E8h 00007FF602E6178C mov rbp,rsp 00007FF602E6178F mov rdi,rsp 00007FF602E61792 mov ecx,3Ah 00007FF602E61797 mov eax,0CCCCCCCCh 00007FF602E6179C rep stos dword ptr [rdi] 00007FF602E6179E mov rcx,qword ptr [rsp+108h] int sum = a + b + c + d + e + f + g;00007FF602E617A6 mov eax,dword ptr [b] 00007FF602E617AC mov ecx,dword ptr [a] 00007FF602E617B2 add ecx,eax 00007FF602E617B4 mov eax,ecx 00007FF602E617B6 add eax,dword ptr [c] 00007FF602E617BC add eax,dword ptr [d] 00007FF602E617C2 add eax,dword ptr [e] 00007FF602E617C8 add eax,dword ptr [f] 00007FF602E617CE add eax,dword ptr [g] 00007FF602E617D4 mov dword ptr [sum],eax return sum;00007FF602E617D7 mov eax,dword ptr [sum] # 存放返回值}00007FF602E617DA lea rsp,[rbp+0E8h] 00007FF602E617E1 pop rdi 00007FF602E617E2 pop rbp 00007FF602E617E3 ret # 沒做棧平衡
ARM/ARM64 函數調用約定
ARM和ARM64使用的是ATPCS(ARM-Thumb Procedure Call Standard/ARM-Thumb過程調用標準)的函數調用約定。
ATPCS 函數調用約定
ARM
參數1~參數4 分別保存到 R0~R3 寄存器中 ,剩下的參數從右往左依次入棧,被調用者實現棧平衡,返回值存放在 R0 中。
; 該代碼是 arm-linux-androideabi-gcc + IDA PRO 生成的反彙編代碼.text:00008438 MOV R3, #5.text:0000843C STR R3, [SP].text:00008440 MOV R3, #6.text:00008444 STR R3, [SP,#4].text:00008448 MOV R3, #7.text:0000844C STR R3, [SP,#8].text:00008450 MOV R3, #8.text:00008454 STR R3, [SP,#12].text:00008458 MOV R3, #9.text:0000845C STR R3, [SP,#16].text:00008460 MOV R3, #10.text:00008464 STR R3, [SP,#20].text:00008468 MOV R0, #1.text:0000846C MOV R1, #2.text:00008470 MOV R2, #3.text:00008474 MOV R3, #4.text:00008478 BL add.text:0000847C STR R0, [R11,#-8].text:000083C4 EXPORT add.text:000083C4.text:000083C4 STR R11, [SP,#-4]!.text:000083C8 ADD R11, SP, #0.text:000083CC SUB SP, SP, #0x1C.text:000083D0 STR R0, [R11,#-16].text:000083D4 STR R1, [R11,#-20].text:000083D8 STR R2, [R11,#-24].text:000083DC STR R3, [R11,#-28].text:000083E0 LDR R2, [R11,#-16].text:000083E4 LDR R3, [R11,#-20].text:000083E8 ADD R2, R2, R3.text:000083EC LDR R3, [R11,#-24].text:000083F0 ADD R2, R2, R3.text:000083F4 LDR R3, [R11,#-28].text:000083F8 ADD R2, R2, R3.text:000083FC LDR R3, [R11,#4].text:00008400 ADD R2, R2, R3.text:00008404 LDR R3, [R11,#8].text:00008408 ADD R2, R2, R3.text:0000840C LDR R3, [R11,#12].text:00008410 ADD R3, R2, R3.text:00008414 STR R3, [R11,#-8].text:00008418 LDR R3, [R11,#-8].text:0000841C MOV R0, R3.text:00008420 SUB SP, R11, #0.text:00008424 LDR R11, [SP],#4.text:00008428 BX LR
ARM64
參數1~參數8 分別保存到 X0~X7 寄存器中 ,剩下的參數從右往左依次入棧,被調用者實現棧平衡,返回值存放在 X0 中。
; 該代碼是 aarch64-linux-android-gcc + IDA PRO 生成的反彙編代碼.text:000000000040065C MOV W0, #9.text:0000000000400660 STR W0, [SP].text:0000000000400664 MOV W0, #10.text:0000000000400668 STR W0, [SP,#8].text:000000000040066C MOV W0, #1.text:0000000000400670 MOV W1, #2.text:0000000000400674 MOV W2, #3.text:0000000000400678 MOV W3, #4.text:000000000040067C MOV W4, #5.text:0000000000400680 MOV W5, #6.text:0000000000400684 MOV W6, #7.text:0000000000400688 MOV W7, #8.text:000000000040068C BL add.text:0000000000400690 STR W0, [X29,#28].text:00000000004005E8 EXPORT add.text:00000000004005E8.text:00000000004005E8 SUB SP, SP, #0x30.text:00000000004005EC STR W0, [SP,#28].text:00000000004005F0 STR W1, [SP,#24].text:00000000004005F4 STR W2, [SP,#20].text:00000000004005F8 STR W3, [SP,#16].text:00000000004005FC STR W4, [SP,#12].text:0000000000400600 STR W5, [SP,#8].text:0000000000400604 STR W6, [SP,#4].text:0000000000400608 STR W7, [SP].text:000000000040060C LDR W1, [SP,#28].text:0000000000400610 LDR W0, [SP,#24].text:0000000000400614 ADD W1, W1, W0.text:0000000000400618 LDR W0, [SP,#20].text:000000000040061C ADD W1, W1, W0.text:0000000000400620 LDR W0, [SP,#16].text:0000000000400624 ADD W1, W1, W0.text:0000000000400628 LDR W0, [SP,#12].text:000000000040062C ADD W1, W1, W0.text:0000000000400630 LDR W0, [SP,#8].text:0000000000400634 ADD W1, W1, W0.text:0000000000400638 LDR W0, [SP,#4].text:000000000040063C ADD W0, W1, W0.text:0000000000400640 STR W0, [SP,#44].text:0000000000400644 LDR W0, [SP,#44].text:0000000000400648 ADD SP, SP, #0x30.text:000000000040064C RET
本文由看雪論壇 有影 原創 轉載請註明來自看雪社區
推薦閱讀:
※攻擊TrustZone系列(Pt.2) -- 逆向高通TrustZone
※CTF取證類題目指南
※旅行的青蛙Unity遊戲逆向修改Android&iOS
※No Power No Shell --- 非PE攻擊中的套路