While this challenge was under the "Baby's First" section, I think it's a great teaching example of a basic heap exploitation technique. File
$ file beatmeonthedl
beatmeonthedl: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, not stripped
Giving it a run we get:
$ ./beatmeonthedl
__ __ .__ __
/ \ / \ ____ | | ____ ____ _____ ____ _/ |_ ____
\ \/\/ // __ \| | _/ ___\/ _ \ / \_/ __ \ \ __\/ _ \
\ /\ ___/| |_\ \__( <_> ) Y Y \ ___/ | | ( <_> )
\__/\ / \___ >____/\___ >____/|__|_| /\___ > |__| \____/
\/ \/ \/ \/ \/
__ .__ .__ .__ _____ __ .__
_/ |_| |__ ____ | | _____ |__|______ _____/ ____\ _/ |_| |__ ____
\ __\ | \_/ __ \ | | \__ \ | \_ __ \ / _ \ __\ \ __\ | \_/ __ \
| | | Y \ ___/ | |__/ __ \| || | \/ ( <_> ) | | | | Y \ ___/
|__| |___| /\___ > |____(____ /__||__| \____/|__| |__| |___| /\___ >
\/ \/ \/ \/ \/
_________.__ .___ __________ __
/ _____/| |__ _____ __| _/______ _ __ \______ \_______ ____ | | __ ___________ ______
\_____ \ | | \\__ \ / __ |/ _ \ \/ \/ / | | _/\_ __ \/ _ \| |/ \// __ \_ __ \/ ___/
/ \| Y \/ __ \_/ /_/ ( <_> ) / | | \ | | \( <_> ) <\ ___/| | \/\___ \
/_______ /|___| (____ /\____ |\____/ \/\_/ |______ / |__| \____/|__|_ \\___ >__| /____ >
\/ \/ \/ \/ \/ \/ \/ \/
Enter username: test
Invalid user: test
It's apparently looking for a correct username. As is a usual next step, let's run ltrace on it to see if we can have an easy win. I'm cutting the output to the important part.
[pid 34323] SYS_read(0test
, "test\n", 16) = 5
[pid 34323] <... read resumed> , "test\n", 16) = 5
[pid 34323] strlen("mcfly") = 5
[pid 34323] memcmp(0x7ffd6141c6d0, 0x4085d8, 5, 0x4085d8) = 7
[pid 34323] printf("Invalid user: %s\n", "test\n" <unfinished ...>
So it reads in our "test" string, then checks the string length of "mcfly". Let's see if that's correct.
[pid 34348] strlen("mcfly") = 5
[pid 34348] memcmp(0x7ffdc291f8f0, 0x4085d8, 5, 0x4085d8) = 0
[pid 34348] memset(0x7ffdc291f8e0, '\0', 24) = 0x7ffdc291f8e0
[pid 34348] printf("Enter Pass: " <unfinished ...>
[pid 34348] SYS_write(1, "Enter Pass: ", 12Enter Pass: ) = 12
[pid 34348] <... printf resumed> ) = 12
[pid 34348] read(0 <unfinished ...>
[pid 34348] SYS_read(0test
, "test\n", 24) = 5
[pid 34348] <... read resumed> , "test\n", 24) = 5
[pid 34348] sysconf(30, 32, 0, 4) = 4096
[pid 34348] time(0) = 1493773626
[pid 34348] sbrk(0 <unfinished ...>
[pid 34348] SYS_brk(0) = 0x1f8c000
[pid 34348] <... sbrk resumed> ) = 0x1f8c000
[pid 34348] sbrk(4096 <unfinished ...>
[pid 34348] SYS_brk(0x1f8d000) = 0x1f8d000
[pid 34348] <... sbrk resumed> ) = 0x1f8c000
[pid 34348] strlen("awesnap") = 7
[pid 34348] memcmp(0x1f8c010, 0x4085de, 7, 0x4085de) = 19
[pid 34348] printf("Invalid pass: %s\n", "test\n" <unfinished ...>
[pid 34348] SYS_write(1, "Invalid pass: test\n\n", 20Invalid pass: test
So it accepted the username. Next, it asked for a password and compared it against "awesnap". If we go ahead and try that as the password we will get past the login.
Enter username: mcfly
Enter Pass: awesnap
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
|
It's a menu system. Let's try a few inputs:
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 1
Request text > test
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 1
Request text > test2
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 1
Request text > %x
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 2
0) test
1) test2
2) %x
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 4
0) test
1) test2
2) %x
choice: 0
data: test3
I) Request Exploit.
II) Print Requests.
III) Delete Request.
IV) Change Request.
V) Go Away.
| 2
0) test3
1) test2
2) %x
So it lets us give it some input. It then gives us the ability to print that input out, modify it, and delete it. Already this is feeling like a heap challenge. Also, sadly (gladly?) the "%x" didn't get interpreted as a format string, so that's off the table.
At this point, I jumped into the code. Here's main:
Unfortunately, radare2 had a bit of a problem displaying that jump table at the bottom. However, this binary isn't stripped and there are helpful names for the functions.
Let's go through the functions.
- Prev
- Next >>