CSAPP实验(2)---bomblab

实验目的

写在最前面:Bomblab 是一项有趣而具有挑战性的实践项目。这个实验模拟了解除恶意软件炸弹的过程,需要实验者以下能力

  1. 反汇编和逆向工程:实验者需要通过反汇编炸弹程序,分析程序的结构和逻辑,理解每个任务的具体要求,以及找出实现这些要求的代码路径。

  2. 调试和动态分析:实验者需要使用调试器工具(如gdb)来跟踪程序的执行过程,观察程序在不同输入下的行为,定位问题和漏洞,以及验证他们的假设和解决方案。

  3. 漏洞分析和攻击:实验者需要通过分析炸弹程序中的漏洞,例如缓冲区溢出或格式化字符串漏洞,来破解密码或绕过某些安全机制。

  4. 解码和解密:有时候,炸弹程序中的密码可能会加密或以其他方式进行变换,这就我们需要通过理解加密算法或解码逻辑,还原出正确的密码。

写在前面:

  • 提前生成Bomb.c的反汇编文件,在终端打开bomb文件夹,输入
 > objdump -d bomb > bomb.s

          即可得到一个反汇编文件

       本实验需要配置gdb调试器:首先通过gdb载入bomb,在终端输入 gdb bomb ,此时需要输入正确的密钥,

实验原理:

phase1:

  我们去找对应的phase1的反汇编代码 

0000000000400ee0 :
  400ee0:	48 83 ec 08          	sub    $0x8,%rsp
  400ee4:	be 00 24 40 00       	mov    $0x402400,%esi
  400ee9:	e8 4a 04 00 00       	call   401338 
  400eee:	85 c0                	test   %eax,%eax
  400ef0:	74 05                	je     400ef7 
  400ef2:	e8 43 05 00 00       	call   40143a 
  400ef7:	48 83 c4 08          	add    $0x8,%rsp
  400efb:	c3                   	ret    

 通过分析
  400ee4: 向寄存器%esi存放0x402400
  400ee9: callq  401338  调用函数 strings_not_equal,判断输入的字符串                                               和程序内置的字符串(即%esi中存放的数据)是否相同,相同则返回0

不难推出,phase1的密钥就是0x402400对应的字符串,于是在gdb调试下输入

print (char*)0x402400

于是我们得到

 即为phase1的答案

phase2:

 400efc:	55                   	push   %rbp
  400efd:	53                   	push   %rbx
  400efe:	48 83 ec 28          	sub    $0x28,%rsp
  400f02:	48 89 e6             	mov    %rsp,%rsi
  400f05:	e8 52 05 00 00       	call   40145c 
  400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
  400f0e:	74 20                	je     400f30 
  400f10:	e8 25 05 00 00       	call   40143a 
  400f15:	eb 19                	jmp    400f30 
  400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax
  400f1a:	01 c0                	add    %eax,%eax
  400f1c:	39 03                	cmp    %eax,(%rbx)
  400f1e:	74 05                	je     400f25 
  400f20:	e8 15 05 00 00       	call   40143a 
  400f25:	48 83 c3 04          	add    $0x4,%rbx
  400f29:	48 39 eb             	cmp    %rbp,%rbx
  400f2c:	75 e9                	jne    400f17 
  400f2e:	eb 0c                	jmp    400f3c 
  400f30:	48 8d 5c 24 04       	lea    0x4(%rsp),%rbx
  400f35:	48 8d 6c 24 18       	lea    0x18(%rsp),%rbp
  400f3a:	eb db                	jmp    400f17 
  400f3c:	48 83 c4 28          	add    $0x28,%rsp
  400f40:	5b                   	pop    %rbx
  400f41:	5d                   	pop    %rbp
  400f42:	c3                   	ret    

   通过400f05发现主要调用的函数是read_six_numbers,在反汇编代码中找到其对应的代码段,

 400efc:	55                   	push   %rbp
  400efd:	53                   	push   %rbx
  400efe:	48 83 ec 28          	sub    $0x28,%rsp
  400f02:	48 89 e6             	mov    %rsp,%rsi
  400f05:	e8 52 05 00 00       	call   40145c 
  400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
  400f0e:	74 20                	je     400f30 
  400f10:	e8 25 05 00 00       	call   40143a 
  400f15:	eb 19                	jmp    400f30 
  400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax
  400f1a:	01 c0                	add    %eax,%eax
  400f1c:	39 03                	cmp    %eax,(%rbx)
  400f1e:	74 05                	je     400f25 
  400f20:	e8 15 05 00 00       	call   40143a 
  400f25:	48 83 c3 04          	add    $0x4,%rbx
  400f29:	48 39 eb             	cmp    %rbp,%rbx
  400f2c:	75 e9                	jne    400f17 
  400f2e:	eb 0c                	jmp    400f3c 
  400f30:	48 8d 5c 24 04       	lea    0x4(%rsp),%rbx
  400f35:	48 8d 6c 24 18       	lea    0x18(%rsp),%rbp
  400f3a:	eb db                	jmp    400f17 
  400f3c:	48 83 c4 28          	add    $0x28,%rsp
  400f40:	5b                   	pop    %rbx
  400f41:	5d                   	pop    %rbp
  400f42:	c3                   	ret    

发现在调用explode_bomb之前有类似输入的操作,在gdb调试中

print (char*)0x4025dada

CSAPP实验(2)---bomblab_第1张图片

 发现要输入的6个是为整型数,在phase_2的反汇编代码中最早出现的比较是

 400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)

故密钥的第一个数应为1,接着跳转到400f30,即第二个数的输入地址是%rbx,之后%eax的值*2,比较%rbx和%eax,故知第二个数为第一个数的两倍,以此类推,密钥构成公比为2的等比数列,

综上,phase2的密钥为1 2 4 8 16 32

phase3:

 400f43:	48 83 ec 18          	sub    $0x18,%rsp
  400f47:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  400f4c:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx
  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi
  400f56:	b8 00 00 00 00       	mov    $0x0,%eax
  400f5b:	e8 90 fc ff ff       	call   400bf0 <__isoc99_sscanf@plt>
  400f60:	83 f8 01             	cmp    $0x1,%eax
  400f63:	7f 05                	jg     400f6a 
  400f65:	e8 d0 04 00 00       	call   40143a 
  400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)
  400f6f:	77 3c                	ja     400fad 
  400f71:	8b 44 24 08          	mov    0x8(%rsp),%eax
  400f75:	ff 24 c5 70 24 40 00 	jmp    *0x402470(,%rax,8)
  400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax
  400f81:	eb 3b                	jmp    400fbe 
  400f83:	b8 c3 02 00 00       	mov    $0x2c3,%eax
  400f88:	eb 34                	jmp    400fbe 
  400f8a:	b8 00 01 00 00       	mov    $0x100,%eax
  400f8f:	eb 2d                	jmp    400fbe 
  400f91:	b8 85 01 00 00       	mov    $0x185,%eax
  400f96:	eb 26                	jmp    400fbe 
  400f98:	b8 ce 00 00 00       	mov    $0xce,%eax
  400f9d:	eb 1f                	jmp    400fbe 
  400f9f:	b8 aa 02 00 00       	mov    $0x2aa,%eax
  400fa4:	eb 18                	jmp    400fbe 
  400fa6:	b8 47 01 00 00       	mov    $0x147,%eax
  400fab:	eb 11                	jmp    400fbe 
  400fad:	e8 88 04 00 00       	call   40143a 
  400fb2:	b8 00 00 00 00       	mov    $0x0,%eax
  400fb7:	eb 05                	jmp    400fbe 
  400fb9:	b8 37 01 00 00       	mov    $0x137,%eax
  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax
  400fc2:	74 05                	je     400fc9 
  400fc4:	e8 71 04 00 00       	call   40143a 
  400fc9:	48 83 c4 18          	add    $0x18,%rsp
  400fcd:	c3                   	ret    

开始处发现

  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi

通过gdb得知,phase3的密钥为两个整型数

CSAPP实验(2)---bomblab_第2张图片

 接着分析

  cmp    $0x1,%eax      
  400f6f:  ja     400fad  a:无符号大于则跳转,至爆炸,说明第一个数为无符号数,大于0且需要小于等于7,所以第一个数可以等于1-7中的任意整数,于是根据后面的间接跳转

case 0  %eax=0xcf=207   

case 1  %eax=0x137=311
case 2  %eax=0x2c3=707
case 3  %eax=0x100=256
case 4  %eax=0x185=389
case 5  %eax=0xce=206
case 6  %eax=0x2aa=682

 case 7  %eax=0x147=327
 故最终phase3的密钥为0 207;1 311;2 707;3 256;4 389;5 206;6 682;7 327

phase4:

