流星网络电视 2.15
等我搞定了这个程序后,搜索了下论坛,看到已经有战友在去年我刚入道的时候已经发过,感觉非常郁闷!看了看文章,还是不一样,想了想还是发了吧。
这是一个失败的加密算法,虽然搞了非常强悍的算法,n次DES+n次MD5,但是加密注册码与加密用户名+机器码的形式一样,而且key也一样,根本就不用去算DES&MD5,虽然不是明码比较,但在某个地方直接下断就能得到注册码。
ASPack 2.12 -> Alexey Solodovnikov
Borland Delphi 6.0 - 7.0
机器码:9030D2D9
用户名:cyto
注册码:8765432112345678
1.对输入的注册码加密保存到注册表:
定位注册按钮:
005080E8 55 push ebp
对注册码长度的判断:
0050818B 8B45 FC mov eax,dword ptr ss:[ebp-4]
0050818E E8 11CAEFFF call MeteorNe.00404BA4
00508193 83E8 10 sub eax,10
00508196 74 18 je short MeteorNe.005081B0
00508198 83E8 04 sub eax,4
0050819B 74 4B je short MeteorNe.005081E8
0050819D 83E8 04 sub eax,4
005081A0 74 7B je short MeteorNe.0050821D
005081A2 83E8 08 sub eax,8
005081A5 0F84 A7000000 je MeteorNe.00508252
005081AB E9 88010000 jmp MeteorNe.00508338
看样子对输入的注册码有要求,可以为16位,20位,24位,32位,得到不同的值,可能对应不同版,比如标准版,豪华版等等。
输入注册码16位:
005081B9 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 待加密值
005081BC E8 1334F7FF call MeteorNe.0047B5D4 ; MD5
005081C1 8B45 D4 mov eax,dword ptr ss:[ebp-2C]
005081C4 8D4D D8 lea ecx,dword ptr ss:[ebp-28]
005081C7 BA A4835000 mov edx,MeteorNe.005083A4 ; ASCII "Impressions"
005081CC E8 1726F7FF call MeteorNe.0047A7E8 ; DES
005081D1 8B45 D8 mov eax,dword ptr ss:[ebp-28] ; 加密值
005081D4 B9 0A000000 mov ecx,0A
005081D9 BA 06000000 mov edx,6
005081DE E8 21CCEFFF call MeteorNe.00404E04 ; 取值
硬件访问断点可以跟踪到DES加解密的地方:
0047A2D0 8B45 0C mov eax,dword ptr ss:[ebp+C] ; 待加密的数据
0047A2D3 8B55 08 mov edx,dword ptr ss:[ebp+8]
0047A2D6 E8 81F9FFFF call MeteorNe.00479C5C
0047A2DB 84DB test bl,bl
0047A2DD 0F85 B5000000 jnz MeteorNe.0047A398 ; 判断加密或解密
因为跟过好多DES,看到数据窗口显示两排一样的值,感觉就是DES加密,然后代码窗口往下就看到了可爱的加解密判断。
比如输入练码:8765432112345678,
MD5(注册码):堆栈 ss:[0012FA0C]=00E13690, (ASCII "b367880002f343b544d1c40e2a5e4c55")
DES加密值:堆栈 ss:[0012FA10]=00E1F9C4, (ASCII "367C0DBDA07EDD2B7FE9B592DD04FC4F52B4075FE9E30F203DF448112325EB0D")
取值:DBDA07EDD2
如果输入注册码为20位:
比如练码:87654321123456788888
MD5:堆栈 ss:[0012FA04]=00E1E554, (ASCII "e4cff04950d1de18ec1a59fe8ec55b25")
DES:堆栈 ss:[0012FA08]=00E201BC, (ASCII "76F759CDA212914538DE07F2FC3A3825EA411498F0A27B9B00458A4EBE556AC2")
取值:F759CDA2129145
如果注册码为24位:
比如练码:876543211234567888884444
MD5:堆栈 ss:[0012F9FC]=00E202EC, (ASCII "87249b9fe34297a230c0004a14062dc4")
DES:堆栈 ss:[0012FA00]=00E21454, (ASCII "956C42F9EF9A06A427F6D73543BBD4A632AF6ED7E98AFED82CC512DA66D3F99B")
取值:42F9EF9A06A427F6
如果注册码为32位:
比如练码为:87654321123456788765432112345678
MD5:堆栈 ss:[0012F9F4]=00E21660, (ASCII "50ce9374eb73de35f8439b25a5bee3e2")
DES:堆栈 ss:[0012F9F8]=00E2177C, (ASCII "DDE34549170DF92BA0AA66896DEFA36D1A86CC0B7D2EAB9B2C1A9F1611537EBC")
取值:DF92BA0AA668
算法很清楚,就是对输入的注册码MD5(注册码),然后DES(),key可能为Impressions,然后根据xx版要去取值。
即经过运算为:Char[DES(MD5(注册码),Impressions)]
注册码长度与注册表里值的长度关系:16对应10,24对应14,28对应16,32对应12。
写入注册表,分别为:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\olympic\pic SUCCESS "DBDA07EDD2"
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\olympic\pic SUCCESS "F759CDA2129145"
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\olympic\pic SUCCESS "42F9EF9A06A427F6"
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\olympic\pic SUCCESS "DF92BA0AA668"
2.算法之旅:
搜索pic:
0050409D BA CC455000 mov edx,MeteorNe.005045CC ; ASCII "pic"
2.1用户名+机器码的运算:[用户名+机器码运算中间值]
MD5(cyto):
00504124 8B83 A0040000 mov eax,dword ptr ds:[ebx+4A0]
0050412A E8 A574F7FF call MeteorNe.0047B5D4
0047B38C C700 01234567 mov dword ptr ds:[eax],67452301
0047B392 C740 04 89ABCDEF mov dword ptr ds:[eax+4],EFCDAB89
0047B399 C740 08 FEDCBA98 mov dword ptr ds:[eax+8],98BADCFE
0047B3A0 C740 0C 76543210 mov dword ptr ds:[eax+C],10325476
堆栈 ss:[0012FD50]=00E15EE0, (ASCII "369d1922e56a67d428fedd5c31ee6887")
2.2 XOR(MD5(cyto)):
00504132 BA 40465000 mov edx,MeteorNe.00504640 ; ASCII "killyou?yes"
00504137 8B45 FC mov eax,dword ptr ss:[ebp-4] ; MD5(cyto)
0050413A E8 25B0FDFF call MeteorNe.004DF164
0050413F 8B55 E8 mov edx,dword ptr ss:[ebp-18] ; 计算值
进入call:
004DF2EA 3245 E7 xor al,byte ptr ss:[ebp-19]
参数:
00504640=MeteorNe.00504640 (ASCII "killyou?yes")
堆栈 ss:[0012FD50]=00E15EE0, (ASCII "369d1922e56a67d428fedd5c31ee6887")
运算:
顺取MD5(cyto)的字符,与内置字符串的第一个字符异或,循环次数为32,得到结果
异或结果再与内置字符串第二个字符异或,一直循环到内置字符串结束。
总共循环:11×32。
最后值:
堆栈 ss:[0012FD3C]=00E1767C, (ASCII "0207085500080303540407500706550503095754555504520200545407090906")
2.3 对机器码的DES加密:DES(机器码)
0050414D BA 54465000 mov edx,MeteorNe.00504654 ; ASCII "http://www.jesen.cn"
00504152 8B83 A4040000 mov eax,dword ptr ds:[ebx+4A4] ; 机器码"9030d2d9"
00504158 E8 8B66F7FF call MeteorNe.0047A7E8 ; DES加密
0050415D 8B55 E0 mov edx,dword ptr ss:[ebp-20] ; 计算值
参数:机器码"9030d2d9"
结果:ASCII "6DB43263A7568F1D"
2.4 对用户名计算值的DES:DES(XOR(MD5(cyto)),DES(机器码))
0050415D 8B55 E0 mov edx,dword ptr ss:[ebp-20] ; ASCII "6DB43263A7568F1D")
00504160 8D4D E4 lea ecx,dword ptr ss:[ebp-1C]
00504163 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 用户名计算值
00504166 E8 7D66F7FF call MeteorNe.0047A7E8
0050416B 8B55 E4 mov edx,dword ptr ss:[ebp-1C] ; 加密值
这个是分步加密的,因为用户名计算值太大,8个8个加密,比如:02070855 00080303 ...。
参数:
用户名计算值:0207085500080303540407500706550503095754555504520200545407090906
机器码加密值:ASCII "6DB43263A7568F1D"
加密值:堆栈 ss:[0012FD38]=00E15F68, (ASCII "4C9BC7F1450EB1201E2D682D30498EC50B6DFB3F15DBC30E86FE6CD2DC0B310ED5D0A0D2112D64D64F667A2CAB3110E115C40D12F2C93C13573DA61D89B2D6CA")
2.5 然后对这个DES值MD5加密:MD5(DES(XOR(MD5(cyto)),DES(机器码)))
00504179 8B45 FC mov eax,dword ptr ss:[ebp-4] ; 用户名计算值的DES加密值
0050417C E8 5374F7FF call MeteorNe.0047B5D4 ; md5
00504181 8B55 DC mov edx,dword ptr ss:[ebp-24] ; 值
参数:
4C9BC7F1450EB1201E2D682D30498EC50B6DFB3F15DBC30E86FE6CD2DC0B310ED5D0A0D2112D64D64F667A2CAB3110E115C40D12F2C93C13573DA61D89B2D6CA
值:堆栈 ss:[0012FD30]=00E15FF8, (ASCII "28528b2dd30e89192bb06c5e100741e2")
这个暂时称为:用户名+机器码运算中间值,
[用户名+机器码运算中间值]=MD5(DES(XOR(MD5(cyto)),DES(机器码)))
2.6 运算分水岭:
判断注册表里注册码的长度,运算分水岭:
0050418C 8B83 98040000 mov eax,dword ptr ds:[ebx+498]
00504192 E8 0D0AF0FF call MeteorNe.00404BA4
00504197 83E8 0A sub eax,0A
0050419A 74 62 je short MeteorNe.005041FE ; 标准版
0050419C 83E8 02 sub eax,2
0050419F 74 17 je short MeteorNe.005041B8 ;
005041A1 83E8 02 sub eax,2
005041A4 0F84 18010000 je MeteorNe.005042C2 ; VIP版
005041AA 83E8 02 sub eax,2
005041AD 0F84 D3010000 je MeteorNe.00504386 ; 钻石版
005041B3 E9 A5030000 jmp MeteorNe.0050455D
根据注册表的加密值长度进行不同的运算。
因为我们是按照16位注册码来跟踪的,因此在0050419A处跳转。
2.7根据要求取值:Char[用户名+机器码运算中间值]
00504207 B9 05000000 mov ecx,5
0050420C BA 10000000 mov edx,10
00504211 8B45 FC mov eax,dword ptr ss:[ebp-4]
00504214 E8 EB0BF0FF call MeteorNe.00404E04 ; 根据要求取值
00504219 FF75 C4 push dword ptr ss:[ebp-3C] ; 92bb0
0050421C 8D45 C0 lea eax,dword ptr ss:[ebp-40]
0050421F 50 push eax
00504220 B9 04000000 mov ecx,4
00504225 BA 04000000 mov edx,4
0050422A 8B45 FC mov eax,dword ptr ss:[ebp-4]
0050422D E8 D20BF0FF call MeteorNe.00404E04
00504232 FF75 C0 push dword ptr ss:[ebp-40] ; 28b2
00504235 8D45 BC lea eax,dword ptr ss:[ebp-44]
00504238 50 push eax
00504239 B9 04000000 mov ecx,4
0050423E BA 12000000 mov edx,12
00504243 8B45 FC mov eax,dword ptr ss:[ebp-4]
00504246 E8 B90BF0FF call MeteorNe.00404E04
0050424B FF75 BC push dword ptr ss:[ebp-44] ; bb06
0050424E 8D45 B8 lea eax,dword ptr ss:[ebp-48]
00504251 50 push eax
00504252 B9 03000000 mov ecx,3
00504257 BA 1D000000 mov edx,1D
0050425C 8B45 FC mov eax,dword ptr ss:[ebp-4]
0050425F E8 A00BF0FF call MeteorNe.00404E04
00504264 FF75 B8 push dword ptr ss:[ebp-48] ; 41e
00504267 8D45 C8 lea eax,dword ptr ss:[ebp-38]
0050426A BA 04000000 mov edx,4
0050426F E8 F009F0FF call MeteorNe.00404C64 ; 连接
00504274 8B45 C8 mov eax,dword ptr ss:[ebp-38] ; (ASCII "92bb028b2bb0641e")
参数:28528b2dd30e89192bb06c5e100741e2
得到:92bb028b2bb0641e
2.8再次MD5:MD5(Char[用户名+机器码运算中间值])
00504274 8B45 C8 mov eax,dword ptr ss:[ebp-38] ; (ASCII "92bb028b2bb0641e")
00504277 8D55 CC lea edx,dword ptr ss:[ebp-34]
0050427A E8 5573F7FF call MeteorNe.0047B5D4 ; MD5
0050427F 8B45 CC mov eax,dword ptr ss:[ebp-34] ; 值
参数:92bb028b2bb0641e
值:堆栈 ss:[0012FD20]=00E16060, (ASCII "d8ffa201ad4be2508736a9d632ff8e05")
2.9 DES加密:DES(MD5(Char[用户名+机器码运算中间值]))
0050427F 8B45 CC mov eax,dword ptr ss:[ebp-34] ; 待加密数据
00504282 8D4D D0 lea ecx,dword ptr ss:[ebp-30]
00504285 BA 70465000 mov edx,MeteorNe.00504670 ; ASCII "Impressions"
0050428A E8 5965F7FF call MeteorNe.0047A7E8 ; DES
0050428F 8B45 D0 mov eax,dword ptr ss:[ebp-30] ; 值
参数:d8ffa201ad4be2508736a9d632ff8e05
结果:
堆栈 ss:[0012FD24]=00E160C0, (ASCII "0B8412DE40B70E5B7B18714BB5984459CE91633C25CCBC63450818C6348DF172")
2.10 取值:Char[DES(MD5(Char[用户名+机器码运算中间值]))]
0050428F 8B45 D0 mov eax,dword ptr ss:[ebp-30] ; 值
00504292 B9 0A000000 mov ecx,0A
00504297 BA 06000000 mov edx,6
0050429C E8 630BF0FF call MeteorNe.00404E04
参数:0B8412DE40B70E5B7B18714BB5984459CE91633C25CCBC63450818C6348DF172
结果:2DE40B70E5
2.11取值:Char[Char[DES(MD5(Char[用户名+机器码运算中间值]))]]
0050446B B9 06000000 mov ecx,6
00504470 BA 04000000 mov edx,4
00504475 A1 AC115100 mov eax,dword ptr ds:[5111AC]
0050447A E8 8509F0FF call MeteorNe.00404E04
0050447F 8B85 70FFFFFF mov eax,dword ptr ss:[ebp-90]
参数:2DE40B70E5
结果:堆栈 ss:[0012FCC4]=00E16148, (ASCII "40B70E")
2.12转换:Change[Char[Char[DES(MD5(Char[用户名+机器码运算中间值]))]]]
0050447F 8B85 70FFFFFF mov eax,dword ptr ss:[ebp-90] ; (ASCII "40B70E")
00504485 8D95 74FFFFFF lea edx,dword ptr ss:[ebp-8C]
0050448B E8 38ACFDFF call MeteorNe.004DF0C8 ; 转换
00504490 8B85 74FFFFFF mov eax,dword ptr ss:[ebp-8C] ; (ASCII "343042373045")
2.13 DES加密:DES(Change[Char[Char[DES(MD5(Char[用户名+机器码运算中间值]))]]])
00504490 8B85 74FFFFFF mov eax,dword ptr ss:[ebp-8C] ; (ASCII "343042373045")
00504496 8D8D 78FFFFFF lea ecx,dword ptr ss:[ebp-88]
0050449C BA D0465000 mov edx,MeteorNe.005046D0 ; ASCII "sgpj-nmmd"
005044A1 E8 4263F7FF call MeteorNe.0047A7E8 ; DES加密
005044A6 8B85 78FFFFFF mov eax,dword ptr ss:[ebp-88] ; 值
参数:343042373045
结果:堆栈 ss:[0012FCCC]=00E161B8, (ASCII "4647E7E41E3B465B2C30516C9360B162")
这样就得到了最后比较的参数之一:eax=4647E7E41E3B465B2C30516C9360B162
得到这个值经过的运算为:
DES(Change[Char[Char[DES(MD5(Char[用户名+机器码运算中间值]))]]])
其中[用户名+机器码运算中间值]=MD5(DES(XOR(MD5(cyto)),DES(机器码)))
整合在一起就是:DES(Change[Char[Char[DES(MD5(Char[MD5(DES(XOR(MD5(cyto)),DES(机器码)))]))]]])
经过4次DES+3次MD5+取值变换等。
2.14取注册表,对注册码加密值的运算:
取值:Char[注册码加密值]
005044B4 B9 06000000 mov ecx,6
005044B9 BA 04000000 mov edx,4
005044BE 8B83 98040000 mov eax,dword ptr ds:[ebx+498] ; 注册码(ASCII "DBDA07EDD2")
005044C4 E8 3B09F0FF call MeteorNe.00404E04
005044C9 8B85 64FFFFFF mov eax,dword ptr ss:[ebp-9C] ; (ASCII "A07EDD")
参数:注册码在注册表里的值(ASCII "DBDA07EDD2")
结果:(ASCII "A07EDD")
2.15 转换:Change[Char[注册码加密值]]
005044C9 8B85 64FFFFFF mov eax,dword ptr ss:[ebp-9C] ; (ASCII "A07EDD")
005044CF 8D95 68FFFFFF lea edx,dword ptr ss:[ebp-98]
005044D5 E8 EEABFDFF call MeteorNe.004DF0C8 ; 转换
005044DA 8B85 68FFFFFF mov eax,dword ptr ss:[ebp-98] ; (ASCII "413037454444")
2.16 DES加密:DES(Change[Char[注册码加密值]])
005044DA 8B85 68FFFFFF mov eax,dword ptr ss:[ebp-98] ; (ASCII "413037454444")
005044E0 8D8D 6CFFFFFF lea ecx,dword ptr ss:[ebp-94]
005044E6 BA D0465000 mov edx,MeteorNe.005046D0 ; ASCII "sgpj-nmmd"
005044EB E8 F862F7FF call MeteorNe.0047A7E8 ; DES加密
005044F0 8B95 6CFFFFFF mov edx,dword ptr ss:[ebp-94] ; 值
参数:413037454444
结果:得到最后比较的参数之一
堆栈 ss:[0012FCC0]=00E16258, (ASCII "D5EB524F0C87E52266E9EA42B23E3DB1")
这个值经过的运算:DES(Change[Char[注册码加密值]]),
其中注册码加密值=Char[DES(MD5(注册码),Impressions)]
2.17这样得到了2个比较的参数,往下来到比较的地方:
005044F0 8B95 6CFFFFFF mov edx,dword ptr ss:[ebp-94]
005044F6 58 pop eax
005044F7 E8 F407F0FF call MeteorNe.00404CF0
005044FC 75 5F jnz short MeteorNe.0050455D
如果eax=edx,那么就通过注册。
3.反推注册码:
开始输入的注册码经过md5加密+DES加密,好像不能反推,可是看看对用户名+机器码的运算就可以发现直接可以得到注册码,连反推都省了。
在对用户名+机器码的运算是这样的:
DES(Change[Char[Char[DES(MD5(Char[MD5(DES(XOR(MD5(cyto)),DES(机器码)))]),Impressions)]]],,sgpj-nmmd)
对注册码的运算是这样的:
DES(Change[Char[Char[DES(MD5(注册码),Impressions)]]],sgpj-nmmd)
因为key相同,而且取值也是一样,只要注册码=Char[MD5(DES(XOR(MD5(cyto)),DES(机器码)))]就可以,
也就是:Char[用户名+机器码运算中间值]=92bb028b2bb0641e=92BB028B2BB0641E
机器码:9030D2D9
用户名:cyto
注册码:92BB028B2BB0641E
呵呵,提示注册给我了:标准版。
其他长度的注册码的运算大通小异,只是在运算分水岭上走向不同而已,也同样可以反推得到注册码。