首页
社区
课程
招聘
[原创]屏保“黑客帝国Matrix.scr”的注册码分析
发表于: 2012-11-22 16:14 9199

[原创]屏保“黑客帝国Matrix.scr”的注册码分析

2012-11-22 16:14
9199

  很久以前在网上发现一个不错的屏保,类似黑客帝国的画面,基色调是幽幽的绿色,随机的字符码从天而降,带你进入3D数字世界。于是就放到了U盘里,转眼几年了还在那里放着,今天无意中又设置了下,发现还是个未注册的版本,于是试着逆下看看能不能把码抓出来,现场直播哦~亲。

  最近新装的系统OD还原了,发现还有个IDA于是载入,不管是代码格式还是图形模式,别把自己陷入偌大的流程谜团里,先试着看下导入函数发现有两个熟悉的函数
  DialogBoxParamA
  GetWindowTextA
可以试着下个断点探探水深不
可是IDA怎么下断点呢,双击DialogBoxParamA函数后进到了十六进制窗口(Hex View),根本不是代码区域,不过定位的位置是0x00441214,没办法手动定位吧,切换到代码窗口
(IDA View)搜索到0x00441214位置显示为DATA段,不是代码段里,右键看下有个Jump to Xref to Operand…项选择后弹出个类似代码引用该函数的窗体,有两个条目可能是说有两处调用。分别点击OK,哈哈,来到了代码段(IDA不熟,么见怪!),GetWindowTextA同F2下断。
断点下好了,现在调试运行吧,F9运行,设置调试器为Local Win32 debugger.运行后断在DialogParamA位置,继续F5运行弹出欢迎界面

点击确定弹出程序设置界面如图

点击注册按钮程序又断在DialogBoxParamA位置,F9继续后弹出注册信息窗口,
输入用户名:AJISky,号码:ABCD-EFGH-IJKL-MNOP确定断在GetWindowTextA位置,看来水确实不深!!
接下来就可以逐步分析算法了
.text:0040F972 push    400h            ; nMaxCount
.text:0040F977 mov     ecx, [edi+1Ch]
.text:0040F97A push    eax             ; lpString
.text:0040F97B push    ecx             ; hWnd
.text:0040F97C mov     [ebp+lpCaption], edi
.text:0040F97F mov     [ebp+var_4], 0
.text:0040F986 call    ebx ; GetWindowTextA  ;取用户名字符串
.text:0040F988 mov     edx, ds:lpString
.text:0040F98E lea     eax, [ebp+String] 
.text:0040F994 test    eax, eax
.text:0040F996 mov     [ebp+var_20], edx
.text:0040F999 jz      short loc_40F9F3
.text:0040F99B lea     ecx, [ebp+String]
.text:0040F9A1 shr     ecx, 10h
.text:0040F9A4 jnz     short loc_40F9B7
.text:0040F9A6 lea     edx, [ebp+String]
.text:0040F9AC lea     ecx, [ebp+var_20]
.text:0040F9AF push    edx             ; uID
.text:0040F9B0 call    sub_40EF70
.text:0040F9B5 jmp     short loc_40F9F3
.text:0040F9B7 ; ---------------------------------------------------------------------------
.text:0040F9B7
.text:0040F9B7 loc_40F9B7:                             ; CODE XREF: sub_40F940+64j
.text:0040F9B7  lea     eax, [ebp+String]
.text:0040F9BD  push    eax             ; lpString
.text:0040F9BE  call    lstrlenA
.text:0040F9C4  mov     esi, eax        ; 取用户名长度
.text:0040F9C6  test    esi, esi
.text:0040F9C8  jz      short loc_40F9F3
.text:0040F9CA  push    esi
.text:0040F9CB  lea     ecx, [ebp+var_20]
.text:0040F9CE  call    sub_403FF0      ; 分配空间为转存用户名到内存地址做准备
.text:0040F9D3  test    eax, eax
.text:0040F9D5  jz      short loc_40F9F3
.text:0040F9D7  mov     edi, [ebp+var_20]
.text:0040F9DA  mov     ecx, esi
.text:0040F9DC  mov     edx, ecx
.text:0040F9DE  lea     esi, [ebp+String]
.text:0040F9E4  shr     ecx, 2
.text:0040F9E7  rep movsd          通过movsb指令转存用户名到内存地址
.text:0040F9E9  mov     ecx, edx
.text:0040F9EB  and     ecx, 3
.text:0040F9EE  rep movsb        通过movsb指令转存用户名到内存地址
.text:0040F9F0  mov     edi, [ebp+lpCaption]
.text:0040F9F3
接下来获取注册码过程同上类似,省略。
.text:0040FA74   mov     eax, [ebp+lpString]
.text:0040FA77   mov     ebx, 2
.text:0040FA7C   push    eax             ; lpString
.text:0040FA7D   mov     ecx, offset unk_46EAAC
.text:0040FA82   mov     byte ptr [ebp+var_4], bl
.text:0040FA85   call    sub_40E170      ; 主变换算法
.text:0040FA8A   test    eax, eax      ;返回结果为0则弹出错误提示框
.text:0040FA8C   jz      loc_40FC47    

