公司内部通讯使用内网通(以下简称NWT),他有个好玩的功能:登陆积分可以兑换姓名后的皇冠等。在版本3.4.3035更新前,他的兑换机制还算合理,5000积分可以换个铜冠,所以内网通聊天列表里很多人名字后面顶着皇冠。(强制)升级到3.4.3035后,需要用以前10倍的积分才能兑换东西(恩,物价飞涨!)。更重要的,以前的刷积分外挂失效了。上帝关上一堵门,必然会为你打开一扇窗,内网通的作者可能也想到要够到铜冠太难了,于是,他提供了RMB玩家解决方案----你可以购买积分,如下图:

另外,作者还开了网店,通过扫二维码,进入作者网店消费。通过这种方式,可以获得可怜兮兮的若干积分。 看着软件作者手头比较紧,需要摇钱树功能的软件...

本着不断人财路的初衷,本文只提供逆向思路,并不会公开逆向的方法(这也是大多数逆向论坛的一贯作风),下面开始正文。先查壳,diewin显示NWT的主程序ShiYeLine.exe(事业线?作者想表达什么含义?)并没有加壳,并且由vs2008编译生成:

没加壳,又是c++写的,看来这软件是个可以捏的软柿子。

NWT本身有很多窗口,而且又由vs2008生成,我决定先用spy++收集窗口和控件信息,毕竟能收集到控件信息可以节省很多分析的时间。但是很可惜,spy++只能捕获到对话框信息,而对话框上的控件它一概无法捕捉,换句话说,作者并没有使用标准控件,可能是将Button,Edit等控件绘制在对话框上。

起初,我只是想修改总积分,所以尝试用Cheat Engine搜索并修改总积分,居然还真改成功了:

但是通过CE找到的总积分往往都在NWT的消息循环内(响应OnCopy消息时,总积分地址包含在消息体中),虽然可以修改,但有一半的概率会修改失败,所以我放弃了这种方式,转而根据错误提示来定位和分析NWT产生验证码的代码:

NWT添加积分的规则为:点击试试手气,弹出"试试手气"对话框。对话框中含有二维码,手机扫码后,会进入作者的网店;同时,手机上出现4位验证码,将这串验证码输入"试试手气"的Edit框,验证正确NWT会随机地添加少的可怜的若干积分;验证失败提示无效的验证码。

起初我怀疑NWT弹出"试试手气"对话框前会生成并发送验证码给服务器,然而,我抓包后并没有什么收获。看来没有什么取巧的办法了,我只能把NWT拖进IDA进行分析。当IDA加载完毕后,在Functions window中看到NWT导出了一堆函数名:

百度一下这些函数名发现,原来NWT用了ShinUI框架实现UI部分。ShinUI的设计者本着方便切换各种资源的目的,将对话框布局做成xml文件,xml文件中规定了创建对话框时需要加载哪些字符串/图片,而"试试手气"对话框的xml文件位于安装目录res\ShiYeLine\layout\ScanCodeDialog.xml中:

<SkinDialog DefaultWidth="375" DefaultHeight="520" Caption="IDS_SCAN_CODE" Animation="SizeChange" Icon="128" SysButton="CLOSE"><SkinTextView Id="101" LayoutHeight="28" AlignParentLeft="25" AlignParentRight="25" AlignParentTop="50" Text="IDS_SCAN_CODE_TIPS1" FontStyle="ID_FONT_BOLD_BIG"/><SkinRelativeLayout Id="106" LayoutWidth="300" LayoutHeight="300" AlignParentHorizontalCenter="0" BkgColor="ID_COLOR_WHITE" ToBottomOf="101,17"><SkinImageView Id="102" LayoutWidth="WrapContent" LayoutHeight="WrapContent" AlignParentHorizontalCenter="0" AlignParentVerticalCenter="0" /></SkinRelativeLayout><SkinTextView Id="103" LayoutHeight="28" AlignParentLeft="25" AlignParentRight="25" ToBottomOf="106,17"Text="IDS_SCAN_CODE_TIPS2" FontStyle="ID_FONT_BOLD_BIG"/><SkinEditView Id="104" LayoutHeight="28" AlignParentLeft="75" AlignParentRight="75" ToBottomOf="103,10" Limit="4" Image="Edit.png"/><SkinTextView Id="105" LayoutHeight="28" AlignParentLeft="75" AlignParentRight="75" ToBottomOf="104,3" FontColor="ID_COLOR_RED"/>
</SkinDialog>

