By 飘云/P.Y.G
http://bbs.chinapyg.com
http://www.dllhook.com
先写一段函数:
int addFunction(int a, int b)
{
int ret = a + b;
return ret;
}
/*
__text:00002078 EXPORT _addFunction
__text:00002078 _addFunction ; CODE XREF: _main+24p
__text:00002078
__text:00002078 var_C = -0xC
__text:00002078 var_8 = -8
__text:00002078 var_4 = -4
__text:00002078
__text:00002078 STMFD SP!, {R7,LR}
__text:0000207C
__text:0000207C loc_207C ; DATA XREF: __text:off_2074o
__text:0000207C ADD R7, SP, #0
__text:00002080 SUB SP, SP, #0xC
__text:00002084 STR R0, [SP,#0xC+var_8] ; 将R0保存到栈 [SP+0x0] = R0
__text:00002088 STR R1, [SP,#0xC+var_C] ; 将R1保存到栈 [SP+0x4] = R1
__text:0000208C LDR R2, [SP,#0xC+var_8] ; R2 = [SP+0x0] = R0
__text:00002090 LDR R3, [SP,#0xC+var_C] ; R3 = [SP+0x4] = R1
__text:00002094 ADD R3, R2, R3 ; R3 = R2 + R3
__text:00002098 STR R3, [SP,#0xC+var_4] ; 保存到变量var_4 --- [SP+0x8]
__text:0000209C LDR R3, [SP,#0xC+var_4] ; 又从变量传回到R3 --- 这玩意反正是成对使用,慢慢习惯就好了,不要问为什么
__text:000020A0 MOV R0, R3 ; 最后把结果存到R0
__text:000020A4 SUB SP, R7, #0
__text:000020A8 LDMFD SP!, {R7,PC}
__text:000020A8 ; End of function _addFunction
*/
调用:
int c = addFunction(0x11, 0x22);
/*
__text:000020C8 MOV R0, #0x11
__text:000020CC MOV R1, #0x22
__text:000020D0 BL _addFunction
*/
结论:调用函数不是用CALL 而是BL 第一个参数放在R0,第二个参数放在R1 从右到左
然后再写一段4个参数的
int addFunction2(int a, int b, int c, int d)
{
int ret = a + b + c + d;
return ret;
}
/*
__text:000020AC EXPORT _addFunction2
__text:000020AC _addFunction2 ; CODE XREF: _main+54p
__text:000020AC
__text:000020AC var_14 = -0x14
__text:000020AC var_10 = -0x10
__text:000020AC var_C = -0xC
__text:000020AC var_8 = -8
__text:000020AC var_4 = -4
__text:000020AC
__text:000020AC STMFD SP!, {R7,LR}
__text:000020B0 ADD R7, SP, #0
__text:000020B4 SUB SP, SP, #0x14
__text:000020B8 STR R0, [SP,#0x14+var_8]
__text:000020BC STR R1, [SP,#0x14+var_C]
__text:000020C0 STR R2, [SP,#0x14+var_10]
__text:000020C4 STR R3, [SP,#0x14+var_14]
__text:000020C8 LDR R2, [SP,#0x14+var_8]
__text:000020CC LDR R3, [SP,#0x14+var_C]
__text:000020D0 ADD R2, R2, R3
__text:000020D4 LDR R3, [SP,#0x14+var_10]
__text:000020D8 ADD R2, R2, R3
__text:000020DC LDR R3, [SP,#0x14+var_14]
__text:000020E0 ADD R3, R2, R3
__text:000020E4 STR R3, [SP,#0x14+var_4]
__text:000020E8 LDR R3, [SP,#0x14+var_4]
__text:000020EC MOV R0, R3 // 返回值到R0
__text:000020F0 SUB SP, R7, #0
__text:000020F4 LDMFD SP!, {R7,PC}
__text:000020F4 ; End of function _addFunction2
*/
addFunction2(0x11, 0x22, 0x33, 0x44);
/*
__text:0000213C MOV R0, #0x11
__text:00002140 MOV R1, #0x22
__text:00002144 MOV R2, #0x33
__text:00002148 MOV R3, #0x44
__text:0000214C BL _addFunction2
*/
结论:调用函数不是用CALL 而是BL 第一个参数放在R0,第二个参数放在R1 第三个参数放在R2 第四个参数放在R3 从右到左
继续写一段8个参数的函数测试:
int addFunction3(int a, int b, int c, int d, int e, int f, int g, int h)
{
int ret = a + b + c + d + e + f + g + h;
return ret;
}
/*
__text:000020F8 EXPORT _addFunction3
__text:000020F8 _addFunction3 ; CODE XREF: _main+A4p
__text:000020F8
__text:000020F8 var_14 = -0x14
__text:000020F8 var_10 = -0x10
__text:000020F8 var_C = -0xC
__text:000020F8 var_8 = -8
__text:000020F8 var_4 = -4
__text:000020F8 arg_0 = 8
__text:000020F8 arg_4 = 0xC
__text:000020F8 arg_8 = 0x10
__text:000020F8 arg_C = 0x14
__text:000020F8
__text:000020F8 STMFD SP!, {R7,LR}
__text:000020FC ADD R7, SP, #0
__text:00002100 SUB SP, SP, #0x14
__text:00002104 STR R0, [SP,#0x14+var_8]
__text:00002108 STR R1, [SP,#0x14+var_C]
__text:0000210C STR R2, [SP,#0x14+var_10]
__text:00002110 STR R3, [SP,#0x14+var_14]
__text:00002114 LDR R2, [SP,#0x14+var_8]
__text:00002118 LDR R3, [SP,#0x14+var_C]
__text:0000211C ADD R2, R2, R3
__text:00002120 LDR R3, [SP,#0x14+var_10]
__text:00002124 ADD R2, R2, R3
__text:00002128 LDR R3, [SP,#0x14+var_14]
__text:0000212C ADD R2, R2, R3
__text:00002130 LDR R3, [SP,#0x14+arg_0]
__text:00002134 ADD R2, R2, R3
__text:00002138 LDR R3, [SP,#0x14+arg_4]
__text:0000213C ADD R2, R2, R3
__text:00002140 LDR R3, [SP,#0x14+arg_8]
__text:00002144 ADD R2, R2, R3
__text:00002148 LDR R3, [SP,#0x14+arg_C]
__text:0000214C ADD R3, R2, R3
__text:00002150 STR R3, [SP,#0x14+var_4]
__text:00002154 LDR R3, [SP,#0x14+var_4]
__text:00002158 MOV R0, R3 // 返回值到R0
__text:0000215C SUB SP, R7, #0
__text:00002160 LDMFD SP!, {R7,PC}
__text:00002160 ; End of function _addFunction3
*/
ret = addFunction3(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);
/*
__text:00002164 var_14 = -0x14
__text:00002164 var_10 = -0x10
__text:00002164 var_C = -0xC
__text:00002164 var_8 = -8
__text:00002164 var_4 = -4
.
.
.
.
.
.
__text:000021D8 MOV R3, #0x55
__text:000021DC STR R3, [SP,#0x14+var_14] ; 0x0
__text:000021E0 MOV R3, #0x66
__text:000021E4 STR R3, [SP,#0x14+var_10] ; 0x4
__text:000021E8 MOV R3, #0x77
__text:000021EC STR R3, [SP,#0x14+var_C] ; 0x8
__text:000021F0 MOV R3, #0x88
__text:000021F4 STR R3, [SP,#0x14+var_8] ; 0xC
__text:000021F8 MOV R0, #0x11
__text:000021FC MOV R1, #0x22
__text:00002200 MOV R2, #0x33
__text:00002204 MOV R3, #0x44
__text:00002208 BL _addFunction3
*/
结论:调用函数不是用CALL 而是BL 第一个参数放在R0,第二个参数放在R1 第三个参数放在R2 第四个参数放在R3 后面开始用栈传递
printf("result=%d\n", ret);
/*
__text:00002208 BL _addFunction3
__text:0000220C MOV R3, R0 ; 返回到R0 --- R3 = R0
__text:00002210 STR R3, [SP,#0x14+var_4] ; 保存R3到变量 var_4
__text:00002214 LDR R3, =(aResultD - 0x2220) ; 载入格式化字符串“result=%d\n”地址到R3
__text:00002218 ADD R3, PC, R3 ; "result=%d\n"
__text:0000221C MOV R0, R3 ; char *
__text:00002220 LDR R1, [SP,#0x14+var_4] ; 载入变量var_4
__text:00002224 BL _printf ; 调用printf函数
*/
发表评论