Just for fun.
动手keygen Winlicense 1.8.5.5. 会了这个基本上Winlicense 加授权系列的其他版本的都会了。用1.8.5.5 做样例是因为1.8.5.5的RSA校验是摆看的。
现在都是无key脱壳,无key过授权。所以仅仅是学习一下。没什么用,大牛们就直接略过。
Keygen Winlicense softworm、shoooo、HyperChem 都讲过步骤,HyperChem还发了个视频,但是视频中找关键的数据涉及到VM,也就没讲了。
我们主要是找到License Unique Key的三部分数据,就可以keygen了。我这有一个License Unique Key是我自己找的正确的key:
111111115UZHI2H92Ab07JaAu4im5QOik0vRqGsYCWQ374g3eEKA9RTARUR9pXJ0XzN88RFa2D39Sajm5c8kuo0hTUErpsCnj3ro1111111111111111111111111111111111111111111111111
License Unique Key的结构:
0-0x7 可以任意指定 11111111
0x8 + -0xC 5UZH + I2H9为realkey的解密后+0位的dword值。即:0x35555A48 + 0x 49324839 =0x7E87A281
0x10 + -0x14 2Ab0 + 7JaA为realkey的解密后+16位的dword值。0x32416230 + 0x374A6141 =0x698BC371
+0x18 u4 + im 为realkey的解密后+33位的word值。0x 7534 + 0x 696D =0xDEA1
+0x1C + -0x2C = 0x9CB6856C
+0x20 + -0x30 = 0x9CB6856C
+0x24 + -0x34 = 0x9AC799AA
+0x28 + -0x38 = 0x6CA3AC95
+0x3C + -0x40 = 0xC8D29868 这上面的数据都是在key运行解密的时候要用到的。(+0x3C + -0x40只有在1.8.5.5的这个版本 解密key的时候用到,高版本可以任意填写,我最开始keygen的时候就卡在这里,先入为主的认为这个数据是没用的)
+0x44 8RFa2D39Sajm5c8kuo0hTUErpsCnj3ro 上面的都可以在程序解密key文件的时候找到。明码存储。
+0x64任意指定1111111111111111111111111111111111111111111111111
两两之和的数据只要拆分成数字和字母组成字符串的就可以了。
(逆向调试WinlicenseSDK.dll可以得到这些信息)
现在我们来找上面的数据。od载入主程序,下断CreateFileA函数尾。已知F9直到ESP+4为$+4 > 0073DACB ASCII "C:\WINDOWS\system32\KERNEL32.dll" 。修改eax为-1(0x0FFFFFFFF).这个主要是为了防止wl模拟dll 造成调试障碍。继续F9直到
0012FF20 00F118AE 返回到 WinLicen.00F118AE
0012FF24 00DD8C13 WinLicen.00DD8C13
0012FF28 80000000
0012FF2C 00000001
0012FF30 00000000
0012FF34 00000003
0012FF38 00000020
0012FF3C 00000000
0012FF40 03B80270
0012FF44 00DDA2F7 ASCII "WLlicense.dat"
打开 key文件为止。取消断点,F7单步走。看到retn 0xC ,单击F4 再F7.
00F11A68 8985 5CA44906 mov dword ptr ss:[ebp+649A45C],eax
00F11A6E E8 16000000 call WinLicen.00F11A89
00F11A73 C785 60A44906 0>mov dword ptr ss:[ebp+649A460],0
00F11A7D 8B85 5CA44906 mov eax,dword ptr ss:[ebp+649A45C]
00F11A83 FFA5 64A44906 jmp dword ptr ss:[ebp+649A464]
00F11A89 60 pushad
00F11A8A BB 78563412 mov ebx,12345678
00F11A8F 8DB5 F6954906 lea esi,dword ptr ss:[ebp+64995F6]
00F11A95 8DBD 97A34906 lea edi,dword ptr ss:[ebp+649A397]
00F11A9B E9 07000000 jmp WinLicen.00F11AA7
00F11AA0 301E xor byte ptr ds:[esi],bl
00F11AA2 003E add byte ptr ds:[esi],bh
00F11AA4 D1CB ror ebx,1
00F11AA6 46 inc esi
00F11AA7 3BF7 cmp esi,edi
00F11AA9 ^ 0F82 F1FFFFFF jb WinLicen.00F11AA0
00F11AAF 61 popad
00F11AB0 C3 retn
在010D9E03 下断点,F9 两次。取消断点,这个时候 key已经被加载到内存了。Alt+M 打开内存窗口,复制WLlicense.dat 文件里面的一段数据,在内存窗口中搜索,找到key加载的内存,
Memory map, 条目 91
地址=03410000
大小=00002000 (8192.)
属主= 03410000 (自身)
区段=
类型=Priv 00021004
访问=RW
初始访问=RW
(这个段一般位于0x10000000这个地址前面,是新申请的内存 大小为0x2000)
在这个内存段下内存访问断点,F9运行断下,
018B19C2 FF32 push dword ptr ds:[edx]
018B19C4 53 push ebx
018B19C5 BB 6F59010C mov ebx,0C01596F
018B19CA 816C24 04 DE467>sub dword ptr ss:[esp+4],7B7646DE
018B19D2 015C24 04 add dword ptr ss:[esp+4],ebx
018B19D6 814424 04 DE467>add dword ptr ss:[esp+4],7B7646DE
018B19DE 5B pop ebx
018B19DF FF3424 push dword ptr ss:[esp]
在反汇编代码窗口搜索命令序列:
popad
popfd
retn
找到9处 retn全下F2断点。这个地方是VM的出口。
删除key内存段的内存访问断点,f9运行。直到寄存器出现(不用多少次,一般第七次)
EAX 00000000
ECX 00000000
EDX 89B8A74D
EBX 00F0A4D4 ASCII "8RFa2D39Sajm5c8kuo0hTUErpsCnj3ro"
ESP 0012FF1B
EBP FAA775CE
ESI 00F1388B WinLicen.00F1388B
EDI 03A90000
EIP 018F1C84
"8RFa2D39Sajm5c8kuo0hTUErpsCnj3ro"这个数据就是上面的+44数据。
删除所有断点,记住key内存段的位置,F9运行,主程序运行了。在数据窗口中ctrl+g 输入key内存段,可以看到key文件解密后的数据,复制出来:
7E 87 A2 81 6C CC 2C 1C 01 3D 6C 1D 01 3D 88 1C
01 3D E8 1C 01 3D 69 8B C3 71 48 A0 F4 48 9C F0
44 98 EC BC 1D 00 00 58 05 01 3D C8 E3 BB F0 AC
05 01 3D DE A1 C8 E3 A7 DC FF FF FF FF FF FF FF
FF 4A 65 66 66 72 65 79 20 53 69 6C 66 65 72 FF
FF FF FF FF FF FF FF 71 65 6E 74 79 6E 73 63 6F
6C 6F 72 40 65 61 72 74 68 6C 69 6E 6B 2E 6E 65
74 FF FF FF FF FF FF FF FF 31 30 31 30 2D 32 34
32 34 2D 32 33 35 32 2D 33 38 37 36 FF FF FF FF
FF FF FF FF FE FF FF FF FE FF FF FF 61 70 E9 2C
4F EE 41 88 43 88 AE BA B2 38 43 C3 EF 94 24 C7
9C 47 B5 96 4B 5B 71 0D EF 57 96 C7 8B 92 34 79
91 BF C3 30 11 E7 EF 9C 7C 3A 66 73 E2 FB A7 FB
D6 95 14 2E 45 46 A9 36 82 A2 8A 3A 2F 55 1B 0A
DE 68 D7 80 82 65 FC 3A 1E A0 9A EC 24 CD 29 A4
A4 F4 55 10 0F 48 CC E6 75 09 0E 6F 69 A3 7A A1
D8 53 0F AA 15 B0 F0 AD C2 62 81 7D 71 76 3D F4
15 73 62 AE B1 AD 00 60 B7 DA 8F 17 37 02 BC 83
A2 55 32 5A 08 17 74 E2 FC B0 E0 14 6B 61 75 1D
A8 BD 56 21 55 70 E7 F0 04 84 A3 67 A8 80 C8 21
44 BB 66 D3 4A E8 F5 8A CA 0F 22 F7 35 63 98 CD
9B 24 DA 55 8F BE 46 88 FE 6E DB 90 3B CB BC 94
E8 7D 4D 64 97 91 09 DB 3B 8E 2E 95 D7 C8 CC 46
DD F5 5B FE 5D 1D 88 6A C8 70 FE 40 2E 32 40 C9
22 CC AC FB 91 7C 41 04 CE D8 22 08 7B 8B B3 D7
我们只要前面的数据
7E 87 A2 81 6C CC 2C 1C 01 3D 6C 1D 01 3D 88 1C
01 3D E8 1C 01 3D 69 8B C3 71 48 A0 F4 48 9C F0
44 98 EC BC 1D 00 00 58 05 01 3D C8 E3 BB F0 AC
05 01 3D DE A1 C8 E3 A7 DC FF FF FF FF FF FF FF
红色标出来的数据 就是我们要找的 +0x8 - +0x18
4F EE 41 88 这个是前面数据的校验和
当然 如果 你需要替换RSA数据,
43 88 AE BA B2 38 43 C3 EF 94 24 C7
9C 47 B5 96 4B 5B 71 0D EF 57 96 C7 8B 92 34 79
91 BF C3 30 11 E7 EF 9C 7C 3A 66 73 E2 FB A7 FB
D6 95 14 2E 45 46 A9 36 82 A2 8A 3A 2F 55 1B 0A
DE 68 D7 80 82 65 FC 3A 1E A0 9A EC 24 CD 29 A4
A4 F4 55 10 0F 48 CC E6 75 09 0E 6F 69 A3 7A A1
D8 53 0F AA 15 B0 F0 AD C2 62 81 7D 71 76 3D F4
15 73 62 AE B1 AD 00 60 B7 DA 8F 17 37 02 BC 83
A2 55 32 5A 08 17 74 E2 FC B0 E0 14 6B 61 75 1D
A8 BD 56 21 55 70 E7 F0 04 84 A3 67 A8 80 C8 21
44 BB 66 D3 4A E8 F5 8A CA 0F 22 F7 35 63 98 CD
9B 24 DA 55 8F BE 46 88 FE 6E DB 90 3B CB BC 94
E8 7D 4D 64 97 91 09 DB 3B 8E 2E 95 D7 C8 CC 46
DD F5 5B FE 5D 1D 88 6A C8 70 FE 40 2E 32 40 C9
22 CC AC FB 91 7C 41 04 CE D8 22 08 7B 8B B3 D7
这个就是的了。
接下来就是最麻烦的几个数据了。
+0x1C + -0x2C = 0x9CB6856C
+0x20 + -0x30 = 0x9CB6856C
+0x24 + -0x34 = 0x9AC799AA
+0x28 + -0x38 = 0x6CA3AC95
+0x3C + -0x40 = 0xC8D29868
不懂wl vm的童鞋可以去看看softworm天书,只要看到第三部分就可以了(当然你也可以深入了解,多看看没坏处)。我找数据纯粹是取巧。没有还原VM的能力,没办法。
HyperChem 在keygen wl 的视频教程里讲了这里四个数据的用途。
汇编大致是
sub xx,1c-2c
xor xx,xx
以及类似的操作,可以去看看HyperChem的教程。这里我们可以看到WinlicenseSDK.dll是怎么使用这五组数据的,其中
+0x1C + -0x2C = 0x9CB6856C
+0x20 + -0x30 = 0x9CB6856C
+0x24 + -0x34 = 0x9AC799AA
+0x28 + -0x38 = 0x6CA3AC95
是在一起使用的,
+0x3C + -0x40 = 0xC8D29868
单独使用。
text:100023BF add eax, 9E3779B9h
.text:100023C4 mov edx, ecx
.text:100023C6 shl edx, 4
.text:100023C9 add ebx, edx
.text:100023CB mov edx, [esi]
.text:100023CD xor edx, ecx
.text:100023CF add ebx, edx
.text:100023D1 mov edx, ecx
.text:100023D3 shr edx, 5
.text:100023D6 xor edx, eax
.text:100023D8 add ebx, edx
.text:100023DA add ebx, [esi+4]
.text:100023DD mov edx, ebx
.text:100023DF shl edx, 4
.text:100023E2 add ecx, edx
.text:100023E4 mov edx, [esi+8]
.text:100023E7 xor edx, ebx
.text:100023E9 add ecx, edx
.text:100023EB mov edx, ebx
.text:100023ED shr edx, 5
.text:100023F0 xor edx, eax
.text:100023F2 add ecx, edx
.text:100023F4 add ecx, [esi+0Ch]
这个是前面四组数据,基本上是 相加移位和异或。
所以在解密key数据的时候,下断在 Vm_sub 和 Vm_xor 是可以获取到正确的数据的。据说这个四个数据在主程序里面是在特定的时候明文出现的,可以直接替换,估计海风月影的通杀lpk就是这么做的,不过替换的地方我暂时没找到。希望大牛们指点指点。
知道这些,我们开始动手找数据。
先重新载入主程序,运行到key访问。(由于多次需要这样操作,我写了个脚本,自动运行到这个地方,打包在附件里面)
018B19C2 FF32 push dword ptr ds:[edx]
018B19C4 53 push ebx
018B19C5 BB 6F59010C mov ebx,0C01596F
018B19CA 816C24 04 DE467>sub dword ptr ss:[esp+4],7B7646DE
018B19D2 015C24 04 add dword ptr ss:[esp+4],ebx
018B19D6 814424 04 DE467>add dword ptr ss:[esp+4],7B7646DE
018B19DE 5B pop ebx
018B19DF FF3424 push dword ptr ss:[esp]
停在这里。 把反汇编窗口拉到最上面,搜索指令序列:
sub RA,RB
pushfd
和
xor RA,RB
pushfd
在 所有找到的 32位寄存器操作的地方下断点。比如:
01839BB1 FF77 70 push dword ptr ds:[edi+70]
01839BB4 9D popfd
01839BB5 29C3 sub ebx,eax
01839BB7 9C pushfd
01839BB8 8F47 70 pop dword ptr ds:[edi+70]
01839BBB 08D2 or dl,dl
这种特征在高版本(我在keygen Winlicense 2.10 的时候是下面的特征)里面有些不同,可以搜索
xor dwrod ptr [esp],eax
pushfd
和
sub dwrod ptr [esp],eax
pushfd
(hc刚刚和我说,这个是CISC虚拟机的特征)
低版本搜索的时候可以找到大概8-10个的样子,而 高版本找到的地方只有2个。也就是只存在一份handler。低版本主要用的也只有两个,但是没有好的办法区分,只能全部都下断点。然后运行,发现数据完全看不出规律,而且杂乱数据太多了。
最后我写了个脚本,打印操作数到文件,从访问的这个地方一直到程序运行,获得到了一个60kb的数据文件。
脚本:
var sub1
var sub2
var sub3
var sub4
var sub5
var sub6
var xor1
var xor2
var xor3
var xor4
mov sub1,01839BB5
mov sub2,0184B953
mov sub3,018B5D6D
mov sub4,018CD945
mov sub5,0194A88E
mov sub6,0195EF1F
mov xor1,0184E9BF
mov xor2,01879AC8
mov xor3,018FFD40
mov xor4,0193CFE6
bp 01839BB5 //始终 sub ebx,eax
[注意]看雪招聘,专注安全领域的专业人才平台!