本文演示如何对程序的CALL进行远程调用,实现顺序如下:
1.使用OpenProcess函数获取进程句柄,函数原型如下
HANDLE OpenProcess(
[in] DWORD dwDesiredAccess, 权限
[in] BOOL bInheritHandle, 继承句柄
[in] DWORD dwProcessId 进程ID
);
2.使用CreateRomteThread函数实现功能,函数原型如下
HANDLE CreateRemoteThread(
[in] HANDLE hProcess, 进程句柄
[in] LPSECURITY_ATTRIBUTES lpThreadAttributes, 安全描述符
[in] SIZE_T dwStackSize, 堆栈初始大小
[in] LPTHREAD_START_ROUTINE lpStartAddress, CALL具体地址
[in] LPVOID lpParameter, CALL的参数
[in] DWORD dwCreationFlags, 线程是否挂起
[out] LPDWORD lpThreadId 线程标识符
);
从上面的信息可知,目标程序call的内存地址为0x00CE101E,该call使用__cdecl调用约定,在X86环境中采取外平栈方式,这个call实现的功能是将[ebp+8]传给eax,然后将eax和0xCE7B30入栈,调用printf输出显示。通过平栈时的汇编指令(add esp, 0x4)可以看出这个call具有一个参数,并且上面也已经push了一个参数(十六进制数的64)
实现代码:
#include<stdio.h>
#include<windows.h>
HANDLE crossProcessCall1(DWORD pid, LPTHREAD_START_ROUTINE callAddress, LPVOID parameter) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
/*
CreateRemoteThread(
_In_ HANDLE hProcess, 进程句柄
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress, call地址
_In_opt_ LPVOID lpParameter, call参数
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
*/
HANDLE hThread = CreateRemoteThread(
hProcess,
NULL,
0,
callAddress,
parameter,
0,
NULL
);
if (hThread != NULL) return hThread;
else return 0;
}
int main() {
DWORD pid = 45272;
UINT_PTR callAddress = 0x00CE101E;
crossProcessCall1(pid, (LPTHREAD_START_ROUTINE)callAddress, (LPVOID)50);
getchar();
return 0;
}
此时运行目标程序,可以看到此程序输出了100(十六进制的64)
此时运行刚刚编写的调用call代码后,程序call成功被调用,输出了50。
评论: