The Report of the Bomb Lab

The Report of the Bomb Lab

The Lab2 in CS:APP

毒液哥 Fudan University

The CS:APP Bomb Lab teaches students principles of
machine-level programs, as well as general debugger and reverse
engineering skills.


Preface

This Lab is done in the WSL(Windows Subsystem for Linux) experiment, cost about 20 hours.

First, I used objdump -d bomb > assembly code.s to print the assembly code of bomb.
Then, I read the disassembly code with GDB debugging, including:
r to run the bomb.
x /s address to read the string starting from the address.
x /64xw address to read some integers from the address.
b *address to set the breakpoint in a statement of disassembly code.
c to continue the bomb till next breakpoint.
Finally, I updated the code with my annotation to better understand the code.

Solution

Phase_1

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

The piece of code above checks is the input string is equal to the givin string, which starts from 0x402400. Using GDB with x /s address, we have:

The string in Phase_1

Hence, we figured out the first password:
"Border relations with Canada have never been better."

Phase_2

0000000000400efc <phase_2>:
  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       	callq  40145c <read_six_numbers> 
  400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp)
  400f0e:	74 20                	je     400f30 <phase_2+0x34>
  400f10:	e8 25 05 00 00       	callq  40143a <explode_bomb>
  400f15:	eb 19                	jmp    400f30 <phase_2+0x34>
  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 <phase_2+0x29>
  400f20:	e8 15 05 00 00       	callq  40143a <explode_bomb>
  400f25:	48 83 c3 04          	add    $0x4,%rbx
  400f29:	48 39 eb             	cmp    %rbp,%rbx
  400f2c:	75 e9                	jne    400f17 <phase_2+0x1b>
  400f2e:	eb 0c                	jmp    400f3c <phase_2+0x40>
  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 <phase_2+0x1b>
  400f3c:	48 83 c4 28          	add    $0x28,%rsp
  400f40:	5b                   	pop    %rbx
  400f41:	5d                   	pop    %rbp
  400f42:	c3                   	retq   

Before callq 40145c <read_six_numbers> , we notice that mov %rsp,%rsi pushes the address in %rsp into %rsi as the second argument of the function we call. We can infer that <read_six_numbers> read 6 numbers from the givin string and saved them in an array startinng from %rsp. Thus, the following loop simply checks if the geometric array is starting with 1.

Consequently, we figured out the second password:
"1 2 4 8 16 32"

Phase_3

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

Using GDB with x /s address, we get the string starting from 0x4025cf.

The string in Phase_3

Similarly to Phase_2, we can infer that 0x8(%rsp) and 0xc(%rsp) is the first and the second integer we input, respectively.

The following piece of code obviously represent a switch-case. From the piece of code with annotation, we infer that the first integer should be 7 and the second integer should be 0x147.

Hence, we figured out the third password:
"7 327"

Phase_4

000000000040100c <phase_4>:
  40100c:	48 83 ec 18          	sub    $0x18,%rsp
  401010:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx # 0xc(%rsp) : the second input integer.
  401015:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx # 0x8(%rsp) : the first input integer.
  40101a:	be cf 25 40 00       	mov    $0x4025cf,%esi
  40101f:	b8 00 00 00 00       	mov    $0x0,%eax
  401024:	e8 c7 fb ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  401029:	83 f8 02             	cmp    $0x2,%eax
  40102c:	75 07                	jne    401035 <phase_4+0x29>
  40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp)
  401033:	76 05                	jbe    40103a <phase_4+0x2e>
  401035:	e8 00 04 00 00       	callq  40143a <explode_bomb>
  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       	callq  400fce <func4> # %rdi %rsi %rdx
  40104d:	85 c0                	test   %eax,%eax
  40104f:	75 07                	jne    401058 <phase_4+0x4c> # the return value shoule be 0.
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp) # the second input integer shoule be 0.
  401056:	74 05                	je     40105d <phase_4+0x51>
  401058:	e8 dd 03 00 00       	callq  40143a <explode_bomb>
  40105d:	48 83 c4 18          	add    $0x18,%rsp
  401061:	c3                   	retq  
0000000000400fce <func4>: # arguments: input x 0 14 -- %rdi %rsi %rdx
  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 # %ecx = %eax = %edx - %esi = 14 - 0 = 14. 14 >> 31 == 0
  400fdb:	01 c8                	add    %ecx,%eax # %eax = 14 + 0 = 14;
  400fdd:	d1 f8                	sar    %eax # %eax >> 1 = 7.
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx # %ecx = 7. %rcx =  (%rdx - %rsi) / 2.
  400fe2:	39 f9                	cmp    %edi,%ecx # if(%rcx <= x) jump
  400fe4:	7e 0c                	jle    400ff2 <func4+0x24>
  400fe6:	8d 51 ff             	lea    -0x1(%rcx),%edx # %rdx = %rcx - 1
  400fe9:	e8 e0 ff ff ff       	callq  400fce <func4>
  400fee:	01 c0                	add    %eax,%eax
  400ff0:	eb 15                	jmp    401007 <func4+0x39>
  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax 
  400ff7:	39 f9                	cmp    %edi,%ecx # if(%rcx >= x) jump
  400ff9:	7d 0c                	jge    401007 <func4+0x39>
  400ffb:	8d 71 01             	lea    0x1(%rcx),%esi # %rsi = %rcx + 1
  400ffe:	e8 cb ff ff ff       	callq  400fce <func4>
  401003:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax # %eax = 1 + %eax * 2.
  401007:	48 83 c4 08          	add    $0x8,%rsp
  40100b:	c3                   	retq   

Distinctly, the second input integer and the return value of fun4(x, 14, 0) should be both 0, where x is the first input integer.

Turn to fun4. In fact, I didn’t really understand what this function do after a quick-view, but I soon found that if x=7x = 7, the return value is 0.

Hence, we figured out the fourth password:
"7 0"

Phase_5

0000000000401062 <phase_5>:
  401062:	53                   	push   %rbx
  401063:	48 83 ec 20          	sub    $0x20,%rsp
  401067:	48 89 fb             	mov    %rdi,%rbx # Now %rbx denotes the begin address of the input string.
  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) # 0x18(%rsp) = %fs:0x28
  401078:	31 c0                	xor    %eax,%eax
  40107a:	e8 9c 02 00 00       	callq  40131b <string_length>
  40107f:	83 f8 06             	cmp    $0x6,%eax # The length of input string should be 6.
  401082:	74 4e                	je     4010d2 <phase_5+0x70>
  401084:	e8 b1 03 00 00       	callq  40143a <explode_bomb>

  401089:	eb 47                	jmp    4010d2 <phase_5+0x70>
  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx # The address of the i-th charactor in the input string have been saved in %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) # It seems that 6 chars will be moved into an array by some rules from the input.
  4010a4:	48 83 c0 01          	add    $0x1,%rax # From this, we know that %rax is the accumulator i.
  4010a8:	48 83 f8 06          	cmp    $0x6,%rax
  4010ac:	75 dd                	jne    40108b <phase_5+0x29>
  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp) # The end of the string is set to 0.

  4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi 
  4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi # 9 f e 5 6 7 : the least nibbles of the chars in the string we need, respectively.
  4010bd:	e8 76 02 00 00       	callq  401338 <strings_not_equal> # Check if the string we created and the given string are equal.
  4010c2:	85 c0                	test   %eax,%eax
  4010c4:	74 13                	je     4010d9 <phase_5+0x77>
  4010c6:	e8 6f 03 00 00       	callq  40143a <explode_bomb>
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4010d0:	eb 07                	jmp    4010d9 <phase_5+0x77>
  4010d2:	b8 00 00 00 00       	mov    $0x0,%eax
  4010d7:	eb b2                	jmp    40108b <phase_5+0x29>

  4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
  4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax #Check if 0x18(%rsp) = %fs:0x28.
  4010e5:	00 00 
  4010e7:	74 05                	je     4010ee <phase_5+0x8c>
  4010e9:	e8 42 fa ff ff       	callq  400b30 <__stack_chk_fail@plt>
  4010ee:	48 83 c4 20          	add    $0x20,%rsp
  4010f2:	5b                   	pop    %rbx
  4010f3:	c3                   	retq   

Apparently, the length of the input string should be 6. With the annotation, we found that the function will construct a string according to our input.

  40108f:	88 0c 24             	mov    %cl,(%rsp)
  401092:	48 8b 14 24          	mov    (%rsp),%rdx
  401096:	83 e2 0f             	and    $0xf,%edx

The piece of code above shows that the i-th char will be C[A[i] & 0xf] where C is a char array starting from 0x4024b0, A is the string we input.
And then the string we construct will be compared with the string starting from 0x40245e. Using GDB with x /s address and x /16cb address, we get the string starting from 0x40245e and the char array starting from 0x4024b0.

The string in Phase_5

The char array in Phase_5

Thus, the least neebles of the chars in the input string should be 9, f, e, 5, 6 and 7, respectively.

Consequently, we figured out the fifth password:
")/.%&'"

Phase_6

