以前也曾多次提到远程线程注入导致进程崩溃的现象。

此次崩溃不同于前几次。

之前,采用的是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);