关于CODASM
CODASM是一款针对Payload的编码工具,该工具针对红蓝队研究人员设计,可以帮助我们对Payload执行编码操作并显著降低Payload的熵值。
该工具允许您将任意数据编码为伪 ASM 指令,并将其编译到二进制文件的 .text 部分。
开销为 80-120%(例如 380KB CS shellcode => 870KB CODASM 有效负载)。
功能介绍
Payload(尤其是 shellcode)具有相当高的熵,在编译后的二进制文件中的大多数位置看起来都不合适。CODASM 旨在将Payload隐藏在已经具有高熵的位置:.text包含二进制文件编译代码的部分。为此,CODASM 将生成良性 shellcode,并支持嵌入任意Payload。
CODASM 是一个 Python 脚本,可以生成以下内容:
1、良性的 shellcode,用于任意Payload;
2、一个 C 头文件,你可以在程序中使用它将 shellcode 嵌入到二进制文件中,并在运行时检索它;
对于编码Payload,CODASM 执行以下操作:
1、生成有效 x86_64 函数;
2、将Payload字节嵌入到指令操作数中(例如mov eax, <4 bytes of payload>);
3、对嵌入的Payload字节进行异或加密;
为了解码Payload,生成的 C 头文件执行以下操作:
1、解析单个指令,直到检索到所需数量的Payload字节:
2、检测单个指令,确定它们是否包含Payload字节;
3、如果指令包含Payload字节,则提取并解密它们;
工具要求
Python 3
工具安装
由于该工具基于Python 3开发,因此我们首先需要在本地设备上安装并配置好最新版本的Python 3环境。
接下来,广大研究人员可以直接使用下列命令将该项目源码克隆至本地:
git clone https://github.com/NVISOsecurity/codasm
工具使用
usage: codasm.py [-h] -i INPUT [-oa OUT_ASM] [-ob OUT_BIN] [-oc OUT_C] [-op OUT_P] [--rng RNG] [-vbmin VAL_BYTES_MIN] [-vbmax VAL_BYTES_MAX] [-vbch VAL_BYTES_CHANCE] [-v] CODASM encoding utility options: -h, --help 显示此帮助消息并退出 -i INPUT, --input INPUT 要编码为ASM/二进制指令的输入文件的路径 -oa OUT_ASM, --out-asm OUT_ASM 将生成的ASM指令写入的路径 -ob OUT_BIN, --out-bin OUT_BIN 将生成的二进制指令写入的路径 -oc OUT_C, --out-c OUT_C 将生成的CODASM解码器写入的路径 -op OUT_P, --out-p OUT_P 将嵌入式Payload写入的路径 --rng RNG 用于随机化的rng种子(异或密钥、有效载荷指令顺序、解码操作顺序) -vbmin VAL_BYTES_MIN, --val-bytes-min VAL_BYTES_MIN 编码到单个方法中的最小字节数(默认值64) -vbmax VAL_BYTES_MAX, --val-bytes-max VAL_BYTES_MAX 编码到单个方法中的最大字节数(默认256) -vbch VAL_BYTES_CHANCE, --val-bytes-chance VAL_BYTES_CHANCE 操作成为编码数据而不是虚拟数据的机会(0.1-0.9,默认值0.1) -v, --verbose 输出详细程度(0-3,默认值0) Note: ASM output is meant to be used for manual reference, not for compiling!
使用样例
1、准备 shellcode (例如 CS/BR shellcode) 并另存为shellcode.bin;
2、使用 CODASM 对 shellcode 进行编码:
./codasm.py --i shellcode.bin -oc codasmloader.h
3、复制codasmloader.h到您最喜欢的加载器或独立的最小加载器中(例如/demo/codasm.c);
4、确保decode在调用 shellcode 之前调用 CODASM:
/* ~snip CODASM decode~*/ #include <stdlib.h> // "INTEXT" macro ensures that the payload is pleced into the `.text` section INTEXT uint8_t payload[5978] = { 0x50, 0x53, 0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, /* ... */ }; int main() { uint64_t xor_key = 0xFFFDA6803A51E3FB; // Generated by CODASM uint8_t* input = (uint8_t*)payload; uint8_t* output = (uint8_t*)malloc(sizeof(payload)); uint32_t output_length = 0xac4; int32_t res = 0; if ((res = decode(input, sizeof(payload), output, output_length, xor_key)) < 0) return 1; // Some doo-doo happened, investigate value of res // You successfully recovered the payload, do something fun with it here :) return 0; }
5、编译你的加载器;
6、确保生成的二进制文件删除所有调试信息;
工具运行演示
# Input file $ cat test.txt my secret message # Encode & generate C file $ ./codasm.py -i test.txt -ob test.bin -oa test.asm -oc test.c # Generated mashine code $ xxd test.bin 00000000: 5053 5152 4150 4151 4152 4153 4154 4155 PSQRAPAQARASATAU 00000010: 4156 4157 4883 ec28 751b 757f c705 5696 AVAWH..(u.u...V. 00000020: 44e9 6df6 61d6 84c0 488d 0d91 9e02 2640 D.m.a...H.....&@ 00000030: 32ff b91b 8052 f975 8283 f99c 85c9 7513 2....R.u......u. 00000040: 4883 c428 415f 415e 415d 415c 415b 415a H..(A_A^A]A\A[AZ 00000050: 4159 4158 5a59 5b68 c3cc AYAXZY[X.. # Generated ASM $ cat test.asm push rax ... push r15 sub RSP, 0x28 jnz 0x1B jnz 0x7F mov 0xE9449656,0xD661F66D test al,al lea 0x26029E91 xor dil,dil mov ecx,0xF952801B jnz 0x82 cmp ecx,0x9C test ecx,ecx jnz 0x13 add RSP, 0x28 pop r15 ... pop rax retn ; Padding # Prepare generated C file for compilation $ sed -i "s/\/\* Generated.*//" test.c $ sed -i "s/Sample usage://" test.c $ sed -i "s/}\*\//}/" test.c # Minimal program in C file: $ tail -n 30 test.c #endif // CODASM_DECODE #include <stdlib.h> INTEXT uint8_t payload[90] = { 0x50, 0x53, 0x51, 0x52, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, /* ... */ int main() { uint64_t xor_key = 0xFBE38A21E5760676; uint8_t* input = (uint8_t*)payload; uint8_t* output = (uint8_t*)malloc(sizeof(payload)); uint32_t output_length = 0x11; int32_t res = 0; if ((res = decode(input, sizeof(payload), output, output_length, xor_key)) < 0) return 1; // Some doo-doo happened, investigate value of res // You successfully recovered the payload, do something fun with it here :) return 0; } # Compile using MINGW $ x86_64-w64-mingw32-gcc test.c -o test.exe # Find generated ASM in compiled EXE: $ objdump -d test.exe ... 0000000140002da0 <payload>: 140002da0: 50 push %rax ... 140002db2: 41 57 push %r15 140002db4: 48 83 ec 28 sub $0x28,%rsp 140002db8: 75 1b jne 140002dd5 <payload+0x35> 140002dba: 75 7f jne 140002e3b <main+0x41> 140002dbc: c7 05 56 96 44 e9 6d movl $0xd661f66d,-0x16bb69aa(%rip) # 12944c41c <__size_of_stack_reserve__+0x12924c41c> 140002dc3: f6 61 d6 140002dc6: 84 c0 test %al,%al 140002dc8: 48 8d 0d 91 9e 02 26 lea 0x26029e91(%rip),%rcx # 16602cc60 <.debug_ranges+0x25fde970> 140002dcf: 40 32 ff xor %dil,%dil 140002dd2: b9 1b 80 52 f9 mov $0xf952801b,%ecx 140002dd7: 75 82 jne 140002d5b <decode+0x4f> 140002dd9: 83 f9 9c cmp $0xffffff9c,%ecx 140002ddc: 85 c9 test %ecx,%ecx 140002dde: 75 13 jne 140002df3 <payload+0x53> 140002de0: 48 83 c4 28 add $0x28,%rsp 140002de4: 41 5f pop %r15 ... 140002df7: 58 pop %rax 140002df8: c3 ret 140002df9: cc int3 ...
嵌入的payload在IDA中如下所示:
检测
您可以使用以下 YARA 规则来潜在地检测嵌入 CODASM 生成的输出的 PECOFF 文件。您可以在代码块下方找到规则的简要说明:
import "pe" import "math" private rule IsPE { meta: description = "Tests whether the file starts with the MZ header." author = "Moritz Thomas" date = "2024-07-24" condition: uint16(0) == 0x5A4D } private rule ExampleUsage { meta: description = "Detects malloc and invoking the decode function, passing in references to the .data section" author = "Moritz Thomas" date = "2024-07-24" strings: $AllocDecode = { 8b 0d ?? ?? ?? ?? // MOV ECX, dword ptr [DAT_1400fb070] 89 4c 24 ?? // MOV dword ptr [RSP + 0x3c], ECX e8 ?? ?? ?? ?? // CALL MSVCRT.DLL::malloc // ECX = DAT_1400fb070 // [RSP + 0x3c] = ECX // malloc() 8b 15 ?? ?? ?? ?? // MOV EDX, dword ptr [DAT_1400fb080] 44 8b 4c 24 ?? // MOV R9D, dword ptr [RSP + 0x3c] // EDX = DAT_1400fb080 // R9D = [RSP + 0x3c] 48 8d 0d ?? ?? ?? ?? // LEA RCX, [FUN_140001460] 48 89 c3 // MOV RBX, RAX 48 8b 05 ?? ?? ?? ?? // MOV RAX, qword ptr [DAT_1400fb090] 49 89 d8 // MOV R8, RBX 48 89 44 24 ?? // MOV qword ptr [RSP + 0x20], RAX // RCX = &FUN_140001460 // RBX = RAX // RAX = DAT_1400fb090 // R8 = RBX // [RSP + 0x20] = RAX e8 ?? ?? ?? ?? // CALL FUN_1400f9cf0 // FUN_1400f9cf0() 89 c2 // MOV EDX, EAX 85 c0 // TEST EAX, EAX 79 13 // JNS LAB_1400fac7b // EDX = EAX // if (EAX >= 0) goto LAB_1400fac7b 48 8d 0d ?? ?? ?? ?? // LEA RCX, [LAB_1400fc0e3] e8 ?? ?? ?? ?? // CALL FUN_1400faae0 // RCX = &LAB_1400fc0e3 // FUN_1400faae0() b8 01 00 00 00 // MOV EAX, 0x1 eb ?? // JMP !AB_1400faca3 // EAX = 1 // goto LAB_1400faca3 83 f8 42 // CMP EAX, 0x42 75 ?? // JNZ LAB_1400fac8a // if (EAX != 0x42) goto LAB_1400fac8a b9 22 00 00 00 // MOV ECX, 0x22 e8 ?? ?? ?? ?? // CALL FUN_140001460 // ECX = 0x22 // FUN_140001460() } // if (iVar2 == 0x42) FUN_140001460(0x22, 0x42); $PseudoCall= { 83 f8 42 // CMP EAX, 0x42 75 ?? // JNZ LAB_1400FACA3 b9 22 00 00 00 // MOV ECX, 0x22 e8 ?? ?? ?? ?? // CALL FUN_140001460 } condition: IsPE and $AllocDecode and $PseudoCall } private rule Decode { meta: description = "Detects parameter validation (null-checks), returning -2 and performing a pseudo call RBX(22h)" author = "Moritz Thomas" date = "2024-07-24" strings: $NullTest = { 48 85 c9 // TEST param_1,param_1 74 ?? // JZ LAB_1400f9d76 4d 85 c0 // TEST param_3,param_3 74 ?? // JZ LAB_1400f9d76 } $ReturnMinusTwo = { b8 fe ff ff ff // MOV EAX,0xfffffffe } $PseudoCall = { b9 22 00 00 00 // MOV ECX,0x22 ff d3 // CALL RBX } condition: IsPE and $NullTest and $ReturnMinusTwo and $PseudoCall } private rule PEAnalysis { meta: description = "Detects PE files with very large .text sections (>=90%) that have reasonable entropy (5.0 < e(.text) < 7.0)." author = "Moritz Thomas" date = "2024-07-24" condition: IsPE and // Check for MZ header for any i in (0..pe.number_of_sections - 1) : ( pe.sections[i].name == ".text" and pe.sections[i].raw_data_size > (filesize * 0.9) and math.in_range( math.entropy(pe.sections[i].raw_data_offset, pe.sections[i].raw_data_size), 5.0, 7.0 ) ) } rule CODASMed { condition: ExampleUsage or (Decode and PEAnalysis) }
许可证协议
本项目的开发与发布遵循MIT开源许可协议。
项目地址
CODASM:【GitHub传送门】
参考资料
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)