Article Index

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.