为什么我的DllMain中的DLL_PROCESS_ATTACH没有执行?

WalkersChen 2009-08-24 05:30:23
本人照着《windows核心编程》中的"插入Dll和挂接API"里的例子DLL插入其他进程写了一遍,
但是DllMain中的所有分支并没有执行!(在switch( ul_reason_for_call )就加入断点)
换成本身进程的ID就可以正确执行,希望有大侠可以解答!
(在Visual Studio 2008环境下)
...全文
435 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
fishion 2009-08-25
  • 打赏
  • 举报
回复
汗一个先。。。。hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThread,
(LPVOID)pszLibFile, 0, NULL);加载错了
雪影 2009-08-25
  • 打赏
  • 举报
回复
hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThread,
(LPVOID)pszDllPath, 0, NULL);
第四个参数只不过是线程函数pfnThread的参数.和上面的问题有什么关系?

不过话有说回来,你传递pszDllPath字符串给远程线程函数pfnThread是不会成功的.因为你不能跨进程传递字符串指针.而pszLibPath指针是远程进程自己的字符串,因此传递pszLibPath可以成功.
WalkersChen 2009-08-25
  • 打赏
  • 举报
回复
哈哈!终于找到原因了!问题就出在"CreateRemoteThread"里的"pszDllPath"参数,
应该是"pszLibFile"!至于为什么,留给大家自己分析吧!^-^
(可以睡得着了......)
MoXiaoRab 2009-08-24
  • 打赏
  • 举报
回复
发个代码瞧瞧
fishion 2009-08-24
  • 打赏
  • 举报
回复
发代码吧
jyh_baoding 2009-08-24
  • 打赏
  • 举报
回复
帮顶
WalkersChen 2009-08-24
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 tr0j4n 的回复:]
引用 7 楼 tttyd 的回复:
你是使用WriteProcessMemory载入DLL文件的,当然不会调用了.
只有使用LoadLibrary或者LoadLibraryEx,载入DLL,才会调用.

这个是远程注入,会调用的

我怀疑楼主是死锁了。在DLL_PROCESS_ATTACH 中开辟线程很多时候都会死锁
[/Quote]

有什么解决方法吗?
MoXiaoRab 2009-08-24
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 tttyd 的回复:]
你是使用WriteProcessMemory载入DLL文件的,当然不会调用了.
只有使用LoadLibrary或者LoadLibraryEx,载入DLL,才会调用.
[/Quote]
这个是远程注入,会调用的

我怀疑楼主是死锁了。在DLL_PROCESS_ATTACH 中开辟线程很多时候都会死锁
雪影 2009-08-24
  • 打赏
  • 举报
回复
CreateRemoteThread创建新线程
会有DLL_THREAD_ATTACH 消息,你可以测试一下
雪影 2009-08-24
  • 打赏
  • 举报
回复
你是使用WriteProcessMemory载入DLL文件的,当然不会调用了.
只有使用LoadLibrary或者LoadLibraryEx,载入DLL,才会调用.
WalkersChen 2009-08-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 tttyd 的回复:]
插入到千千里并没有弹出MessageBox, 但在WM_CREATE里的把进程ID换成DllInject的ID就可以。
什么意思,没看到WM_CREATE啊.

你的想说的是不是MessageBox(NULL, TEXT("Dll Process Attach!"), NULL, MB_OK);没有运行?
[/Quote]

是啊!
雪影 2009-08-24
  • 打赏
  • 举报
回复
插入到千千里并没有弹出MessageBox, 但在WM_CREATE里的把进程ID换成DllInject的ID就可以。
什么意思,没看到WM_CREATE啊.

你的想说的是不是MessageBox(NULL, TEXT("Dll Process Attach!"), NULL, MB_OK);没有运行?
WalkersChen 2009-08-24
  • 打赏
  • 举报
回复
下面是主要代码,以插入DLL到千千静听为例子。
工程名为 DllInject.

