
x86, x64, 또는 AMD64+x86 포지션 독립적 셸코드를 생성하여, 메모리에서 .NET 어셈블리, PE 파일 및 기타 Windows 페이로드를 로드하고 매개변수와 함께 실행합니다.

현재 버전: v1.1
Donut은 VBScript, JScript, EXE, DLL 파일 및 dotNET 어셈블리를 메모리에서 실행할 수 있게 해주는 위치 독립적 코드입니다. Donut으로 생성된 모듈은 HTTP 서버에서 스테이징하거나 로더 자체에 직접 포함시킬 수 있습니다. 모듈은 선택적으로 Chaskey 블록 암호와 128비트 무작위 생성 키를 사용하여 암호화됩니다. 파일이 메모리에 로드되어 실행된 후에는 원본 참조가 지워져 메모리 스캐너를 탐지하기 어렵게 합니다. 생성기와 로더는 다음 기능을 지원합니다:
Linux 및 Windows용 동적 및 정적 라이브러리가 있으며, 이를 자신의 프로젝트에 통합할 수 있습니다. 또한 Python 확장 빌드 및 사용에 대한 자세한 내용을 확인할 수 있는 Python 모듈도 있습니다.
Donut은 지원되는 각 파일 유형에 대한 개별 로더를 포함합니다. dotNET EXE/DLL 어셈블리의 경우, Donut은 Unmanaged CLR Hosting API를 사용하여 공용 언어 런타임(CLR)을 로드합니다. CLR이 호스트 프로세스에 로드되면 새 애플리케이션 도메인이 생성되어 폐기 가능한 AppDomain에서 어셈블리를 실행할 수 있습니다. AppDomain이 준비되면 dotNET 어셈블리는 AppDomain.Load_3 메서드를 통해 로드됩니다. 마지막으로, EXE의 진입점 또는 사용자가 지정한 DLL의 public 메서드가 추가 매개변수와 함께 호출됩니다. Unmanaged CLR Hosting API에 대한 자세한 내용은 MSDN 문서를 참조하세요. CLR 호스트의 독립 실행형 예제는 여기 코드를 참조하세요.
VBScript 및 JScript 파일은 IActiveScript 인터페이스를 사용하여 실행됩니다. Windows Script Host(wscript/cscript)가 제공하는 일부 메서드에 대한 최소한의 지원도 있습니다. 독립 실행형 예제는 여기 코드를 참조하세요. 더 자세한 설명은 JavaScript, VBScript, JScript 및 XSL의 메모리 내 실행을 읽어보세요.
관리되지 않는 또는 네이티브 EXE/DLL 파일은 지연 가져오기, TLS 및 명령줄 패치를 지원하는 사용자 정의 PE 로더를 사용하여 실행됩니다. 재배치 정보가 있는 파일만 지원됩니다. 자세한 내용은 DLL의 메모리 내 실행을 읽어보세요.
로더는 AMSI 및 WLDP를 비활성화하여 메모리에서 실행되는 악성 파일 탐지를 회피하는 데 도움을 줄 수 있습니다. 자세한 내용은 레드 팀이 .NET 동적 코드에 대해 AMSI 및 WLDP를 우회하는 방법을 읽어보세요. 또한 aPLib 또는 RtlDecompressBuffer API를 사용하여 메모리에서 파일 압축 해제를 지원합니다. 자세한 내용은 데이터 압축을 읽어보세요.
v1.0부터 ETW도 우회됩니다. AMSI/WLDP와 마찬가지로, 기본 우회를 자신의 것으로 교체할 수 있는 모듈식 시스템입니다. 기본 우회는 XPN의 연구에서 파생되었습니다. 자세한 내용은 .NET 숨기기 - ETW를 읽어보세요.
기본적으로 로더는 관리되지 않는 PE의 PE 헤더(기본 주소부터 `IMAGE_OPTIONAL_HEADER.SizeOfHeaders`까지)를 덮어씁니다. 디코이 모듈이 사용되지 않으면(모듈 오버로딩) PE 헤더는 0으로 설정됩니다. 디코이 모듈이 사용되면 디코이 모듈의 PE 헤더가 페이로드 모듈의 헤더를 덮어쓰는 데 사용됩니다. 이는 메모리 내 모듈의 PE 헤더와 디스크에 있는 파일을 비교하는 탐지를 방지하기 위함입니다. 사용자는 모든 PE 헤더를 원래 상태로 유지하도록 요청할 수 있습니다. 이는 페이로드 모듈이 포함된 PE 리소스 조회와 같이 PE 헤더에 접근해야 하는 시나리오에서 유용합니다.
생성기 사용 및 Donut이 전술에 미치는 영향에 대한 자세한 설명은 Donut - .NET 어셈블리를 셸코드로 삽입을 읽어보세요. 로더에 대한 자세한 내용은 메모리에서 .NET 어셈블리 로드를 읽어보세요.
내부 구조에 대해 더 알고 싶은 분들은 개발자 노트를 참조하세요.
두 가지 유형의 빌드가 있습니다. Donut을 디버깅하려면 여기 문서를 참조하세요. 그렇지 않다면 릴리스 빌드를 위해 계속 읽으세요.
Windows 명령 프롬프트 또는 Linux 터미널에서 저장소를 클론합니다.
git clone http://github.com/thewover/donut.git
다음 단계는 운영 체제와 사용할 컴파일러에 따라 다릅니다. 현재 Donut의 생성기 및 로더 템플릿은 Microsoft Visual Studio 2019 및 MingGW-64 모두에서 성공적으로 컴파일할 수 있습니다. 자신의 C/C++ 프로젝트에서 라이브러리를 사용하려면 여기 제공된 예제를 참조하세요.
로더 템플릿, 동적 라이브러리 donut.dll, 정적 라이브러리 donut.lib 및 생성기 donut.exe를 생성하려면 x64 Microsoft Visual Studio 개발자 명령 프롬프트를 시작하고 Donut 저장소를 클론한 디렉터리로 변경한 후 다음을 입력하세요:
nmake -f Makefile.msvc
Windows 또는 Linux에서 MinGW-64를 사용하여 동일한 작업을 수행하려면 Donut 저장소를 클론한 디렉터리로 변경한 후 다음을 입력하세요:
make -f Makefile.mingw
동적 라이브러리 donut.so, 정적 라이브러리 donut.a 및 생성기 donut을 생성하려면 Donut 저장소를 클론한 디렉터리로 변경하고 간단히 make를 입력하세요.
Donut은 Python 모듈로 설치 및 사용할 수 있습니다. 소스에서 설치하려면 Python3용 pip가 필요합니다. 먼저, Linux 터미널 또는 Microsoft Visual Studio 명령 프롬프트에서 다음 명령을 실행하여 이전 버전의 donut-shellcode가 설치되지 않았는지 확인하세요.
pip3 uninstall donut-shellcode
이전 버전이 더 이상 설치되지 않았음을 확인한 후 다음 명령을 실행하세요.
pip3 install .
PyPi 저장소에서 가져와 Donut을 Python 모듈로 설치할 수도 있습니다.
pip3 install donut-shellcode
자세한 내용은 Python 확장 빌드 및 사용을 참조하세요.
Docker 컨테이너 빌드.
docker build -t donut .
Donut 실행.
docker run -it --rm -v "${PWD}:/workdir" donut -h
Donut에는 별도로 빌드할 수 있는 몇 가지 다른 실행 파일이 포함되어 있습니다. 여기에는 "hash.exe", "encrypt.exe", "inject.exe", "inject_local.exe"가 있습니다. 처음 두 개는 셸코드 생성에 사용됩니다. 나머지 두 개는 Donut 셸코드 테스트를 지원하기 위해 제공됩니다. "inject.exe"는 원시 바이너리 파일(loader.bin)을 PID 또는 프로세스 이름으로 프로세스에 주입합니다. "inject_local.exe"는 원시 바이너리 파일을 자신의 프로세스에 주입합니다.
이러한 지원 실행 파일을 별도로 빌드하려면 MSVC makefile을 사용할 수 있습니다. 예를 들어, Donut 셸코드를 테스트하기 위해 "inject_local.exe"를 빌드하려면 다음을 실행할 수 있습니다.
nmake inject_local -f Makefile.msvc
Donut의 각 릴리스 버전에 대해 컴파일된 실행 파일이 포함된 태그가 제공되었습니다.