很久以前在网上发现一个不错的屏保,类似黑客帝国的画面,基色调是幽幽的绿色,随机的字符码从天而降,带你进入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
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)