Tut01: GDB/x86

IOLI-crackme

Did you successfully connect to the CTF server? Let's play with a binary.

We prepared four binaries. The goal is very simple: find a password that each binary accepts. Before tackling this week's challenges, you will learn how to use GDB, how to read x86 assembly, and a hacker's mindset!

We highly recommend to tackle crackme binaries first (at least upto 0x03) before jumping into the bomblab. In bomblab, if you make a mistake (i.e., exploding the bomb), you will get some deduction.

In this tutorial, we walk together to solve two binaries.

crackme0x00

# login to the CTF server
# ** check Canvas for login information! **
[host] $ ssh lab01@<ctf-server-address>

# let's start lab01!
[CTF server] $ cat README
[CTF server] $ cd tut01-crackme

Where to start? There are many ways to start:

  1. reading the whole binary first (e.g., try objdump -M intel -d crackme0x00);

  2. starting with a gdb session (e.g., gdb ./crackme0x00) and setting a breakpoint on a well-known entry (e.g., luckily main() is exposed, try nm crackme0x00);

  3. run ./crackme0x00 first (waiting on the "Password" prompt) and attach it to gdb (e.g., gdb -p $(pgrep crackme0x00));

  4. or just running with gdb then press C-c (i.e., sending a SIGINT signal).

Let's take 4. as an example

$ gdb ./crackme0x00
Reading symbols from ./crackme0x00...(no debugging symbols found)...done.
(gdb) r

[r]un: run a program, please check help run

Starting program: /home/lab01/tut01-crackme/crackme0x00
IOLI Crackme Level 0x00
Password: ^C

press ctrl+C (^C) to send a signal to stop the process

Program received signal SIGINT, Interrupt.
0xf7fd8d09 in __kernel_vsyscall ()
(gdb) bt
#0  0xf7fd5079 in __kernel_vsyscall ()
#1  0xf7ecbdf7 in __GI___libc_read (fd=0, buf=0x804b570, nbytes=1024) at ../sysdeps/unix/sysv/linux/read.c:27
#2  0xf7e58258 in _IO_new_file_underflow (fp=<optimized out>) at fileops.c:531
#3  0xf7e5937b in __GI__IO_default_uflow (fp=0xf7fbd5c0 <_IO_2_1_stdin_>) at genops.c:380
#4  0xf7e3ccb1 in _IO_vfscanf_internal (s=<optimized out>, format=<optimized out>, argptr=<optimized out>, errp=<optimized out>) at vfscanf.c:630
#5  0xf7e47e25 in __scanf (format=0x80487f1 "%s") at scanf.c:33
#6  0x080486d1 in main (argc=1, argv=0xffffd6c4) at crackme0x00.c:14

[bt]: print backtrace (e.g., stack frames). Again, don't forget to check help bt

(gdb) tbreak *0x080486d1
Temporary breakpoint 1 at 0x080492fa

set a (temporary) breakpoint (help b, tb, rb) to the call site (next) of the scanf(), which is potentially the most interesting part.

(gdb) c
Continuing.
aaaaaaaaaaaaaa

[c]ontinue to run the process, type aaaaaaaaaaaaaa (inject a random input)

Temporary breakpoint 1, 0x080492fa in main ()

ok, it hits the breakpoint, let check the context

[disas]semble: dump the assembly code in the current scope

(gdb) set disassembly-flavor intel
(gdb) disas
   0x080486a3 <+0>: push   ebp
   0x080486a4 <+1>: mov    ebp,esp
   0x080486a6 <+3>: sub    esp,0x10
   0x080486a9 <+6>: push   0x80487f4
   0x080486ae <+11>:    call   0x8048470 <puts@plt>
   0x080486b3 <+16>:    add    esp,0x4
   0x080486b6 <+19>:    push   0x804880c
   0x080486bb <+24>:    call   0x8048430 <printf@plt>
   0x080486c0 <+29>:    add    esp,0x4
   0x080486c3 <+32>:    lea    eax,[ebp-0x10]
   0x080486c6 <+35>:    push   eax
   0x080486c7 <+36>:    push   0x80487f1
   0x080486cc <+41>:    call   0x8048480 <scanf@plt>
=> 0x080486d1 <+46>:    add    esp,0x8
   0x080486d4 <+49>:    push   0x8048817
   0x080486d9 <+54>:    lea    eax,[ebp-0x10]
   0x080486dc <+57>:    push   eax
   0x080486dd <+58>:    call   0x8048420 <strcmp@plt>
   0x080486e2 <+63>:    add    esp,0x8
   0x080486e5 <+66>:    test   eax,eax
   0x080486e7 <+68>:    jne    0x8048705 <main+98>
   0x080486e9 <+70>:    push   0x804881e
   0x080486ee <+75>:    call   0x8048470 <puts@plt>
   0x080486f3 <+80>:    add    esp,0x4
   0x080486f6 <+83>:    push   0x804882d
   0x080486fb <+88>:    call   0x80485f6 <print_key>
   0x08048700 <+93>:    add    esp,0x4
   0x08048703 <+96>:    jmp    0x8048712 <main+111>
   0x08048705 <+98>:    push   0x804883c
   0x0804870a <+103>:   call   0x8048470 <puts@plt>
   0x0804870f <+108>:   add    esp,0x4
   0x08048712 <+111>:   mov    eax,0x0
   0x08048717 <+116>:   leave
   0x08048718 <+117>:   ret
End of assembler dump.

