反汇编测试

反汇编测试


任务详情

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.编译情况

image-20211101202835776

2.发现在树莓派arm64架构下无法完成,便转到kali上做了。

image-20211101205559577

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

image-20211101205848876

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

image-20211101210029858

用x mian查看主函数的内存地址:

首先,结合display命令和寄存器或pc内部变量,做如下设置:display /i $pc,这样在每次执行下一条汇编语句时,都会显示出当前执行的语句。

image-20211102091745502

call指令将下一条指令的地址入栈,此时%esp,%ebp和堆栈的值为:

image-20211102093213399

将上一个函数的基址入栈,从当前%esp开始作为新基址:

image-20211102093527513

先为传参做准备:

image-20211102093801321

f函数的汇编代码:

image-20211102093949549

实参入栈:

image-20211102094125998

主函数汇编代码:

image-20211102094502986


知识点

跟着博客做完整个人还是很晕,于是想梳理一下知识点。

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。

image-20211102140922607

4.使用si步入下一条指令,使用x(examine) /nfu + 内存地址查看堆栈内容(之后每一步都要用到,不重复说明)。

call指令调用f函数,f函数的地址在0x5655619e

image-20211102140103395

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

image-20211102135701329

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

image-20211102141232311

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

image-20211102142015117

7.sub指令代表第一个寄存器中的值减去第二个寄存器中的值,将结果存入第一个寄存器中。这里就是用10(我的学号)减去esp中的值(此处应该是8),得到了2,存入?

(此处不理解)将我的学号传入f函数中,堆栈中存入了0xf7de2fd6。

image-20211102142513989

此处因为进入了f函数中,所以ebp指向了f函数的栈底0xffffd15c。

8.call指令调用(此处应该是一个奇奇怪怪的函数,估计是某个库函数,用来初始化函数调用的?),建立该函数的帧。

esp减去了16,说明存入了4个东西(为什么呢)

image-20211102144144974

9.mov指令将esp的地址存入了eax寄存器中,地址为0x565561a9,存入了堆栈中,esp中的值减去4。

image-20211102144312122

10.ret指令用于终止当前函数的执行,将运行权交还给上层函数。也就是,当前函数的帧将被回收。

随着函数的终止,系统就回到刚才f函数中断的地方,继续往下执行。

image-20211102144615115

11.add指令是将0x2e57与eax寄存器中的值相加,存到?

此处应该发生了pop指令,esp寄存器的值加上4。

image-20211102145139156

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

image-20211102145312214

13.push将地址(ebp的值0+8,就是8)中的值取出来写入f函数这个帧,esp减去4。

image-20211102150055177

14.call指令调用g函数,建立g函数的帧。

image-20211102150843846

15.push命令将ebp中的值(地址0xffffd15c的值,此处应是0xa)写入g函数帧里,esp的地址减去4。

image-20211102151703325

16.mov将esp中的值写入ebp中(为传回上层函数做准备)。

image-20211102152132580

17.call指令调用不知名函数。

image-20211102152327988

18.mov指令将寄存器eax中的值存入地址(寄存器esp的值)中。

image-20211102152432179

19.ret指令终止函数,返回上层函数的帧。

image-20211102152623460

20.add指令将0x2e6f与寄存器eax中的值(0x56556191)相加,存入eax中。

image-20211102152811118

21.mov指令将寄存器ebp中的值(此处为0)加8,存入eax寄存器中。

image-20211102153038631

22.add指令将3加上eax中的值存入eax中(3+8=11)。

image-20211102153332093

23.pop指令

image-20211102153504867

24.ret指令终止当前函数。

image-20211102153626430

25.add指令将4与esp寄存器中的值(此处为8)相加,存入esp寄存器中。

image-20211102153806067

25.mov指令将地址(寄存器ebp的值减去4)中的值存入寄存器edx中。

image-20211102154141197

26.add指令将edx中的值与eax中的值相加(11+8=21),存入eax中。

image-20211102154222592

27.leave指令用于释放当前堆栈中的内容。

image-20211102181539933

28.ret指令用于终止函数。

image-20211102181824981

29.add指令将4与寄存器esp中的值相加,存到esp中(4+8 = 12)

image-20211102181911321

30.add指令将1与寄存器eax中的值相加,存到eax中(21+1 = 22)。

image-20211102181948090

31.leave指令释放当前堆栈的内容。

image-20211102182052262

32.ret指令结束当前函数调用,之后就是系统调用,很多看不完。

image-20211102182324016

总结

​ 看了一整天,看麻了!

原文地址:https://www.cnblogs.com/sisterben/p/15500525.html