神刀安全网

Defusing a binary bomb with – Part 6

Defusing a binary bomb with gdb – Part 6

19 May 2016

This post is part of a series where I show how to defuse a binary bomb by reading assembly code and using gdb . You might want to readthe first part if you haven’t yet.

Here we are at the last phase. This is the most interesting phase so far. The code for phase_6 is the following:

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   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   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   40112c:   41 83 fc 06             cmp    $0x6,%r12d   401130:   74 21                   je     401153 <phase_6+0x5f>   401132:   44 89 e3                mov    %r12d,%ebx   401135:   48 63 c3                movslq %ebx,%rax   401138:   8b 04 84                mov    (%rsp,%rax,4),%eax   40113b:   39 45 00                cmp    %eax,0x0(%rbp)   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   401148:   83 fb 05                cmp    $0x5,%ebx   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   401158:   4c 89 f0                mov    %r14,%rax   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)   401166:   48 83 c0 04             add    $0x4,%rax   40116a:   48 39 f0                cmp    %rsi,%rax   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   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   401188:   48 89 54 74 20          mov    %rdx,0x20(%rsp,%rsi,2)   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   40119a:   83 f9 01                cmp    $0x1,%ecx   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   4011b0:   48 8d 44 24 28          lea    0x28(%rsp),%rax   4011b5:   48 8d 74 24 50          lea    0x50(%rsp),%rsi   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   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>   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 

It’s longer than the other phases and seems more complicated so we’re going to break it in parts to explain what each part is doing.

The first part we can look at is where the function initializes. It starts by saving some registers values because they are going to be used as local variables in this function, then making room for other local variables and then reading the input that will be used to defuse the phase. At 0x401106 we can see that the input for this phase must be six numbers:

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 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 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> 

After reading the six numbers and placing the first one on rsp the code copies the address pointing to the first one into r14 then it sets up other variables and finally on 0x40111e it checks whether or not the first number we provided is less than or equal to 6 . How it did that?

rsi is used to hold the second argument for a function call and prior to calling read_six_numbers (at 0x401103 ) the address of rsp was copied to rsi to be used by read_six_numbers . That’s where our numbers were stored, in an array that starts at the address that is on rsi . This same address is also stored on rsp and r13 . We can look at the registers to see which address this is:

(gdb) i r rsp rsi r13 rsp            0x7fffffffdd60   0x7fffffffdd60 rsi            0x7fffffffdd60   140737488346464 r13            0x7fffffffdd60   140737488346464 

After returning from read_six_numbers this same address is stored on r14 at 0x40110b and on 0x40114 it is stored on rbp as well.

Then on 0x401117 the value stored in the address on r13 , our first number, is copied to eax and then the code checks if it is less than or equal to 6 .

So now that we understand how the check was made, let’s proceed to the next part:

401128: 41 83 c4 01             add    $0x1,%r12d 40112c: 41 83 fc 06             cmp    $0x6,%r12d 401130: 74 21                   je     401153 <phase_6+0x5f> 401132: 44 89 e3                mov    %r12d,%ebx 401135: 48 63 c3                movslq %ebx,%rax 401138: 8b 04 84                mov    (%rsp,%rax,4),%eax 40113b: 39 45 00                cmp    %eax,0x0(%rbp) 40113e: 75 05                   jne    401145 <phase_6+0x51> 401140: e8 f5 02 00 00          callq  40143a <explode_bomb> 

Remember that on line 0x40110e the register r12d stored the value 0 so the first three lines are just for checking if the code already went through 6 iterations. Let’s continue on 0x401132 where the new value of r12d (which is 1 for the first iteration) is copied into ebx which then is copied to rax by sign-extending from double word (4 bytes) to quad word (8 bytes) since ebx is a 32-bit register while rax is a 64-bit register.

After that the next number we entered is checked against the first one. The second number is copied to eax by this instruction:

401138: 8b 04 84                mov    (%rsp,%rax,4),%eax 

What this line actually does is: multiply by 4 the value on rax ( 1 since it came from r12d ) and add that value to value stored on rsp (the starting address of the array holding our input numbers). For the first iteration the resulting address will be:

(gdb) x $rsp+$rax*0x4 0x7fffffffdd64: 0x00000002 

The value stored at this resulting address will then be copied to eax . For the first iteration it means our second input number.

Then our second value (on eax ) is compared to first one to see if they are not equal and jumps to the next part:

