首页
社区
课程
招聘
[求助]dll嵌入exe,exe退出时dll不能退出的问题
2006-5-30 10:44 6307

[求助]dll嵌入exe,exe退出时dll不能退出的问题

2006-5-30 10:44
6307
我在做一个小游戏外挂的时候遇到的问题:我有个自己的dll嵌入到exe中,通过exe的收发包来进行操作,实现一个自动的过程.里面启动了一个辅助线程,有个循环来处理任务.
我是通过发送鼠标和键盘消息来操作的.退出游戏也是通过消息来完成.问题在于:发送了键盘消息使exe的界面按钮被点击了,exe正常退出了,可我的线程死在了内存里,在任务管理器中查看exe还在,线程数有时1有时2,可能就是我的辅助线程没有退出,是不是还有个嵌入dll的线程也没有退出?
请问怎么样才能解决这样的问题?
多次启动exe就会在内存中驻留了多个exe,最后占用内存太多了就无法运行了.

请大家给指点一下.

[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

收藏
点赞0
打赏
分享
最新回复 (7)
雪    币: 208
活跃值: (371)
能力值: ( LV12,RANK:330 )
在线值:
发帖
回帖
粉丝
moodsky 8 2006-5-30 12:31
2
0
来个转贴[ZT]

除虫记之八(WM_QUIT和结束线程:1小时/1人)

公测的时候又发现一个问题,因为一个商务上问题,程序中去掉了一个模块(dll)的调用,打包公测后,发现程序在退出后而聊天进程没有退出,等待了很长时间也没有退出。

开发人员在调试的时候,已经在debug版本下重现了这个bug,跟踪代码出错部分的流程如下:
发送WM_QUIT消息给一个工作线程让其退出;
用WaitForSingleObject等待那个线程的句柄有信号;
如果有信号,就直接CloseHandle掉这个线程句柄;
如果超时没有信号,就直接用_endthreadex()杀死线程。

开发人员跟踪了好多次发现消息发送过去后线程并没有退出,每次都要超时进入强杀流程,但强杀调用确没有杀死线程,从thread里面还可以明确的看到这个线程在运行,于是就导致了进程没有退出!

跟踪了好几次都找不到问题所在,让我过去看看。

很明显,进程没有退出,就是因为这个线程没有退出的缘故。我一开始怀疑是不是线程没有收到这个消息,于是在处理消息的地方加上断点,ft,结果频频进入断点,程序一下子就失去了反应,连VC都没有响应了,不得已在进程管理器中杀死,按说在调试状态,进程管理器是不让杀的,但不知为何偏偏杀死了,且不管他。把断点去掉,在Post线程消息前加断点,然后再在线程的消息处理中加断点。运行,Post线程消息成功,F5运行,靠,竟然没有走到线程消息处理的断点里面。线程没有收到消息????

运行多次,都是同一个现象。

因为只是一个杀死线程的操作,想让线程死还不容易啊,于是建议开发人员用TerminateThread()强杀线程,开发人员开始不理解,说线程是用_beginthreadex启动的,应该用_endthreadex杀死。我说就按我说的做,呵呵,线程如期被我们干掉了,进程退出了。

趁此机会,又给开发人员讲解了一番C运行库函数和Win32API的优劣比较。

让他们编译release版后送给测试部去验证,我又开始仔细那个线程处理消息的流程,我打了好多调试语句,怎么都发现没有收到退出的消息。晕啊。

忽然,注意到了WM_QUIT消息,哈,想起来了,自己曾经又一次就是用这个消息让线程退出,但没有成功,后来改程自定义的消息就可以了,立刻动手改成WM_USER+113,哈,收到了退出的消息,线程如期自动退出了!

哈哈,立刻又第n次的简单看了看WM_QUIT消息,然后告诉开发人员说WM_QUIT消息只能由应用程序主线程处理做程序退出。

我犯了一个大错误!

刚转了一圈回来,开发人员小声的说不是WM_QUIT消息的问题,被我听到了。
立刻追问,原来开发人员第一次的认真看了看WM_QUIT消息的MSDN文档,发现并不是线程不能处理WM_QUIT消息,而是线程中用GetMessage接收消息,而接收到这个消息后GetMessage返回0,就是这个0,被程序用if给if掉了!

我犯了一个大错误!我以为我对API已经很熟悉了,但看来远远不是!远远不是!

教训:尽可能用Win32的API,尽量的少用 c 运行库函数。WM_QUIT消息可以被任何线程处理。
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
悲酥清风 2006-5-30 15:43
3
0
按照楼上的启发我在我的线程里PostMessage()发送WM_QUIT消息,结果还是一样的,在任务管理器里的进程仍然还在,线程数为2
好像不行
有没有其他方法?
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-5-30 16:32
4
0
Originally posted by 悲酥清风
我在做一个小游戏外挂的时候遇到的问题:我有个自己的dll嵌入到exe中,通过exe的收发包来进行操作,实现一个自动的过程.里面启动了一个辅助线程,有个循环来处理任务.
我是通过发送鼠标和键盘消息来操作的.退出游戏也是通过消息来完成.问题在于:发送了键盘消息使exe的界面按钮被点击了,exe正常退出了,可我的线程死在了内存里,在任务管理器中查看exe还在,线程数有时1有时2,可能就是我的辅助线程没有退出,是不是还有个嵌入dll的线程也没有退出?
请问怎么样才能解决这样的问题?
多次启动exe就会在内存中驻留了多个exe,最后占用内存太多了就无法运行了.

........


你需要对线程进行同步。
界面线程(主线程)与事务处理线程之间的同步
可以使用内核事件对象,HANDLE hEvent ;
通过 SetEvent, ResetEvent操作该事件对象
在主线程退出之前使用等待函数,例如WaitForSingleObject等,来等待事务处理线程的结束

上面的方法只不过是线程同步的一种比较常用方法。
为的就是保存在结束主线程之前结束事务处理线程
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
悲酥清风 2006-5-31 10:10
5
0
楼上:
主线程exe是游戏线程,我没办法操作,只能控制我自己嵌入的线程啊
雪    币: 1852
活跃值: (504)
能力值: (RANK:1010 )
在线值:
发帖
回帖
粉丝
北极星2003 25 2006-6-1 06:36
6
0
可以利用子类化技术来实现,对于你的问题,解决方法大致如下:
(说明,仅仅是伪代码,参数需自己补充 )

首先,取得该按扭的ID,(可以利用资源软件)

// 你所嵌入的线程
NewThread ( .... )
{
   hButton = GetDlgItem ( ID ) ;
   DefWndProc = SetWindowLong ( hButton, GWL_WNDPROC, NewButtonProc ) ;
   
   // 你需要实现的功能
}

LRESULT CALLBACK NewButtonProc ( HWND hEdit, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
  // 在这里检测按扭消息
   if ( 这个按扭消息来了 )
   {
          // 结束线程
    }
  return CallWindowProc ( (WNDPROC)DefWndProc, hEdit, uMsg, wParam, lParam ) ;
}

关于子类化技术的更详细资料,可以参考
http://bbs.pediy.com/showthread.php?s=&threadid=15428
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
willii 2006-6-1 09:10
7
0
没写过这种dll,不过可以试试在dllmain里面的线程退出或进程退出消息中作一些处理看看能不能终止你的线程
雪    币: 214
活跃值: (70)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
fengercn 2006-6-1 23:55
8
0
控制台工作线程都可以正常退出,你的倒没见过
游客
登录 | 注册 方可回帖
返回