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);
此次崩溃不同于前几次。
之前,采用的是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);
相关文章推荐
- 一个多线程问题引发的血案-(代码段执行完毕,子进程未执行完毕导致段错误)
- 导致vc程序崩溃的原因
- Linux下socket编程write()函数崩溃导致进程退出
- 在VC中实现一次执行一个进程,如果同时打开两个,则报该程序已经运行
- 利用远程线程将代码注入到目标进程中执行
- Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, &, disown)
- C程序fork进程导致PHP执行不退出
- 目标进程收到消息后崩溃
- 使用VC创建进程和执行命令行程序的方法
- 多进程导致 Application 多次执行的问题研究
- 究竟是什么导致了进程崩溃?
- PHPEXCEL导入数据库,执行到load导致系统崩溃问题
- centos 7.2系统bug导致HGDB后台进程崩溃,数据库无法访问
- VC程序调用MATCOM导致进程不自动结束的解决办法
- 执行一个shell脚本而导致虚拟机centos6崩溃,慎重使用root权限
- 异常信息:CLR无法从COM 上下文0x645e18 转换为COM上下文0x645f88,这种状态已持续60秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作.这种情况通常会影响到性能,甚至可能导致应用程序不响应或者使用的内存随时间不断累积
- 关于 AppDomain 未知异常导致进程崩溃的处理办法
- 格式程序VC中scanf/sscanf不支持%hhx格式,若使用将可能导致程序错误甚至崩溃
- 自定义widget导致Launcher进程崩溃
- VC程序调用MATCOM导致进程不自动结束的解决办法