BOOL WINAPI InjectDll(DWORD dwProcessID, LPCTSTR pszDllPath)
{
BOOL bSucceed = FALSE;
HANDLE hProcess = NULL, hThread = NULL;
LPCTSTR pszLibFile = NULL;
__try
{
hProcess = OpenProcess(PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwProcessID);
if( hProcess == NULL )
{
OutError();
__leave;
}
int cch = lstrlen(pszDllPath) + 1;
int cb = cch * sizeof(TCHAR);
pszLibFile = (LPCTSTR)VirtualAllocEx(hProcess, NULL, cb,
MEM_COMMIT, PAGE_READWRITE);
if( pszLibFile == NULL )
{
OutError();
__leave;
}
if( !WriteProcessMemory(hProcess, (PVOID)pszLibFile, (PVOID)pszDllPath,
cb, NULL) )
{
OutError();
__leave;
}
PTHREAD_START_ROUTINE pfnThread = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("kernel32")), "LoadLibraryW");
if( pfnThread == NULL )
{
OutError();
__leave;
}
hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThread,
(LPVOID)pszDllPath, 0, NULL);
if( hThread == NULL )
{
OutError();
__leave;
}
WaitForSingleObject(hThread, INFINITE);
bSucceed = TRUE;
}
__finally
{
if( pszLibFile != NULL )
VirtualFreeEx(hProcess, (LPVOID)pszLibFile, 0, MEM_RELEASE);
if( hThread != NULL )
CloseHandle(hThread);
if( hProcess != NULL )
CloseHandle(hProcess);
}

return bSucceed;
}



void OutError()
{
DWORD dwError = GetLastError();
LPVOID pBuffer = NULL;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&pBuffer,
0, NULL);
MessageBox(NULL, (LPCWSTR)pBuffer, NULL, MB_OK);
LocalFree(pBuffer);
}




// OnCreate
HWND hFrame = ::FindWindow(TEXT("TTPlayer_LyricWnd"), NULL);
if( !IsWindow(hFrame) )
return;
DWORD dwProcessID;
GetWindowThreadProcessId(hFrame, &dwProcessID);
TCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szName[_MAX_FNAME], szExt[_MAX_EXT];
TCHAR szText[MAX_PATH];
GetModuleFileName(NULL, szText, MAX_PATH);
_tsplitpath_s(szText, szDrive, szDir, szName, szExt);
memset(szText, 0, sizeof(szText));
swprintf_s(szText, TEXT("%s%s"), szDrive, szDir);
lstrcat(szText, TEXT("TTInject.dll"));
InjectDll(dwProcessID, szText);


Dll里面的代码:

BOOL DllMain(HMODULE hModule, DWORD dwReason, LPVOID pvReserve)
{
if( dwReason == DLL_PROCESS_ATTACH )
MessageBox(NULL, TEXT("Dll Process Attach!"), NULL, MB_OK);
return TRUE;
}