00000000004010f4 <phase_6>:
  4010f4:	41 56                	push   %r14
  4010f6:	41 55                	push   %r13
  4010f8:	41 54                	push   %r12
  4010fa:	55                   	push   %rbp
  4010fb:	53                   	push   %rbx
  4010fc:	48 83 ec 50          	sub    $0x50,%rsp
  401100:	49 89 e5             	mov    %rsp,%r13 # %rsp is the starting address of the array.
  401103:	48 89 e6             	mov    %rsp,%rsi
  401106:	e8 51 03 00 00       	callq  40145c <read_six_numbers>
  40110b:	49 89 e6             	mov    %rsp,%r14
  40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d
  401114:	4c 89 ed             	mov    %r13,%rbp # %rbp = %r13 = the address of the current integer.
  401117:	41 8b 45 00          	mov    0x0(%r13),%eax
  40111b:	83 e8 01             	sub    $0x1,%eax
  40111e:	83 f8 05             	cmp    $0x5,%eax
  401121:	76 05                	jbe    401128 <phase_6+0x34>
  401123:	e8 12 03 00 00       	callq  40143a <explode_bomb>
  401128:	41 83 c4 01          	add    $0x1,%r12d # It seems that %r12d is an accumulator i.
  40112c:	41 83 fc 06          	cmp    $0x6,%r12d
  401130:	74 21                	je     401153 <phase_6+0x5f>
  401132:	44 89 e3             	mov    %r12d,%ebx # j = i.
  401135:	48 63 c3             	movslq %ebx,%rax
  401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax # Push the i-th input interger into %eax.
  40113b:	39 45 00             	cmp    %eax,0x0(%rbp) # Check if the j-th is equal to the current integer.
  40113e:	75 05                	jne    401145 <phase_6+0x51>
  401140:	e8 f5 02 00 00       	callq  40143a <explode_bomb>
  401145:	83 c3 01             	add    $0x1,%ebx # %ebx is also an accumulator j.
  401148:	83 fb 05             	cmp    $0x5,%ebx # Another loop in the first loop?
  40114b:	7e e8                	jle    401135 <phase_6+0x41>
  40114d:	49 83 c5 04          	add    $0x4,%r13
  401151:	eb c1                	jmp    401114 <phase_6+0x20>

  401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi # The ending address.
  401158:	4c 89 f0             	mov    %r14,%rax # Now %rax = %r14 = %rsp, the starting address.
  40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
  401160:	89 ca                	mov    %ecx,%edx 
  401162:	2b 10                	sub    (%rax),%edx 
  401164:	89 10                	mov    %edx,(%rax) # (%rax) = 0x7 - (%rax)
  401166:	48 83 c0 04          	add    $0x4,%rax
  40116a:	48 39 f0             	cmp    %rsi,%rax # Obviously let each integer A[i] = 7 - A[i];
  40116d:	75 f1                	jne    401160 <phase_6+0x6c>

  40116f:	be 00 00 00 00       	mov    $0x0,%esi
  401174:	eb 21                	jmp    401197 <phase_6+0xa3>
  401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
  40117a:	83 c0 01             	add    $0x1,%eax
  40117d:	39 c8                	cmp    %ecx,%eax # %ecx denote the number we selected.
  40117f:	75 f5                	jne    401176 <phase_6+0x82>
  401181:	eb 05                	jmp    401188 <phase_6+0x94>
  401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx # %edx denotes the head of the list.
  401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2) # %rdx denotes the address of the A[i]-th node in the list
  40118d:	48 83 c6 04          	add    $0x4,%rsi
  401191:	48 83 fe 18          	cmp    $0x18,%rsi
  401195:	74 14                	je     4011ab <phase_6+0xb7>
  401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx # It shows that %rsi denotes the accumulator i and %ecx = A[i];
  40119a:	83 f9 01             	cmp    $0x1,%ecx # if %ecx <= 1, jump. That means that we don't need to find the node in the list using loop.
  40119d:	7e e4                	jle    401183 <phase_6+0x8f>
  40119f:	b8 01 00 00 00       	mov    $0x1,%eax
  4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx
  4011a9:	eb cb                	jmp    401176 <phase_6+0x82>

  4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx # %rbx : the head.
  4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax # %rax : the first node.
  4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi # %rsi : the end. Thus, the listnodes have been arranged by the given order.
  4011ba:	48 89 d9             	mov    %rbx,%rcx
  4011bd:	48 8b 10             	mov    (%rax),%rdx
  4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
  4011c4:	48 83 c0 08          	add    $0x8,%rax
  4011c8:	48 39 f0             	cmp    %rsi,%rax
  4011cb:	74 05                	je     4011d2 <phase_6+0xde>
  4011cd:	48 89 d1             	mov    %rdx,%rcx
  4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>
  4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
  4011d9:	00 
  4011da:	bd 05 00 00 00       	mov    $0x5,%ebp # we have changed the node address to the array address.
  4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
  4011e3:	8b 00                	mov    (%rax),%eax
  4011e5:	39 03                	cmp    %eax,(%rbx)
  4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>
  4011e9:	e8 4c 02 00 00       	callq  40143a <explode_bomb> # If the array is not in ascending order, Bomb!
  4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx
  4011f2:	83 ed 01             	sub    $0x1,%ebp
  4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
  4011f7:	48 83 c4 50          	add    $0x50,%rsp
  4011fb:	5b                   	pop    %rbx
  4011fc:	5d                   	pop    %rbp
  4011fd:	41 5c                	pop    %r12
  4011ff:	41 5d                	pop    %r13
  401201:	41 5e                	pop    %r14
  401203:	c3                   	retq   