40100c:	48 83 ec 18          	sub    $0x18,%rsp
  401010:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  401015:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx
  40101a:	be cf 25 40 00       	mov    $0x4025cf,%esi
  40101f:	b8 00 00 00 00       	mov    $0x0,%eax
  401024:	e8 c7 fb ff ff       	call   400bf0 <__isoc99_sscanf@plt>
  401029:	83 f8 02             	cmp    $0x2,%eax
  40102c:	75 07                	jne    401035 
  40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp)
  401033:	76 05                	jbe    40103a 
  401035:	e8 00 04 00 00       	call   40143a 
  40103a:	ba 0e 00 00 00       	mov    $0xe,%edx
  40103f:	be 00 00 00 00       	mov    $0x0,%esi
  401044:	8b 7c 24 08          	mov    0x8(%rsp),%edi
  401048:	e8 81 ff ff ff       	call   400fce 
  40104d:	85 c0                	test   %eax,%eax
  40104f:	75 07                	jne    401058 
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
  401056:	74 05                	je     40105d 
  401058:	e8 dd 03 00 00       	call   40143a 
  40105d:	48 83 c4 18          	add    $0x18,%rsp
  401061:	c3                   	ret    

同phase3知,输入的数为两个整型数

40104d:	85 c0                	test   %eax,%eax
  40104f:	75 07                	jne    401058       //如果fun4返回值%eax不等于0,则跳转至爆炸,所以需要知道当num1为何值时,%eax为0
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
  401056:	74 05                	je     40105d       //如果num2=0,则跳转至结束,否则爆炸,所以输入的第二个数据只能为0
  401058:	e8 dd 03 00 00       	callq  40143a 

  40105d:	48 83 c4 18          	add    $0x18,%rsp     //释放空间

 40104f:func4后%eax的值必须为0

401051:rsp的值与0进行比较,

4010556:相等则跳转结束,不等则explode,故第二个数的值为零

接下来通过funct4研究第一个数的值

0000000000400fce :
  400fce:	48 83 ec 08          	sub    $0x8,%rsp
  400fd2:	89 d0                	mov    %edx,%eax
  400fd4:	29 f0                	sub    %esi,%eax
  400fd6:	89 c1                	mov    %eax,%ecx
  400fd8:	c1 e9 1f             	shr    $0x1f,%ecx
  400fdb:	01 c8                	add    %ecx,%eax
  400fdd:	d1 f8                	sar    %eax
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx
  400fe2:	39 f9                	cmp    %edi,%ecx
  400fe4:	7e 0c                	jle    400ff2 
  400fe6:	8d 51 ff             	lea    -0x1(%rcx),%edx
  400fe9:	e8 e0 ff ff ff       	call   400fce 
  400fee:	01 c0                	add    %eax,%eax
  400ff0:	eb 15                	jmp    401007 
  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax
  400ff7:	39 f9                	cmp    %edi,%ecx
  400ff9:	7d 0c                	jge    401007 
  400ffb:	8d 71 01             	lea    0x1(%rcx),%esi
  400ffe:	e8 cb ff ff ff       	call   400fce 
  401003:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax
  401007:	48 83 c4 08          	add    $0x8,%rsp
  40100b:	c3                   	ret 

 mov    %edx,%eax          %eax=%edx=14
sub    %esi,%eax          %eax=%eax-%esi=14-0=14
mov    %eax,%ecx          %ecx=%eax=14
shr    $0x1f,%ecx         %ecx的值逻辑右移31位,即%ecx=%ecx>>31=1110>>31=14/2^31=0
add    %ecx,%eax          %eax=%eax+%ecx=14+0=14
sar    %eax               算术右移1位,%eax=%eax/2=14/2=7

400fe4:	7e 0c                	jle    400ff2     //有符号小于等于则跳转
400ff2:	b8 00 00 00 00       	mov    $0x0,%eax                //%eax=0

注意到,第一个数输入若为7则一定能跳转,故7 0 为phase4的一个密钥

phase5:

