Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- For the bomb, I solved everything through using objdump and then
- making sense of the disassembly by inserting annotations until
- I figured out what each of the functions did. I didn't use gdb at all.
- For 4 and 5 I reverse engineered the function that determined whether or not
- the input is valid and just wrote a C program to brute force the correct answer
- (the C programs are included).
- I wasn't able to get 6 figured out so I just included my work on it so far.
- 0000000000400e70 <phase_1>: the solution: "Science isn't about why, it's about why not?"
- ; just does a string compare, that's all
- 400e70: 48 83 ec 08 sub rsp,0x8
- 400e74: be f8 1a 40 00 mov esi,0x401af8 ; pointer to "Science isn't about why, it's about why not?"
- 400e79: e8 bf 03 00 00 call 40123d <strings_not_equal>
- explode the bomb if this returns 0
- 400e7e: 85 c0 test eax,eax
- 400e80: 74 05 je 400e87 <phase_1+0x17>
- 400e82: e8 b6 07 00 00 call 40163d <explode_bomb>
- 400e87: 48 83 c4 08 add rsp,0x8
- 400e8b: c3 ret
- 0000000000400e8c <phase_2>: a solution: "1 1 1 1 1 1"
- ; read 6 integers, and make sure the first three match the second three
- for(int x=0; x<3; x++)
- if(numbers[x] != numbers[x+3])
- blow_up();
- 400e8c: 48 89 5c 24 e0 mov QWORD PTR [rsp-0x20],rbx ; stack stuff
- 400e91: 48 89 6c 24 e8 mov QWORD PTR [rsp-0x18],rbp
- 400e96: 4c 89 64 24 f0 mov QWORD PTR [rsp-0x10],r12
- 400e9b: 4c 89 6c 24 f8 mov QWORD PTR [rsp-0x8],r13
- 400ea0: 48 83 ec 48 sub rsp,0x48
- 400ea4: 48 89 e6 mov rsi,rsp
- 400ea7: e8 97 08 00 00 call 401743 <read_six_numbers>
- 400eac: 48 89 e5 mov rbp,rsp ; rbp = current position in the stack
- 400eaf: 4c 8d 6c 24 0c lea r13,[rsp+0xc] ; r13 = pointer to the fourth number
- 400eb4: 41 bc 00 00 00 00 mov r12d,0x0 ; r12 is a counter of some sort?
- loop:
- 400eba: 48 89 eb mov rbx,rbp
- 400ebd: 8b 45 0c mov eax,DWORD PTR [rbp+0xc] ; pointer to 3 numbers after the current one
- 400ec0: 39 45 00 cmp DWORD PTR [rbp+0x0],eax ; and it's just checking to make sure that they're equal...
- 400ec3: 74 05 je 400eca <phase_2+0x3e> ; so let's just pass the same number 6 times
- 400ec5: e8 73 07 00 00 call 40163d <explode_bomb>
- 400eca: 44 03 23 add r12d,DWORD PTR [rbx]
- 400ecd: 48 83 c5 04 add rbp,0x4 ; step to the next number in the array
- 400ed1: 4c 39 ed cmp rbp,r13 ; are we at the fourth number yet? if not keep going
- 400ed4: 75 e4 jne loop ;400eba <phase_2+0x2e>
- 400ed6: 45 85 e4 test r12d,r12d
- ; if r12d is nonzero, no exploding
- 400ed9: 75 05 jne 400ee0 <phase_2+0x54>
- 400edb: e8 5d 07 00 00 call 40163d <explode_bomb>
- 400ee0: 48 8b 5c 24 28 mov rbx,QWORD PTR [rsp+0x28]
- 400ee5: 48 8b 6c 24 30 mov rbp,QWORD PTR [rsp+0x30]
- 400eea: 4c 8b 64 24 38 mov r12,QWORD PTR [rsp+0x38]
- 400eef: 4c 8b 6c 24 40 mov r13,QWORD PTR [rsp+0x40]
- 400ef4: 48 83 c4 48 add rsp,0x48
- 400ef8: c3 ret
- 0000000000400ef9 <phase_3>: a solution: "0 535"
- ; read two integers. first integer (0 to 6, 6+ explodes) is used to select a point in the jump table
- ; and the result of that MUST match the second integer
- 400ef9: 48 83 ec 18 sub rsp,0x18
- ; point rcx and rdx to integers on the stack to store the two read integers in
- 400efd: 48 8d 4c 24 08 lea rcx,[rsp+0x8] ; second integer
- 400f02: 48 8d 54 24 0c lea rdx,[rsp+0xc] ; first integer
- 400f07: be be 1e 40 00 mov esi,0x401ebe ; "%d %d"
- 400f0c: b8 00 00 00 00 mov eax,0x0
- 400f11: e8 9a fb ff ff call 400ab0 <__isoc99_sscanf@plt>
- 400f16: 83 f8 01 cmp eax,0x1
- 400f19: 7f 05 jg 400f20 <phase_3+0x27> ; explode if <= 1 items
- 400f1b: e8 1d 07 00 00 call 40163d <explode_bomb>
- 400f20: 83 7c 24 0c 07 cmp DWORD PTR [rsp+0xc],0x7 ; explode if 7+
- 400f25: 77 3c ja do_explode ; 400f63 <phase_3+0x6a>
- 400f27: 8b 44 24 0c mov eax,DWORD PTR [rsp+0xc]
- 400f2b: ff 24 c5 60 1b 40 00 jmp QWORD PTR [rax*8+0x401b60] ;
- ; jump table
- ; case 0:
- 400f32: b8 17 02 00 00 mov eax,0x217 ; 535 in decimal
- 400f37: eb 3b jmp 400f74 <phase_3+0x7b>
- ; case 1:
- 400f39: b8 d6 00 00 00 mov eax,0xd6
- 400f3e: eb 34 jmp 400f74 <phase_3+0x7b>
- ; case 2:
- 400f40: b8 53 01 00 00 mov eax,0x153
- 400f45: eb 2d jmp 400f74 <phase_3+0x7b>
- ; case 3:
- 400f47: b8 77 00 00 00 mov eax,0x77
- 400f4c: eb 26 jmp 400f74 <phase_3+0x7b>
- ; case 4:
- 400f4e: b8 60 01 00 00 mov eax,0x160
- 400f53: eb 1f jmp 400f74 <phase_3+0x7b>
- ; case 5:
- 400f55: b8 97 03 00 00 mov eax,0x397
- 400f5a: eb 18 jmp 400f74 <phase_3+0x7b>
- ; case 6:
- 400f5c: b8 9c 01 00 00 mov eax,0x19c
- 400f61: eb 11 jmp 400f74 <phase_3+0x7b>
- ; default:
- do_explode:
- 400f63: e8 d5 06 00 00 call 40163d <explode_bomb>
- 400f68: b8 00 00 00 00 mov eax,0x0
- 400f6d: eb 05 jmp 400f74 <phase_3+0x7b> ; \
- 400f6f: b8 9e 03 00 00 mov eax,0x39e ; |
- ; v
- 400f74: 3b 44 24 08 cmp eax,DWORD PTR [rsp+0x8] ; explode unless eax == [rsp+0x8]
- 400f78: 74 05 je 400f7f <phase_3+0x86>
- 400f7a: e8 be 06 00 00 call 40163d <explode_bomb>
- 400f7f: 48 83 c4 18 add rsp,0x18
- 400f83: c3 ret
- 0000000000400f84 <func4>:
- ; recursive, input goes in edi which is an integer
- ; returns the answer in EAX
- ; equivalent to this:
- int func4(int n) {
- if(n <= 1) // base case, 0 or 1
- return 1;
- return func4(n-1)+func4(n-2);
- }
- 400f84: 48 89 5c 24 f0 mov QWORD PTR [rsp-0x10],rbx
- 400f89: 48 89 6c 24 f8 mov QWORD PTR [rsp-0x8],rbp
- 400f8e: 48 83 ec 18 sub rsp,0x18
- 400f92: 89 fb mov ebx,edi ; ebx = edi, for the two leas
- 400f94: b8 01 00 00 00 mov eax,0x1 ; EAX starts at 1
- 400f99: 83 ff 01 cmp edi,0x1 ; if EDI is 1 or 0, return 1
- 400f9c: 7e 14 jle skip ;400fb2 <func4+0x2e>
- ; EAX = func(edi-1)+func(edi-2)
- 400f9e: 8d 7b ff lea edi,[rbx-0x1] ; lea is just the smallest way to set edi to rbx-whatever
- 400fa1: e8 de ff ff ff call 400f84 <func4>
- 400fa6: 89 c5 mov ebp,eax ; save eax somewhere that func4 won't touch
- 400fa8: 8d 7b fe lea edi,[rbx-0x2]
- 400fab: e8 d4 ff ff ff call 400f84 <func4>
- 400fb0: 01 e8 add eax,ebp ; add the two results together
- skip: (EAX still = 1 if we skipped down to here)
- 400fb2: 48 8b 5c 24 08 mov rbx,QWORD PTR [rsp+0x8]
- 400fb7: 48 8b 6c 24 10 mov rbp,QWORD PTR [rsp+0x10]
- 400fbc: 48 83 c4 18 add rsp,0x18
- 400fc0: c3 ret
- 0000000000400fc1 <phase_4>: the solution: "9"
- ; read an integer, run func4 with it as the parameter and explode if the result isn't 0x37
- ; I used this to get the answer:
- int func4(int n) {
- if(n <= 1) // base case, 0 or 1
- return 1;
- return func4(n-1)+func4(n-2);
- }
- int main() {
- int x;
- for(x=0;x<100;x++)
- if(func4(x) == 0x37)
- printf("%i\n", x);
- }
- 400fc1: 48 83 ec 18 sub rsp,0x18
- ; point rdx on an integer on the stack to store the result in
- 400fc5: 48 8d 54 24 0c lea rdx,[rsp+0xc]
- 400fca: be c1 1e 40 00 mov esi,0x401ec1 ; "%d", read one integer
- 400fcf: b8 00 00 00 00 mov eax,0x0
- 400fd4: e8 d7 fa ff ff call 400ab0 <__isoc99_sscanf@plt>
- 400fd9: 83 f8 01 cmp eax,0x1
- 400fdc: 75 07 jne 400fe5 <phase_4+0x24>
- ; explode if we don't have at least one number
- 400fde: 83 7c 24 0c 00 cmp DWORD PTR [rsp+0xc],0x0
- 400fe3: 7f 05 jg 400fea <phase_4+0x29>
- 400fe5: e8 53 06 00 00 call 40163d <explode_bomb>
- 400fea: 8b 7c 24 0c mov edi,DWORD PTR [rsp+0xc]
- ; call func4, explode if the result isn't 0x37
- 400fee: e8 91 ff ff ff call 400f84 <func4>
- 400ff3: 83 f8 37 cmp eax,0x37
- 400ff6: 74 05 je 400ffd <phase_4+0x3c>
- 400ff8: e8 40 06 00 00 call 40163d <explode_bomb>
- 400ffd: 48 83 c4 18 add rsp,0x18
- 401001: c3 ret
- 0000000000401002 <phase_5>: solution: "7 93"
- // C program I used to find it:
- int phase_5(int n) {
- int table[] = {0xa, 0x2, 0xe, 0x7,
- 0x8, 0xc, 0xf, 0xb,
- 0x0, 0x4, 0x1, 0xd,
- 0x3, 0x9, 0x6, 0x5};
- n &= 0xf;
- if(n == 0xf)
- return 0;
- int ecx = 0, edx = 0;
- while(n != 0xf) {
- edx++;
- n = table[n];
- ecx += n;
- }
- if(edx != 0xc)
- return 0;
- printf("ecx is %i\n", ecx);
- return 1;
- }
- int main() {
- int x;
- for(x=0; x<16; x++)
- if(phase_5(x))
- printf("got it, %i\n", x);
- }
- 401002: 48 83 ec 18 sub rsp,0x18
- ; point rcx and rdx at two integers on the stack
- 401006: 48 8d 4c 24 08 lea rcx,[rsp+0x8] ; second integer
- 40100b: 48 8d 54 24 0c lea rdx,[rsp+0xc] ; first integer
- ; read two integers; explode if we don't get at least 2
- 401010: be be 1e 40 00 mov esi,0x401ebe ; "%d %d"
- 401015: b8 00 00 00 00 mov eax,0x0
- 40101a: e8 91 fa ff ff call 400ab0 <__isoc99_sscanf@plt>
- 40101f: 83 f8 01 cmp eax,0x1 ; don't explode if we read at least 2 integers
- 401022: 7f 05 jg 401029 <phase_5+0x27>
- 401024: e8 14 06 00 00 call 40163d <explode_bomb>
- ; all but the lowest four bits in the first integer are zero'd out
- 401029: 8b 44 24 0c mov eax,DWORD PTR [rsp+0xc]
- 40102d: 83 e0 0f and eax,0xf
- 401030: 89 44 24 0c mov DWORD PTR [rsp+0xc],eax
- ; and if the lowest four bits are 1, explode
- 401034: 83 f8 0f cmp eax,0xf
- 401037: 74 2c je do_explode ;401065 <phase_5+0x63>
- 401039: b9 00 00 00 00 mov ecx,0x0
- 40103e: ba 00 00 00 00 mov edx,0x0
- loop:
- 401043: 83 c2 01 add edx,0x1 ; EDX++
- 401046: 48 98 cdqe ; RAX = sign-extend of EAX
- 401048: 8b 04 85 a0 1b 40 00 mov eax,DWORD PTR [rax*4+0x401ba0] ; look up an item in the table below
- 40104f: 01 c1 add ecx,eax ; ECX += the item in the table
- 401051: 83 f8 0f cmp eax,0xf
- 401054: 75 ed jne loop ;401043 <phase_5+0x41> ; if not 0xf, loop back
- 401056: 89 44 24 0c mov DWORD PTR [rsp+0xc],eax
- 40105a: 83 fa 0c cmp edx,0xc
- 40105d: 75 06 jne do_explode ;401065 <phase_5+0x63>
- 40105f: 3b 4c 24 08 cmp ecx,DWORD PTR [rsp+0x8]
- 401063: 74 05 je dont_explode ;40106a <phase_5+0x68>
- do_explode:
- 401065: e8 d3 05 00 00 call 40163d <explode_bomb>
- dont_explode:
- 40106a: 48 83 c4 18 add rsp,0x18
- 40106e: c3 ret
- ; table of 16 items (little endian):
- 401ba0 0a000000 02000000 0e000000 07000000 ................
- 401bb0 08000000 0c000000 0f000000 0b000000 ................
- 401bc0 00000000 04000000 01000000 0d000000 ................
- 401bd0 03000000 09000000 06000000 05000000 ................
- 000000000040106f <fun6>:
- void fun6(long long *rdi) {
- long long r8 = rdi[1];
- rdi[1] = 0;
- long long rax = rdi;
- long long rcx = rdi;
- }
- ; input: rdi = 602780
- 40106f: 4c 8b 47 08 mov r8,QWORD PTR [rdi+0x8]
- 401073: 48 c7 47 08 00 00 00 00 mov QWORD PTR [rdi+0x8],0x0
- 40107b: 48 89 f8 mov rax,rdi
- 40107e: 48 89 f9 mov rcx,rdi
- 401081: 4d 85 c0 test r8,r8
- 401084: 75 40 jne skip1 ;4010c6 <fun6+0x57>
- 401086: 48 89 f8 mov rax,rdi
- 401089: c3 ret
- loop_1:
- 40108a: 48 89 d1 mov rcx,rdx
- loop_2:
- 40108d: 48 8b 51 08 mov rdx,QWORD PTR [rcx+0x8]
- 401091: 48 85 d2 test rdx,rdx
- 401094: 74 09 je JUMP_3 ;40109f <fun6+0x30>
- 401096: 39 32 cmp DWORD PTR [rdx],esi
- 401098: 7f f0 jg loop_1 ;40108a <fun6+0x1b>
- 40109a: 48 89 cf mov rdi,rcx
- 40109d: eb 03 jmp JUMP_4 ;4010a2 <fun6+0x33>
- JUMP_3:
- 40109f: 48 89 cf mov rdi,rcx
- JUMP_4:
- if(rdi == rdx) {
- mov rax,r8
- } else {
- mov QWORD PTR [rdi+0x8],r8
- }
- 4010a2: 48 39 d7 cmp rdi,rdx
- 4010a5: 74 06 je 4010ad <fun6+0x3e>
- 4010a7: 4c 89 47 08 mov QWORD PTR [rdi+0x8],r8
- 4010ab: eb 03 jmp :+ ;4010b0 <fun6+0x41>
- 4010ad: 4c 89 c0 mov rax,r8
- :
- 4010b0: 49 8b 48 08 mov rcx,QWORD PTR [r8+0x8]
- 4010b4: 49 89 50 08 mov QWORD PTR [r8+0x8],rdx
- if(!rcx)
- return;
- 4010b8: 48 85 c9 test rcx,rcx
- 4010bb: 74 1a je exit ;4010d7 <fun6+0x68>
- 4010bd: 49 89 c8 mov r8,rcx
- 4010c0: 48 89 c1 mov rcx,rax
- 4010c3: 48 89 c7 mov rdi,rax
- skip1:
- 4010c6: 48 89 ca mov rdx,rcx
- 4010c9: 48 85 c9 test rcx,rcx
- 4010cc: 74 d4 je JUMP_4 ;4010a2 <fun6+0x33>
- 4010ce: 41 8b 30 mov esi,DWORD PTR [r8]
- 4010d1: 39 31 cmp DWORD PTR [rcx],esi
- 4010d3: 7f b8 jg loop_2 ;40108d <fun6+0x1e>
- 4010d5: eb cb jmp 4010a2 <fun6+0x33>
- exit:
- 4010d7: f3 c3 repz ret ; the repz is for optimization purposes
- 00000000004010d9 <phase_6>:
- 4010d9: 48 83 ec 08 sub rsp,0x8
- 4010dd: ba 0a 00 00 00 mov edx,0xa ; strtol(input, NULL, 10)
- 4010e2: be 00 00 00 00 mov esi,0x0 ; ... in other words this takes a single integer
- ; (in decimal) and stores the result in 602780
- ; which I assume is a global variable
- 4010e7: e8 94 fa ff ff call 400b80 <strtol@plt>
- 4010ec: 89 05 8e 16 20 00 mov DWORD PTR [rip+0x20168e],eax # 602780 <node0>
- 4010f2: bf 80 27 60 00 mov edi,0x602780 ; pointer to the strtol result
- 4010f7: e8 73 ff ff ff call 40106f <fun6>
- 4010fc: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
- 401100: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
- 401104: 48 8b 40 08 mov rax,QWORD PTR [rax+0x8]
- 401108: 8b 15 72 16 20 00 mov edx,DWORD PTR [rip+0x201672] # 602780 <node0>
- 40110e: 39 10 cmp DWORD PTR [rax],edx
- 401110: 74 05 je 401117 <phase_6+0x3e>
- 401112: e8 26 05 00 00 call 40163d <explode_bomb>
- 401117: 48 83 c4 08 add rsp,0x8
- 40111b: c3 ret
- 0000000000401743 <read_six_numbers>:
- 401743: 48 83 ec 18 sub rsp,0x18
- 401747: 48 89 f2 mov rdx,rsi
- 40174a: 48 8d 4e 04 lea rcx,[rsi+0x4]
- 40174e: 48 8d 46 14 lea rax,[rsi+0x14]
- 401752: 48 89 44 24 08 mov QWORD PTR [rsp+0x8],rax
- 401757: 48 8d 46 10 lea rax,[rsi+0x10]
- 40175b: 48 89 04 24 mov QWORD PTR [rsp],rax
- 40175f: 4c 8d 4e 0c lea r9,[rsi+0xc]
- 401763: 4c 8d 46 08 lea r8,[rsi+0x8]
- 401767: be b2 1e 40 00 mov esi,0x401eb2 ; points to "%d %d %d %d %d %d"
- 40176c: b8 00 00 00 00 mov eax,0x0
- 401771: e8 3a f3 ff ff call 400ab0 <__isoc99_sscanf@plt> ; returns the number of items successfully read in EAX
- 401776: 83 f8 05 cmp eax,0x5 ; explode if less than 6 items
- 401779: 7f 05 jg 401780 <read_six_numbers+0x3d>
- 40177b: e8 bd fe ff ff call 40163d <explode_bomb>
- 401780: 48 83 c4 18 add rsp,0x18
- 401784: c3 ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement