伊始
当我们目标应用程序由于需要使用外部其他应用程序指定,启动一些函数,比如计算空间使用大小,显示当前空间内成员使用率时,开关打印日志时,需要手动触发计算时,可以利用这个方案。
主体
一切都是为了需求而做,而我们需要的就是落地!。
那我们开始吧!
首先,我们要有一个要API函数,我们要以此函数作为接口,实现我们的需求。这里我们就以最简单MessageBox来作为接口。
理由如下:大部分程序都在加载“User32.dll”
而且因此我们很容易获取到MessageBox的地址。当然啦,我们也可以用我们自己的dll,不用系统的dll也可以啦,但这个涉及到dll注入技术。请参考我的博客DLL注入与安全
这里不做探讨啦!。
首先介绍用到了哪些东西。
序号 | API |
---|---|
1 | OpenProcess |
2 | VirtualAllocEx |
3 | WriteProcessMemory |
4 | CreateRemoteThread |
第一步:首先要找到我们业务程序的空间啦
打开进程函数
HANDLE WINAPI OpenProcess(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId
);
第二步:当然是为我们扩展的函数开辟内存空间
开辟空间API函数
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
);
第三步:我们需要把我们扩展的函数写入到开辟的空间中
写入API函数
BOOL WINAPI WriteProcessMemory(
_In_ HANDLE hProcess,
_In_ LPVOID lpBaseAddress,
_In_reads_bytes_(nSize) LPCVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_opt_ SIZE_T * lpNumberOfBytesWritten
);
第四步:我们需要为我们API函数,要传的参数开辟空间`
开辟空间函数
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect
第五步:写入我们要传入的参数
写入API函数
BOOL WINAPI WriteProcessMemory(
_In_ HANDLE hProcess,
_In_ LPVOID lpBaseAddress,
_In_reads_bytes_(nSize) LPCVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_opt_ SIZE_T * lpNumberOfBytesWritten
)
第六步:调用远程线程。执行我们的线程函数
远程线程函数
HANDLE WINAPI CreateRemoteThread(
_In_ HANDLE hProcess,
_In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_opt_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_opt_ LPDWORD lpThreadId
);
结束语
此文主要用来介绍多个应用程序之间的交互,方便手动控制API执行以检测内部运行情况。
最后附上部分代码
DWORD dwPid = 0;//这里输入PID
HANDLE hProcess=OpenProcess(PROCESS_ALL_ACCESS, 0, dwPid);
void* pRemoteThread = VirtualAllocEx(hProcess, 0, dwThreadSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!pRemoteThread)
{
MessageBox(NULL, TEXT("分配失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
//将线程体拷贝到宿主进程中
if (!WriteProcessMemory(hProcess, pRemoteThread, &threadProc, dwThreadSize, 0))
{
MessageBox(NULL, TEXT("拷贝失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
//定义线程参数结构体变量
RemoteParam remoteData;
ZeroMemory(&remoteData, sizeof(RemoteParam));
HMODULE hmod = LoadLibrary(TEXT("User32.dll"));
if (NULL == hmod)
{
MessageBox(NULL, TEXT("获取DLL失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
remoteData.dwMessageBox = (TypeMessageBoxW)GetProcAddress(hmod, "MessageBoxW");
wcscat_s(remoteData.szMsg, msg);
RemoteParam* pRemoteParam = (RemoteParam*)VirtualAllocEx(hProcess, 0, sizeof(RemoteParam), MEM_COMMIT, PAGE_READWRITE);
if (!pRemoteParam)
{
MessageBox(NULL, TEXT("分配空间失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
//将线程参数拷贝到宿主进程地址空间中
if (!WriteProcessMemory(hProcess, pRemoteParam, &remoteData, sizeof(remoteData), 0))
{
MessageBox(NULL, TEXT("写入失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
//在宿主进程中创建线程
HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (DWORD(__stdcall *)(void *))pRemoteThread, pRemoteParam, 0, &dwWriteBytes);
if (!hRemoteThread)
{
MessageBox(NULL, TEXT("开启远程线程失败!"), TEXT("Notice"), MB_ICONINFORMATION | MB_OK);
return;
}
您的赞就是我不断写干货的动力,请不要吝啬哦,让我们共同进步!
链接地址代码