0000000000401062 :
  401062:	53                   	push   %rbx
  401063:	48 83 ec 20          	sub    $0x20,%rsp
  401067:	48 89 fb             	mov    %rdi,%rbx
  40106a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  401071:	00 00 
  401073:	48 89 44 24 18       	mov    %rax,0x18(%rsp)
  401078:	31 c0                	xor    %eax,%eax
  40107a:	e8 9c 02 00 00       	call   40131b 
  40107f:	83 f8 06             	cmp    $0x6,%eax
  401082:	74 4e                	je     4010d2 
  401084:	e8 b1 03 00 00       	call   40143a 
  401089:	eb 47                	jmp    4010d2 
  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx
  40108f:	88 0c 24             	mov    %cl,(%rsp)
  401092:	48 8b 14 24          	mov    (%rsp),%rdx
  401096:	83 e2 0f             	and    $0xf,%edx
  401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx
  4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1)
  4010a4:	48 83 c0 01          	add    $0x1,%rax
  4010a8:	48 83 f8 06          	cmp    $0x6,%rax
  4010ac:	75 dd                	jne    40108b 
  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
  4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi
  4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi
  4010bd:	e8 76 02 00 00       	call   401338 
  4010c2:	85 c0                	test   %eax,%eax
  4010c4:	74 13                	je     4010d9 
  4010c6:	e8 6f 03 00 00       	call   40143a 
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4010d0:	eb 07                	jmp    4010d9 
  4010d2:	b8 00 00 00 00       	mov    $0x0,%eax
  4010d7:	eb b2                	jmp    40108b 
  4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
  4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  4010e5:	00 00 
  4010e7:	74 05                	je     4010ee 
  4010e9:	e8 42 fa ff ff       	call   400b30 <__stack_chk_fail@plt>
  4010ee:	48 83 c4 20          	add    $0x20,%rsp
  4010f2:	5b                   	pop    %rbx
  4010f3:	c3                   	ret    

先分析如下段代码

 40107a:	e8 9c 02 00 00       	call   40131b 
  40107f:	83 f8 06             	cmp    $0x6,%eax
  401082:	74 4e                	je     4010d2 

 40107a~401082说明需要比较我们输入的字符串长度是否为6,否则爆炸。故此题要求输入一个长度为6的字符串。接下来跳到0x4010d2处的代码,发现将%eax清空,接着回到40108b进入循环,
 

 401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx

通过gdb调试得知

 接着我们找到对应的字符串

CSAPP实验(2)---bomblab_第3张图片

 

分析可知这一关通过取我们输入六个字符的ASCII码的低四位作为索引值,查找maduiersnfotvbylSo里的字符组成的,最后返回的字符应该是flyers。maduiersnfotvbylSo中f为第9位,l为第15位,y第14位,e第5位,r第6位,s第7位,即我们需要输入6个字符,使它们ASCII码低四位分别是:1001, 1111, 1110, 0101, 0110, 0111。查看ASCII表可找到对应字符,

其中一种解码可为ionefw

phase6:

phase6的代码长度有明显的提升,故可以采用分段的手法来处理

 part1:

0x401100    mov    %rsp,%r13                                                                                                                                                              
0x401103    mov    %rsp,%rsi  
0x401106    callq  0x40145c                                                                                                                                             
0x40110b    mov    %rsp,%r14                                                                                                                                                              
0x40110e    mov    $0x0,%r12d                                                                                                                                                             
0x401114    mov    %r13,%rbp                                                                                                                                                              
0x401117    mov    0x0(%r13),%eax                                                                                                                                                         
0x40111b    sub    $0x1,%eax                                                                                                                                                              
0x40111e    cmp    $0x5,%eax                                                                                                                                                              
0x401121    jbe    0x401128                                                                                                                                                   
0x401123    callq  0x40143a                                                                                                                                                 
0x401128    add    $0x1,%r12d                                                                                                                                                             
0x40112c    cmp    $0x6,%r12d                                                                                                                                                             
0x401130    je     0x401153                                                                                                                                                   
0x401132    mov    %r12d,%ebx                                                                                                                                                             
0x401135    movslq %ebx,%rax                                                                                                                                                              
0x401138    mov    (%rsp,%rax,4),%eax
0x40113b    cmp    %eax,0x0(%rbp)                                                                                                                                                         
0x40113e    jne    0x401145                                                                                                                                                   
0x401140    callq  0x40143a                                                                                                                                                 
0x401145    add    $0x1,%ebx                                                                                                                                                              
0x401148    cmp    $0x5,%ebx                                                                                                                                                              
0x40114b    jle    0x401135                                                                                                                                                   
0x40114d    add    $0x4,%r13                                                                                                                                                              
0x401151    jmp    0x401114                                                                                                                                                   
0x401153    lea    0x18(%rsp),%rsi

函数的第一部分是一个双循环语句,其性质为输入六个数,当其存在重复元素或元素大于5时explode,

part2:

0x401153    lea    0x18(%rsp),%rsi                                                                                                                                                        
0x401158   mov    %r14,%rax                                                                                                                                                              
0x40115b   mov    $0x7,%ecx                                                                                                                                                              
0x401160   mov    %ecx,%edx                                                                                                                                                              
0x401162   sub    (%rax),%edx                                                                                                                                                            
0x401164   mov    %edx,(%rax)                                                                                                                                                            
0x401166   add    $0x4,%rax                                                                                                                                                              
0x40116a   cmp    %rsi,%rax                                                                                                                                                              
0x40116d   jne    0x401160 

part2的功能是将之前输入的6个数对7取补

part3:

0x40116f   mov    $0x0,%esi                                                                                                                                                              
0x401174   jmp    0x401197                                                                                                                                                  
0x401176   mov    0x8(%rdx),%rdx                                                                                                                                                         
0x40117a   add    $0x1,%eax                                                                                                                                                              
0x40117d   cmp    %ecx,%eax                                                                                                                                                              
0x40117f   jne    0x401176                                                                                                                                                  
0x401181   jmp    0x401188                                                                                                                                                  
0x401183   mov    $0x6032d0,%edx                                                                                                                                                         
0x401188   mov    %rdx,0x20(%rsp,%rsi,2)                                                                                                                                                 
0x40118d   add    $0x4,%rsi                                                                                                                                                              
0x401191   cmp    $0x18,%rsi                                                                                                                                                             
0x401195   je     0x4011ab                                                                                                                                                  
0x401197   mov    (%rsp,%rsi,1),%ecx                                                                                                                                                     
0x40119a   cmp    $0x1,%ecx                                                                                                                                                              
0x40119d   jle    0x401183                                                                                                                                                 
0x40119f   mov    $0x1,%eax                                                                                                                                                              
0x4011a4   mov    $0x6032d0,%edx                                                                                                                                                         
0x4011a9   jmp    0x401176         

使用gdb调试

CSAPP实验(2)---bomblab_第4张图片

 可以看出在0x6032d0 - 0x603310的相邻16的六个地址(设其为ad)中,具有 *(ad+8) == ad+16 的性质。根据此性质即可理解 的内层循环语句,其将rdx寄存器中的值加上了 ($ecx-1)*16。可以看出,该部分将 $rsp 处存放的6个整数作为偏移量,在栈帧处存放了6个指针数据。可以看出,该部分将 $rsp 处存放的6个整数作为偏移量,在栈帧处存放了6个指针数据。

 part4

0x4011da   mov    $0x5,%ebp                                                                                                                                                              
0x4011df   mov    0x8(%rbx),%rax                                                                                                                                                         
0x4011e3   mov    (%rax),%eax                                                                                                                                                            
0x4011e5   cmp    %eax,(%rbx)                                                                                                                                                            
0x4011e7   jge    0x4011ee                                                                                                                                                  
0x4011e9   callq  0x40143a                                                                                                                                                 
0x4011ee   mov    0x8(%rbx),%rbx                                                                                                                                                         
0x4011f2   sub    $0x1,%ebp                                                                                                                                                              
0x4011f5   jne    0x4011df 

每个 ad[i]+8 中存放的地址即为 ad[i+1],因此,为了不触发炸弹函数,指针数组中存放的相邻两个地址之间的值应当满足前一个地址处的值大于后一个地址处的值。
按照地址中存储值的大小进行排序,可以得到 

*0x6032f0 > *0x603300 > *0x603310 > *0x603320 > *0x6032d0 > *0x6032e0

根据part1至part3中的分析,指针数组中存放的指针与输入的整数满足

addrs[i] == 0x6032d0 + (7-num[i])*16

据此即可得到phase6的密钥为4 3 2 1 6 5

测试数据

实验结果界面展示:

CSAPP实验(2)---bomblab_第5张图片

实验小结:

首先,Bomblab实验对于一个刚入门的学生来说是相当具有挑战性的。当我第一次面对被称作"炸弹"的程序时,我感到有点手足无措。 

但是,在实验中,我通过反汇编和分析程序的逻辑和结构,意识到了二进制代码的重要性,并深入了解了计算机系统。

通过调试工具和动态分析,我能够跟踪程序的执行过程,观察程序在不同输入下的行为。这对于找出漏洞和定位问题非常有帮助。我学会了使用调试器工具(如gdb),并且能够验证自己的假设和解决方案。这让我看到了逆向工程的魅力和乐趣。

另外,我还学到了一些关于密码的加密和解密技术。有时候,炸弹程序中的密码会以加密或其他方式进行变换。通过理解加密算法和解码逻辑,还原出正确的密码的过程非常有趣

你可能感兴趣的:(java,前端,javascript)