目录

XShell 6评估版逆向分析


信息
本篇文章只做技术分享,不提供破解版本下载!

1. 引言

XShell作为一个强大的SSH连接工具,一直深受我喜爱。某天,我突然发现自己的XShell不能用了,就像下面这样:

/images/XShell6评估版逆向分析/6735a14df1965fba0b09b921edbd1eda0a84221ac551cf010c21ac110a61996e.png
到期窗口

XShell分为个人版和企业版,个人版是永久免费的,而企业版则需要购买。个人版与企业版的区别在于:个人版的窗口标签页被限制为4个,其余的与企业版差别不大。而我当时不知道有个人版,一直用的都是评估版,评估版是有期限的,只能用31天,于是就诞生了这篇文章。


2. 测试环境和工具

  • 测试环境: Windows7 32位
  • 使用工具:
    • OllyDbg、火绒剑、010Editor、Resource Hacker、IDA Pro等等

3. 初步猜测分析

逆向一个软件之前,需要先猜测需要逆向的功能是如何写出来的,这样在逆向的时候将会事半功倍。这个软件我的猜测是这样的:

  • 创建窗口/对话框:这个是肯定的,毕竟也有个到期窗口嘛
  • 检查了时间:这里就不确定是本地检查还是联网检查,需要进一步分析
  • 设置窗口标题:这个可能会设置,也可能对话框本身自己就有名称
  • 程序是否有反调试/加壳:这个需要第一时间检查

4. 正式分析

根据以上的猜测,开始进行正式分析。

4.1 检查程序是否存在反调试/加壳

第一件事就是检查程序是否有加壳、是否存在反调试,这样才有继续下去的可能性。

  1. 检查是否被加壳: PEiD查看主程序

    /images/XShell6评估版逆向分析/bef1f7d9a90aec85abbcc2ac9d8ac3b1aca245fd35369c923bd56ad953a28213.png
    PEiD查壳

    从上面可以看到,能识别出来是VC6.0编译的(但是链接器版本是11.0,可能是VS2012编译的,毕竟VC也太老了点),而且区段很正常,很明显没有加壳

  2. 检查是否有反调试:无插件的ODx64Dbg打开程序

    /images/XShell6评估版逆向分析/c50423ca0da0670747fa7d3230c4ba2041e2849f8536ebea89066551b724df93.png
    检查反调试

    这里用无插件ODx64Dbg都能发现程序存在反调试,虽然用吾爱破解OD可以反反调试,不过这里抱着学习的态度,来找找这个反调试:

    • 首先在关键API上下断,我这里先在IsDebuggerPresent下断,发现是可以断下来的:

      /images/XShell6评估版逆向分析/8e7099242138a9a250bbba4be21b01c386f75065aec41b3d0069da415a70afe6.png
      断点在IsDebuggerPresent

    • 接下来让程序跑起来可以发现,IsDebuggerPresent这个函数被执行了很多次,需要找到关键的位置,这里的思路是在ExitProcess函数下断,然后栈回溯:

      /images/XShell6评估版逆向分析/435a015a529943138eef3f85ccc8dc113b461dc14f5e3e170d75489d68f69a98.png
      断点在ExitProcess

      这里程序是在RtlExitUserProcess函数断下来的,需要注意!!!

    • 通过分析RtlExitUserProcess的栈回溯,找到了执行关键函数的地方,是在NsActivate_libFNP.dll这个模块中,如下图:

      /images/XShell6评估版逆向分析/bb4e84e63362d8bd992eac58e038f5fe4dcdf4d8181060aab44d6dc0d615a646.png
      栈回溯ExitProcess

      从上图可以看出:执行RtlExitUserProcess的关键函数是0x66811264这个函数,而执行0x66811264这个函数的地址是0x6683C342

    • 既然找到了关键地址,那么就来分析这个地址附近的内容,分析如下:

      /images/XShell6评估版逆向分析/926d744f7de4e0b1bbb7311fa966910895dc1798ace62c5d18c87baa1da1d903.png
      关键位置分析

      关键就是EAXESI必须相等,否则就退出程序

    • 我这里的目的只是为了让程序不退出,方便调试,所以我没有去具体分析ESI的值怎么来的等等,感兴趣的可以自行去分析一波。我这里将CALL EAX函数中的内容给改了,使EAX = ESI,然后Dump之后替换文件就可以过掉反调试了,修改如下:

      /images/XShell6评估版逆向分析/0e01ed04f353d22b17208d1321efa495b52e2ad7dfa62a122c7ad1b0d7648f44.png
      修改文件,过掉反调试

    • 这里需要注意一点:当替换了文件之后,运行程序可能会报如下错误,这里并不影响程序执行流程,所以可以忽略

      /images/XShell6评估版逆向分析/fd725264a1d099b46582481e3e6f33bb9d81796d0d823f7a5f4bf7c711ab8a25.png

