Reading and Debugging X86 Programs

Introduction

Lab Steps

Part 1 – Find The Number

  1. Log into your Unix account on felix or helix or matrix (not on tanner, since we need a Linux machine for this lab). In your systems directory create another directory called x86, then switch your current directory to systems/x86.

  2. Copy the executable guess_one_number from the /mnt/a/mdamian/x86 directory into your systems/x86 directory. Invoke gdb with guess_one_number as an argument:
        gdb ./guess_one_number
    

  3. Set the disassembly language to Intel:
        set disassembly-flavor intel
    

  4. Disassemble the main function:
        disas main
    

  5. The piece of code of interest to you is the following:
        0x08048495 <main+51>:       cmp    eax,0x309
        0x0804849a <main+56>:       jg     0x80484a1 <main+63>
        0x0804849c <main+58>:       call   0x8048444 <print_error>
        0x080484a1 <main+63>:       mov    DWORD PTR [esp],0x80485c0
        0x080484a8 <main+70>:       call   0x8048370 <puts@plt>
    

  6. Set a breakpoint to the first cmp machine instruction:
        break *(main+51)
    

  7. Tell the debugger to display the next machine instruction to be executed:
        display /i $eip
    

  8. Tell the debugger to start running your program
        run
    Execution will stop at the first breakpoint.

  9. The program will ask you to guess the secret number. Enter a number that you can easily recognize if you stumble upon it while inspecting memory contents -- something like 222. Step carefully through instructions, inspecting registers and stack contents:
        p /d $eax   (inspect register contents)
        p /d 0x309	(convert hexadecimal to decimal)
        ni		(execute next instruction)
    

  10. Rerun the program (type in run to restart from the beginning), hoping to “guess” the secret number this time.

  11. Execution will stop at the breakpoint. To step through machine instructions, type in the debugger command
        ni
    To continue execution till the end of the program, type in the debugger command
        cont

  12. Once you have your number, quit the debugger with quit.

  13. Write down your number: _________________

Part 2 – Find The Two Numbers

  1. Copy the executable guess_two_numbers from the /mnt/a/mdamian/x86 directory into your systems/x86 directory. Invoke gdb with guess_two_numbers as an argument:
        gdb ./guess_two_numbers
    

  2. Set the disassembly language to Intel:
        set disassembly-flavor intel
    

  3. Disassemble the main function:
        disas main
    

  4. The piece of code of interest to you is the following:
        0x0804849c <main+58>:       cmp    eax,0xb
        0x0804849f <main+61>:       jle    0x80484a6 <main+68>
        0x080484a1 <main+63>:       call   0x8048444 <print_error>
        0x080484a6 <main+68>:       mov    eax,DWORD PTR [ebp-0x8]
        0x080484a9 <main+71>:       lea    edx,[eax+0x2]
        0x080484ac <main+74>:       mov    eax,DWORD PTR [ebp-0xc]
        0x080484af <main+77>:       cmp    edx,eax
        0x080484b1 <main+79>:       je     0x80484b8 <main+86>
        0x080484b3 <main+81>:       call   0x8048444 <print_error>
        0x080484b8 <main+86>:       mov    DWORD PTR [esp],0x80485e8
        0x080484bf <main+93>:       call   0x8048370 <puts@plt>
    

  5. Set a breakpoint to the first cmp machine instruction:
        break *(main+58)
    

  6. Tell the debugger to display the next machine instruction to be executed:
        display /i $eip
    

  7. Invoke the run command to start running the program. When prompted for input, enter two numbers that you can easily recognize later as you inspect memory contents (something like 111 and 222). Execution will stop at the first breakpoint.

  8. Inspect the contents of the register eax (recall to use the command p $eax to print the contents of the register eax - see step 9 from part 1). What number is that value compared with?

  9. Step carefully through instructions, inspecting registers (using the p command, which stands for print).

  10. Rerun the program as many times as necessary to find the two numbers.

  11. Write down the two numbers: _____________________

Part 3 – Find The Three Numbers

Now that you’ve warmed up to the debugger, let’s try a slightly more challenging hunt.
  1. Copy the executable guess_three_numbers from the /mnt/a/mdamian/x86 directory into your systems/x86 directory. Invoke gdb with guess_three_numbers as an argument.

  2. Set the disassembly language to intel.

  3. Disassemble the main function. The piece of code of interest to you is the following:
        0x080484f8 <main+86>:       cmp    edx,eax
        0x080484fa <main+88>:       je     0x8048501 <main+95>
        0x080484fc <main+90>:       call   0x8048484 <print_error>
        0x08048501 <main+95>:       mov    eax,DWORD PTR [ebp-0x8]
        0x08048504 <main+98>:       lea    edx,[eax+0xa]
        0x08048507 <main+101>:      mov    eax,DWORD PTR [ebp-0x10]
        0x0804850a <main+104>:      cmp    edx,eax
        0x0804850c <main+106>:      je     0x8048513 <main+113>
        0x0804850e <main+108>:      call   0x8048484 <print_error>
        0x08048513 <main+113>:      mov    edx,DWORD PTR [ebp-0x8]
        0x08048516 <main+116>:      mov    eax,DWORD PTR [ebp-0x10]
        0x08048519 <main+119>:      lea    eax,[edx+eax*1]
        0x0804851c <main+122>:      lea    edx,[eax+0xa]
        0x0804851f <main+125>:      mov    eax,DWORD PTR [ebp-0xc]
        0x08048522 <main+128>:      cmp    edx,eax
        0x08048524 <main+130>:      je     0x804852b <main+137>
        0x08048526 <main+132>:      call   0x8048484 <print_error>
        0x0804852b <main+137>:      mov    DWORD PTR [esp],0x804865c
        0x08048532 <main+144>:      call   0x80483a4 <puts@plt>
    
  4. Set a breakpoint to the first cmp machine instruction.

  5. Tell the debugger to display the next machine instruction to be executed.

  6. Start running the program. The program will ask you for your username and three numbers. Enter the data. Here’s an example:
        mdamian 11 22 33
    Execution will stop at the first breakpoint.

  7. Go step by step through the assembly code. Inspect register contents (using the p command, which stands for print) to learn the three numbers that the program expects. Rerun your code as many times as necessary to figure out the answer.

  8. Write down the three numbers: ______________________________________