homework08分析

本文环境为ubuntu-16.04-i686-desktop。(不能用docker,因为 docker 不支持32位)

0x00

homework08 的程序流程为:

0x01

运行./homework08出现段错误。

0x02

​ 使用gdb调试,发现有:

2

​ 之后运行 disas main,disas f00,disas f01,disas f02。分别有:

image-20221031161154523

image-20221031161256546

image-20221031161338741

image-20221031161624460

0x03

在函数f00的入口,对strcpy的调用以及出口设置断点。并设置每次执行到断点后都输出一下 $eip 的值。

1
2
3
4
b *(f00+0)
b *(f00+24)
b *(f00+34)
display/i $eip

0x04

​ 输入 r 并运行,输入 x/x $esp 并运行查看此时栈的地址。

image-20221031163016127

​ 上述截图表示,此时程序运行到f00的入口,此时esp指针中的内容为0x08048578,此时 esp指向的地址为 0xbfff03c

​ 输入 c 并运行。

image-20221031163448114

​ 上述截图表示,此时程序运行到f00的strcpy函数处。此时查看某些信息,有:

image-20221031164616975

​ 可以得到,此时 Lbuffer 为src,而 0xbffef5c 是 Lbuffer 复制的目的地址。可见,Lbuffer 的地址 0x0804a040 保存在地址为0xbfffef44 的栈中,而 des 的首地址 0xbffef5c 保存在 0xbfffef40 的栈中。

知识点1:由于 C 语言默认将参数逆序推入堆栈。因此 C 函数 strcpy(des,src) 的 src 先进栈(高地址),des 后进栈(低地址)。(栈的顺序是由高地址到低地址扩展的。)

​ 因此,可以计算出 des 的首地址与返回地址所在栈的距离 0xbfff03c - 0xbffef5c = 0xe0 = 224。因此,如果 Lbuffer 的内容超过 224 字节,则将发生缓冲区溢出,并且返回地址被改写。

0x05

​ 输入 c 并运行,得到:

image-20221031170555775

知识点2:ret 指令让 eip 等于 esp 指向的内容 并且 esp 等于 esp+ 4。

​ 查看此时的 esp 地址,即下一条指令地址,变为字符串为 “QRST”。

image-20221031170837601

0x06

​ 类似的,运行 ./homework 08 arg1 与 ./homework 08 arg1 arg2。

image-20221031171423299

​ 发现一个报错一个不报错,因此,f01存在缓冲区溢出,f02不存在缓冲区溢出。

​ 与0x01-0x05类似,不同的是要在程序调试之前加上 set args argv,这样才能调试函数 f01。

​ 最后,计算 0xbffff03c - 0xbfffef61= 0xdb = 219,此时下一条指令地址变为 “LMNO”。

gdb常用命令:

1
2
3
4
5
6
7
8
r //执行程序到断点
disas // 反汇编 disassemble,例如 disas main
b // 设置断点,例如 b *(f00+24),表示对strcpy处设置断点
display // 设置程序中断后欲显示的数据及其格式,例如 display /i $pc。 $pc表示当前汇编指令,/i 表示16进制
x // 查看内存地址中的值,例如 x/x $esp 是查看当前$esp中的16进制值, x/s $esp 是查看当前$esp中的字符串值
c // 程序继续往下运行,直到遇到断点或者程序结束
set args 参数 // 调试带参数的程序
show args // 显示程序参数

留言

2022-10-31

© 2024 wd-z711

⬆︎TOP