Arm 什么样的C代码可以编译成汇编代码,比如;LDR R3,[R4,#0x18],“;,其中R3是指针
我用IDA Pro反转了一个ARM固件;部分汇编代码如下所示:Arm 什么样的C代码可以编译成汇编代码,比如;LDR R3,[R4,#0x18],“;,其中R3是指针,arm,reverse-engineering,ida,Arm,Reverse Engineering,Ida,我用IDA Pro反转了一个ARM固件;部分汇编代码如下所示: ROM:08079B00 MOVS R1,R0 ROM:08079B02 BEQ loc_8079B14 ROM:08079B04 LDR R0[R4,#0x10] ROM:08079B06 LDR R2[R1,#4] ROM:08079B08接头R0,R0,#3 ROM:08079B0A STRH R0[R2,#0x10] ROM:08079B0C LDR R3[R4,#0x18] ROM:08079B0E LDR R2[R4
ROM:08079B00 MOVS R1,R0 ROM:08079B02 BEQ loc_8079B14 ROM:08079B04 LDR R0[R4,#0x10] ROM:08079B06 LDR R2[R1,#4] ROM:08079B08接头R0,R0,#3 ROM:08079B0A STRH R0[R2,#0x10] ROM:08079B0C LDR R3[R4,#0x18] ROM:08079B0E LDR R2[R4,#0x20] ROM:08079B10 LDR R0[R5] ROM:08079B12 BLX R3
偏移量0x08079B12处的指令是BLX R3,因此R3是指针;R3的值来自偏移量0x08079B0C处的LDR指令(LDR R3,[R4,#0x18]) 什么样的C代码可以编译成汇编代码,如“LDR R3,[R4,#0x18]”,其中R3是指针。
typedef int(*fun)(int a,int b);
typedef int (*fun)(int a , int b );
typedef struct _str
{
int a;
int b;
fun op;
} STR;
STR funop;
int fun2 ( int a, int b)
{
funop.a=a;
funop.b=b;
return(funop.op(a,b)+1);
}
00000000 <fun2>:
0: e59f3014 ldr r3, [pc, #20] ; 1c <fun2+0x1c>
4: e92d4010 push {r4, lr}
8: e5932008 ldr r2, [r3, #8]
c: e8830003 stm r3, {r0, r1}
10: e12fff32 blx r2
14: e2800001 add r0, r0, #1
18: e8bd8010 pop {r4, pc}
1c: 00000000
类型定义结构
{
INTA;
int b;
趣味op;
}STR;
STR-funop;
int fun2(int a,int b)
{
funop.a=a;
funop.b=b;
返回(funop.op(a,b)+1);
}
00000000 :
0:e59f3014 ldr r3[pc,#20];1c
4:e92d4010推送{r4,lr}
8:e5932008 ldr r2[r3,#8]
c:e8830003 stm r3,{r0,r1}
10:E12FF32 blx r2
14:e2800001加上r0,r0,#1
18:e8bd8010 pop{r4,pc}
1c:00000000
只需要使用基址加偏移地址来读取函数的地址,然后调用它。blx执行调用,因此值是函数指针,因此代码与函数指针相关。如果没有结构,它可能不会执行基本+偏移,而是执行pc相对负载
它不一定是全球性的
int (*fun)(int a , int b );
int fun2 ( int a, int b)
{
return((fun)(a,b)+1);
}
00000000 <fun2>:
0: e59f3018 ldr r3, [pc, #24] ; 20 <fun2+0x20>
4: e92d4010 push {r4, lr}
8: e5933000 ldr r3, [r3]
c: e1a0e00f mov lr, pc
10: e12fff13 bx r3
14: e8bd4010 pop {r4, lr}
18: e2800001 add r0, r0, #1
1c: e12fff1e bx lr
20: 00000000 .word 0x00000000
int(*fun)(int a,int b);
int fun2(int a,int b)
{
返回((乐趣)(a、b)+1);
}
00000000 :
0:e59f3018 ldr r3,[pc,#24];20
4:e92d4010推送{r4,lr}
8:e5933000 ldr r3[r3]
c:e1a0e00f mov lr,pc
10:E12FF13 bx r3
14:e8bd4010 pop{r4,lr}
18:e2800001加上r0,r0,#1
1c:E12FF1E bx lr
20:00000000。字0x00000000
因为我使它是全局的,所以它必须做双间接的事情,所以它仍然是一个基数加偏移量(零)
intfun3(inta,intb);
int fun2(int a,int b)
{
内部(*fun)(内部a、内部b);
乐趣=乐趣3;
返回((乐趣)(a、b)+1);
}
00000000 :
0:e92d4010推送{r4,lr}
4:ebfffffe bl 0
8:e8bd4010 pop{r4,lr}
c:e2800001加上r0,r0,#1
10:E12FF1E bx lr
链接器填充直接偏移量,因此没有寄存器加偏移量寻址。根本没有ldr,因为它可以通过分支链接处理
我认为这些是在链接时解析的bl或在链接时解析的池值的双重间接选择。无论是否为结构,它都是一个带有寄存器加偏移量的ldr(如果为零,gnu反汇编程序不显示偏移量)。函数指针指向结构谢谢。确实,该结构包含函数指针。请注意此处的拼写,尤其是包含撇号的单词。这里有一些正确的拼写,加上你的帖子历史记录中的拼写错误:不(765),不(488),不能(306),不会(217),不是(148)。对于那些没有英语作为第一语言的人来说,这里有一些宽容,但是文体和故意拼错的作品违背了网站的目标,并且是故意为志愿编辑做的大量工作。您的浏览器中有拼写检查程序吗?
int fun3(int a , int b );
int fun2 ( int a, int b)
{
int (*fun)(int a , int b );
fun=fun3;
return((fun)(a,b)+1);
}
00000000 <fun2>:
0: e92d4010 push {r4, lr}
4: ebfffffe bl 0 <fun3>
8: e8bd4010 pop {r4, lr}
c: e2800001 add r0, r0, #1
10: e12fff1e bx lr