目录

跨进程

跨进程分配内存

概览


VirtualAlloc

1
2
3
4
5
6
LPVOID VirtualAlloc(
  [in, optional] LPVOID lpAddress,	//要分配的内存的起始地址
  [in]           SIZE_T dwSize,	//内存大小,以字节为单位
  [in]           DWORD  flAllocationType,	//内存分配的类型
  [in]           DWORD  flProtect	//要分配的页面区域的内存保护
);

VirtualFree

1
2
3
4
5
BOOL VirtualFree(
  [in] LPVOID lpAddress,	//指向要释放内存地址的指针
  [in] SIZE_T dwSize,	//要释放的内存区域的大小,以字节为单位
  [in] DWORD  dwFreeType	//释放的类型
);

VirtualAllocEx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
LPVOID VirtualAllocEx(
  [in]           HANDLE hProcess,	//申请内存所在的进程句柄
  [in, optional] LPVOID lpAddress,	//保留页面的内存地址;一般用NULL自动分配 
  [in]           SIZE_T dwSize,	//欲分配的内存大小,字节单位;注意实际分 配的内存大小是页内存大小的整数倍
  [in]           DWORD  flAllocationType,	//一般用MEM_COMMIT
  [in]           DWORD  flProtect	//一般用PAGE_READWRITE(读写)
);

//实例			
	LPVOID 目标进程内存地址 = VirtualAllocEx(进程句柄,NULL,1024,MEM_COMMIT,PAGE_EXECUTE_READWRITE);

flAllocationType 可取下列值:

  • MEM_COMMIT:为特定的页面区域分配内存中或磁盘的页面文件中的物理存储
  • MEM_PHYSICAL :分配物理内存(仅用于地址窗口扩展内存)
  • MEM_RESERVE:保留进程的虚拟地址空间,而不分配任何物理存储。保留页面可通过继续调用VirtualAlloc()而被占用
  • MEM_RESET :指明在内存中由参数lpAddress和dwSize指定的数据无效
  • MEM_TOP_DOWN:在尽可能高的地址上分配内存(Windows 98忽略此标志)
  • MEM_WRITE_WATCH:必须与MEM_RESERVE一起指定,使系统跟踪那些被写入分配区域的页面(仅针对Windows 98)

flProtect 可取下列值

  • PAGE_READONLY: 该区域为只读。如果应用程序试图访问区域中的页的时候,将会被拒绝访

  • PAGE_READWRITE 区域可被应用程序读写

  • PAGE_EXECUTE: 区域包含可被系统执行的代码。试图读写该区域的操作将被拒绝。

  • PAGE_EXECUTE_READ :区域包含可执行代码,应用程序可以读该区域。

  • PAGE_EXECUTE_READWRITE: 区域包含可执行代码,应用程序可以读写该区域。

  • PAGE_GUARD: 区域第一次被访问时进入一个STATUS_GUARD_PAGE异常,这个标志要和其他保护标志合并使用,表明区域被第一次访问的权限

  • PAGE_NOACCESS: 任何访问该区域的操作将被拒绝

  • PAGE_NOCACHE: RAM中的页映射到该区域时将不会被微处理器缓存(cached)

    注:PAGE_GUARD和PAGE_NOCHACHE标志可以和其他标志合并使用以进一步指定页的特征。PAGE_GUARD标志指定了一个防护页(guard page),即当一个页被提交时会因第一次被访问而产生一个one-shot异常,接着取得指定的访问权限。PAGE_NOCACHE防止当它映射到虚拟页的时候被微处理器缓存。这个标志方便设备驱动使用直接内存访问方式(DMA)来共享内存块。


VirtualFreeEx

1
2
3
4
5
6
BOOL VirtualFreeEx(
  [in] HANDLE hProcess,	//进程句柄
  [in] LPVOID lpAddress,	//指向要释放内存地址的指针
  [in] SIZE_T dwSize,	//要释放的内存区域的大小,以字节为单位
  [in] DWORD  dwFreeType	//释放的类型
);

lpAddress

​ 指向要释放的虚拟内存空间首地址的指针

​ 如果 dwFreeType 为 MEM_RELEASE, 则该参数必须为VirtualAllocEx的返回值.

dwSize

​ 虚拟内存空间的字节数

​ 如果 dwFreeType 为 MEM_RELEASE,则 dwSize 必须为0 . 按 VirtualAllocEx申请时的大小全部释放。

​ 如果dwFreeType 为 MEM_DECOMMIT, 则释放从lpAddress 开始的一个或多个字节 ,即 lpAddress +dwSize。

dwFreeType

​ 释放类型,取值见下表:

释义
MEM_DECOMMIT 0x400016384D 这种试 仅标示 内存空间不可用,内存页还将存在。
MEM_RELEASE 0x800032768D 这种方式 很彻底,完全回收。

跨进程读写

[WriteProcessMemory](句柄 进程 模块 读写.md)

[ReadProcessMemory](句柄 进程 模块 读写.md)

跨进程调用代码

1
2
3
4
5
6
7
8
9
HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,	//目标进程句柄
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,	//指针,一般设置为NULL
  [in]  SIZE_T                 dwStackSize,	//纯种堆栈大小,一船设置为0,表示默认为1M
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,	//线程函数的地址(目标进程代码地址)
  [in]  LPVOID                 lpParameter,	//线程参数
  [in]  DWORD                  dwCreationFlags,	//线程的创建标志
  [out] LPDWORD                lpThreadId	//输出参数,记录创建的远程线程的ID,不输出可传NULL
);

线程的创建标志.

含义
0 线程创建后立即运行
CREATE_SUSPENDED
0x00000004
线程创建后先将线程挂起,直到 ResumeThread 被调用.
STACK_SIZE_PARAM_IS_A_RE
SERVATION
0x00010000
dwStackSize 参数指定为线程栈预订大小,如果STACK_SIZE_PARAM_IS_A_RESERVATION没有被指定,dwStackSize 参数指定为线程栈分配大小.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//实例

UINT64 nRet64 =0;
DWORD lpExitCode=0;

HWND 窗口句柄 = FindWindowA("WTWindow","Wow");
DWORD 进程PID =0;
GetWindowThreadProcessId(窗口句柄,&进程PID);
HANDLE 进程句柄 = OpenProcess(PROCESS_ALL_ACCESS,  FALSE,进程PID);

//在目标进程分配内存
LPVOID 目标进程内存地址=VirtualAllocEx(进程句柄,NULL,1024,MEM_COMMIT,PAGE_EXECUTE_READWRITE);

SIZE_T nWriten =0;//用于返回实际写入字节数

//写入要注入的DLL的路径		
BOOL br = WriteProcessMemory(进程句柄,目标进程内存地址,dllFullPathName,strlen(dllFullPathName)+1, &nWriten);
			
HANDLE ht= CreateRemoteThread( 
				进程句柄, 
				NULL,
				0,//0x400000
				(LPTHREAD_START_ROUTINE)LoadLibraryA,//LoadLibraryA("c:\\123.dll")
				目标进程内存地址,//LoadLibraryA(目标进程内存地址)
				0,
				&tid
);