Linux의 X86-64 ELF Binaries 용 패커/보호자. Kiteshield는 ELF Binaries를 여러 계층의 암호화로 감싸고 사용자 공간에서 포장 된 이진을 완전히 해독,지도 및 실행하는 로더 코드를 주입합니다. PTRACE 기반 런타임 엔진은 현재 콜 스택의 기능 만 주어진 시간에 해독하고 추가로 포장 된 바이너리를 최대한 역 엔지니어로 만들기 위해 다양한 방지 방지 기술을 구현하도록합니다. 단일 및 멀티 스레드 바이너리 모두 지원됩니다.
Kiteshield의 작동 방식에 대한 조감도는 아래의 아키텍처 및 코드베이스 레이아웃 섹션을 참조하십시오.
Kiteshield는 소스 코드가 주어지면 실제 세계에서 사용할 수있는 것이 아니라 이진 난독 화에서 재미있는 학업 운동이되어 공개적입니다.
11 세기에 Normans가 선호하는 방패로 지명되었습니다 (또는 구식 Runescape에서 널리 퍼져있는 Kiteshields).
Kiteshield는 BitDefender Disassembler 라이브러리가 Packer의 지침을 해독해야합니다. packer/bddisasm 에서 서브 모듈로 포함됩니다. 신선한 클론에서 구축하려면 다음을 실행하십시오 (참고 CMAKE를 설치해야합니다).
git submodule update --init
cd packer/bddisasm
mkdir build
cd build
cmake ..
make
이제 최상위 디렉토리에서 make 실행하여 릴리스 모드에서 KitEShield를 빌드 할 수 있습니다. 또는 make debug 로 디버그 빌드를 만들 수 있습니다. Kiteshield의 디버그 빌드는 모든 방지 방지 기능을 비활성화하고 로더의 매우 장황한 디버그 로깅을 켭니다.
실제 방지 방지 기능을 디버깅하려면 make debug-antidebug 사용하여 방지 기능을 켜진 상태에서 디버그 모드에서 KITESHIELD를 빌드 할 수 있습니다.
이진이라는 이진 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 응용 프로그램입니다. 커널에서 초기 제어를 받고 바이너리의 모든 적절한 세그먼트를 메모리에 맵핑하고 (해당되는 경우 동적 링커 포함) 응용 프로그램에 제어 할 수 있습니다. 로더에는 또한 런타임 엔진이 포함되어 있으며, 이는 런타임에 입력 및 종료 될 때 동적으로 암호화 및 암호화 기능을 동적으로 암호화하고 암호화합니다.
로더는 커널로부터 초기 제어를 수신하기 때문에 (즉, 공유 라이브러리가 일반적으로 동적 링커에 의해 매핑되기 전에) LIBC에 액세스 할 수 없으므로 LIBC가 제공하는 필요한 모든 기능은 로더 코드로 다시 구현됩니다.
패커 및 로더 코드는 각각 packer/ 및 loader/ 디렉토리에서 찾을 수 있습니다. 둘 다에 공통적 인 코드는 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 암호화의 2 개 (또는 -n 플래그를 사용하는 경우 1 개) 층의 엘프 바이너리를 입력하는 엘프 바이너리를 입력합니다. 이 레이어는 로더가 런타임에 제거됩니다.
암호화의 첫 번째 층 (코드베이스에서 "외부 레이어"로 지칭)은 전체 입력 바이너리에 대한 단일 RC4 패스로 구성됩니다. 이것은 주로 정적 분석과 싸우기 위해 설계되었습니다. 키가 deobfuscated (로더 코드에 의존하는) 방법으로 인해 첫 번째 암호화 레이어는 포장 된 바이너리를 실행하기 전에 로더 코드를 효과적으로 확인하여 Kiteshield가 코드 패치에 저항합니다.
암호화의 두 번째 층 (코드베이스에서 "내부 층"으로 언급)은 입력 바이너리 (팩 타임에서 기호 테이블을 통해 식별)에서 거의 모든 함수의 개별 암호화로 구성됩니다. PTRACE 기반 런타임 엔진은 모든 기능 입력에서 트리거되고 각 기능의 입력 명령어를 교체하고 모든 리턴 명령어를 int3 명령어 (실행시 SIGTRAP 전달 함)를 통해 종료됩니다. 트랩을 수신하면 런타임 엔진은 현재 함수를 조회하고 필요에 따라 암호화하거나 해독하여 현재 통화 스택 내의 기능 만 어느 시점에서 해독되도록합니다.
레이어 1을 벗기고 나면 Kiteshield는 사용자 공간에서 exec SYSCALL을 효과적으로 재 형성합니다 ( loader/loader.c 참조이 기술은 일반적으로 "사용자 공간 exec"또는 "userland exec"로 표시됩니다. 포장 된 바이너리를 일련의 mmap / mprotect 통화를 통해 포장 된 콜링을 통해 메모리를 메모리에 맵핑하고 포장 된 자녀에 대한 컨트롤을 통해 런닝 된 Binary and the Protending and the Protending in the Protending in the Protect를 통해 메모리에 메모리에 매핑합니다. ptrace 사용).
암호화 외에도 Kiteshield의 로더 코드에는 실행중인 이진을 분석하기가 어려워 지도록 설계된 여러 가지 방지 기능이 포함되어 있습니다 ( loader/anti_debug.c 및 loader/include/anti_debug.h ).
kiteshield의 구체적인 예를 들으려면 다음 Hello World 프로그램을 고려하십시오. Debug 모드에서 Kiteshield와 함께 포장 할 것입니다.
#include <stdio.h>
int main ()
{
puts ( "Hello World!" );
return 0 ;
}디버그 모드에 포장되면 포장 된 바이너리의 로더 코드는 매우 장황한 디버그 정보를 기록합니다. 다음은 위 프로그램에 해당하는 포장 된 이진의 로그입니다. kiteshield의 구체적인 예를 제공하기 위해 주석이 주석 (및 명확성을 위해 추가)되었습니다.
$ ./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 런타임을 갇히는 것은 매우 비쌉니다. Layer 2 암호화로 가득 찬 프로그램은 심각한 성능을 기대해야합니다.
MIT © Rhys Rustad-Elliott