上一篇文章介绍了“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做个外挂系列之三--构建外挂软件的定制代码框架的更多相关文章

  1. 给Source Insight做个外挂系列之一--发现Source Insight

    一提到外挂程序,大家肯定都不陌生,QQ就有很多个版本的去广告外挂,很多游戏也有用于扩展功能或者作弊的工具,其中很多也是以外挂的形式提供的.外挂和插件的区别在于插件通常依赖于程序的支持,如果程序不支持插 ...

  2. 给Source Insight做个外挂系列之六--“TabSiPlus”的其它问题

    关于如何做一个Source Insight外挂插件的全过程都已经写完了,这么一点东西拖了一年的时间才写完,足以说明我是一个很懒的人,如果不是很多朋友的关心和督促,恐怕是难以完成了.许多朋友希望顺着本文 ...

  3. 给Source Insight做个外挂系列之二--将本地代码注入到Source Insight进程

    上一篇文章介绍了如何发现正在运行的“Source Insight”窗口,本篇将介绍“TabSiPlus”是如何进行代码注入的.Windows 9x以后的Windows操作系统都对进程空间进行了严格的保 ...

  4. 给Source Insight做个外挂系列之五--Insight “TabSiPlus”

    “TabSiPlus 外挂插件”主要有两部分组成,分别是“外挂插件加载器”和“插件动态库”.“插件动态库”完成Source Insight窗口的Hook,显示Tab标签栏,截获Source Insig ...

  5. 给Source Insight做个外挂系列之四--分析“Source Insight”

    外挂的目的就是将代码注入到其它进程中,所以必须要有目标进程才能完成注入,而所谓的目标进程通常是某软件的一部分或者是全部,所以要对目标程序有深入地了解.一般外挂都是针对某个应用程序开发的,其装载.运行都 ...

  6. 【转】破解Source Insight 3.5.0072过程 附:安装软件+注册机

    转载地址:http://blog.csdn.net/qs_hud/article/details/8884867 注册机及软件下载地址:http://download.csdn.net/detail/ ...

  7. Source Insight 3.X 标签插件v1.0发布

    Source Insight可以说是一款程序员必备的开发/阅读源码工具,美中不足的是SI没有标签栏,多个源码之间切换很不方便,于是我就乘闲暇之余写了该作品sihook:标签插件;不过严格意义上来说si ...

  8. Source Insight 插件

    一提到外挂程序,大家肯定都不陌生,QQ就有很多个版本的去广告外挂,很多游戏也有用于扩展功能或者作弊的工具,其中很多也是以外挂的形式提供的.外挂和插件的区别在于插件通常依赖于程序的支持,如果程序不支持插 ...

  9. Source Insight 4.0安装使用教程

    一.说明 Source Insight是什么:Source Insight是一款代码编缉.浏览.分析工具. Source Insight与文本编缉器有什么区别:Notepad++等文本编缉器也可以编缉 ...

随机推荐

  1. testng教程之testng.xml的配置和使用,以及参数传递

    昨天学习了一下testng基础教程,http://www.cnblogs.com/tobecrazy/p/4579414.html 昨天主要学习的是testng 的annotation基本用法和生命周 ...

  2. 关于js实现分页效果的简单代码

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  3. 曲线救国:IIS7集成模式下如何获取网站的URL

    如果我们在Global中的Application_Start事件中访问HttpContext.Current.Request对象,如: protected void Application_Start ...

  4. Java中分割字符串

    java.lang.String 的 split() 方法, JDK 1.4 or later public String[] split(String regex,int limit) 示例代码 p ...

  5. hadoop入门(3)——hadoop2.0理论基础:安装部署方法

    一.hadoop2.0安装部署流程         1.自动安装部署:Ambari.Minos(小米).Cloudera Manager(收费)         2.使用RPM包安装部署:Apache ...

  6. FTP安装与使用

    1.查看ftp是否已安装:rpm -qa | grep vsftpd 2.安装ftp:rpm -ivh vsftpd 或yum install vsftpd 3.匿名用户配置文件主要参数: anony ...

  7. LeetCode——Best Time to Buy and Sell Stock II (股票买卖时机问题2)

    问题: Say you have an array for which the ith element is the price of a given stock on day i. Design a ...

  8. Redis学习笔记(3) Redis基础类型及命令之二

    1. 集合类型 集合类型与列表类型有很多相似之处,但二者的区别在于:前者具有唯一性,但不具有有序性:后者具有有序性,但不具有唯一性.集合类型的常用操作是向集合中加入或删除元素.判断某个元素是否存在等, ...

  9. Hibernate关联关系的映射

    实体之间的关系 实体之间有三种关系 一对多:一个用户,生成多个订单,每一个订单只能属于一个用户 建表原则:在多的一方创建一个字段,作为外键,指向一的一方的主键 多对多:一个学生可以选择多门课程,一个课 ...

  10. 源码解析-Volley(转自codeKK)

    Volley 源码解析 本文为 Android 开源项目源码解析 中 Volley 部分项目地址:Volley,分析的版本:35ce778,Demo 地址:Volley Demo分析者:grumoon ...