您的位置:首页 > 编程语言

VC:执行远程线程注入的代码段导致目标进程崩溃

2010-04-26 17:44 302 查看
以前也曾多次提到远程线程注入导致进程崩溃的现象。
此次崩溃不同于前几次。
之前,采用的是dll注入的方式,注入后,由于同一个dll文件在不同的进程中映射的基地址不同,导致远程线程函数的入口地址不同,以至崩溃,这种情况,多数是本进程采用静态链接加载待远程注入的dll文件,而其他进程则动态加载该dll文件,两次加载将在内存中产生两个dll实例。
此次,需要向远程进程注入代码段,远程线程函数入口地址正确。测试时,为了方便,特地增加了一个消息框MessageBox,远程线程函数仅仅调用这个弹出消息框的函数,然后退出。结果,消息框正常弹出,但是,当点击确定退出消息框后,目标进程立即崩溃。原因不明。

200807210756注:
实在不知道问题出哪儿了,于是就想看看注入的VC代码对应的反汇编代码,这时,忽然想到一点,即:我都是在Debug模式下执行的,这可能会有问题。
进一步思考。Debug版本和Release版本最大的不同在于,每次调用一个函数后,Debug版本会进行堆栈检测。而目标进程显然是处于release模式,此时,如果注入的是Debug版本的代码,那么,调用函数之后,会有一句检测堆栈的机器指令,这很可能就是进程崩溃的原因所在。
于是,改为release环境测试,一切正常!OK!

(我用控制台程序实现时没有问题,用MFC程序实现就有问题,因此发现以上内容,将Debug版改为Release版就没问题了)
另附上远程注入的主要代码段,供参考,有问题望指教!!!

#include "windows.h"
#include <string.h>
#include "stdio.h"
#include "Shlwapi.h"
#include "tlhelp32.h"
#include "Psapi.h"
#include <TChar.h>
#pragma comment(lib,"Psapi.lib")
#pragma comment(lib,"Shlwapi.lib")
//参数结构 ;
typedef struct _RemotePara{
DWORD dwExitProcessFunc;
}RemotePara;
// 远程线程执行体
DWORD __stdcall ThreadProc(RemotePara *Para){
typedef void (__stdcall *pExitProcess) ( UINT );
pExitProcess ExitProcessFunc = (pExitProcess)Para->dwExitProcessFunc;
ExitProcessFunc(0);
return 0 ;
}
BOOL EnablePrivilege(HANDLE hToken,LPCTSTR szPrivName,BOOL fEnable)
{
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL,szPrivName,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes = fEnable ? SE_PRIVILEGE_ENABLED:0;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
return((GetLastError() == ERROR_SUCCESS));
}
DWORD GetPidByName(char *szName)
{
HANDLE hProcessSnap = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe32={0};
DWORD dwRet=0;
hProcessSnap =CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap == INVALID_HANDLE_VALUE)
return 0;
pe32.dwSize = sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap, &pe32))
{
do
{
if(StrCmpNI(szName,pe32.szExeFile,strlen(szName))==0)
{
dwRet=pe32.th32ProcessID;
break;
}
}while (Process32Next(hProcessSnap,&pe32));
}
else
return 0;
if(hProcessSnap != INVALID_HANDLE_VALUE)
CloseHandle(hProcessSnap);
return dwRet;
}
int main()
{
// DeleteFile("D://BioFileLogOp.dll");
const DWORD THREADSIZE=1024*4;
DWORD pID;
DWORD byte_write;
HANDLE hToken,hRemoteProcess,hThread;
RemotePara myRemotePara,*pRemotePara;
void *pRemoteThread;
HINSTANCE hUser32 ;
char szSafePath[MAX_PATH] = {"C://Program Files//Safe Office//oem//BioFileLogOp.dll"};
char szKxPath[MAX_PATH] = {"C://Program Files//KeXin WPS Office//oem//BioFileLogOp.dll"};
HANDLE hSafeFind;
HANDLE hKxFind;
WIN32_FIND_DATA FindFileData,FindKxFileData;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken); //打开进程
EnablePrivilege(hToken,SE_DEBUG_NAME,TRUE); //提升为调试权限
// 获得指定进程句柄,并设其权限为PROCESS_ALL_ACCESS
pID = GetPidByName("KxIdentifyServer.exe");
if(pID == 0)
{
return 0;
}
hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pID);
if(!hRemoteProcess)
return 0;
// 在远程进程地址空间分配虚拟内存
pRemoteThread = VirtualAllocEx(hRemoteProcess, 0, THREADSIZE, MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
if(!pRemoteThread)
return 0;
// 将线程执行体ThreadProc写入远程进程
if(!WriteProcessMemory(hRemoteProcess, pRemoteThread, &ThreadProc, THREADSIZE,0))
return 0;
ZeroMemory(&myRemotePara,sizeof(RemotePara));
hUser32 = LoadLibrary("kernel32.dll");
myRemotePara.dwExitProcessFunc = (DWORD)GetProcAddress(hUser32, "ExitProcess");
//写进目标进程
pRemotePara =(RemotePara *)VirtualAllocEx (hRemoteProcess ,0,sizeof(RemotePara),MEM_COMMIT,PAGE_READWRITE);
if(!pRemotePara)
return 0;
if(!WriteProcessMemory (hRemoteProcess ,pRemotePara,&myRemotePara,sizeof myRemotePara,0))
return 0;
// 启动线程
hThread = CreateRemoteThread(hRemoteProcess ,0,0,(DWORD (__stdcall *)(void *))pRemoteThread ,pRemotePara,0,&byte_write);
FreeLibrary(hUser32);
CloseHandle(hRemoteProcess);
CloseHandle(hToken);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