Csapp_lab2
实验报告
实 验(三)
题 目 Binary Bomb
二进制炸弹
专 业 英才自动化
学 号
班 级
学 生
指 导 教 师
实 验 地 点
实 验 日 期
计算学部
目 录
2.1 Ubuntu下CodeBlocks反汇编(10分) - 5 -
2.2 Ubuntu下EDB运行环境建立(10分) - 5 -
第1章 实验基本信息
1.1 实验目的
熟练掌握计算机系统的ISA指令系统与寻址方式
熟练掌握Linux下调试器的反汇编调试跟踪分析机器语言的方法
增强对程序机器级表示、汇编语言、调试器和逆向工程等的理解
1.2 实验环境与工具
1.2.1 硬件环境
Cpu: AMD Ryzen 5800H
Gpu: Nvidia RTX 3070
1.2.2 软件环境
版本 Windows 11 专业版
版本 21H2
操作系统版本 22000.613
体验 Windows 功能体验包 1000.22000.613.0
虚拟机:vmware16pro
虚拟系统:ubuntu 20.04
1.2.3 开发工具
Visual studio, codeblocks, gdb, edb
1.3 实验预习
上实验课前,必须认真预习实验指导书(PPT或PDF)
了解实验的目的、实验环境与软硬件工具、实验操作步骤,复习与实验有关的理论知识。
请写出C语言下包含字符串比较、循环、分支(含switch)、函数调用、递归、指针、结构、链表等的例子程序sample.c。
生成执行程序sample.out。
用gcc –S或CodeBlocks或GDB或OBJDUMP等,反汇编,比较。
列出每一部分的C语言对应的汇编语言。
修改编译选项-O (缺省2)、O0、O1、O3、Og、-m32/m64。再次查看生成的汇编语言与原来的区别。
注意O1之后缺省无栈帧,RBP为普通寄存器。用 -fno-omit-frame-pointer加上栈指针。
GDB命令详解–tui模式 ^XA切换 layout改变等等
有目的地学习: 看VS的功能,GDB命令用什么?
第2章 实验环境建立
2.1 Ubuntu下CodeBlocks反汇编(10分)
CodeBlocks运行hello.c。反汇编查看printf函数的实现。
要求:C、ASM、内存(显示hello等内容)、堆栈(call printf前)、寄存器同时在一个窗口。
图2-1 Ubuntu下CodeBlocks反汇编截图
2.2 Ubuntu下EDB运行环境建立(10分)
用EDB调试hello.c的执行文件,截图,要求同2.1
图2-2 Ubuntu下EDB截图
第3章 各阶段炸弹破解与分析
每阶段30分,密码10分,分析20分,总分不超过80分
3.1 阶段1的破解与分析
密码如下:When a problem comes along, you must zip it!
破解过程:phase_1调用了strings_not_equal函数来检查输入的字符串和密码之间是否相等,并且把地址$0x403150作为参数给该函数,推测密码就在该地址内。
3.2 阶段2的破解与分析
密码如下:0 1 3 6 10 15(答案不唯一,为首项大于等于0且相邻两项差依次递增的数列)
破解过程:观察反汇编的phase_2。初始几句是常规的栈保护,直到出现
callq 4018da <read_six_numbers>
说明调用了read_six_numbers函数来读取六个数,猜测密码为六个数,而%rsi为作为参数传递给该函数,寄存着%rsp的值,说明六个数存储的地址从栈顶开始。
cmpl $0x0,(%rsp) 将0与第一个数比较,小于0则引爆,说明第一个数大于等于0。之后进入循环,注意关键语句
add (%rsp,%rdx,4),%ecx
cmp %ecx,(%rsp,%rax,4)
je 401430 <phase_2+0x26>
%ecx每个循环都在按1递增,这三句比较了后项与前项是否相差%ecx,则可以得知密码为首项大于等于0,相邻两项差从1递增的六项数列。
首项为1时拆炸弹
首项为0时拆炸弹
3.3 阶段3的破解与分析
密码如下:0 984(或1 511或2 530或3 715或4 173或5 567或6 283或7 384)
破解过程: mov $0x40330f,%esi
%esi存储的地址作为参数给sscanf函数,通过查询发现该地址存储的参数为,说明密码由两个数构成。
mov 0xc(%rsp),%eax
cmp $0x7,%eax
ja 4014c8 <phase_3+0x75>
检验第一个数小于等于7。
jmpq *0x4031b0(,%rax,8)说明跳转表存储在0x4031b0中,查看该地址
发现跳转表存储着8中情况对应的跳转地址,经过计算就是答案。
3.4 阶段4的破解与分析
密码如下:8 35
破解过程: mov $0x40330f,%esi
该地址作为参数传递过sscanf函数,查看,发现密码应该为两个数。
mov 0xc(%rsp),%eax
test %eax,%eax
js 401543 <phase_4+0x2f>
cmp $0xe,%eax
jle 401548 <phase_4+0x34>
这五句说明第一个数在1到14之间
mov $0xe,%edx
mov $0x0,%esi
mov 0xc(%rsp),%edi
callq 4014e2 <func4>
这三个寄存器的值作为参数传递给func4,而观察func4可以写出其代码
-
int a = 0;
-
int edx = 0;
-
int edi = 0;
-
int esi = 0;
-
int func4() {
-
a = edx;
-
a = a - esi;
-
int b = a;
-
b = b >> 31;
-
b = b + a;
-
b = b >> 1;
-
b = b + esi;
-
if (b > edi) {
-
edx = b - 1;
-
func4();
-
b = b + a;
-
}
-
else if (b < edi) {
-
esi = b + 1;
-
func4();
-
b = b + a;
-
}
-
a = b;
-
return a;
-
}
cmp $0x23,%eax要求返回值为35,经过尝试8满足条件。
cmpl $0x23,0x8(%rsp)要求第二个值为35,则密码为8 35.
3.5 阶段5的破解与分析
密码如下:
ans1 |
) 9 I Y i y |
ans2 |
/ ? O _ o |
ans3 |
. > N ^ n ~ |
ans4 |
% 5 E U e u |
ans5 |
& 6 F V f v |
ans6 |
' 7 G W g w |
(6个字符的各种可能横向列出,可任意选择)
破解过程:
3.6 阶段6的破解与分析
密码如下:1 4 6 2 5 3
破解过程:phase_6的代码可以分为几个大块。
第一个大块是个双层循环,作用是确定输入的六个数只能是1、2、3、4、5、6的排列组合。
第二块的作用是按照输入的数字将节点储存在栈顶。例如第一个数输入4则在栈顶储存node4,第二个数输入2则在栈顶的下一个区域储存node2。查看节点链表所在的内存区域:
第三块的作用是把储存在栈顶的结点依次起来,并依顺序比较节点储存的数是否小于下一节点的数。据此可以推荐堆栈内节点的顺序应该是node1、node4、node6、node2、node5、node3.因此答案是1 4 6 2 5 3.
3.7 阶段7的破解与分析(隐藏阶段)
密码如下:35(四阶段字符串为DrEvil)
破解过程:
炸弹的关键为secret_phase阶段的二叉树地址,根据地址查询到二叉树的数据,不难观察节点n包含自身的值和其中一个子节点地址,而n+16为节点n的另一个子节点地址。需要由func7输出6,逆推过程如下
第4章 总结
4.1 请总结本次实验的收获
熟悉了汇编语言,明白了循环在汇编语言里如何实现,同时熟悉了地址访问方式,加深了对函数传递参数的概念理解。
4.2 请给出对本次实验内容的建议
无
注:本章为酌情加分项。
参考文献
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现