401145: 83 c3 01                add    $0x1,%ebx 401148: 83 fb 05                cmp    $0x5,%ebx 40114b: 7e e8                   jle    401135 <phase_6+0x41> 40114d: 49 83 c5 04             add    $0x4,%r13 401151: eb c1                   jmp    401114 <phase_6+0x20> 

The first three lines will check if we did this check for all six numbers which means we cannot input repeated numbers. After that, on 0x40114d , r13 is changed to hold the address of the second input number by adding 4 bytes ( sizeof(int) ) to the address r13 is currently storing. Then it goes back to 0x401114 to do the same checks against the other numbers we provided.

Now we know some facts about the expected input:

  • It must be six numbers;
  • They need to be less than or equal to 6 ;
  • They cannot repeat.

Let’s continue to see which other characteristics these numbers must have.

After doing these initial checks the code will jump to 0x401153 :

401153: 48 8d 74 24 18          lea    0x18(%rsp),%rsi 401158: 4c 89 f0                mov    %r14,%rax 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) 401166: 48 83 c0 04             add    $0x4,%rax 40116a: 48 39 f0                cmp    %rsi,%rax 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> 

The first line of this part simply defines the address that means we iterated over all six numbers. The first number is stored on the address that rsp holds and the sixth number will be on $rsp + 0x14 (start address + offset of 5 int ).

r14 also holds the address for the first number so it’s going to be copied to rax on 0x401158 to be used in this iteration. Then on the next two lines both ecx and edx store the value 7 . After the setup the actual iteration will start by first subtracting from edx the value stored by the address in rax (our first number in the first iteration). At 0x401164 the result of this subtraction will overwrite the value on rax and then on 0x401166 the code will move to the next int we provided, compare on 0x40116d if we iterated over all six numbers and jump back to 0x401160 if we did not, otherwise get out of the loop and continue execution on 0x401197 .

Let’s simulate what happens after this loop is executed. Suppose we entered 1 2 3 4 5 6 as our input numbers for this phase. Then after iterating in this loop our array will have the following new values: 6 5 4 3 2 1 . The loop just changes the all numbers in the array to be abs(n-7) .

After exiting the loop we continue on 0x401197 which brings us to the next part in this phase:

401176: 48 8b 52 08             mov    0x8(%rdx),%rdx 40117a: 83 c0 01                add    $0x1,%eax 40117d: 39 c8                   cmp    %ecx,%eax 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 401188: 48 89 54 74 20          mov    %rdx,0x20(%rsp,%rsi,2) 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 40119a: 83 f9 01                cmp    $0x1,%ecx 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> 

Although the first line of this part is at 0x401176 , execution actually starts at 0x401197 . After executing this line ecx will hold the first number from our array because the value stored on rsi is 0 (from 0x40116f ) and the instruction on 0x401197 means: copy the value stored by the address of $rsi*0x1 + $rsp to ecx . This operation clearly means it is part of some iteration and we can guess that rsi will be updated in the process to go over the other numbers in the array.

401197: 8b 0c 34                mov    (%rsp,%rsi,1),%ecx 40119a: 83 f9 01                cmp    $0x1,%ecx 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> 

If the current number on ecx is less than or equal to 1 the code will jump to 0x401183 , otherwise it will jump to 0x401176 .

In the last part our array became: 6 5 4 3 2 1 . So the code will jump to 0x401176 . Let’s see what happens there.

401176: 48 8b 52 08             mov    0x8(%rdx),%rdx 40117a: 83 c0 01                add    $0x1,%eax 40117d: 39 c8                   cmp    %ecx,%eax 40117f: 75 f5                   jne    401176 <phase_6+0x82> 401181: eb 05                   jmp    401188 <phase_6+0x94> 

Notice that before jumping to 0x401176 , the address 0x6032d0 was stored on edx . Then the value stored after the first 8 bytes of this address will be copied to rdx on 0x401176 . After this operation, eax will be incremented and compared with ecx to then conditionally jump to another place in this part or again to 0x401176 . The initial value of eax in this case is 1 that was set on 0x40119f before jumping to 0x401176 . ecx holds the value 6 so we go back to 0x401176 and copy the value on $rdx + 0x8 to rdx , increment eax and check against ecx .

The values on ecx and eax will match only after six iterations: in our example, ecx starts with 6 and eax with 1 . In this case before jumping to 0x401188 , rdx will have whatever value is stored in $rdx + 0x48 (six times adding 0x8 to the initial address and copying the value in the new address to rdx ).

