2008年12月14日星期日

由CreateRemoteThread引起的一个小问题

  昨晚在写CRemoteInject类的时候,添加了一个返回目标进程中前先注入的DLL的Base Address的函数,代码如下:

CODE:

//=========================================
// 函数名: GetPrevDllBaseAddr
// 输  入: dwPID(DWORD) - 目标进程的PID值
// 输  出: BYTE* - 成功DLL的BaseAddr, 失败FALSE
// 功  能: 得到目标进程中先前注入的DLL的BaseAddr
//=========================================
DWORD CRemoteInject::GetPrevDllBaseAddr(DWORD dwPID)
{
 HANDLE hSnapShot = NULL; 
 MODULEENTRY32 ModEntry;
 BOOL bRet = FALSE;
 DWORD dwRet = FALSE;

 // 同样得先初始化大小
 ModEntry.dwSize = sizeof(MODULEENTRY32);
 ASSERT(dwPID);
 hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
 ASSERT(hSnapShot);
 // 取回第一条快照
 bRet = Module32First(hSnapShot, &ModEntry);
 bool bFound = FALSE;

 while (bRet)
 {
  bFound = (0 == lstrcmpi((LPCTSTR)m_sDllPath, ModEntry.szExePath));
 
  if (bFound)
  {
   dwRet = (DWORD)ModEntry.modBaseAddr;
   break;
  }

  bRet = Module32Next(hSnapShot, &ModEntry);
 }

 CloseHandle(hSnapShot);
 return dwRet;
}

  如上代码所示,成功返回BaseAddress,失败返回FALSE。但是当我测试UnInject的代码的时候,发现即使我没注入DLL,UnInject也返回TRUE。于是我下断点调试,发现一个很有意思的问题。

  dwDllBaseAddr为0,但是CreateRemoteThread能够正常创建,所以最终导致返回值是TRUE。后来翻翻MSDN,发现下面一段话:

CODE:

Note that CreateRemoteThread may succeed even if lpStartAddress points to data, code, or is not accessible. If the start address is invalid when the thread runs, an exception occurs, and the thread terminates. Thread termination due to a invalid start address is handled as an error exit for the thread's process. This behavior is similar to the asynchronous nature of CreateProcess, where the process is created even if it refers to invalid or missing dynamic-link libraries (DLL).

也就是说,即使lpStartAddress不正确,CreateRemoteThread也可能执行成功。更何况我传的参数都正确。而dwBaseAddr的0值,只会影响FreeLibrary,即使FreeLibrary返回0,也已经和CreateRemoteThread无关了,毕竟线程已经创建完毕了。

  解决方法也很简单,在GetPrevDllBaseAddr之后,检查下返回值即可。

没有评论:

发表评论

1、可以使用<b>、<i>、<a>等Html标志,让评论更有特色...
2、支持OpenID登录,技术达到国际先进水平。但切记,评论内容不代表本站观点!
3、当遇到“连接被重置”、“连接超时”和“此网页无法访问”等而发表不了评论的话,请多刷新几次页面,或迟三分钟后再试;
4、对你的浏览造成不便,站长在此代表全国G.FW工作人员向你鞠躬致歉!!!