反汇编测试

反汇编测试 任务详情

1 通过输入gcc -S -o main.s main.c 将下面c程序”week0303学号.c“编译成汇编代码 int g(int x){ return x+3; } int f(int x){ int i = 学号后两位; return g(x)+i; } int main(void){ return f(8)+1; }2. 参考http://www.cnblogs.com/lxm20145215----/p/5982554.html,使用gdb跟踪汇编代码,在纸上画出f中每一条语句引起的eip(rip),ebp(rbp),esp(rsb),eax(rax)的值和栈的变化情况。提交照片,要有学号信息。

完成过程 1.编译情况
反汇编测试
文章图片

2.发现在树莓派arm64架构下无法完成,便转到kali上做了。
反汇编测试
文章图片

使用gcc - g example.c -o example -m32指令在64位的机器上产生32位汇编,然后使用gdb example指令进入gdb调试器:
反汇编测试
文章图片

进入之后先在main函数处设置一个断点,再run一下,使用disassemble指令获取汇编代码,用i(info) r(registers)指令查看各寄存器的值:
反汇编测试
文章图片

用x mian查看主函数的内存地址:
首先,结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。
反汇编测试
文章图片

call指令将下一条指令的地址入栈,此时%esp,%ebp和堆栈的值为:
反汇编测试
文章图片

将上一个函数的基址入栈,从当前%esp开始作为新基址:
反汇编测试
文章图片

先为传参做准备:
反汇编测试
文章图片

f函数的汇编代码:
反汇编测试
文章图片

实参入栈:
反汇编测试
文章图片

主函数汇编代码:
反汇编测试
文章图片

