Advertisement
NovaYoshi

bomb solutions

Dec 13th, 2015
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.69 KB | None | 0 0
  1. For the bomb, I solved everything through using objdump and then
  2. making sense of the disassembly by inserting annotations until
  3. I figured out what each of the functions did. I didn't use gdb at all.
  4.  
  5. For 4 and 5 I reverse engineered the function that determined whether or not
  6. the input is valid and just wrote a C program to brute force the correct answer
  7. (the C programs are included).
  8.  
  9. I wasn't able to get 6 figured out so I just included my work on it so far.
  10.  
  11. 0000000000400e70 <phase_1>: the solution: "Science isn't about why, it's about why not?"
  12. ; just does a string compare, that's all
  13. 400e70: 48 83 ec 08 sub rsp,0x8
  14. 400e74: be f8 1a 40 00 mov esi,0x401af8 ; pointer to "Science isn't about why, it's about why not?"
  15. 400e79: e8 bf 03 00 00 call 40123d <strings_not_equal>
  16. explode the bomb if this returns 0
  17. 400e7e: 85 c0 test eax,eax
  18. 400e80: 74 05 je 400e87 <phase_1+0x17>
  19. 400e82: e8 b6 07 00 00 call 40163d <explode_bomb>
  20. 400e87: 48 83 c4 08 add rsp,0x8
  21. 400e8b: c3 ret
  22.  
  23. 0000000000400e8c <phase_2>: a solution: "1 1 1 1 1 1"
  24. ; read 6 integers, and make sure the first three match the second three
  25.  
  26. for(int x=0; x<3; x++)
  27. if(numbers[x] != numbers[x+3])
  28. blow_up();
  29.  
  30. 400e8c: 48 89 5c 24 e0 mov QWORD PTR [rsp-0x20],rbx ; stack stuff
  31. 400e91: 48 89 6c 24 e8 mov QWORD PTR [rsp-0x18],rbp
  32. 400e96: 4c 89 64 24 f0 mov QWORD PTR [rsp-0x10],r12
  33. 400e9b: 4c 89 6c 24 f8 mov QWORD PTR [rsp-0x8],r13
  34. 400ea0: 48 83 ec 48 sub rsp,0x48
  35.  
  36. 400ea4: 48 89 e6 mov rsi,rsp
  37. 400ea7: e8 97 08 00 00 call 401743 <read_six_numbers>
  38. 400eac: 48 89 e5 mov rbp,rsp ; rbp = current position in the stack
  39. 400eaf: 4c 8d 6c 24 0c lea r13,[rsp+0xc] ; r13 = pointer to the fourth number
  40. 400eb4: 41 bc 00 00 00 00 mov r12d,0x0 ; r12 is a counter of some sort?
  41.  
  42. loop:
  43. 400eba: 48 89 eb mov rbx,rbp
  44. 400ebd: 8b 45 0c mov eax,DWORD PTR [rbp+0xc] ; pointer to 3 numbers after the current one
  45. 400ec0: 39 45 00 cmp DWORD PTR [rbp+0x0],eax ; and it's just checking to make sure that they're equal...
  46. 400ec3: 74 05 je 400eca <phase_2+0x3e> ; so let's just pass the same number 6 times
  47. 400ec5: e8 73 07 00 00 call 40163d <explode_bomb>
  48. 400eca: 44 03 23 add r12d,DWORD PTR [rbx]
  49. 400ecd: 48 83 c5 04 add rbp,0x4 ; step to the next number in the array
  50. 400ed1: 4c 39 ed cmp rbp,r13 ; are we at the fourth number yet? if not keep going
  51. 400ed4: 75 e4 jne loop ;400eba <phase_2+0x2e>
  52.  
  53. 400ed6: 45 85 e4 test r12d,r12d
  54. ; if r12d is nonzero, no exploding
  55. 400ed9: 75 05 jne 400ee0 <phase_2+0x54>
  56. 400edb: e8 5d 07 00 00 call 40163d <explode_bomb>
  57. 400ee0: 48 8b 5c 24 28 mov rbx,QWORD PTR [rsp+0x28]
  58. 400ee5: 48 8b 6c 24 30 mov rbp,QWORD PTR [rsp+0x30]
  59. 400eea: 4c 8b 64 24 38 mov r12,QWORD PTR [rsp+0x38]
  60. 400eef: 4c 8b 6c 24 40 mov r13,QWORD PTR [rsp+0x40]
  61. 400ef4: 48 83 c4 48 add rsp,0x48
  62. 400ef8: c3 ret
  63.  
  64. 0000000000400ef9 <phase_3>: a solution: "0 535"
  65. ; read two integers. first integer (0 to 6, 6+ explodes) is used to select a point in the jump table
  66. ; and the result of that MUST match the second integer
  67. 400ef9: 48 83 ec 18 sub rsp,0x18
  68. ; point rcx and rdx to integers on the stack to store the two read integers in
  69. 400efd: 48 8d 4c 24 08 lea rcx,[rsp+0x8] ; second integer
  70. 400f02: 48 8d 54 24 0c lea rdx,[rsp+0xc] ; first integer
  71. 400f07: be be 1e 40 00 mov esi,0x401ebe ; "%d %d"
  72. 400f0c: b8 00 00 00 00 mov eax,0x0
  73. 400f11: e8 9a fb ff ff call 400ab0 <__isoc99_sscanf@plt>
  74. 400f16: 83 f8 01 cmp eax,0x1
  75. 400f19: 7f 05 jg 400f20 <phase_3+0x27> ; explode if <= 1 items
  76. 400f1b: e8 1d 07 00 00 call 40163d <explode_bomb>
  77.  
  78. 400f20: 83 7c 24 0c 07 cmp DWORD PTR [rsp+0xc],0x7 ; explode if 7+
  79. 400f25: 77 3c ja do_explode ; 400f63 <phase_3+0x6a>
  80. 400f27: 8b 44 24 0c mov eax,DWORD PTR [rsp+0xc]
  81. 400f2b: ff 24 c5 60 1b 40 00 jmp QWORD PTR [rax*8+0x401b60] ;
  82.  
  83. ; jump table
  84. ; case 0:
  85. 400f32: b8 17 02 00 00 mov eax,0x217 ; 535 in decimal
  86. 400f37: eb 3b jmp 400f74 <phase_3+0x7b>
  87. ; case 1:
  88. 400f39: b8 d6 00 00 00 mov eax,0xd6
  89. 400f3e: eb 34 jmp 400f74 <phase_3+0x7b>
  90. ; case 2:
  91. 400f40: b8 53 01 00 00 mov eax,0x153
  92. 400f45: eb 2d jmp 400f74 <phase_3+0x7b>
  93. ; case 3:
  94. 400f47: b8 77 00 00 00 mov eax,0x77
  95. 400f4c: eb 26 jmp 400f74 <phase_3+0x7b>
  96. ; case 4:
  97. 400f4e: b8 60 01 00 00 mov eax,0x160
  98. 400f53: eb 1f jmp 400f74 <phase_3+0x7b>
  99. ; case 5:
  100. 400f55: b8 97 03 00 00 mov eax,0x397
  101. 400f5a: eb 18 jmp 400f74 <phase_3+0x7b>
  102. ; case 6:
  103. 400f5c: b8 9c 01 00 00 mov eax,0x19c
  104. 400f61: eb 11 jmp 400f74 <phase_3+0x7b>
  105. ; default:
  106. do_explode:
  107. 400f63: e8 d5 06 00 00 call 40163d <explode_bomb>
  108.  
  109. 400f68: b8 00 00 00 00 mov eax,0x0
  110. 400f6d: eb 05 jmp 400f74 <phase_3+0x7b> ; \
  111. 400f6f: b8 9e 03 00 00 mov eax,0x39e ; |
  112. ; v
  113. 400f74: 3b 44 24 08 cmp eax,DWORD PTR [rsp+0x8] ; explode unless eax == [rsp+0x8]
  114. 400f78: 74 05 je 400f7f <phase_3+0x86>
  115. 400f7a: e8 be 06 00 00 call 40163d <explode_bomb>
  116. 400f7f: 48 83 c4 18 add rsp,0x18
  117. 400f83: c3 ret
  118.  
  119. 0000000000400f84 <func4>:
  120. ; recursive, input goes in edi which is an integer
  121. ; returns the answer in EAX
  122. ; equivalent to this:
  123. int func4(int n) {
  124. if(n <= 1) // base case, 0 or 1
  125. return 1;
  126. return func4(n-1)+func4(n-2);
  127. }
  128.  
  129. 400f84: 48 89 5c 24 f0 mov QWORD PTR [rsp-0x10],rbx
  130. 400f89: 48 89 6c 24 f8 mov QWORD PTR [rsp-0x8],rbp
  131. 400f8e: 48 83 ec 18 sub rsp,0x18
  132. 400f92: 89 fb mov ebx,edi ; ebx = edi, for the two leas
  133. 400f94: b8 01 00 00 00 mov eax,0x1 ; EAX starts at 1
  134. 400f99: 83 ff 01 cmp edi,0x1 ; if EDI is 1 or 0, return 1
  135. 400f9c: 7e 14 jle skip ;400fb2 <func4+0x2e>
  136.  
  137. ; EAX = func(edi-1)+func(edi-2)
  138. 400f9e: 8d 7b ff lea edi,[rbx-0x1] ; lea is just the smallest way to set edi to rbx-whatever
  139. 400fa1: e8 de ff ff ff call 400f84 <func4>
  140. 400fa6: 89 c5 mov ebp,eax ; save eax somewhere that func4 won't touch
  141. 400fa8: 8d 7b fe lea edi,[rbx-0x2]
  142. 400fab: e8 d4 ff ff ff call 400f84 <func4>
  143. 400fb0: 01 e8 add eax,ebp ; add the two results together
  144. skip: (EAX still = 1 if we skipped down to here)
  145.  
  146. 400fb2: 48 8b 5c 24 08 mov rbx,QWORD PTR [rsp+0x8]
  147. 400fb7: 48 8b 6c 24 10 mov rbp,QWORD PTR [rsp+0x10]
  148. 400fbc: 48 83 c4 18 add rsp,0x18
  149. 400fc0: c3 ret
  150.  
  151. 0000000000400fc1 <phase_4>: the solution: "9"
  152. ; read an integer, run func4 with it as the parameter and explode if the result isn't 0x37
  153.  
  154. ; I used this to get the answer:
  155. int func4(int n) {
  156. if(n <= 1) // base case, 0 or 1
  157. return 1;
  158. return func4(n-1)+func4(n-2);
  159. }
  160. int main() {
  161. int x;
  162. for(x=0;x<100;x++)
  163. if(func4(x) == 0x37)
  164. printf("%i\n", x);
  165. }
  166.  
  167. 400fc1: 48 83 ec 18 sub rsp,0x18
  168.  
  169. ; point rdx on an integer on the stack to store the result in
  170. 400fc5: 48 8d 54 24 0c lea rdx,[rsp+0xc]
  171. 400fca: be c1 1e 40 00 mov esi,0x401ec1 ; "%d", read one integer
  172. 400fcf: b8 00 00 00 00 mov eax,0x0
  173. 400fd4: e8 d7 fa ff ff call 400ab0 <__isoc99_sscanf@plt>
  174. 400fd9: 83 f8 01 cmp eax,0x1
  175. 400fdc: 75 07 jne 400fe5 <phase_4+0x24>
  176.  
  177. ; explode if we don't have at least one number
  178. 400fde: 83 7c 24 0c 00 cmp DWORD PTR [rsp+0xc],0x0
  179. 400fe3: 7f 05 jg 400fea <phase_4+0x29>
  180. 400fe5: e8 53 06 00 00 call 40163d <explode_bomb>
  181. 400fea: 8b 7c 24 0c mov edi,DWORD PTR [rsp+0xc]
  182.  
  183. ; call func4, explode if the result isn't 0x37
  184. 400fee: e8 91 ff ff ff call 400f84 <func4>
  185. 400ff3: 83 f8 37 cmp eax,0x37
  186. 400ff6: 74 05 je 400ffd <phase_4+0x3c>
  187. 400ff8: e8 40 06 00 00 call 40163d <explode_bomb>
  188. 400ffd: 48 83 c4 18 add rsp,0x18
  189. 401001: c3 ret
  190.  
  191. 0000000000401002 <phase_5>: solution: "7 93"
  192. // C program I used to find it:
  193. int phase_5(int n) {
  194. int table[] = {0xa, 0x2, 0xe, 0x7,
  195. 0x8, 0xc, 0xf, 0xb,
  196. 0x0, 0x4, 0x1, 0xd,
  197. 0x3, 0x9, 0x6, 0x5};
  198. n &= 0xf;
  199. if(n == 0xf)
  200. return 0;
  201.  
  202. int ecx = 0, edx = 0;
  203.  
  204. while(n != 0xf) {
  205. edx++;
  206. n = table[n];
  207. ecx += n;
  208. }
  209. if(edx != 0xc)
  210. return 0;
  211. printf("ecx is %i\n", ecx);
  212. return 1;
  213. }
  214.  
  215. int main() {
  216. int x;
  217. for(x=0; x<16; x++)
  218. if(phase_5(x))
  219. printf("got it, %i\n", x);
  220. }
  221.  
  222. 401002: 48 83 ec 18 sub rsp,0x18
  223.  
  224. ; point rcx and rdx at two integers on the stack
  225. 401006: 48 8d 4c 24 08 lea rcx,[rsp+0x8] ; second integer
  226. 40100b: 48 8d 54 24 0c lea rdx,[rsp+0xc] ; first integer
  227.  
  228. ; read two integers; explode if we don't get at least 2
  229. 401010: be be 1e 40 00 mov esi,0x401ebe ; "%d %d"
  230. 401015: b8 00 00 00 00 mov eax,0x0
  231. 40101a: e8 91 fa ff ff call 400ab0 <__isoc99_sscanf@plt>
  232. 40101f: 83 f8 01 cmp eax,0x1 ; don't explode if we read at least 2 integers
  233. 401022: 7f 05 jg 401029 <phase_5+0x27>
  234. 401024: e8 14 06 00 00 call 40163d <explode_bomb>
  235.  
  236. ; all but the lowest four bits in the first integer are zero'd out
  237. 401029: 8b 44 24 0c mov eax,DWORD PTR [rsp+0xc]
  238. 40102d: 83 e0 0f and eax,0xf
  239. 401030: 89 44 24 0c mov DWORD PTR [rsp+0xc],eax
  240.  
  241. ; and if the lowest four bits are 1, explode
  242. 401034: 83 f8 0f cmp eax,0xf
  243. 401037: 74 2c je do_explode ;401065 <phase_5+0x63>
  244.  
  245. 401039: b9 00 00 00 00 mov ecx,0x0
  246. 40103e: ba 00 00 00 00 mov edx,0x0
  247. loop:
  248. 401043: 83 c2 01 add edx,0x1 ; EDX++
  249. 401046: 48 98 cdqe ; RAX = sign-extend of EAX
  250. 401048: 8b 04 85 a0 1b 40 00 mov eax,DWORD PTR [rax*4+0x401ba0] ; look up an item in the table below
  251. 40104f: 01 c1 add ecx,eax ; ECX += the item in the table
  252.  
  253. 401051: 83 f8 0f cmp eax,0xf
  254. 401054: 75 ed jne loop ;401043 <phase_5+0x41> ; if not 0xf, loop back
  255. 401056: 89 44 24 0c mov DWORD PTR [rsp+0xc],eax
  256. 40105a: 83 fa 0c cmp edx,0xc
  257. 40105d: 75 06 jne do_explode ;401065 <phase_5+0x63>
  258. 40105f: 3b 4c 24 08 cmp ecx,DWORD PTR [rsp+0x8]
  259. 401063: 74 05 je dont_explode ;40106a <phase_5+0x68>
  260. do_explode:
  261. 401065: e8 d3 05 00 00 call 40163d <explode_bomb>
  262. dont_explode:
  263. 40106a: 48 83 c4 18 add rsp,0x18
  264. 40106e: c3 ret
  265.  
  266. ; table of 16 items (little endian):
  267. 401ba0 0a000000 02000000 0e000000 07000000 ................
  268. 401bb0 08000000 0c000000 0f000000 0b000000 ................
  269. 401bc0 00000000 04000000 01000000 0d000000 ................
  270. 401bd0 03000000 09000000 06000000 05000000 ................
  271.  
  272. 000000000040106f <fun6>:
  273.  
  274. void fun6(long long *rdi) {
  275. long long r8 = rdi[1];
  276. rdi[1] = 0;
  277. long long rax = rdi;
  278. long long rcx = rdi;
  279. }
  280.  
  281. ; input: rdi = 602780
  282. 40106f: 4c 8b 47 08 mov r8,QWORD PTR [rdi+0x8]
  283. 401073: 48 c7 47 08 00 00 00 00 mov QWORD PTR [rdi+0x8],0x0
  284. 40107b: 48 89 f8 mov rax,rdi
  285. 40107e: 48 89 f9 mov rcx,rdi
  286. 401081: 4d 85 c0 test r8,r8
  287. 401084: 75 40 jne skip1 ;4010c6 <fun6+0x57>
  288. 401086: 48 89 f8 mov rax,rdi
  289. 401089: c3 ret
  290.  
  291. loop_1:
  292. 40108a: 48 89 d1 mov rcx,rdx
  293. loop_2:
  294. 40108d: 48 8b 51 08 mov rdx,QWORD PTR [rcx+0x8]
  295. 401091: 48 85 d2 test rdx,rdx
  296. 401094: 74 09 je JUMP_3 ;40109f <fun6+0x30>
  297. 401096: 39 32 cmp DWORD PTR [rdx],esi
  298. 401098: 7f f0 jg loop_1 ;40108a <fun6+0x1b>
  299.  
  300.  
  301. 40109a: 48 89 cf mov rdi,rcx
  302. 40109d: eb 03 jmp JUMP_4 ;4010a2 <fun6+0x33>
  303. JUMP_3:
  304. 40109f: 48 89 cf mov rdi,rcx
  305. JUMP_4:
  306.  
  307. if(rdi == rdx) {
  308. mov rax,r8
  309. } else {
  310. mov QWORD PTR [rdi+0x8],r8
  311. }
  312. 4010a2: 48 39 d7 cmp rdi,rdx
  313. 4010a5: 74 06 je 4010ad <fun6+0x3e>
  314. 4010a7: 4c 89 47 08 mov QWORD PTR [rdi+0x8],r8
  315. 4010ab: eb 03 jmp :+ ;4010b0 <fun6+0x41>
  316. 4010ad: 4c 89 c0 mov rax,r8
  317. :
  318.  
  319. 4010b0: 49 8b 48 08 mov rcx,QWORD PTR [r8+0x8]
  320. 4010b4: 49 89 50 08 mov QWORD PTR [r8+0x8],rdx
  321.  
  322. if(!rcx)
  323. return;
  324. 4010b8: 48 85 c9 test rcx,rcx
  325. 4010bb: 74 1a je exit ;4010d7 <fun6+0x68>
  326.  
  327. 4010bd: 49 89 c8 mov r8,rcx
  328. 4010c0: 48 89 c1 mov rcx,rax
  329. 4010c3: 48 89 c7 mov rdi,rax
  330. skip1:
  331. 4010c6: 48 89 ca mov rdx,rcx
  332. 4010c9: 48 85 c9 test rcx,rcx
  333. 4010cc: 74 d4 je JUMP_4 ;4010a2 <fun6+0x33>
  334. 4010ce: 41 8b 30 mov esi,DWORD PTR [r8]
  335. 4010d1: 39 31 cmp DWORD PTR [rcx],esi
  336. 4010d3: 7f b8 jg loop_2 ;40108d <fun6+0x1e>
  337. 4010d5: eb cb jmp 4010a2 <fun6+0x33>
  338. exit:
  339. 4010d7: f3 c3 repz ret ; the repz is for optimization purposes
  340.  
  341. 00000000004010d9 <phase_6>:
  342. 4010d9: 48 83 ec 08 sub rsp,0x8
  343. 4010dd: ba 0a 00 00 00 mov edx,0xa ; strtol(input, NULL, 10)
  344. 4010e2: be 00 00 00 00 mov esi,0x0 ; ... in other words this takes a single integer
  345. ; (in decimal) and stores the result in 602780
  346. ; which I assume is a global variable
  347. 4010e7: e8 94 fa ff ff call 400b80 <strtol@plt>
  348.  
  349. 4010ec: 89 05 8e 16 20 00 mov DWORD PTR [rip+0x20168e],eax # 602780 <node0>
  350.  
  351. 4010f2: bf 80 27 60 00 mov edi,0x602780 ; pointer to the strtol result
  352. 4010f7: e8 73 ff ff ff call 40106f <fun6>
  353.  
  354. 4010fc: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
  355. 401100: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
  356. 401104: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
  357. 401108: 8b 15 72 16 20 00 mov edx,DWORD PTR [rip+0x201672] # 602780 <node0>
  358. 40110e: 39 10 cmp DWORD PTR [rax],edx
  359. 401110: 74 05 je 401117 <phase_6+0x3e>
  360. 401112: e8 26 05 00 00 call 40163d <explode_bomb>
  361. 401117: 48 83 c4 08 add rsp,0x8
  362. 40111b: c3 ret
  363.  
  364. 0000000000401743 <read_six_numbers>:
  365. 401743: 48 83 ec 18 sub rsp,0x18
  366. 401747: 48 89 f2 mov rdx,rsi
  367. 40174a: 48 8d 4e 04 lea rcx,[rsi+0x4]
  368. 40174e: 48 8d 46 14 lea rax,[rsi+0x14]
  369. 401752: 48 89 44 24 08 mov QWORD PTR [rsp+0x8],rax
  370. 401757: 48 8d 46 10 lea rax,[rsi+0x10]
  371. 40175b: 48 89 04 24 mov QWORD PTR [rsp],rax
  372. 40175f: 4c 8d 4e 0c lea r9,[rsi+0xc]
  373. 401763: 4c 8d 46 08 lea r8,[rsi+0x8]
  374. 401767: be b2 1e 40 00 mov esi,0x401eb2 ; points to "%d %d %d %d %d %d"
  375. 40176c: b8 00 00 00 00 mov eax,0x0
  376. 401771: e8 3a f3 ff ff call 400ab0 <__isoc99_sscanf@plt> ; returns the number of items successfully read in EAX
  377. 401776: 83 f8 05 cmp eax,0x5 ; explode if less than 6 items
  378. 401779: 7f 05 jg 401780 <read_six_numbers+0x3d>
  379. 40177b: e8 bd fe ff ff call 40163d <explode_bomb>
  380. 401780: 48 83 c4 18 add rsp,0x18
  381. 401784: c3 ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement