给Source Insight做个外挂系列之三--构建外挂软件的定制代码框架
上一篇文章介绍了“TabSiPlus”是如何进行代码注入的,本篇将介绍如何构建一个外挂软件最重要的部分,也就是为其扩展功能的定制代码。本文前面提到过,由于windows进程管理的限制,扩展代码必须以动态链接库的形式挂载到被挂程序的进程空间中,使用上一篇介绍的方法已经可以通过创建远程线程的方式启动一个线程,让这个线程加载我们的定制动态链接库,现在就看看这个动态链接库是如何实现的。
首先这是一个动态链接库,因为考虑到扩展功能中有大量的界面操作,所以选择支持MFC,同时,还要提供一个名为“InitFunc”的导出函数,供在被挂程序中启动的远程线程调用,以初始化外挂动态链接库,这个导出函数的原型是这样的:
typedef DWORD (WINAPI *PFN)();
没有参数,但是有一个返回值用于表示初始化是否成功。现在就用Visual C++的向导生成一个支持MFC的动态链接库的框架,并手工添加一个名为“InitFunc”的导出函数,如果你还不清楚怎么做,那么可以停止看本文了,因为本文可能对你毫无用处。
在生成的代码中,MFC对DllMain进行了封装,所以有了一个CxxxApp的类,xxx与你的动态链接库的名字一致,TabSiPlus使用的是CTabSiPlusApp,现在有三个地方需要特别注意,一个是CTabSiPlusApp::InitInstance(),一个是CTabSiPlusApp::ExitInstance(),另一个就是我们的导出函数“InitFunc”。当远程线程中LoadLibrary()调用我们的定制动态链接库时,CTabSiPlusApp::InitInstance()被调用,当FreeLibrary()调用发生时,CTabSiPlusApp::ExitInstance()被调用,当然,伴随而出现的还有两个函数调用,那就是CTabSiPlusApp类的构造函数和析构函数,部分初始化代码也可以放在构造函数中完成,不过并不推荐这样做,因为如果因为构造函数触发异常导致LoadLibrary()失败,那么随后的析构函数也不会被调用,因为构造函数没有完成对象的构造,同时,由于LoadLibrary()失败,使得FreeLibrary()调用分支没有执行,那么导致CTabSiPlusApp::ExitInstance()也没有被调用,这会引起资源释放的异常。
很显然,CTabSiPlusApp::InitInstance()的调用发生在InitFunc函数的调用之前,所以要控制好初始化代码之前的先后关系。CTabSiPlusApp::InitInstance()中布置对资源初始化的代码,而诸如创建文件标签栏窗口,Hook “Source Insight”窗口消息,管理这些消息的代码则可以布置到InitFunc函数中实现。这里需要注意的是由于我们的外挂代码是以动态链接库的形式挂载到“Source Insight”进程中的,所以它没有消息循环,所有的窗口UI系统无法正常工作,解决的办法有两个,一个是在InitFunc函数创建窗口之后人为地添加一个消息循环,关于这一点如何实现可以参考Windows SDK编程的方法;另一个方法就是不要把主要的工作放在InitFunc,而是在InitFunc函数中再创建一个本地线程,把窗口UI这些麻烦的东西放在这个线程中处理,这样就可以利用这个线程的消息循环使窗口UI系统工作起来,这样做还有一个好处,就是InitFunc函数可以立即返回,加载外挂的宿主程序也可以及时得到外挂的加载情况,以便根据情况安排下一次加载动作(就是调用CreateRemoteThread()),同时还可以及时释放在被挂程序中分配的内存。TabSiPlus就是采用的第二种方法,下面就是TabSiPlus的InitFunc函数实现,当然省去了一些代码,主要核心就是一行:
DWORD WINAPI InitFunc()
{
//其它初始化操作
g_pTabWndUIThread = (CTabWndUIThread *)AfxBeginThread(RUNTIME_CLASS(CTabWndUIThread),THREAD_PRIORITY_NORMAL,0,0,NULL);
//其它操作
return (g_pTabWndUIThread != NULL);
}
在CTabWndUIThread类的InitInstance()函数中创建标签栏窗口,hook “Source Insight”中相关窗口的消息:
BOOL CTabWndUIThread::InitInstance()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
g_pSiFrameWnd = new CSIFrameWnd(); //CWnd::FromHandle(hDevStudioWnd);
g_pSiFrameWnd->Attach(hWndSIFrame); //hook SI主窗口
HWND hMDIWnd = g_pSiFrameWnd->GetMDIClientWnd();
//UINT uThressID = GetCurrentThreadId();
// create the tabs window
m_pTabbarWnd = new CTabBarsWnd();
m_pTabbarWnd->Create(CWnd::FromHandle(g_pSiFrameWnd->GetSafeHwnd()),
RBS_BANDBORDERS | RBS_AUTOSIZE | RBS_FIXEDORDER | RBS_DBLCLKTOGGLE,
WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | CBRS_TOP | CBRS_SIZE_FIXED, AFX_IDW_REBAR );
m_pMainWnd = m_pTabbarWnd;//这很重要,否则这个线程就无法退出
g_pSiFrameWnd->SetTabbarWnd(m_pTabbarWnd->GetSafeHwnd());
g_MdiChildMng.SetTabbarWnd(m_pTabbarWnd->GetSafeHwnd());
m_pTabbarWnd->SetWindowPos(CWnd::FromHandle(hMDIWnd)->GetWindow(GW_HWNDPREV), 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
g_pSiMDIClientWnd = new CSiMDIWnd();
g_pSiMDIClientWnd->SetTabbarWnd(m_pTabbarWnd->GetSafeHwnd());
DebugTracing(gnDbgLevelNormalDebug,_T("MDI Client Attach..."));
g_pSiMDIClientWnd->Attach(hMDIWnd);
DebugTracing(gnDbgLevelNormalDebug,_T("MDI Client Enum..."));
g_pSiMDIClientWnd->EnumMdiChildWnd(g_MdiChildMng,TRUE);
DebugTracing(gnDbgLevelNormalDebug,_T("MDI Client Enum end (%d)"),g_MdiChildMng.GetChildCount());
pGlobalActiveSIWindow = g_MdiChildMng.LookupMdiChild(g_pSiMDIClientWnd->MDIGetActive(NULL));
g_pSiMDIClientWnd->SetManaging(true);
return TRUE;
}
是不是很象标准单文档结构的MFC程序中的CxxxApp::InitInstance()函数?特别是对m_pMainWnd的赋值?对m_pMainWnd赋值其实很重要,否则线程就会直接退出,对m_pMainWnd赋值还有一个好处,就是关闭m_pTabbarWnd窗口就会中止CTabWndUIThread线程,这和标准单文档结构的MFC程序中的结果一样。
CTabWndUIThread::InitInstance()函数中有很多是对“Source Insight”内部窗口进行hook的代码,那么TabSiPlus是如何得到这些窗口的句柄呢,又是如何关联它们之间的消息呢,请看下篇:给Source Insight做个外挂系列之四--分析“Source Insight”
Source Insignt文件标签外挂:TabSiPlus的下载地址:
http://blog.csdn.net/orbit/
版权声明:本文为博主原创文章,未经博主允许不得转载。
给Source Insight做个外挂系列之三--构建外挂软件的定制代码框架相关推荐
- 给Source Insight做个外挂系列之一--发现Source Insight
作者:星轨(oRbIt) E_Mail :inte2000@163.com 一提到外挂程序,大家肯定都不陌生,QQ就有很多个版本的去广告外挂,很多游戏也有用于扩展功能或者作弊的工具,其中很多也是以 ...
- 给Source Insight做个外挂系列之六--“TabSiPlus”的其它问题
关于如何做一个Source Insight外挂插件的全过程都已经写完了,这么一点东西拖了一年的时间才写完,足以说明我是一个很懒的人,如果不是很多朋友的关心和督促,恐怕是难以完成了.许多朋友希望顺着本文 ...
- 给Source Insight做个外挂系列之二--将本地代码注入到Source Insight进程
作者:星轨(oRbIt) E_Mail :inte2000@163.com 上一篇文章介绍了如何发现正在运行的"Source Insight"窗口,本篇将介绍"TabS ...
- 给Source Insight做个外挂系列之五--Insight “TabSiPlus”
"TabSiPlus 外挂插件"主要有两部分组成,分别是"外挂插件加载器"和"插件动态库"."插件动态库"完成Sourc ...
- 给Source Insight做个外挂系列之四--分析“Source Insight”
外挂的目的就是将代码注入到其它进程中,所以必须要有目标进程才能完成注入,而所谓的目标进程通常是某软件的一部分或者是全部,所以要对目标程序有深入地了解.一般外挂都是针对某个应用程序开发的,其装载.运行都 ...
- 【转】破解Source Insight 3.5.0072过程 附:安装软件+注册机
转载地址:http://blog.csdn.net/qs_hud/article/details/8884867 注册机及软件下载地址:http://download.csdn.net/detail/ ...
- Source Insight 3.X 标签插件v1.0发布
Source Insight可以说是一款程序员必备的开发/阅读源码工具,美中不足的是SI没有标签栏,多个源码之间切换很不方便,于是我就乘闲暇之余写了该作品sihook:标签插件;不过严格意义上来说si ...
- C++用桌面图标系列之三【整理-时钟】
他来了,他来了,桌面图标一百种玩法第三种,桌面时钟. 学会了就发给女朋友玩吧,效果炫酷,学不了吃亏,学不了上当,走过路过不要错过. 老规矩,先看看视频效果. C++用桌面图标系列之三[整理-时钟] 核 ...
- Source Insight 4.0使用介绍
简介 Source Insight是一个功能非常强大的,面向项目的程序编辑器,具有针对C/C ++,C#,Java,Objective-C等的内置动态分析.Source Insight可实现多文件代码 ...
最新文章
- 打开阿兹海默之门:华裔张复伦利用RNN成功解码脑电波,合成语音 | Nature
- [ARM异常]-armv8/armv9异步异常类型、路由、屏蔽
- 如何查找SAP的旧TCODE对应新的TCODE
- 【工具使用系列】关于 MATLAB 电路与系统分析,你需要知道的事
- BigDecimal类型一定不会失真吗?不一定。参数类型为double的构造方法的结果有一定的不可预知性,是有可能产生失真的。
- Fragment与Activity交互(使用接口)
- jedispool redis哨兵_通过java哨兵JedisSentinelPool代码示例连接对配置的redis哨兵主从模式进行测试验证...
- js结合jquery实现的ajax瀑布流加载实例
- 如何创建一个简单 APT 仓库
- 33 计算机维修,33.计算机硬件检测维修与数据恢复竞赛规程(修改)全解.doc
- 设计模式视频教程——【从设计到模式】
- 阶段5 3.微服务项目【学成在线】_day03 CMS页面管理开发_05-新增页面-服务端-接口测试...
- c语言转化音乐格式转换器安卓版,MP3格式转换器APP
- 阿里巴巴JAVA开发手册----(二)异常日志
- sht20中写用户寄存器_谁用过sht20这块温湿度传感器,有调通的程序分享下吧
- C++ Debug编译成XP系统下运行
- React SSR渲染
- 刨根究底字符编码之零——前言
- python迭代器是什么百度百科_【python】迭代器与生成器究竟是什么?看完你就知道...
- 2055041-21-7,Acid-PEG4-S-PEG4-acid在EDC和HATU等活化剂存在下,羧酸基团可与伯胺反应