这里要说明一下的是,用吾爱破解OD是可以直接过掉这个反调试的,所以接下来我都是使用的吾爱破解OD

4.2 分析创建窗口/对话框

过掉反调试之后,就可以正式开始分析程序了。 逆向破解软件,从能看见的窗口入手,然后往回推是最快的方法。

  1. 首先在所有创建窗口/对话框的API上下断,断下来之后观察栈传递的参数,例如下面这样:

    /images/XShell6评估版逆向分析/a005bd5fdfda7d57ecc0e6d2a992069fe5cf336aca731d477bb97d0dd0094182.png
    窗口传递的参数

    可以通过观察窗口的类名、名称和回调函数来确定是不是要寻找的窗口。但在这里,如果你使用的是吾爱破解OD的插件设置的API断点的话,那基本上是找不到到期窗口是在哪里被创建的。因为吾爱破解OD的这个插件是这样的:

    /images/XShell6评估版逆向分析/4cce71370f7908118c67e0eca9a20f58f153eead9c6befc8e12dc2842edc8a9c.png
    API断点工具

    这个插件可以快捷的设置API断点,但这里你把所有的创建窗口/对话框的API都勾上确定之后,的确很多API上都能被设置上断点,可唯独DialogBoxIndirectParam(A/W)这个API没有设置上断点,而恰恰这个到期窗口就是使用这个API创建的对话框(不要问我为什么知道,我也是调试了很久才找到这个原因的),所以还是手动设置这些API的断点吧。

  2. 这里以DialogBoxIndirectParam(A/W)被设置上断点为基础,发现被调用了一次之后,到期窗口显示出来,那么可以怀疑这次调用就是创建到期窗口,那么可以详细分析,先观察其调用时参数:

    /images/XShell6评估版逆向分析/98588e83a24a068135e7161b412f9f11dc4638ed2014fec8df26f89b0f442402.png
    DialogBoxIndirectParamW

    对话框的名称和类都是看不到的,但是可以看到一个对话框的回调函数10001C60,这里可以跟进去看看,就能发现这个回调函数就是到期窗口的回调函数,在这个窗口中设置了窗口的标题,也就是最初猜测的第三点,通过在SetWindowTextA/W下断点有时也能找到一些东西,如下:

    /images/XShell6评估版逆向分析/ae7cb4f94a4ee029990bbf44675e834777582334ad6d2c42efe2559b64afea82.png
    设置窗口标题

  3. 既然找到了关键创建窗口的位置,那么就可以栈回溯,找到创建窗口的位置,如下:

    /images/XShell6评估版逆向分析/d73c1fa9af6b942ba1b0c3a66172a954450441a5f0a9576b7cf9bd406b62d400.png
    到期窗口栈回溯

    通过分析,10001000这个函数是调用DialogBoxIndirectParamW的主要函数,而调用10001000函数的位置是10003F88,也就是说10003F88才是关键需要分析的位置,10003F88所在位置的代码如下:

    /images/XShell6评估版逆向分析/c1a12c8e161221b786b9dacd96ede5718e4575a1028dd3db642e76c35e1eeda0.png
    关键位置代码

    从上面可以看到,10003F88这个位置的执行是从某个地方跳转过来的,也就是上面某个位置跳转到了10003F6E这个地方,然后紧接着执行了10001000这个函数,随后创建了到期窗口。通过OD可以查看到是哪里跳转到了10003F6E这里来的,如下:

    /images/XShell6评估版逆向分析/1914f8b42a3488a076a3cf8e0d16c304538c92bdd75223922bb555264cb7603f.png
    关键判断位置

  4. 从上面可以看到,10003F0710003F21是跳转的位置,可以直接下断点到这两个地方,然后修改寄存器的值,就可以测试出,只要10003F21不跳转,那么就不会提示到期,然后NOP掉这里程序也就不会提示到期了,就像这样:

    /images/XShell6评估版逆向分析/bac55322de86bd2296a0dd6b2c59b31d8222b0e1a9060d6dec51fbf36b2088c9.png
    NOP掉判断位置

    可以看到已经不会提示到期了,这时就可以Dump下来,然后替换文件就实现了永久不到期的功能了,这里调用的模块是nslicens,所对应的模块是XShell安装目录下的nslicens.dll

    /images/XShell6评估版逆向分析/a1ec59a3e3033434c1ab003f8177a15f4554c58109f940840c873efa30d90c2c.png
    查看模块位置

  5. 上面是动态分析的结果,其实找到关键点之后,通过IDA很快就能看出逻辑:

    /images/XShell6评估版逆向分析/93ae68bf3b9653bc9c190ec15766f377f22746712cc9311f7d237d2aa8640050.png
    IDA观察关键点逻辑

    10001000这个函数中是这样的:

    /images/XShell6评估版逆向分析/2c90f475abf2cc8501f1d3c7cd9f588911583a3415849aa6cfdb3ba15f105f1f.png
    IDA中10001000函数

    可以看到资源ID103,通过Resource Hacker查看资源:

    /images/XShell6评估版逆向分析/e17f857c09c92f551bb59346e825017be802ea7bc3ef841f4a57a438c9bb825b.png
    ReHacker查看资源

