Linux上X86-64精灵二进制的包装工/保护器。 Kiteshield用多层加密包装Elf Binaries,并向它们注入加载,地图并完全在用户空间中执行包装的二进制文件。基于PTRACE的运行时引擎可确保在任何给定时间中仅解密当前呼叫堆栈中的功能,并还实现了各种反欺骗技术,以使包装的二进制文件尽可能难以反向工程。支持单读和多线程二进制文件。
有关Kiteshield的工作方式,请参见下面的架构和代码库布局部分。
Kiteshield旨在在二元混淆中进行有趣的学术练习,而不是在源代码中可以在现实世界中使用的东西,因此是公开的。
以诺曼人在11世纪首选的盾牌命名(另外:在旧派符号中如此普遍的基特岛)。
Kiteshield要求BitDefender拆卸器库在包装器中解码说明。它作为packer/bddisasm的子模块包含在内。要从新鲜的克隆构建它,请运行以下(请注意,您需要安装CMAKE):
git submodule update --init
cd packer/bddisasm
mkdir build
cd build
cmake ..
make
现在,您可以通过从顶级目录运行make来构建释放模式的Kiteshield。另外,您可以使用make debug创建调试构建。 Kiteshield的调试构建禁用所有反欺骗功能,并打开装载机的非常详细的调试记录。
为了调试实际的反欺骗功能,您可以在调试模式下构建Kiteshield,使用反欺骗功能打开使用make debug-antidebug 。
要打包一个名为program的二进制文件并输出包装的二进制文件packed.ks ,运行:
./packer/kiteshield program packed.ks
现在可以运行packed.ks ,并且应该在功能上等同于program ,但已加密且难以反向工程师。请注意,对于要应用的第2层加密,当Kiteshield依赖于存在的符号表时,不得将输入二进制剥离。在大多数Linux发行版中,标准系统实用程序(例如/bin/ls )通常被剥离。
但是,您仍然可以使用-n标志包装剥离的二进制文件,而无需第2层加密:
./packer/kiteshield -n program packed.ks
这将产生仅使用第1层加密和运行时引擎的输出二进制填充。
Kiteshield由两个单独的部分组成。包装器是一个常规的C应用程序,可读取,仪器和加密输入二进制文件。加载程序是负责动态功能解密和反欺骗功能的独立c应用程序,该功能被包装器注入输入二进制文件。它从内核接收初始控件,将二进制的所有适当段映射到内存中(包括适用的动态链接器),然后将控制权移交给应用程序。加载程序还包含运行时引擎,该引擎在输入并在运行时退出时动态解密和加密功能。
由于加载程序从内核接收初始控件(即。
包装器和加载程序代码分别可以在packer/和loader/ Directories中找到。两者共有的代码可以在common/目录中找到。代码库重要部分的高级概述如下:
kiteshield
├── common # Code common to packer/loader
│ ├── include
│ │ ├── defs.h
│ │ ├── obfuscation.h
│ │ └── rc4.h
│ ├── obfuscation.c # Obfuscation utilities
│ └── rc4.c # RC4 stream cipher implementation
├── LICENSE
├── loader # Loader code
│ ├── anti_debug.c # Anti-debugging functionality
│ ├── bin_to_header.py # Script to "headerize" a compiled loader
│ ├── entry.S # Loader entry point code
│ ├── include
│ │ ├── anti_debug.h
│ │ ├── debug.h
│ │ ├── elf_auxv.h
│ │ ├── errno.h
│ │ ├── malloc.h
│ │ ├── obfuscated_strings.h # Generated file produced by string_obfuscation.py
│ │ ├── signal.h
│ │ ├── string.h
│ │ ├── syscalls.h
│ │ └── types.h
│ ├── link.lds # Custom linker script for building loader
│ ├── loader.c # Binary loading/mapping code (userspace exec)
│ ├── Makefile
│ ├── malloc.c # Freestanding malloc/free implementation
│ ├── runtime.c # Main body of runtime engine code
│ ├── string.c # String processing utilities (eg. strncat)
│ ├── string_obfuscation.py # String obfuscation helper script
│ ├── syscalls.c # System call implementations in inline assembly
│ └── test # Loader unit tests
│ ├── attounit.h
│ ├── Makefile
│ ├── test_main.c
│ ├── test_malloc.c
│ └── test_rc4.c
├── Makefile
├── packer # Packer code
│ ├── bddisasm # Bitdefender x86-64 disassembler library (submodule)
│ ├── elfutils.c # ELF binary reading/writing utilities
│ ├── include
│ │ └── elfutils.h
│ ├── kiteshield.c # Main body of packer code
│ └── Makefile
├── README.md
└── testing # Integration tests (see testing/README.md)
Kiteshield将RC4加密的两个(如果使用-n标志)层将输入Elf二进制文件包装在两个(或一个,如果使用-n标志)层,以使磁盘上的二进制二进制相当混淆。这些层在运行时被装载机剥离。
加密的第一层(在代码库中称为“外层”)由单个RC4通过整个输入二进制组成。这主要是为了对抗静态分析。由于钥匙的方式被去除(取决于加载器代码),因此加密的第一层在执行包装的二进制之前还有效地检查了加载程序代码,从而使Kiteshield抗代码修补。
加密的第二层(在代码库中称为“内层”)由单个对输入二进制中几乎每个函数的加密组成(通过包装时的符号表识别)。每个功能条目都会触发基于PTRACE的运行时引擎,并通过更换每个功能的输入说明及其所有返回指令退出int3指令(执行时会提供SIGTRAP )。收到陷阱后,运行时引擎查找当前功能,并根据需要对其进行加密或解密,以便在当前呼叫堆栈中的功能在任何时间点都被解密。
剥离第1层后,机式避难所有效地重新插入了用户空间中的exec (请参阅loader/loader.c 。在文献中通常称为“用户空间exec”或“ userland exec”。以通过一系列mmap / MMAP / mprotect CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE CORTINE BRIANDER(the Chord of Croun)映射到包装的二进制中。使用ptrace的孩子)。
除了加密外,Kiteshield的加载程序代码还包含许多抗干吊销功能,旨在使分析运行的包装二进制的功能尽可能困难(请参阅loader/anti_debug.c和loader/include/anti_debug.h )。
为了给基特岛的具体示例,请考虑以下Hello World程序,我们将在调试模式下与Kiteshield打包。
#include <stdio.h>
int main ()
{
puts ( "Hello World!" );
return 0 ;
}在调试模式下包装时,包装二进制文件中的加载器代码将记录非常详细的调试信息。以下是与上述程序相对应的包装二进制的日志。它已被注释(并为清晰而添加了其他新线),以提供基特岛的具体示例:
$ ./packed.ks
# Runtime startup
[kiteshield] starting ptrace runtime
[kiteshield] number of trap points: 5
[kiteshield] number of encrypted functions: 3
# List of points in memory that have been instrumented with an int3 instruction
[kiteshield] list of trap points:
[kiteshield] 8000011ac value: c3, type: ret, function: __libc_csu_init (#0)
[kiteshield] 800001150 value: 41, type: ent, function: __libc_csu_init (#0)
[kiteshield] 800001050 value: 31, type: ent, function: _start (#1)
[kiteshield] 80000114b value: c3, type: ret, function: main (#2)
[kiteshield] 800001135 value: 55, type: ent, function: main (#2)
# Runtime has started and is waiting on the packed app, begin mapping binary
# Stripping layer one encryption
[kiteshield] RC4 decrypting binary with key 85e19ad41fb8cc13e87e3cd1589a45fb
[kiteshield] decrypted 12336 bytes
# Mapping segments from packed binary program header table
[kiteshield] mapping LOAD section from packed binary at 800000000
[kiteshield] mapping LOAD section from packed binary at 800001000
[kiteshield] mapping LOAD section from packed binary at 800002000
[kiteshield] mapping LOAD section from packed binary at 800003000
# Mapping dynamic linker specified in INTERP header of packed binary
[kiteshield] mapping INTERP ELF at path /lib64/ld-linux-x86-64.so.2
[kiteshield] mapped LOAD section from fd at b00000000
[kiteshield] interpreter base address is b00000000
[kiteshield] mapped LOAD section from fd at b00001000
[kiteshield] mapped LOAD section from fd at b0001f000
[kiteshield] mapped extra space for static data (.bss) at b00029000 len 400
[kiteshield] mapped LOAD section from fd at b00027000
[kiteshield] binary base address is 800000000
# Modifying ELF auxiliary vector as needed for program execution
[kiteshield] taking 7ffff2997c60 as auxv start
[kiteshield] replaced auxv entry 9 with value 34359742544 (0x800001050)
[kiteshield] replaced auxv entry 3 with value 34359738432 (0x800000040)
[kiteshield] replaced auxv entry 7 with value 47244640256 (0xb00000000)
[kiteshield] replaced auxv entry 5 with value 11 (0xb)
[kiteshield] finished mapping binary into memory
[kiteshield] control will be passed to packed app at b00001090
# Mapping done
# Runtime attaches to the packed application with ptrace
[kiteshield] child is traced, handing control to packed binary
# Program is executing, functions are logged on entry/exit
[kiteshield] tid 13508: entering encrypted function _start decrypting with key 74c974f9d097e5a8c60049c3842c6110
[kiteshield] tid 13508: entering encrypted function __libc_csu_init decrypting with key 9124511baa87daa76c09b2426355dfca
[kiteshield] tid 13508: leaving function __libc_csu_init for address 7fa9a821d02a (no function record) via ret at 8000011ac
[kiteshield] tid 13508: entering encrypted function main decrypting with key 2f1c20e77ff3617b0b89a579669aba48
# Actual program output
Hello World!
# Packed application returns from main() and exits
[kiteshield] tid 13508: leaving function main for address 7fa9a821d09b (no function record) via ret at 80000114b
[kiteshield] tid 13508: exited with status 0
[kiteshield] all threads exited, exiting
Kiteshield有一系列广泛的集成测试,可以验证几个不同平台的正确性。有关详细信息,请参见testing/README.md 。
Kiteshield的写作是构想的,而不是速度。在每个功能入口处捕获Kiteshield运行时,并且出口非常昂贵。包装有第2层加密的程序应期望遭受严重的性能。
MIT©Rhys Rustad-Elliott