一些汇编题目分析

最近在学习汇编做MOOC和练习题的时候碰到了几道比较难的题,觉得可以总结一下。

栈溢出和大小端

有如下的C代码以及对应的反汇编出来的汇编代码(x86-32体系结构):

  1. 当strcpy调用完成返回到foo过程时,buf[0]、buf[1]、buf[2]的值分别是多少?
  2. 在执行0x0804850d的ret指令前(popl后),ebp的值是多少?
  3. 上述ret指令执行后,eip的值是多少?用32位16进制表示,注意大小端。e.g. 0x00000000
    字符的十六进制转换表已给出


    一些汇编题目分析_第1张图片

    一些汇编题目分析_第2张图片

通过分析可以画出调用strcpy之前完整的栈(具体分析过程略)如下表(每个格子代表4个字节,address向下递减)

内容 指向该位置的指针
callfoo过程保存的%ebp
empty
empty
empty
empty
empty
string address (0x0804859c)
foo过程的返回地址 (0x08048523)
foo过程保存的%ebp %ebp
buf
empty
empty
empty
empty
empty
empty
empty
string address (strcpy的第二个参数)
%ebp - 4 (buf)

可以看出,传递给strcpy的buf指针就是%ebp-4,在复制了字符串"abcdefghi"之后,会发生溢出,破坏栈中保存的%ebp和返回地址。但现在的问题是,在考虑大小端之后,栈中的实际内容到底应该是什么样子的呢?

由于X86的字节序为小端(“低对低,高对高”),可以画出从buf指针开始向上到string address位置中实际的保存内容(一个格子代表一个字节,地址从上往下递减):

描述 内容
string address (高) 08
04
85
string address (低) 9c
foo的返回地址 (高) 08
04
85
foo的返回地址 (低) 23
保存的%ebp (高) ??
??
??
保存的%ebp (低) ??
buf[0] (高) ??
??
??
buf[0] (低) ??

在向以buf开头的地址中写入字符串"abcdefghi\0"(转换成16进制,就是0x61626364656667686900)时,由于char类型的大小只有一个字节,大小端对它来说是无所谓的,只要从低地址向高地址覆写就可以。于是,我们得到了修改过的栈帧:

描述 内容
string address (高) 08
04
85
string address (低) 9c
foo的返回地址 (buf[2]) (高) 08
04
85 00
foo的返回地址 (buf[2]) (低) 23 69
保存的%ebp (buf[1]) (高) ?? 68
?? 67
?? 66
保存的%ebp (buf[1]) (低) ?? 65
buf[0] (高) ?? 64
?? 63
?? 62
buf[0] (低) ?? 61

而寄存器会以小端模式来解释内存中的内容,因此可得,buf[0] = 0x64636261,buf[1] = 0x68676665,buf[2] = 0x08040069;popl后得到的%ebp为0x68676665,执行ret后%eip的值(也就是要返回到什么地址)为0x08040069。

本题来自学堂在线“汇编语言程序设计”,参考了关于x86系统中“大小端”在C++中的应用实例分析和函数调用的地址问题。其实,做bufbomb的时候我对char和寄存器之间字节顺序的问题想得还挺明白的,不知怎的现在就忘了……

你可能感兴趣的:(一些汇编题目分析)