sub_40E170:
.text:0040E1BF    push    ecx             ; int
.text:0040E1C0    push    edx             ; int
.text:0040E1C1    push    eax             ; lpString
.text:0040E1C2    mov     ecx, esi
.text:0040E1C4    mov     byte ptr [esp+13Ch+var_4], 2
.text:0040E1CC   call    sub_40E7A0      ; 检测XXXX-XXXX-XXXX格式并拆分XXXX,XXXX,XXXX数值
.text:0040E1D1                 lea     ecx, [esp+12Ch+var_120] ; IJKL
.text:0040E1D5                 lea     edx, [esp+12Ch+var_124] ; EFGH
.text:0040E1D9                 push    ecx             ; 压入IJKL
.text:0040E1DA                 lea     eax, [esp+130h+var_118]
.text:0040E1DE                 push    edx             ; 压入EFGH
.text:0040E1DF                 push    eax
.text:0040E1E0                 call    sub_40EDF0      ; 连接两个串EFGHIJKL
.text:0040E1E5                 mov     eax, [eax]
.text:0040E1E7                 lea     ecx, [esp+12Ch+var_114]
.text:0040E1EB                 push    ecx
.text:0040E1EC                 push    eax
.text:0040E1ED                 mov     ecx, esi
.text:0040E1EF                 mov     byte ptr [esp+134h+var_4], 3
.text:0040E1F7                 call    sub_40EBD0    ; 对EFGHIJKL变换并求得结果 
变换算法为
; for (i=0;i<8;i++)
; NUM=(i&1)*8<<STRING[i]+Num

.text:0040E235                 mov     eax, [esp+12Ch+var_11C]
.text:0040E239                 lea     ecx, [esp+12Ch+var_110]
.text:0040E23D                 push    ecx
.text:0040E23E                 lea     edx, [esp+130h+var_10C]
.text:0040E242                 push    100h
.text:0040E247                 push    edx
.text:0040E248                 push    eax
.text:0040E249                 mov     ecx, esi
.text:0040E24B                 call    sub_40EB30      ; 变换前四位数
算法:
前四位要在ABCDFGHKMNPRSTXZ串中
设第一个字母在串中偏移位置a
第二个在串中偏移为b
a= (a or 4<<b)
执行2遍,第一遍为低八位,第二遍为高八位
.text:0040E2FE                 mov     eax, [esp+12Ch+var_10C]
.text:0040E302                 mov     edx, [esp+12Ch+var_114]
.text:0040E306                 and     eax, 0FFFFh
.text:0040E30B                 xor     ecx, ecx
.text:0040E30D                 cmp     edx, eax
.text:0040E30F                 mov     eax, [esp+12Ch+var_120]
.text:0040E313                 setz    cl              ; 比较前四和后八结果相同置1

算法挺简单,也就是对注册码做变换,结果相等就成功,名字可以任意起。
例如XXXX-1111-1111 求XXXX
1111-1111按照如下算法结果为
; for (i=0;i<8;i++)
; NUM=(i&1)*8<<STRING[i]+Num
第一次:i=0; num=31+227c=22AD
第二次:i=1; num=3100+22AD=53AD
第三次:i=2; num=31+53AD=53DE
第四次:i=3; num=3100+53DE=84DE
第五次:i=4; num=31+84DE=850F
第六次:i=5; num=3100+850F=B60F
第七次:i=6; num=31+B60F=B640
第八次:i=7; num=3100+B640=E740
结果为E740
算法2:
串:ABCDFGHKMNPRSTXZ
表达式a= (a or 4<<b)得出
40为a=0即为A,b=4即为F故AF
E7为a=7即为K,b=E即为X故KX
所以XXXX=AFKX
输入
用户名AJISKY 
注册码:AFKX-1111-1111确定
弹出


附上很赞的屏保: Matrix.rar


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 6
支持
分享
最新回复 (8)
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
屏保相当美腻~
2012-11-22 16:29
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
我觉得屏保很不错,谢谢
2012-11-22 17:00
0
雪    币: 59
活跃值: (1506)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
这个东西还真是卡啊。呵呵,运行了一会,电脑直接迟钝了
2012-11-22 17:06
0
雪    币: 269
活跃值: (906)
能力值: ( LV12,RANK:345 )
在线值:
发帖
回帖
粉丝
5
哥,我觉得还是你电脑有问题
2012-11-22 18:31
0
雪    币: 215
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
非常感谢AJISky的分享, 作为一个新手, 我想问的问题是...
在断点之后往下调试, 会遇到比较多的Call, 那么请问你是怎么知道哪一个Call是关键的"主变换算法"? 是你一个一个Call分析下去, 还是利用弹出错误对话框的断点向上分析?...

还有比如说
.text:0040F9CE call sub_403FF0 ; 分配空间为转存用户名到内存地址做准备

请问了解这个call的功能, 是进了这个call看的, 还是其他的方法, 比如说利用eax里的内容判断的?

我知道这些问题可能很傻, 但是麻烦照顾一下新手吧...多谢了!
2013-1-5 15:28
0
雪    币: 269
活跃值: (906)
能力值: ( LV12,RANK:345 )
在线值:
发帖
回帖
粉丝
7
兄弟,你问这个call是如何定位的,针对大多数小程序,上边已经取文本框内容了,一般GetWindowTextA取完内容后紧接着就开始用算法计算注册码了。所以稍微跟踪下就可以了。
另外,一般程序跟踪最好先搂一眼导入表函数,看到比较“特殊”的函数就点进去看看,可以少走不少捷径
2013-1-6 17:37
0
雪    币: 190
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
屏保拿走,顶贴走人
2013-1-8 15:29
0
雪    币: 215
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
soga, 多谢指点最近期末考试, 刚刚看到哈~
也就是说经验最重要啊~
2013-1-15 23:09
0
游客
登录 | 注册 方可回帖
返回
//