The first paragraph above read in 6 numbers and then check if they are identical.

The second paragraph replace each elements x with 7 - x.

When looking at the third paragraph first time, we will be quite confused what the loop functions. But notice that there is a immediate address in the piece of code. Using x /32xw address, we find that there are some nodes of some class whose size is 16 bytes, and the third number is the address of a certain node.

The linked list in Phase_6

Thus, we infer that this paragraph fill A[i] with the address of the C[i]-th node, where A is an array starting from 0x20(%rsp) and C is the input array(remember that the array has been changed).

The fourth paragraph simply replace the address of each node with the value of it, respectively.

Finally the value array should be in acsending order. From the figure above we knew the value of each node, we can infer the sixth password:
"4 3 2 1 6 5"

Secret_Phase

00000000004015c4 <phase_defused>:
  4015c4:	48 83 ec 78          	sub    $0x78,%rsp
  4015c8:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax
  4015cf:	00 00 
  4015d1:	48 89 44 24 68       	mov    %rax,0x68(%rsp)
  4015d6:	31 c0                	xor    %eax,%eax
  4015d8:	83 3d 81 21 20 00 06 	cmpl   $0x6,0x202181(%rip)        # 603760 <num_input_strings>
  4015df:	75 5e                	jne    40163f <phase_defused+0x7b>
  4015e1:	4c 8d 44 24 10       	lea    0x10(%rsp),%r8
  4015e6:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx
  4015eb:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx
  4015f0:	be 19 26 40 00       	mov    $0x402619,%esi # "%d%d%s"
  4015f5:	bf 70 38 60 00       	mov    $0x603870,%edi # the forth input string.
  4015fa:	e8 f1 f5 ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  4015ff:	83 f8 03             	cmp    $0x3,%eax
  401602:	75 31                	jne    401635 <phase_defused+0x71>
  401604:	be 22 26 40 00       	mov    $0x402622,%esi # "DrEvil"
  401609:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi # %rdi denotes the string following the forth input line.
  40160e:	e8 25 fd ff ff       	callq  401338 <strings_not_equal>
  401613:	85 c0                	test   %eax,%eax
  401615:	75 1e                	jne    401635 <phase_defused+0x71>
  401617:	bf f8 24 40 00       	mov    $0x4024f8,%edi
  40161c:	e8 ef f4 ff ff       	callq  400b10 <puts@plt>
  401621:	bf 20 25 40 00       	mov    $0x402520,%edi
  401626:	e8 e5 f4 ff ff       	callq  400b10 <puts@plt>
  40162b:	b8 00 00 00 00       	mov    $0x0,%eax
  401630:	e8 0d fc ff ff       	callq  401242 <secret_phase>
0000000000401242 <secret_phase>:
  401242:	53                   	push   %rbx
  401243:	e8 56 02 00 00       	callq  40149e <read_line>
  401248:	ba 0a 00 00 00       	mov    $0xa,%edx
  40124d:	be 00 00 00 00       	mov    $0x0,%esi
  401252:	48 89 c7             	mov    %rax,%rdi
  401255:	e8 76 f9 ff ff       	callq  400bd0 <strtol@plt> # Input an integer x.
  40125a:	48 89 c3             	mov    %rax,%rbx
  40125d:	8d 40 ff             	lea    -0x1(%rax),%eax
  401260:	3d e8 03 00 00       	cmp    $0x3e8,%eax # if x - 1 <= 0x3e8, jump.
  401265:	76 05                	jbe    40126c <secret_phase+0x2a>
  401267:	e8 ce 01 00 00       	callq  40143a <explode_bomb>
  40126c:	89 de                	mov    %ebx,%esi # %esi denotes x.
  40126e:	bf f0 30 60 00       	mov    $0x6030f0,%edi # 36
  401273:	e8 8c ff ff ff       	callq  401204 <fun7>
  401278:	83 f8 02             	cmp    $0x2,%eax # The return value should be 2.
  40127b:	74 05                	je     401282 <secret_phase+0x40>
  40127d:	e8 b8 01 00 00       	callq  40143a <explode_bomb>
  401282:	bf 38 24 40 00       	mov    $0x402438,%edi
  401287:	e8 84 f8 ff ff       	callq  400b10 <puts@plt>
  40128c:	e8 33 03 00 00       	callq  4015c4 <phase_defused>
  401291:	5b                   	pop    %rbx
  401292:	c3                   	retq   
