因考察 obf-llvm 对代码的展平化效果,想在win上编译obf-llvm。
根据官方简单的mkdir & cd & cmake & vs-compile 遭遇一些错误,需对源码做一些修正。
如下:
----------------
建立2017解决方案
----------------
根据官方说明用cmake通过源码建立2017解决方案
Download and install CMake. Version 2.8 is the minimum required.
Open a shell. Your development tools must be reachable from this shell through the PATH environment variable.
Create a directory for containing the build. It is not supported to build LLVM on the source directory. cd to this directory:
$ mkdir mybuilddir
$ cd mybuilddir
Execute this command on the shell replacing path/to/llvm/source/root with the path to the root of your LLVM source tree:
$ cmake path/to/llvm/source/root
这里我们解压释放的源码目录为obf_llvm_361
mkdir mybuilddir
cd mybuilddir
cmake ..\obf_llvm_361
-----------------------------------------------------------------
%ROOTDIR%\obf_llvm_361\lib\Transforms\Obfuscation\CryptoUtils.cpp
-----------------------------------------------------------------
编译解决方案会,执行会 提示 /dev/random 无法读取,window平台理所当然会出错。
由于源码目的市初始化16字节的key,我们改为srand,rand来完成key的随机初始化。
#include <time.h>
void tritium_init_rand_key(char * buf,unsigned int buflen) {
unsigned int i;
srand(time(NULL));
for (i = 0; i < buflen; i++) {
buf[i] = char(rand() & 0xFF);
}
}
#define __tritium__
void CryptoUtils::prng_seed() {
#ifdef __tritium__
LLVMContext &ctx = llvm::getGlobalContext();
tritium_init_rand_key(key, 16);
DEBUG_WITH_TYPE("cryptoutils", dbgs() << "cryptoutils seeded with time srand and rand\n");
memset(ctr, 0, 16);
// Once the seed is there, we compute the
// AES128 key-schedule
aes_compute_ks(ks, key);
seeded = true;
#else
//原函数体代码
#endif // __tritium__
}
------------------------------------------------------
%ROOTDIR%\obf_llvm_361\lib\Support\Windows\Program.inc
------------------------------------------------------
对于已经在命令行运行了vcvarsall.bat初始化编译环境后,link.exe找不到,这部分代码检测文件是否可执行,
去不去都没啥影响,这里在检测该错误的过程去掉了,这里也去掉(方便确定的确市找不到文件的问题)。
/* mask by tritium
if (!sys::fs::can_execute(Program)) {
if (ErrMsg)
*ErrMsg = "program not executable";
return false;
}*/
-----------------------------------------------------
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Driver\Job.cpp
-----------------------------------------------------
这部分代码会导致输入的提示,都是\\,而不是单个\,这里我们直接清除两行代码
// Quote and escape. This isn't really complete, but good enough.
OS << '"';
while (const char c = *Arg++) {
//if (c == '"' || c == '\\' || c == '$') // mask by tritium
// OS << '\\'; // mask by tritium
OS << c;
}
OS << '"';
---------------------------------------------------------------
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Driver\MSVCToolChain.cpp
---------------------------------------------------------------
这个是由于VS2017的编译环境初始化后,%VCINSTALLDIR%指向的VC目录下并没有bin目录
这里我们选择x86版link.exe,编译目标而言是x86版的目录
// First check the environment variables that vsvars32.bat sets.
llvm::Optional<std::string> VcInstallDir =
llvm::sys::Process::GetEnv("VCINSTALLDIR");
if (VcInstallDir.hasValue()) {
BinDir = VcInstallDir.getValue();
//llvm::sys::path::append(BinDir, "bin"); //modified by tritium
llvm::sys::path::append(BinDir, "Tools\\MSVC\\14.12.25827\\bin\\Hostx86\\x86");
--------------------------------------------------------------------------
//,data(原对象));
,reinterpret_cast<char*> (data(原对象)),原对象.size());// 构建 StringRef
--------------------------------------------------------------------------
这里是编译成功首先要解决的问题,上述是执行出错的问题。
由于EmitRecordWithBlob并没有只针对Vector<...>的原型,所以这里强制转换指针为char*后,再提供size参数,以便内部自行购置StringRef。
这个强制转换部分参考其它类似代码,size根据vector定义,初步也足够。
实际就是指定buf地址(char*),和bufsize。这里修改的严谨性没有再深入考察。
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(1517): Stream.EmitRecordWithBlob(OffsetsAbbrevCode, Record, reinterpret_cast<char*> (data(InputFileOffsets)),InputFileOffsets.size());// by add size param by tritium 2018/10/10
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(1912): Stream.EmitRecordWithBlob(SLocOffsetsAbbrev, Record, reinterpret_cast<char*>(data(SLocEntryOffsets)),SLocEntryOffsets.size()); // by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(2237): reinterpret_cast<char*>(data(MacroOffsets)),MacroOffsets.size()); //by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(2783): Stream.EmitRecordWithBlob(DeclContextLexicalAbbrev, Record, reinterpret_cast<char*>(data(Decls)),Decls.size()); //by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(2802): Stream.EmitRecordWithBlob(TypeOffsetAbbrev, Record, reinterpret_cast<char*>(data(TypeOffsets)),TypeOffsets.size());//by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(2815): Stream.EmitRecordWithBlob(DeclOffsetAbbrev, Record, reinterpret_cast<char*>(data(DeclOffsets)),DeclOffsets.size()); // by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(3520): reinterpret_cast<char*>(data(IdentifierOffsets)),IdentifierOffsets.size()); //by tritium
%ROOTDIR%\obf_llvm_361\tools\clang\lib\Serialization\ASTWriter.cpp(4446): reinterpret_cast<char*>(data(NewGlobalDecls)),NewGlobalDecls.size()); // by tritium
编译成功后就可以在执行了Vs2017编译环境初始化批文件的cmd中用obf-llvm的clang进行展平化测试
clang.exe check_passwd.c -o check_passwd_flat.exe -mllvm -fla
参考链接
import base64
base64.b64decode('aHR0cHM6Ly9wYXBlci5zZWVidWcub3JnLzE5Mi8=')
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。