探索反汇编-基于树莓派
进行反汇编
准备一段C语言程序
代码如下:
int g(int x){
return x+6;
}
int f(int x){
return g(x);
}
int main(){
return f(17)+1;
}
结构很简单,main函数里调用f函数,f函数调用g函数。
对这段程序进行反汇编
感觉树莓派没有32位汇编,所以只能编译为64位汇编,使用如下命令:
gcc -S test.c -o test.s
使用cat命令查看test.s的内容
.arch armv8-a
.file "test.c"
.text
.align 2
.global g
.type g, %function
g:
.LFB0:
.cfi_startproc
sub sp, sp, #16
.cfi_def_cfa_offset 16
str w0, [sp, 12]
ldr w0, [sp, 12]
add w0, w0, 6
add sp, sp, 16
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE0:
.size g, .-g
.align 2
.global f
.type f, %function
f:
.LFB1:
.cfi_startproc
stp x29, x30, [sp, -32]!
.cfi_def_cfa_offset 32
.cfi_offset 29, -32
.cfi_offset 30, -24
mov x29, sp
str w0, [sp, 28]
ldr w0, [sp, 28]
bl g
ldp x29, x30, [sp], 32
.cfi_restore 30
.cfi_restore 29
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE1:
.size f, .-f
.align 2
.global main
.type main, %function
main:
.LFB2:
.cfi_startproc
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
.cfi_offset 29, -16
.cfi_offset 30, -8
mov x29, sp
mov w0, 17
bl f
add w0, w0, 1
ldp x29, x30, [sp], 16
.cfi_restore 30
.cfi_restore 29
.cfi_def_cfa_offset 0
ret
.cfi_endproc
.LFE2:
.size main, .-main
.ident "GCC: (GNU) 10.3.1"
.section .note.GNU-stack,"",@progbits
再使用如下命令除去汇编文件里多余的内容,意思是去掉.开头的段
sed -i '/[.]/d' test.s
最后剩下的内容如下
g:
sub sp, sp, #16
str w0, [sp, 12]
ldr w0, [sp, 12]
add w0, w0, 6
add sp, sp, 16
ret
f:
stp x29, x30, [sp, -32]!
mov x29, sp
str w0, [sp, 28]
ldr w0, [sp, 28]
bl g
ldp x29, x30, [sp], 32
ret
main:
stp x29, x30, [sp, -16]!
mov x29, sp
mov w0, 17
bl f
add w0, w0, 1
ldp x29, x30, [sp], 16
ret
在arm64汇编里,X0-X30是通用寄存器,stp是入栈命令,相当于x86里的push命令,sp是保留栈顶指针,相当于x86里的esp。w0是32位的通用寄存器,ldp命令是出栈命令,相当于x86里的pop命令。bl意思跳转到相应的地址。ldr是加载指令,str是存储指令。
如 : str w0, [sp, 12] 意思是栈顶指针的地址加上12字节然后存入寄存器w0
add w0, w0, 6 意思是将w0的值加上6然后将值保存入w0
具体的堆栈情况可以对比32位的情况(还是不同,毕竟这个汇编是64位的)
感兴趣的可以看看我之前的分析文章汇编与反汇编入门-X86 AT&T汇编