Then the code jumps to 0x401188 :

401183: ba d0 32 60 00          mov    $0x6032d0,%edx 401188: 48 89 54 74 20          mov    %rdx,0x20(%rsp,%rsi,2) 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 40119a: 83 f9 01                cmp    $0x1,%ecx 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> 

At this line the address that rdx is holding will be copied to the address that results from: $rsi*0x2 + $rsp + 0x20 . rsi is the index over the iteration that is going on:

(gdb) i r rsi rsi            0x0  0 

Next, rsi is incremented by 4 ( sizeof(int) ) and compared against 0x18 to see if we iterated over all six numbers. If we did not then on 0x401197 , ecx gets the next number from our array and the next iteration begins.

Now that we know what this iteration is all about let’s see what exactly is stored by the initial address on rdx :

(gdb) x 0x6032d0 0x6032d0 <node1>:   0x0000014c 

Huh, node1 , interesting name, right? Let’s see what this address plus 8 bytes holds:

(gdb) x 0x6032d0+0x8 0x6032d8 <node1+8>: 0x006032e0 

Looking at what is on 0x6032e0 :

(gdb) x 0x6032e0 0x6032e0 <node2>:   0x000000a8 

Aha! That looks like a linked list. To see the address of node3 :

(gdb) x 0x6032e0+0x8 0x6032e8 <node2+8>: 0x006032f0 

And what node3 stores:

(gdb) x *(0x6032e0+0x8) 0x6032f0 <node3>:   0x0000039c 

We have a linked list that holds an int value, the node identifier and the pointer to the next node, something like the following:

struct node {     int x;     int i;     struct node *next; }; 

So when the code jumps to 0x401188 , rdx will have the address of the value stored by node6 since our array is 6 5 4 3 2 1 and it went through 0x401176 six times:

(gdb) i r rdx rdx            0x603320 6304544 (gdb) x 0x6032d0+0x48 0x603318 <node5+8>: 0x00603320 (gdb) x $rdx 0x603320 <node6>:   0x000001bb 

The address rdx holds, which stores the value 0x1bb , will be placed in the first position of a new array starting at $rsp + 0x20 . Since this code iterates over all six numbers, after executing this part for all numbers this new array will actually store the addresses holding the values that the corresponding node stores, based on our transformed input array.

Explaining: from 0x401176 until 0x401181 the code is looking for the corresponding node for the current iteration. On 0x401188 the address of value x that the node holds is then copied to the current iteration index on the new array. Then the next iteration begins.

Let’s see what are the values that each node stores and their addresses. First we define a command to print the node values and move to the next node:

define plist  set var $n = $arg0  while $n   printf "node%d (%p): value = %#.3x, next=%p/n", *($n+0x4), $n, *$n, *($n+0x8)   set var $n = *($n+0x8)  end end 

Printing the values:

(gdb) plist 0x6032d0 node1 (0x6032d0): value = 0x14c, next=0x6032e0 node2 (0x6032e0): value = 0x0a8, next=0x6032f0 node3 (0x6032f0): value = 0x39c, next=0x603300 node4 (0x603300): value = 0x2b3, next=0x603310 node5 (0x603310): value = 0x1dd, next=0x603320 node6 (0x603320): value = 0x1bb, next=(nil) 

After iterating over the six numbers using our input array which was transformed into 6 5 4 3 2 1 the new array (starting at $rsp + 0x20 ) will hold the addresses of x in the following order: node6 node5 node4 node3 node2 node1 .

(gdb) x/6gx $rsp+0x20 0x7fffffffdd80: 0x0000000000603320  0x0000000000603310 0x7fffffffdd90: 0x0000000000603300  0x00000000006032f0 0x7fffffffdda0: 0x00000000006032e0  0x00000000006032d0 

After creating this new array the code continues execution at 0x4011ab which is the next part:

4011ab: 48 8b 5c 24 20          mov    0x20(%rsp),%rbx 4011b0: 48 8d 44 24 28          lea    0x28(%rsp),%rax 4011b5: 48 8d 74 24 50          lea    0x50(%rsp),%rsi 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 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> 4011ee: 48 8b 5b 08             mov    0x8(%rbx),%rbx 4011f2: 83 ed 01                sub    $0x1,%ebp 4011f5: 75 e8                   jne    4011df <phase_6+0xeb> 