0000000000401204 <fun7>:
  401204:	48 83 ec 08          	sub    $0x8,%rsp
  401208:	48 85 ff             	test   %rdi,%rdi # %rdi == 0, return INF.
  40120b:	74 2b                	je     401238 <fun7+0x34>
  40120d:	8b 17                	mov    (%rdi),%edx #
  40120f:	39 f2                	cmp    %esi,%edx # if (%rdi) <= %esi, the input integer x, jump
  401211:	7e 0d                	jle    401220 <fun7+0x1c>
  401213:	48 8b 7f 08          	mov    0x8(%rdi),%rdi # if (%rdi) > x, x = x -> left child.
  401217:	e8 e8 ff ff ff       	callq  401204 <fun7>
  40121c:	01 c0                	add    %eax,%eax
  40121e:	eb 1d                	jmp    40123d <fun7+0x39>  # We should return here.

  401220:	b8 00 00 00 00       	mov    $0x0,%eax
  401225:	39 f2                	cmp    %esi,%edx # if (%rdi) == x, return 0.
  401227:	74 14                	je     40123d <fun7+0x39>
  401229:	48 8b 7f 10          	mov    0x10(%rdi),%rdi # x = x -> right child.
  40122d:	e8 d2 ff ff ff       	callq  401204 <fun7>
  401232:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax
  401236:	eb 05                	jmp    40123d <fun7+0x39>
  401238:	b8 ff ff ff ff       	mov    $0xffffffff,%eax
  40123d:	48 83 c4 08          	add    $0x8,%rsp
  401241:	c3                   	retq   

First, we find that the <secret_phase> will be called in the <phase_defused> function only. We’ll read two integers and a string from 0x603870 which is the starting address of the fourth input password and compared it with the string starting from 0x402622, which can be exposed using x /s address.

The key to the Secret_Phase

Thus, in order to enter the secret_phase, the fourth line should be "7 0 DrEvil".

Turn to <secret_phase>. This function simply read an integer x and check if the return value of fun7(0x6030f0, x) is 2.

The tree in the Secret_Phase

Now we are at <fun7>. From the figure above, we know that it’s a tree starting from 0x6030f0 and the size fo the node is 32 bytes where the first 8 byte is the integer value of this node, and, the second and the third value is the address of the left and the right child, respectively.

The tree in the Secret_Phase

If we illustrate the tree by the figure above, we surprisingly find the tree is a BST(binary-search-tree), and then the return value of fun7 can be easily calculate.

If x equals to the value of current node, return 0.
If x is less than the value, find x in the left subtree and then double the return value.
if x is greater then the value, find x in the right subtree and then double the return value with a increment of 1.

Thus, two value, 0x16 and 0x14, can meet the condition.

Finally, we get a solution to the whole bomb:
Border relations with Canada have never been better. 1 2 4 8 16 32 7 327 7 0 DrEvil )/.%&' 4 3 2 1 6 5 22

Summary

本次Lab大大鞏固了CSAPP第三章的學習內容,加深了我對彙編語言,寄存器,CPU與內存之間的數據交換等知識的理解。更讓我體會到彙編作爲一門面向機器的語言,和如今我們編寫程序直接使用的高級語言之間有多麼大的差異。
在積累一些技巧之前,我看代碼的唯一方式似乎就只能是將人腦當作CPU使用,從上到下一步一步地跟着代碼來。它跳我也跳,反覆模擬很多遍之後才能猜出這段代碼到底要幹嘛。到後面幾個關卡時,自己積累了一些經驗,標記出哪些語句會被跳轉,再找出累加器和終止條件,才能不那麼費力地將每個循環語句分開來。
總的來說這次Lab真是太爽了,雖然花了非常多的時間,但最終完成的喜悅感也是無以倫比,令人感動的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章