COFF文件解析 | CoffLdr
字数 2085 2025-08-30 06:50:27
COFF文件解析与CoffLdr实现详解
1. COFF文件概述
COFF(Common Object File Format)是在程序编译过程中生成的二进制文件,通常以.o或.obj为扩展名。这些文件随后会被链接器处理,生成最终的PE可执行文件。
COFF文件结构
COFF文件主要由以下几个部分组成:
- CoffHead:文件头,不包含StringTable的偏移信息
- Section Header:节区头表
- SectionData:每个节的实际数据
- Reloc Table:重定位表
- Symbol Table:符号表
- String Table:字符串表
2. 现有C2平台COFF加载器的问题分析
2.1 函数槽位不足问题
在Cobalt Strike中,MAX_DYNAMIC_FUNCTIONS宏被硬编码为32(4.5版本),当BOF需要调用超过32个函数时会抛出"No slot for function"错误。
解决方案:
- 应像Havoc框架那样,通过遍历symbolName动态分配GOT(Global Offset Table)大小
- 避免硬编码函数槽位限制
2.2 BSS段处理问题
BSS段用于存放未初始化的全局变量,不同编译器处理方式不同:
- Mingw(基于GCC):显式创建.bss段
- MSVC:不创建.bss段,将未初始化变量放入数据段或堆中
问题表现:
- Cobalt Strike 4.9.1:Beacon崩溃
- BRC4:需要新API格式
- AdaptixC2:BOF解析逻辑缺失
解决方案:
- 对于MSVC编译的COFF,需要手动创建BSS Table实现兼容
- 处理BSS段后,MSVC和Mingw编译的BOF都能正常输出
2.3 异常捕获问题
BOF崩溃会导致整个Beacon崩溃,解决方案:
- 使用VEH(Vectored Exception Handling)捕获异常
- 异常触发时将RIP指向
CoffeeFunctionReturn(COFF的返回地址) - 添加额外判断兼容某些BOF抛出的异常
2.4 OpSec问题
BOF执行会分配内存或踩踏内存,可能触发检测机制。
改进方案:
- 使用Native API调用
- 实现模块踩踏(Module Stomping),使调用栈更正常
- 其他OpSec技术(留给读者探索)
2.5 BeaconGate替代方案
Cobalt Strike 4.10引入BeaconGate控制API调用,在没有此功能时可实现类似效果:
- IAT Hook:控制BOF的API调用
- 实现自定义"Gate"机制,提供开箱即用的规避效果
2.6 参数解析问题
Cobalt Strike Beacon有特定API用于参数解析:
BeaconDataParseBeaconDataExtractBeaconDataIntBeaconPrintf
参数格式解析规则:
- 跳过Buffer总长度字段(前4字节)
- 统一
BeaconDataInt和BeaconDataExtract的结构
3. COFF解析实现细节
3.1 总大小计算(TotalSize)
定义ParseTotalSize函数:
- 遍历每个节,记录节大小和对齐
- 在每个节中查找重定向条目
- 查找每个符号,记录BSS Table Size和GOT Table Size
- 分配完整内存区域(而非多次分配)
3.2 BSS和GOT处理
处理流程:
- 判断是否为Beacon内部函数
- 是:遍历函数数组返回地址
- 维护
BeaconApi数组实现后续行为函数
- 如果是
library$function或function格式- 使用
GetModule/LoadDll获取函数地址
- 使用
- 处理.bss段
- 跳过BSS Table的前4字节
- 返回BSS Table的Offset
- 将
pCoffSymbol->SectionNumber改为对应的BSS Table Section和GOT Section
3.3 重定位处理(Process Relocation)
四种主要情况:
IMAGE_REL_AMD64_REL32&&functionPtr != NULLIMAGE_REL_AMD64_REL32→IMAGE_REL_AMD64_REL32_5IMAGE_REL_AMD64_ADDR32NBIMAGE_REL_AMD64_ADDR64
3.4 获取入口点(Get EntryPoint)
- 遍历所有符号
- 获取EntryPoint地址
- 支持自定义入口点(不限于"go")
3.5 运行COFF(RunCoffee)
- 注册VEH捕获运行时崩溃
- 实现线程欺骗:
- 挂起线程创建
- 恢复线程执行
4. 实现效果展示
部分BOF运行效果:
Askcreds.objwhoami.oCheckAV.o