知识点 跟着博客做完整个人还是很晕,于是想梳理一下知识点。
1.寄存器 参考博客:https://www.cnblogs.com/lihaozy/archive/2011/08/01/2124315.html
(1)ESP:栈指针寄存器(extended stack pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的栈顶。
(2)EBP:基址指针寄存器(extended base pointer),其内存放着一个指针,该指针永远指向系统栈最上面一个栈帧的底部。
(3)Eax用来保存所有API函数的返回值。
(4)寄存器AX和AL通常称为累加器(Accumulator),用累加器进行的操作可能需要更少时间。累加器可用于乘、除、输入/输出等操作,它们的使用频率很高;
(5)寄存器BX称为基地址寄存器(Base Register)。它可作为存储器指针来使用;
(6)寄存器CX称为计数寄存器(Count Register)。在循环和字符串操作时,要用它来控制循环次数;在位操作中,当移多位时,要用CL来指明移位的位数;
(7)寄存器DX称为数据寄存器(Data Register)。在进行乘、除运算时,它可作为默认的操作数参与运算,也可用于存放I/O的端口地址。
(8)寄存器ESI、EDI、SI和DI称为变址寄存器(Index Register),它们主要用于存放存储单元在段内的偏移量,用它们可实现多种存储器操作数的寻址方式,为以不同的地址形式访问存储单元提供方便。变址寄存器不可分割成8位寄存器。作为通用寄存器,也可存储算术逻辑运算的操作数和运算结果。它们可作一般的存储器指针使用。在字符串操作指令的执行过程中,对它们有特定的要求,而且还具有特殊的功能。
2.gdb指令 参考博客:https://blog.csdn.net/moonsheep_liu/article/details/39099969
3.学习汇编语言 参考博客:https://www.ruanyifeng.com/blog/2018/01/assembly-language-primer.html
重新尝试反汇编 试图理解反汇编
1.首先在main函数设置断点 b main
2.使用display设置显示内容。
display /x $esp display /x $ebp display /x $eax display /i $pc

3.使用run指令跳到main函数开始处,使用x(examine) /nfu + 内存地址查看堆栈内容。
push 命令将$0x8放入stack,因为是int型占用4个字节,所以esp寄存器减去4。
这时可以看到栈底地址是0xffffd168。
反汇编测试
文章图片

4.使用si步入下一条指令,使用x(examine) /nfu + 内存地址查看堆栈内容(之后每一步都要用到,不重复说明)。
call指令调用f函数,f函数的地址在0x5655619e。
反汇编测试
文章图片

5.push命令将ebp里的值写入f函数这个帧,内容为0x565561bd,这是因为后面要用到这个寄存器,就先把里面的值取出来,用完后再写回去。这时,push指令会再将 ESP 寄存器里面的地址减去4个字节(累计减去8)。
反汇编测试
文章图片

6.mov指令用于将一个值写入某个寄存器。这一行代码表示,从ebp寄存器存的地址在 Stack 取出数据。根据前面的步骤,可以推算出这里取出的是8,再将8写入ESP寄存器。
反汇编测试
文章图片

这里没有使用push指令,但是esp减去了4(累计减去12),堆栈中也存入了ebp的地址0xffffd168,参照阮一峰的理解是
反汇编测试
文章图片

7.sub指令代表第一个寄存器中的值减去第二个寄存器中的值,将结果存入第一个寄存器中。这里就是用10(我的学号)减去esp中的值(此处应该是8),得到了2,存入?
(此处不理解)将我的学号传入f函数中,堆栈中存入了0xf7de2fd6。
反汇编测试
文章图片

【反汇编测试】此处因为进入了f函数中,所以ebp指向了f函数的栈底0xffffd15c。
8.call指令调用(此处应该是一个奇奇怪怪的函数,估计是某个库函数,用来初始化函数调用的?),建立该函数的帧。
esp减去了16,说明存入了4个东西(为什么呢)
反汇编测试
文章图片

9.mov指令将esp的地址存入了eax寄存器中,地址为0x565561a9,存入了堆栈中,esp中的值减去4。
反汇编测试
文章图片

10.ret指令用于终止当前函数的执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收。
随着函数的终止,系统就回到刚才f函数中断的地方,继续往下执行。
反汇编测试
文章图片

11.add指令是将0x2e57与eax寄存器中的值相加,存到?
此处应该发生了pop指令,esp寄存器的值加上4。
反汇编测试
文章图片

12.movl指令将0xa(10,我的学号)传入地址(ebp的地址减去4,这里应该是i的地址)中,此处movl中的l为长字节的意思(虽然感觉用mov也可以)。
反汇编测试
文章图片

13.push将地址(ebp的值0+8,就是8)中的值取出来写入f函数这个帧,esp减去4。
反汇编测试
文章图片

14.call指令调用g函数,建立g函数的帧。
反汇编测试
文章图片

15.push命令将ebp中的值(地址0xffffd15c的值,此处应是0xa)写入g函数帧里,esp的地址减去4。
反汇编测试
文章图片

16.mov将esp中的值写入ebp中(为传回上层函数做准备)。
反汇编测试
文章图片

17.call指令调用不知名函数。
反汇编测试
文章图片

18.mov指令将寄存器eax中的值存入地址(寄存器esp的值)中。
反汇编测试
文章图片

19.ret指令终止函数,返回上层函数的帧。
反汇编测试
文章图片

20.add指令将0x2e6f与寄存器eax中的值(0x56556191)相加,存入eax中。
反汇编测试
文章图片

21.mov指令将寄存器ebp中的值(此处为0)加8,存入eax寄存器中。
反汇编测试
文章图片

22.add指令将3加上eax中的值存入eax中(3+8=11)。
反汇编测试
文章图片

23.pop指令
反汇编测试
文章图片

24.ret指令终止当前函数。
反汇编测试
文章图片

25.add指令将4与esp寄存器中的值(此处为8)相加,存入esp寄存器中。
反汇编测试
文章图片

25.mov指令将地址(寄存器ebp的值减去4)中的值存入寄存器edx中。
反汇编测试
文章图片

26.add指令将edx中的值与eax中的值相加(11+8=21),存入eax中。
反汇编测试
文章图片

27.leave指令用于释放当前堆栈中的内容。
反汇编测试
文章图片

28.ret指令用于终止函数。
反汇编测试
文章图片

29.add指令将4与寄存器esp中的值相加,存到esp中(4+8 = 12)
反汇编测试
文章图片

30.add指令将1与寄存器eax中的值相加,存到eax中(21+1 = 22)。
反汇编测试
文章图片

31.leave指令释放当前堆栈的内容。
反汇编测试
文章图片

32.ret指令结束当前函数调用,之后就是系统调用,很多看不完。
反汇编测试
文章图片

总结 ? 看了一整天,看麻了!

    推荐阅读