xml中<SkinTextView Id="105">节点,对应了验证码出错时显示的"无效的验证码。"这句话。根据我反反复复调试NWT积累的失败经验,我确定NWT为了显示这句话,必须调用CSkinTextView::DrawForeground在对话框上绘制字符串。而CSkinTextView::DrawForeground又会依次调用CPaintHelper::DrawTextW和User32!DrawTextW进行绘制。切入点出现了!DrawTextW的第二个参数是字符串参数,如果我设置条件断点,比较字符串参数的内容是否为指定字符串,如果是就中断到调试器再参看调用堆栈,那么一定能定位到比对字符串的代码的附近。

前面我也说过ShinUI设计为方便开发者替换各种资源,包括字符串资源。在调试过程使用中文字符串往往会出错,所以,我定位到安装目录下res\ShiYeLine\value\string.xml(这是ShinUI规定的字符串表)中IDS_SCORE_CODE_INVALID的值,将其从"无效的验证码。"替换为"dbgstr"。再次启动NWT,并输入错误的验证码,就会提示dbgstr字样:

现在可以附加windbg并添加条件断点了:

bp 0142ad20 "as /mu $ustr poi(@esp+4);.block {r @$t0=$scmp(@\"$ustr\",@\"dbgstr\");.if(@$t0==0){};.else{gc;}}"

附注:地址0142ad20是NWT内部函数sub_142AC30调用DrawTextW的地址,关于条件断点的设置,可以参考我博客中的相关文章。

再次输入错误的验证码,程序中断后得到下列调用堆栈:

00 00d5e834 01438d9c 75012494 04519e38 00d5e8a4 ShiYeLine!CPaintHelper::operator=+0x4080
01 00d5e864 014211e3 75012494 00d5e8c0 04519e38 ShiYeLine!CPaintHelper::DrawTextW+0x9c
02 00d5e904 01419392 75012494 01a0865c 04519bf0 ShiYeLine!CSkinTextView::DrawForeground+0x10303 00d5e974 01341432 00000001 022093b9 036fb048 ShiYeLine!CSkinView::RedrawView+0x35204 00d5eaa8 0140fc15 0000040b 00000068 08521048 ShiYeLine!CSkinView::GetClientRect+0x1312
05 00d5eae4 0142720b 0000040b 00000068 08521048 ShiYeLine!CSkinWndHost::WindowProc+0x165
06 00d5eb00 74bebe6b 00140d1e 0000040b 00000068 ShiYeLine!CPaintHelper::operator=+0x56b
07 00d5eb2c 74be833a 014271e0 00140d1e 0000040b USER32!AddClipboardFormatListener+0x49b
08 00d5ec14 74be7bee 014271e0 00000000 0000040b USER32!DispatchMessageW+0x97a
09 00d5ec90 74be79d0 d558274a 00d5ecdc 013ff241 USER32!DispatchMessageW+0x22e
0a 00d5ec9c 013ff241 00d5ecbc 04523920 00d5ed30 USER32!DispatchMessageW+0x10
0b 00d5ecdc 01344c2c 0027065c 022096d1 036fbcc0 ShiYeLine!CSkinDialog::DoModal+0xe1
0c 00d5f580 0140faf9 00000193 044fa1f0 00000111 ShiYeLine!CSkinView::GetClientRect+0x4b0c
0d 00d5f5b4 0142720b 00000111 00000193 044fa1f0 ShiYeLine!CSkinWndHost::WindowProc+0x49
0e 00d5f5d0 74bebe6b 0027065c 00000111 00000193 ShiYeLine!CPaintHelper::operator=+0x56b
0f 00d5f5fc 74be833a 014271e0 0027065c 00000111 USER32!AddClipboardFormatListener+0x49b
10 00d5f6e4 74be7bee 014271e0 00000000 00000111 USER32!DispatchMessageW+0x97a
11 00d5f760 74be79d0 d558274a 00d5f7a8 013ff241 USER32!DispatchMessageW+0x22e