4.3 通过时间分析

上面是基于窗口分析的,是最快的方法。但是我因为最开始DialogBoxIndirectParamW没下上断点,所以我是通过时间分析找到关键点的。

  1. 首先要通过时间分析,需要知道它是判断的本地时间还是网络时间,先用本地时间做做测试:

    /images/XShell6评估版逆向分析/eed961500e5b3622aea793938ca0f0fcc51856fd7aa7604b07746b584d8af71a.png
    修改本地时间测试

    可以看到的确是判断的本地时间,也就是说如果不进行逆向,直接修改时间也能达到永久不到期的效果。

  2. 接下来就要分析它是在哪判断的时间了。需要在GetLocalTime下断点。这里有一点和上面有点类似,就是与创建窗口/对话框的API一样,可能这个GetLocalTime会被执行很多次,所以需要找到创建到期窗口之前的那次GetLocalTime。我这里分析的时候是第4次执行GetLocalTime时到了关键位置,这时的栈回溯是这样的:

    /images/XShell6评估版逆向分析/78ca189e3afec43bcee8a6abb6cdfdd0dbc5f5c22956347a04e322048c751abf.png
    获取时间关键位置栈回溯

    可以看到OD帮忙显示了一些很关键的信息,也就是nslicens这个模块中的导出函数名,而这几个函数名很可疑:CheckLicenseAndPackageCheckLicenseGetCurrentDate,很明显就是获取当前时间并检查许可证

  3. 从上面可以看到,10003E24这个位置获取了当前时间,然后就可以从这个位置开始着手分析,我这里使用的是对比的方法分析的,也就是先把时间改成未到期的时间,观察其跳转,然后再把时间改成到期的时间,再观察其跳转,就能很快找到关键判断位置。我的最后分析如下:

    /images/XShell6评估版逆向分析/9c54042df049beadf1fe2c4de9f80bfb37bebfba2523e0f35f27dbc56a1af06c.png
    最后分析
    可以看到第二个判断的位置,也就是10003F21的位置,就是上面通过查找窗口的方式找到的关键跳转位置,所以接下来的事情就不用多说了


5. END

这次分析算是第一个独立分析破解的程序,中途遇到的坑比这写的多了去了。例如第一个对话框API的坑,我连对话框的回调函数都找到了,就是找不到在哪创建的对话框,导致浪费了很长的时间。还有分析时间的时候,因为调用了很多次GetLocalTime,我开始没有想到分析创建窗口之前的那个GetLocalTime,所以我从第一个开始分析的,结果发现前面的根本没鸟用,本来一两个小时就能搞完的东西,导致搞了一整天,这也是经验太少了,这次还是增长了不少快速分析的经验。



最后:

[1] 软件版本:

/images/XShell6评估版逆向分析/56c102ac6c2cb36d65892bc00803113d1d7a56d0c7e695d5678638368e51a2be.png
软件版本

[2] 下载地址:https://www.netsarang.com/zh/all-downloads/