diff options
Diffstat (limited to 'Content')
| -rw-r--r-- | Content/posts/2023-10-04-bomb-lab.md | 131 | 
1 files changed, 128 insertions, 3 deletions
| diff --git a/Content/posts/2023-10-04-bomb-lab.md b/Content/posts/2023-10-04-bomb-lab.md index d235186..98c5272 100644 --- a/Content/posts/2023-10-04-bomb-lab.md +++ b/Content/posts/2023-10-04-bomb-lab.md @@ -1,10 +1,10 @@  ---  date: 2023-10-04 13:12 -description: Introduction, Phases 1-4 of Bomb Lab for CSCI 2400 Lab - 2 +description: Introduction, Phases 1-5 of Bomb Lab for CSCI 2400 Lab - 2  tags: gdb, reverse-engineering, c++, csci2400, assembly  --- -# Bomb Lab Phases 1-4 +# Bomb Lab Phases 1-5  ## Introduction @@ -621,7 +621,7 @@ def func4(edi, esi=0, edx=20):      else:          return 0 -for x in range(10): +for x in range(15): # We can limit to 14     if func4(x) == 2:        print(f"answer is {x}")        break @@ -653,3 +653,128 @@ Continuing.  So you got that one.  Try this one.  ``` +## Phase 5 + +``` +So you got that one.  Try this one. +test string + +Breakpoint 1, 0x0000555555555830 in phase_5 () +(gdb) disas phase_5 +Dump of assembler code for function phase_5: +=> 0x0000555555555830 <+0>:     endbr64  +   0x0000555555555834 <+4>:     push   %rbx +   0x0000555555555835 <+5>:     sub    $0x10,%rsp +   0x0000555555555839 <+9>:     mov    %rdi,%rbx +   0x000055555555583c <+12>:    call   0x555555555b10 <string_length> +   0x0000555555555841 <+17>:    cmp    $0x6,%eax +   0x0000555555555844 <+20>:    jne    0x55555555588b <phase_5+91> +   0x0000555555555846 <+22>:    mov    $0x0,%eax +   0x000055555555584b <+27>:    lea    0x199e(%rip),%rcx        # 0x5555555571f0 <array.0> +   0x0000555555555852 <+34>:    movzbl (%rbx,%rax,1),%edx +   0x0000555555555856 <+38>:    and    $0xf,%edx +   0x0000555555555859 <+41>:    movzbl (%rcx,%rdx,1),%edx +   0x000055555555585d <+45>:    mov    %dl,0x9(%rsp,%rax,1) +   0x0000555555555861 <+49>:    add    $0x1,%rax +   0x0000555555555865 <+53>:    cmp    $0x6,%rax +   0x0000555555555869 <+57>:    jne    0x555555555852 <phase_5+34> +   0x000055555555586b <+59>:    movb   $0x0,0xf(%rsp) +   0x0000555555555870 <+64>:    lea    0x9(%rsp),%rdi +   0x0000555555555875 <+69>:    lea    0x1943(%rip),%rsi        # 0x5555555571bf +   0x000055555555587c <+76>:    call   0x555555555b31 <strings_not_equal> +   0x0000555555555881 <+81>:    test   %eax,%eax +   0x0000555555555883 <+83>:    jne    0x555555555892 <phase_5+98> +   0x0000555555555885 <+85>:    add    $0x10,%rsp +   0x0000555555555889 <+89>:    pop    %rbx +   0x000055555555588a <+90>:    ret     +   0x000055555555588b <+91>:    call   0x555555555d4a <explode_bomb> +   0x0000555555555890 <+96>:    jmp    0x555555555846 <phase_5+22> +   0x0000555555555892 <+98>:    call   0x555555555d4a <explode_bomb> +   0x0000555555555897 <+103>:   jmp    0x555555555885 <phase_5+85> +End of assembler dump. +(gdb)  +``` + +``` +... +   0x000055555555583c <+12>:    call   0x555555555b10 <string_length> +   0x0000555555555841 <+17>:    cmp    $0x6,%eax +   0x0000555555555844 <+20>:    jne    0x55555555588b <phase_5+91> +... +   0x000055555555588b <+91>:    call   0x555555555d4a <explode_bomb> +... +``` + +First things first, these instructions check to make sure the passed string is of length 6, otherwise `explode_bomb` is called. + +We can also see a similar pattern compared to Phase 2, where we had a loop: + +* The looping part: +   * `mov $0x0,%eax` - Initialise `%eax` and set it to 0 (our counter/iterator) +   * `movzbl (%rbx,%rax,1),%edx` - Access `%rbx + 1 * %rax` and store it in `%edx` +   * `and $0xf,%edx` - Take the least significant 4 bits of the byte. +   * `movzbl (%rcx,%rdx,1),%edx` - Use the 4 bits as an index into another array and load the corresponding byte into `%edx` +   * `mov %dl,0x9(%rsp,%rax,1)` - Store the transformed byte into a buffer on the stack +   * `add $0x1,%rax` - Increment `%rax` +   * `cmp    $0x6,%rax` - If the index is not yet 6, loop again +* `movb $0x0,0xf(%rsp)` - Null-terminate the transformed string +* `lea 0x9(%rsp),%rdi` and `lea 0x1943(%rip),%rsi`  +* `all 0x555555555b31 <strings_not_equal>` check if the two strings loaded up just before this are equal or not. + +We can check the reference string we need, which `gdb` has marked as `# 0x5555555571bf`, and the lookup table marked as `# 0x5555555571f0 <array.0>` + +``` +(gdb) x/s 0x5555555571bf +0x5555555571bf: "bruins" +(gdb) x/s 0x5555555571f0 +0x5555555571f0 <array.0>:       "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?" +(gdb)  +``` + +To summarize the transformation process: + +* The function takes each byte of the string +* It keeps only the least significant 4 bits of each byte +* It uses these 4 bits as an index into the lookup table (`array.0`) +* The value from the array is then stored in a buffer + +Here's how the transformation process can be reversed for each character in "bruins": +1. Find the index of `b` in the lookup table (in our case, it is 13 since we index starting 0) +2. Calculate binary representation of this index (in our case 13 can be written as 1101 in binary) +3. Find ASCII character whose least significant 4 bits match (in our case, `m` has binary representation `01101101`) + +Repeat for all 6 characters + +*Hint: Using an [ASCII - Binary Table](http://sticksandstones.kstrom.com/appen.html) can save you time.*  + +Thus, we can have the following transformation: + +``` +b -> m +r -> f  +u -> c +i -> d +n -> h +s -> g +``` + + +Let us try out this answer: + +``` +... +That's number 2.  Keep going! +Halfway there! +So you got that one.  Try this one. +mfcdhg + +Breakpoint 1, 0x0000555555555830 in phase_5 () +(gdb) continue +Continuing. +Good work!  On to the next... +``` + +Awesome! + +## Phase 6 + | 