please try reading (and understanding) the code

   0x080486c3 <+32>:    lea    eax,[ebp-0x10]
   0x080486c6 <+35>:    push   eax
   0x080486c7 <+36>:    push   0x80487f1
   0x080486cc <+41>:    call   0x8048480 <scanf@plt>

can be interpreted as:

-> scanf("%s", buf)

By the way, what's the size of buf?

(gdb) x/1s 0x80487f1
0x80487f1:  "%s"

this is your input

(gdb) x/1s $ebp-0x10
0xffffcb30:     'a' <repeats 24 times>

Please learn about the e[x]amine command (help x), which is one of the most versatile commands in gdb.

   0x080486d4 <+49>:    push   0x8048817
   0x080486d9 <+54>:    lea    eax,[ebp-0x10]
   0x080486dc <+57>:    push   eax
   0x080486dd <+58>:    call   0x8048420 <strcmp@plt>

is equivalent to:

 -> strcmp(buf, "250381")

Examine the arguments:

(gdb) x/1s 0x8048817
0x8048817:  "250381"
   0x080486e5 <+66>:    test   eax,eax
   0x080486e7 <+68>:    jne    0x8048705 <main+98>
   0x080486e9 <+70>:    push   0x804881e
   0x080486ee <+75>:    call   0x8048470 <puts@plt>
   0x080486f3 <+80>:    add    esp,0x4
   0x080486f6 <+83>:    push   0x804882d
   0x080486fb <+88>:    call   0x80485f6 <print_key>
   0x08048700 <+93>:    add    esp,0x4
   0x08048703 <+96>:    jmp    0x8048712 <main+111>
   0x08048705 <+98>:    push   0x804883c
   0x0804870a <+103>:   call   0x8048470 <puts@plt>

->
    if (!strcmp(buf, "250381")) {
        printf("Password OK :)\n")
        ...
    } else {
        printf("Invalid Password!\n");
    }
(gdb) x/1s 0x804883c
0x804a0a4:      "Invalid Password!\n"
(gdb) x/1s 0x804881e
0x804a086:      "Password OK :)\n"

[Task] Try the password we found? Does it work? You can submit the flag to the submission site (see above) to get +20 points!

crackme0x01

Let's go fast on this binary. Please take similar steps from crackme0x00 and reach to this place.

(gdb) disas
   0x08048486 <+0>: push   ebp
   0x08048487 <+1>: mov    ebp,esp
   0x08048489 <+3>: sub    esp,0x4
   0x0804848c <+6>: push   0x8048570
   0x08048491 <+11>:    call   0x8048330 <puts@plt>
   0x08048496 <+16>:    add    esp,0x4
   0x08048499 <+19>:    push   0x8048588
   0x0804849e <+24>:    call   0x8048320 <printf@plt>
   0x080484a3 <+29>:    add    esp,0x4
   0x080484a6 <+32>:    lea    eax,[ebp-0x4]
   0x080484a9 <+35>:    push   eax
   0x080484aa <+36>:    push   0x8048593
   0x080484af <+41>:    call   0x8048340 <scanf@plt>

what's scanf() doing (i.e., what's the value of 0x8048593)?

=> 0x080484b4 <+46>:    add    esp,0x8
   0x080484b7 <+49>:    mov    eax,DWORD PTR [ebp-0x4]
   0x080484ba <+52>:    cmp    eax,0xc8e

it means that our input with 0xc8e(hex? integer?) is password.

   0x080484b4 <+46>:    add    esp,0x8
   0x080484b7 <+49>:    mov    eax,DWORD PTR [ebp-0x4]
   0x080484ba <+52>:    cmp    eax,0xc8e
   0x080484bf <+57>:    jne    0x80484d0 <main+74>
   0x080484c1 <+59>:    push   0x8048596
   0x080484c6 <+64>:    call   0x8048330 <puts@plt>
   0x080484cb <+69>:    add    esp,0x4
   0x080484ce <+72>:    jmp    0x80484dd <main+87>
   0x080484d0 <+74>:    push   0x80485a5
   0x080484d5 <+79>:    call   0x8048330 <puts@plt>
   0x080484da <+84>:    add    esp,0x4
   0x080484dd <+87>:    mov    eax,0x0
   0x080484e2 <+92>:    leave
   0x080484e3 <+93>:    ret

[Task] Try the password we found? Does it work? Great. Please explore all crackme binaries and if you think you are ready, please start bomblab!

Bomblab

Bomblab challenges are in one bomb binary, which you can find under the home directory of lab01 on the CTF server.

[host] ssh lab01@<ctf-server-address>

[CTF server] $ pwd
/home/lab01
[CTF server] $ ls -alh | grep bomb
-rwsr-x---  1 bomb110-raspberry lab01    22K Jan 14  2021 bomb

Execute the bomb binary and provide your API key to get started:

[CTF server] $ ./bomb
Enter your api-key: <your-api-key>

          ,--.!,   ____                  _     _       _
       __/   -*-  | __ )  ___  _ __ ___ | |__ | | __ _| |__
     ,d08b.  '|`  |  _ \ / _ \| '_ ` _ \| '_ \| |/ _` | '_ \
    0088MM        | |_) | (_) | | | | | | |_) | | (_| | |_) |
     `9MMP'       |____/ \___/|_| |_| |_|_.__/|_|\__,_|_.__/
            cs6265

Welcome to my fiendish little bomb. You have N? phases with
which to blow yourself up. See you alive!
(hint: seriously, security question?)
>

[Task] Defuse the bomb by providing the right answer to each phase. Be careful when handling the bomb; if you enter a wrong answer, the bomb will explode, and you will lose points for the phase. Submit the flags from each phase to the submission site to collect points.

Reference