main
<+148> : Since the return value of read_line in the main function is stored in %rdi, we can infer that the input string is stored in %rdi.
0x0000555555401214 <+138>: callq 0x555555400f00 <puts@plt> 0x0000555555401219 <+143>: callq 0x555555401b0d <read_line> 0x000055555540121e <+148>: mov %rax,%rdi 0x0000555555401221 <+151>: callq 0x55555540136d <phase_3>
Testing confirmed that it matches.
(gdb) x/s $rdi 0x555555604760 <input_strings+160>: "50 100"
Analyzing __isoc99_sscanf

We already figured out a lot about the __isoc99_sscanf function in phase2.
- The integers we entered are converted into an array from the string stored in %rdi.
- A pointer to the first element is stored in %rsp.
- The number of integers entered is returned in %rax.
So when we enter 50 100, we get the situation on the right.
Phase_3
Dump of assembler code for function phase_3: 0x000055555540136d <+0>: sub $0x18,%rsp 0x0000555555401371 <+4>: mov %fs:0x28,%rax 0x000055555540137a <+13>: mov %rax,0x8(%rsp) 0x000055555540137f <+18>: xor %eax,%eax 0x0000555555401381 <+20>: lea 0x4(%rsp),%rcx 0x0000555555401386 <+25>: mov %rsp,%rdx 0x0000555555401389 <+28>: lea 0x1a5d(%rip),%rsi # 0x555555402ded 0x0000555555401390 <+35>: callq 0x555555400fc0 <__isoc99_sscanf@plt> 0x0000555555401395 <+40>: cmp $0x1,%eax 0x0000555555401398 <+43>: jle 0x5555554013b3 <phase_3+70> 0x000055555540139a <+45>: cmpl $0x7,(%rsp) 0x000055555540139e <+49>: ja 0x5555554013eb <phase_3+126> 0x00005555554013a0 <+51>: mov (%rsp),%eax 0x00005555554013a3 <+54>: lea 0x1796(%rip),%rdx # 0x555555402b40 0x00005555554013aa <+61>: movslq (%rdx,%rax,4),%rax 0x00005555554013ae <+65>: add %rdx,%rax 0x00005555554013b1 <+68>: jmpq *%rax 0x00005555554013b3 <+70>: callq 0x555555401a90 <explode_bomb> 0x00005555554013b8 <+75>: jmp 0x55555540139a <phase_3+45> 0x00005555554013ba <+77>: mov $0x8c,%eax 0x00005555554013bf <+82>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013c1 <+84>: mov $0x3be,%eax 0x00005555554013c6 <+89>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013c8 <+91>: mov $0x79,%eax 0x00005555554013cd <+96>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013cf <+98>: mov $0x2c9,%eax 0x00005555554013d4 <+103>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013d6 <+105>: mov $0x379,%eax 0x00005555554013db <+110>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013dd <+112>: mov $0x347,%eax 0x00005555554013e2 <+117>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013e4 <+119>: mov $0x39a,%eax 0x00005555554013e9 <+124>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013eb <+126>: callq 0x555555401a90 <explode_bomb> 0x00005555554013f0 <+131>: mov $0x0,%eax 0x00005555554013f5 <+136>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013f7 <+138>: mov $0x123,%eax 0x00005555554013fc <+143>: cmp %eax,0x4(%rsp) 0x0000555555401400 <+147>: je 0x555555401407 <phase_3+154> 0x0000555555401402 <+149>: callq 0x555555401a90 <explode_bomb> 0x0000555555401407 <+154>: mov 0x8(%rsp),%rax 0x000055555540140c <+159>: xor %fs:0x28,%rax 0x0000555555401415 <+168>: jne 0x55555540141c <phase_3+175> 0x0000555555401417 <+170>: add $0x18,%rsp 0x000055555540141b <+174>: retq 0x000055555540141c <+175>: callq 0x555555400f20 <__stack_chk_fail@plt>
<+40 ~ 49>
0x0000555555401395 <+40>: cmp $0x1,%eax 0x0000555555401398 <+43>: jle 0x5555554013b3 <phase_3+70> 0x000055555540139a <+45>: cmpl $0x7,(%rsp) 0x000055555540139e <+49>: ja 0x5555554013eb <phase_3+126>
0x00005555554013b3 <+70>: callq 0x555555401a90 <explode_bomb>
0x00005555554013eb <+126>: callq 0x555555401a90 <explode_bomb>
<+40> : Right now R[%eax] is the number of numbers entered. It compares the number of numbers entered with 1.
<+43> : If it's 1 or less, it jumps to <+70>. <+70> is the bomb, so you have to enter 2 or more numbers. (Since we assumed we entered 50, the bomb explodes.)
<+45> : (%rsp) is the first number we entered. It compares the first number with 7.
<+49> : If it's greater than 7 or less than 0 (since ja is an unsigned operation), it jumps to <+126>. That's the bomb, so the first number has to be between 0 and 7.
From here on, assume we entered 0 291.
<+51 ~ 68>
0x00005555554013a0 <+51>: mov (%rsp),%eax 0x00005555554013a3 <+54>: lea 0x1796(%rip),%rdx # 0x555555402b40 0x00005555554013aa <+61>: movslq (%rdx,%rax,4),%rax 0x00005555554013ae <+65>: add %rdx,%rax 0x00005555554013b1 <+68>: jmpq *%rax
<+51> : Stores the first number we entered in %eax.
<+54> : When the <+54> instruction runs, R[%rip] is the address of <+61>, 0x00005555554013aa. (%rip, the PC, points to the address of the next instruction to run.)
So R[%rdx] = 0x1796 + 0x00005555554013aa = 0x555555402b40.
<+61> : %rax means the first number we entered, and it takes that number, which is between 0 and 7, multiplies it by 4, adds it to %rdx, and stores the value at that address in %rax. I was able to find the referenced values of R[%rdx] + 4 * R[%rax] by testing in gdb.
| First number | R[%rdx] + 4 * R[%rax] | %rax = M[R[%rdx] + 4 * R[%rax]] Hex, Dec |
|---|---|---|
| 0 | 0x555555402b40 | 0xffffffffffffe8b7, -5961 |
| 1 | 0x555555402b44 | 0xffffffffffffe87a, -6022 |
| 2 | 0x555555402b48 | 0xffffffffffffe881, -6015 |
| 3 | 0x555555402b5c | 0xffffffffffffe888, -6008 |
| 4 | 0x555555402b60 | 0xffffffffffffe88f, -6001 |
| 5 | 0x555555402b64 | 0xffffffffffffe896, -5994 |
| 6 | 0x555555402b68 | 0xffffffffffffe89d, -5987 |
| 7 | 0x555555402b7c | 0xffffffffffffe8a4, -5980 |
<+65> : Adds %rdx to %rax once more. ( R[%rdx] is 0x555555402b40, 93824990849856(demical) )
<+68> : Jumps to the address held in %rax. Marking where it jumps for each %rax number and organizing it gives the following.
| First number | %rax Hex, Dec | jump <+ ? > |
|---|---|---|
| 0 | 0x5555554013F7, 93824990843895 | <+138> |
| 1 | 0x5555554013BA, 93824990843834 | <+77> |
| 2 | 0x5555554013C1, 93824990843841 | <+84> |
| 3 | 0x5555554013C8, 93824990843848 | <+119> |
| 4 | 0x5555554013CF, 93824990843855 | <+98> |
| 5 | 0x5555554013D6, 93824990843862 | <+105> |
| 6 | 0x5555554013DD, 93824990843869 | <+112> |
| 7 | 0x5555554013E4, 93824990843876 | <+119> |
<77 ~ 138>
0x00005555554013ba <+77>: mov $0x8c,%eax 0x00005555554013bf <+82>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013c1 <+84>: mov $0x3be,%eax 0x00005555554013c6 <+89>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013c8 <+91>: mov $0x79,%eax 0x00005555554013cd <+96>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013cf <+98>: mov $0x2c9,%eax 0x00005555554013d4 <+103>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013d6 <+105>: mov $0x379,%eax 0x00005555554013db <+110>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013dd <+112>: mov $0x347,%eax 0x00005555554013e2 <+117>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013e4 <+119>: mov $0x39a,%eax 0x00005555554013e9 <+124>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013eb <+126>: callq 0x555555401a90 <explode_bomb> 0x00005555554013f0 <+131>: mov $0x0,%eax 0x00005555554013f5 <+136>: jmp 0x5555554013fc <phase_3+143> 0x00005555554013f7 <+138>: mov $0x123,%eax
Depending on the first number, it jumps and stores a value in %eax.
Organized by number, it looks like this.
| First number | jump <+ ? > | Demical : R[%eax] |
|---|---|---|
| 0 | <+138> | 291 |
| 1 | <+77> | 140 |
| 2 | <+84> | 958 |
| 3 | <+119> | 922 |
| 4 | <+98> | 713 |
| 5 | <+105> | 889 |
| 6 | <+112> | 839 |
| 7 | <+119> | 922 |
<143 ~ 174>
0x00005555554013fc <+143>: cmp %eax,0x4(%rsp) 0x0000555555401400 <+147>: je 0x555555401407 <phase_3+154> 0x0000555555401402 <+149>: callq 0x555555401a90 <explode_bomb> 0x0000555555401407 <+154>: mov 0x8(%rsp),%rax 0x000055555540140c <+159>: xor %fs:0x28,%rax 0x0000555555401415 <+168>: jne 0x55555540141c <phase_3+175> 0x0000555555401417 <+170>: add $0x18,%rsp 0x000055555540141b <+174>: retq
<+143> : 0x4(%rsp) means the second number we entered. It's comparing the second number with R[%eax].
<+147> : If R[%eax] from the table above equals the second number, it jumps to <+154>.
<+149> : If the second number is different from R[%eax], the bomb explodes, so it turns out the second number has to equal R[%eax].
So the answer is the following.
| First number | Second number |
|---|---|
| 0 | 291 |
| 1 | 140 |
| 2 | 958 |
| 3 | 922 |
| 4 | 713 |
| 5 | 889 |
| 6 | 839 |
| 7 | 922 |