借助调用栈中的返回地址(第3列),依次查看该地址所在的函数,终于在frame 3#中找到加载字符串"IDS_SCORE_CODE_INVALID"的线索

这段代码中我圈了3个call指令:第1个call,比较输入的字符串长度是否为4;第2个call,比较输入的字符串是否是NWT生成的目标字符串;第3个call,前一次比较失败时,加载字符串"IDS_SCORE_CODE_INVALID"。由此可知,第二个call是关键所在,进入该函数会看到它前后调用了__wcsicmp用于比较输入和_rand用于产生积分:

.text:014BF6E0 sub_14BF6E0     proc near               ; CODE XREF: sub_1341350+76↑p
.text:014BF6E0......
.text:014BF6FA ; ---------------------------------------------------------------------------
.text:014BF710
.text:014BF710 loc_14BF710:                            ; CODE XREF: sub_14BF6E0+29↑j
.text:014BF710 ; __unwind { // 14BF73C                 ; wchar_t *
.text:014BF710                 push    eax
.text:014BF711                 push    ecx             ; wchar_t *
.text:014BF712                 call    __wcsicmp
.text:014BF717                 add     esp, 8
.text:014BF71A                 test    eax, eax
.text:014BF71C                 jz      short loc_14BF726
.text:014BF71E                 xor     al, al......
.text:014BF726 ; ---------------------------------------------------------------------------
.text:014BF726
.text:014BF726 loc_14BF726:                            ; CODE XREF: sub_14BF6E0+3C↑j
.text:014BF726                 push    1
.text:014BF728                 mov     eax, offset dword_19FFBA0
.text:014BF72D                 call    sub_14BEB80.......
.text:014BF780 ; } // starts at 14BF770
.text:014BF786                 cmp     dword_19FFD48, 0
.text:014BF78D                 jbe     short loc_14BF7BF
.text:014BF78F                 call    _rand
.text:014BF794                 cdq
.text:014BF795                 mov     ecx, 32h
.text:014BF79A                 idiv    ecx

根据这段代码,我们还能顺藤摸瓜,找到NWT产生的验证码,不过对于Cracker来说这已经不重要,完全可以patch产生积分的代码。当然,怎么做我就不公布了,我输不起官司~

Crack内网通积分规则(基于版本3.4.3035)相关推荐

  1. 基于Event Sourcing和DSL的积分规则引擎设计实现案例

    架构设计模式(Architecture Patterns),是"从特殊到普遍"的.基于各种实际问题的解决方案而总结归纳出来的架构设计最佳实践,是一种对典型的.局部的架构逻辑的高度抽 ...

  2. CSDN获取积分规则

    如何获得CSDN下载积分和C币规则 原文取自:http://download.csdn.net/help 如何获得CSDN下载积分 项目名称 获得细则 积分数量 普通资源被下载 100分封顶,下载自己 ...

  3. CSDN博客积分规则和获取积分方法

    博客积分是衡量博客水平的重要标准,博客的排名也将按照积分排列.积分规则具体如下: 1.每发布一篇原创或者翻译文章:可获得10分 2.每发布一篇转载文章:可获得2分 3.博主的文章每被评论一次:可获得1 ...

  4. php积分领取规则,积分规则

    积分规则 1.积分获取 a)  积分专属邮乐,仅限邮乐网内使用; b)  积分可以累积,2年内有效; c)  买家在邮乐网消费购物可以获得积分,积分返点比例为:除3C产品外的所有商品均以2元:1积分计 ...

  5. oracle 定义atp规则,ATP新积分规则详解

    过去52周内,共计18站比赛成绩之和,如果上一个赛季参加了年终总决赛--大师杯,则大师杯的积分作为额外一站计入世界积分(大师杯小组赛胜一场200分,半决赛胜得400分,决赛胜得500分,所有输球比赛均 ...

  6. CSDN博客的积分规则

    积分规则具体如下: 1.每发布一篇原创或者翻译文章:可获得10分 2.每发布一篇转载文章:可获得2分 3.博主的文章每被评论一次:可获得1分 4.每发表一次评论:可获得1分(自己给自己评论.博主回复别 ...

  7. 内网通讯工具都有哪些?

    互联网的迅速发展使得通讯工具在人们的日常生活与工作当中变得越来越普及.现在大多数企业内有使用Saas部署的通讯工具,但随着企业的发展,对信息安全的重视性越来越高,不少企业开始转用内网环境办公,与此同时 ...

  8. Ubuntu18.04下用信使与Windows下用内网通互传文件

    1.前言 前段时间把自己的笔记本装了Ubuntu18.04.因为是五年前的笔记本了,配置有点跟不上了,之前一直用的win10,后来想反正这个旧本本没啥用了,索性在折腾折腾,装个Linux系统玩玩,于是 ...

  9. 最新CSDN博客积分规则和获取积分方法【官方的说明】

    博客积分是衡量博客水平的重要标准,博客的排名也将按照积分排列.积分规则具体如下:  1.每发布一篇原创或者翻译文章:可获得10分  2.每发布一篇转载文章:可获得2分  3.博主的文章每被评论一次:可 ...

  10. oracle 定义atp规则,[转载]ATP新积分规则详解

    过去52周内,共计18站比赛成绩之和,如果上一个赛季参加了年终总决赛--大师杯,则大师杯的积分作为额外一站计入世界积分(大师杯小组赛胜一场200分,半决赛胜得400分,决赛胜得500分,所有输球比赛均 ...

最新文章

  1. Ubuntu 镜像使用帮助
  2. NIO 之 ByteBuffer实现原理
  3. 收集一些常用查询SQL语句以及显示格式
  4. 内核解密 | Oracle 18c 数据库安装ORA-12754的两种解决方案
  5. python做定时任务api_Python—定时任务(APScheduler实现)
  6. RTP audio video profile
  7. 从最大似然再看线性回归
  8. 信息系统高级项目管理师:十大知识领域+五大过程组
  9. java考试座位号_怎么用java编写出座位号(1.0)这样格式?
  10. PC端 宽高自适应问题
  11. vue组件中的方法执行顺序是怎么样的?data和props执行顺序
  12. tpc-c 测试结果 tpc-c
  13. c++define的用法
  14. GRUB2配置文件grub.cfg详解
  15. 关于localhost404打不开
  16. 计算机中浮点数的表示及正负数小数的反码补码
  17. 运用js生成二维码(工作记录)
  18. Django-MTV简介
  19. PS教程:PS制作超萌的表情包
  20. 苏轼《江城子》(十年生死)赏析

热门文章

  1. 认识影片版本(CAM、TS、TC、DVD、HD、BD、TVRIP等)
  2. 企业部署WAPI无线网络的技术详析
  3. payload sql注入_Web安全:SQL注入工具
  4. oracle存储过程实例
  5. MySQL存储过程实例
  6. Linux-firewalld-squid正向代理
  7. 三类主流影音播放器对比
  8. php smarty fetch,fetch - [ smarty完全中文手册 ] - 在线原生手册 - php中文网
  9. 手机社交游戏与触动用户的环节
  10. GPS之家论坛最新地图下载精选 汇集论坛精华 不断更新中(2013.3.30)