插入到千千里并没有弹出MessageBox, 但在WM_CREATE里的把进程ID换成DllInject的ID就可以。
最简单的dll并不比c的helloworld难,只要一个DllMain函数即可,包含objbase.h头文件(支持COM技术的一个头文件)。若你觉得这个头文件名字难记,那么用windows.H也可以。源代码如下:dll_nolib.cpp #include #include BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { HANDLE g_hModule; switch(dwReason) { case DLL_PROCESS_ATTACH: cout<<"Dll is attached!"<DLL_PROCESS_DETACH: cout<<"Dll is detached!"<DllMain是每个dll的入口函数,如同c的main函数一样。DllMain带有三个参数,hModule表示本dll的实例句柄(听不懂就不理它,写过windows程序的自然懂),dwReason表示dll当前所处的状态,例如DLL_PROCESS_ATTACH表示dll刚刚被加载到一个进程DLL_PROCESS_DETACH表示dll刚刚从一个进程卸载。当然还有表示加载到线程和从线程卸载的状态,这里省略。最后一个参数是一个保留参数(目前和dll的一些状态相关,但是很少使用)。 从上面的程序可以看出,当dll被加载到一个进程时,dll打印"Dll is attached!"语句;当dll从进程卸载时,打印"Dll is detached!"语句。 编译dll需要以下两条命令: cl /c dll_nolib.cpp 这条命令会将cpp编译为obj文件,若不使用/c参数则cl还会试图继续将obj链接为exe,但是这里是一个dll没有main函数,因此会报错。不要紧,继续使用链接命令。 Link /dll dll_nolib.obj 这条命令会生成dll_nolib.dll。 注意,因为编译命令比较简单,所以本文不讨论nmake,有兴趣的可以使用nmake,或者写个bat批处理来编译链接dll。 加载DLL(显式调用)
VS2010使用C++创建和使用DL.docx,文档加代码,全了。工程代码下载: 1.生成动态链接库(_declspec(dllexport)方式导出函数) 2.生成动态链接库(以.def文件(模块定义文件)方式导出函数) 3.以加载时动态链接方式调用DLL 4.以运行时动态链接方式调用DLL 5.以模块定义方式(.def文件)建立的动态链接库的调用 遇到的问题: 1.库导入的时候目录的问题。对应文的问题1,后面有解释。 2.字符集的问题(是Unicode字符集还是多字节集),两种方案,一种修改字符集为多字节集,二是将字符串前面加 _T(""),文问题2 3.不知道怎么通过模块定义文件方式生成DLL,通过看参考博客的代码找到了答案,主要修改头文件,和添加模块定义文件。 4.模块定义文件的库文件名应和工程名一致。 DllMain函数 Windows在加载DLL时,需要一个入口函数,就像控制台程序需要main函数一样。有的时候,DLL没有提供DllMain函数,应用程序也能成功引用DLL,这是因为Windows在找不到DllMain的时候,系统会从其它运行库引入一个不做任何操作的默认DllMain函数版本,并不意味着DLL可以抛弃DllMain函数。 根据编写规范,Windows必须查找并执行DLL里的DllMain函数作为加载DLL的依据,它使得DLL得以保留在内存里。这个函数并不属于导出函数,而是DLL的内部函数,这就说明不能在客户端直接调用DllMain函数,DllMain函数是自动被调用的。 DllMain函数在DLL被加载和卸载时被调用,在单个线程启动和终止时,DllMain函数也被调用。参数ul_reason_for_call指明了调用DllMain的原因,有以下四种情况: DLL_PROCESS_ATTACH:当一个DLL被首次载入进程地址空间时,系统会调用该DLLDllMain函数,传递的ul_reason_for_call参数值为DLL_PROCESS_ATTACH。这种情况只有首次映射DLL时才发生; DLL_THREAD_ATTACH:该通知告诉所有的DLL执行线程的初始化。当进程创建一个新的线程时,系统会查看进程地址空间所有的DLL文件映射,之后用DLL_THREAD_ATTACH来调用DLLDllMain函数。要注意的是,系统不会为进程的主线程使用值DLL_THREAD_ATTACH来调用DLLDllMain函数; DLL_PROCESS_DETACH:当DLL从进程的地址空间解除映射时,参数ul_reason_for_call参数值为DLL_PROCESS_DETACH。当DLL处理DLL_PROCESS_DETACH时,DLL应该处理与进程相关的清理操作。如果进程的终结是因为系统有某个线程调用了TerminateProcess来终结的,那么系统就不会用DLL_PROCESS_DETACH来调用DLLDllMain函数来执行进程的清理工作。这样就会造成数据丢失; DLL_THREAD_DETACH:该通知告诉所有的DLL执行线程的清理工作。注意的是如果线程的终结是使用TerminateThread来完成的,那么系统将不会使用值DLL_THREAD_DETACH执行线程的清理工作,这也就是说可能会造成数据丢失,所以不要使用TerminateThread来终结线程。以上所有讲解在工程DLLMainDemo(工程下载)都有体现。 函数导出方式

16,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