At the first line of this part rbx gets the value of the first element of the new array which is the address of x for node6 . In the next line rax gets the second element of the new array and in the third line rsi gets an address that is just past the last element of this new array, most likely to check later if we iterated over the entire new array.

On 0x4011ba , rcx will hold the value of the first element of the new array, then rdx will get the second value and in the next line, 0x4011c0 , this value will be copied to $rcx + 0x8 . Let’s back it up for a minute and see the values in both registers after executing the instruction at 0x4011c0 :

(gdb) i r rcx rdx rcx            0x603320 6304544 rdx            0x603310 6304528 

$rcx + 0x8 is the address that holds the pointer to the next element of the list and after executing 0x4011c0 it will point to the value that rdx is storing:

(gdb) x $rcx+0x8 0x603328 <node6+8>: 0x0000000000603310 

After that, on 0x4011c4 the next value from the new array is placed in rax for the next iteration which is checked against rsi in the next line and the process repeats. At the end of it the next pointer for each node will be changed according to the values of the new array. As we’ve seen above the new array has the following values:

(gdb) x/6gx $rsp+0x20 0x7fffffffdd80: 0x0000000000603320  0x0000000000603310 0x7fffffffdd90: 0x0000000000603300  0x00000000006032f0 0x7fffffffdda0: 0x00000000006032e0  0x00000000006032d0 

These values correspond to node6 node5 node4 node3 node2 node1 so after the iteration above the pointers will be changed to reflect this order. We can confirm it with our plist command after executing the instruction on 0x4011d2 :

(gdb) plist 0x603320 node6 (0x603320): value = 0x1bb, next=0x603310 node5 (0x603310): value = 0x1dd, next=0x603300 node4 (0x603300): value = 0x2b3, next=0x6032f0 node3 (0x6032f0): value = 0x39c, next=0x6032e0 node2 (0x6032e0): value = 0x0a8, next=0x6032d0 node1 (0x6032d0): value = 0x14c, next=(nil) 

With the initial input of 1 2 3 4 5 6 the code has reversed the list. Note that I now used the address of node6 as the starting address for plist since that is the order from the array located at $rsp + 0x20 . Also notice that on 0x4011d2 the next pointer for the last iteration receives the NULL value and in our case it is node1->next .

4011da: bd 05 00 00 00          mov    $0x5,%ebp 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> 4011ee: 48 8b 5b 08             mov    0x8(%rbx),%rbx 4011f2: 83 ed 01                sub    $0x1,%ebp 4011f5: 75 e8                   jne    4011df <phase_6+0xeb> 

Now that the list was changed the execution continues at 0x4011da by storing the value 5 in ebp . Then the address of value x of the next node is stored on rax and then in the next line the actual x value is stored on eax (32-bit register since we’re dealing with int ). On 0x4011e5 the value x from the first node (at rbx ) is compared against the value x of the second and if the first value is greater than or equal to the second the code jumps to 0x4011ee that will update the value of rbx to point to the next x value and also update the value of ebp that is then compared to see if we iterated over the entire list.

So this iteration is checking that the x value of the current node is greater than or equal to the next x for all nodes in the list. If they are not the bomb explodes as we can see at 0x4011e9 .

The other part of this function starting at 0x4011f7 cleanups the stack frame for phase_6 and returns.

Now that we saw everything that this function is doing we know that our input numbers are used to sort the linked list in descending order.

Don’t forget that before being used to reorder the list each input number will be changed to abs(n-7) .

The values of each node are:

node # x (hex) x (dec)
1 0x14c 332
2 0x0a8 168
3 0x39c 924
4 0x2b3 691
5 0x1dd 477
6 0x1bb 443

The values of x for the final list must be in the following order:

924 -> 691 -> 477 -> 443 -> 332 -> 168 

Which means the list must be reordered as:

node3 -> node4 -> node5 -> node6 -> node1 -> node2 

Then the solution for this phase is:

4 3 2 1 6 5 Congratulations! You've defused the bomb! 

Finally! The bomb has been defused!

Or not? There’s something odd in the C file. The main function ends like this:

input = read_line(); phase_6(input); phase_defused();  /* Wow, they got it!  But isn't something... missing?  Perhaps  * something they overlooked?  Mua ha ha ha ha! */  return 0; 

In the next post I will show what exactly is missing. I’ll leave you with this hint from phase_defused :

401630: e8 0d fc ff ff          callq  401242 <secret_phase> 

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Defusing a binary bomb with – Part 6

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址