VS版本: Visual Studio 2022
写于: 2025/10/15
最近看到了隔壁大佬逆向msvc劫持编译器(碎碎念: 顺便一提似乎直接调用微软为warbird提供的接口来实现编译期混淆会更方便,相关内容下面也有写)我也突然来了兴趣(最后因为ttoil过于复杂没分析完所有IL),遂逆向了一番并编写了下列内容,希望对各位有帮助。
隔壁大佬的帖子:
https://bbs.kanxue.com/thread-288764.htm
c1.dll - 用于解析 c 代码并发出 IL
c1xx.dll - 用于解析 cpp 代码并发出 IL
c2.dll - 编译器后端, 负责优化与生成实际汇编代码
linker.exe - 链接器
cl.exe - 编译器命令行程序
主函数 cl.exe -> c1.dll -> ...... -> main_compile
第二阶段初始化
负责打开ex文件
被 ILEmitter 及其相关组件调用, 负责实际写入字节数据
似乎仅用于将 ilsExp 的读写指针 seek 到0x57的位置
用于向buffer中写入单个字节
用于写入压缩整数
此类用于发出 IL
source code -> PrimaryParser::Parse -> yacc语法分析器 -> ttoil(递归) -> ILEmitterVisitor -> ILEmitter -> ILSink -> ilsExp & ilsInit
source code -> PrimaryParser::Parse -> 解析完成 -> SymbolTableManager_t::DumpGlobalSymbols -> SymbolILWriters -> 各种Emitter -> ILSink -> LocalSymbolIL & GlobalSymbolIL
source code -> CVTSInit (初始化并开始记录) -> PrimaryParser::Parse等函数 -> 保存解析时候产生的记录 -> CVTSEnd (结束记录) -> ilsDB
用于打开 c1 生成的 IL
将 IL 文件写入obj中
将 c1 发出的 IL 文件转换为 obj
Warbird 分为两个接口 CreateObfuscator2 与 GetObfuscator
此函数用于在 linker 中初始化混淆器, 负责初始化链接期混淆
此函数用于在 c2.dll 中初始化混淆器, 负责初始化编译期混淆
以下是我在github上搜索到的一些相关代码
06cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6%4K9h3c8T1k6i4u0Y4i4K6u0r3L8i4y4$3j5K6S2Q4x3X3f1H3i4K6g2X3M7r3q4@1j5$3S2W2M7R3`.`.
f60K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6v1j5h3y4C8e0X3!0A6M7X3g2Q4x3V1k6J5k6i4k6W2M7Y4y4W2b7K6u0p5L8r3H3`.
b1aK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4y4@1i4K6u0W2k6$3W2@1K9s2g2T1i4K6u0W2j5$3!0E0i4K6u0r3g2s2u0W2k6h3E0A6i4K6u0r3j5U0b7#2y4e0u0T1k6e0M7#2x3K6N6T1k6r3u0U0x3e0p5%4x3o6k6X3k6h3k6U0x3$3f1#2k6h3k6V1x3r3t1`.
4c9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4y4@1i4K6u0W2k6$3W2@1K9s2g2T1i4K6u0W2j5$3!0E0i4K6u0r3c8i4y4@1k6i4S2z5g2q4)9J5c8X3f1&6z5r3p5I4x3K6R3@1j5U0V1H3y4X3p5K6k6h3g2V1j5h3q4S2x3$3g2W2j5U0N6W2y4e0S2U0k6o6W2V1
init_main2();
if (EmitPragmaFileHash)
SymbolTableManager_t::DumpFileHashes(PchS);
if (!PchUFlag)
{
Comment_type = 10;
Comment_string = "/CLRNETCORE";
op_pragma(0xB);
if (Has_com_entry)
{
Comment_type = 10;
Comment_string = "/NOCOMENTRY";
op_pragma(0xB);
}
}
InjectArtifactsBeforeInputSource();
ApplyCmdLineWarningFlags();
if (!PchUFlag)
{
MetaDataEmitter::Initialize();
metaEmitter = MetaDataEmitter::Instance;
}
if (!PchUFlag || WorkList_t::m_usingWorkList)
{
StoilHeader();
ProcessBEWarnings();
}
if ( PchUFile )
EnsureFilenameIsEmitted();
CallPrimaryParser();
SymbolTableManager_t::DumpGlobalSymbols(PchS);
StoilHeader();
ILSink::closeFile(&ilsExp);
ILSink::closeFile(&LocalSymbolIL);
ILSink::closeFile(&GlobalSymbolIL);
ILSink::closeFile(&ilsInit);
if ( IncludeDebugDataBase )
ILSink::closeFile(&ilsDB);
init_main2();
if (EmitPragmaFileHash)
SymbolTableManager_t::DumpFileHashes(PchS);
if (!PchUFlag)
{
Comment_type = 10;
Comment_string = "/CLRNETCORE";
op_pragma(0xB);
if (Has_com_entry)
{
Comment_type = 10;
Comment_string = "/NOCOMENTRY";
op_pragma(0xB);
}
}
InjectArtifactsBeforeInputSource();
ApplyCmdLineWarningFlags();
if (!PchUFlag)
{
MetaDataEmitter::Initialize();
metaEmitter = MetaDataEmitter::Instance;
}
if (!PchUFlag || WorkList_t::m_usingWorkList)
{
StoilHeader();
ProcessBEWarnings();
}
if ( PchUFile )
EnsureFilenameIsEmitted();
CallPrimaryParser();
SymbolTableManager_t::DumpGlobalSymbols(PchS);
StoilHeader();
ILSink::closeFile(&ilsExp);
ILSink::closeFile(&LocalSymbolIL);
ILSink::closeFile(&GlobalSymbolIL);
ILSink::closeFile(&ilsInit);
if ( IncludeDebugDataBase )
ILSink::closeFile(&ilsDB);
OpenExpFile();
ILSink::fopen(&LocalSymbolIL, Basename, "sy", 6);
ILSink::fopen(&GlobalSymbolIL, Basename, "gl", 6);
ILSink::fopen(&ilsInit, Basename, "in", 6);
if (IncludeDebugDataBase)
ILSink::fopen(&ilsDB, Basename, "db", 6);
OpenExpFile();
ILSink::fopen(&LocalSymbolIL, Basename, "sy", 6);
ILSink::fopen(&GlobalSymbolIL, Basename, "gl", 6);
ILSink::fopen(&ilsInit, Basename, "in", 6);
if (IncludeDebugDataBase)
ILSink::fopen(&ilsDB, Basename, "db", 6);
ILSink::fopen(&ilsExp, Basename, "ex", 6)
if (!PchUFlag)
{
ILSink::chwrite(&ilsExp, 0x5B);
ILSink::lowrite(&ilsExp, 0x58);
status = ILSink::seek();
IOGlobalVal = status;
if (status)
{
}
ILSink::chwrite(&ilsExp, 0);
}
ILSink::fopen(&ilsExp, Basename, "ex", 6)
if (!PchUFlag)
{
ILSink::chwrite(&ilsExp, 0x5B);
ILSink::lowrite(&ilsExp, 0x58);
status = ILSink::seek();
IOGlobalVal = status;
if (status)
{
}
ILSink::chwrite(&ilsExp, 0);
}
fseek(&ilsExp, 0x57, 0);
if (this->buffer_start + this->buffer_size - this->buffer_end >= 2
|| (res = Buffer::grow(this->buffer_start, 2), ok = 0, res) )
{
ok = 1;
}
fail = (ok & this->good) == 0;
this->good &= ok;
if (!fail)
*(uint8_t *)this->buffer_end++ = ch;
if (this->buffer_start + this->buffer_size - this->buffer_end >= 2
|| (res = Buffer::grow(this->buffer_start, 2), ok = 0, res) )
{
ok = 1;
}
fail = (ok & this->good) == 0;
this->good &= ok;
if (!fail)
*(uint8_t *)this->buffer_end++ = ch;
if (this->buffer_start + this->buffer_size - this->buffer_end >= 2
|| (res = Buffer::grow(this->buffer_start, 2), ok = 0, res) )
{
ok = 1;
}
fail = (ok & this->good) == 0;
this->good &= ok;
if (!fail) {
buf = this->buffer_end;
if (val & 0xFFFFFF80 != 0) {
*(uint8_t *)buf = 0x80;
*(uint32_t *)++this->buffer_end = val;
this->buffer_end += 4;
} else {
*(uint8_t *)buf = val;
++this->buffer_end;
}
}
if (this->buffer_start + this->buffer_size - this->buffer_end >= 2
|| (res = Buffer::grow(this->buffer_start, 2), ok = 0, res) )
{
ok = 1;
}
fail = (ok & this->good) == 0;
this->good &= ok;
if (!fail) {
buf = this->buffer_end;
if (val & 0xFFFFFF80 != 0) {
*(uint8_t *)buf = 0x80;
*(uint32_t *)++this->buffer_end = val;
this->buffer_end += 4;
} else {
*(uint8_t *)buf = val;
++this->buffer_end;
}
}
ILEmitter::EmitOPbranch(OPTYPE,Symbol_t *);
ILEmitter::EmitOPgoto(Symbol_t *);
ILEmitter::EmitOPlabel(Symbol_t *);
ILEmitter::EmitOPname(Symbol_t *);
ILEmitter::EmitOPnbranch(Symbol_t *);
ILEmitter::EmitOPpragma(uchar);
ILEmitter::EmitOPswexp(Symbol_t *);
ILEmitter::EmitOPswitch(Symbol_t *,Expr_t *);
ILEmitter::EmitPrFilename(Filename *);
ILEmitter::EmitPragma(PRAGMA_TYPE,MessageNumber);
ILEmitter::EmitPragmaComment(PragmaComment_t::Kind_t,char const *);
ILEmitter::EmitWarningPragma(WarningState_t *,WarningState_t * const,std::vector<WarningNumber> const &);
ILEmitter::toil(s_tree *);
ILEmitter::toil_direct(s_tree *);
ILEmitter::EmitOPbranch(OPTYPE,Symbol_t *);
ILEmitter::EmitOPgoto(Symbol_t *);
ILEmitter::EmitOPlabel(Symbol_t *);
ILEmitter::EmitOPname(Symbol_t *);
ILEmitter::EmitOPnbranch(Symbol_t *);
ILEmitter::EmitOPpragma(uchar);
ILEmitter::EmitOPswexp(Symbol_t *);
ILEmitter::EmitOPswitch(Symbol_t *,Expr_t *);
ILEmitter::EmitPrFilename(Filename *);
ILEmitter::EmitPragma(PRAGMA_TYPE,MessageNumber);
ILEmitter::EmitPragmaComment(PragmaComment_t::Kind_t,char const *);
ILEmitter::EmitWarningPragma(WarningState_t *,WarningState_t * const,std::vector<WarningNumber> const &);
ILEmitter::toil(s_tree *);
ILEmitter::toil_direct(s_tree *);
sy -> LocalSymbolIL // 本地符号信息
gl -> GlobalSymbolIL // 全局符号信息
in -> ilsInit // 变量初始化数据
db -> ilsDB // 调试数据库
ex -> ilsExp // 调用 ttoil 与其下的 ILEmitterVisitor 转换过来的IL
// fg不由 c1.dll 产生
fg -> 命令行参数
sy -> LocalSymbolIL // 本地符号信息
gl -> GlobalSymbolIL // 全局符号信息
in -> ilsInit // 变量初始化数据
db -> ilsDB // 调试数据库
ex -> ilsExp // 调用 ttoil 与其下的 ILEmitterVisitor 转换过来的IL
// fg不由 c1.dll 产生
fg -> 命令行参数
wcscpy_s(file_name, 0x104, basename);
wcscat_s(file_name, 0x104, section);
utc_wfopen_s(&fs, file_name, L"rb")
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!
最后于 2025-10-20 21:00
被EX呵呵编辑
,原因: 添加参考资料