IrfanView 是一个很好的图片查看软件,她支持plugin,对图片的处理很方便。
其中有luratech公司的四个插件,分别对应Jpeg2000,Jpm,Ldf,Lwf 格式的支持。
其中tsrh出了,jpeg2000 and jpm两个注册机。大家到网上就可以找到。
但是对ldf and lwf 两个两个插件一直没有看见,可能是用的人不多吧。
这里主要讲LDF格式的插件的算法分析。
主程序和dll都用peid查了一下,发现是upx的壳,用于我这里主要是通过主程序对dll载入后调试。所以可以不用脱壳。用od直接载入。
在od中忽略所有异常,F9直接跑起来。如果有异常,把最后的异常添加到列表中。
打开IrfanView 的 [View]-> [Multipage Image] -> [create multiImage LDF] 菜单。
再点击[save options]->[show plugin information] 会出现注册框。
随便输入,点击 ok 后,消失。再打开[show plugin information] 发现还是没有注册。
查找注册表,发现内容放在注册表中。
下面很重要哦,打开od的执行模块列表,就是那个E的图标。看到LDF.dll已经载入了。双击,来到ldf.dll的领空。下断 bp RegQueryValueExA。
在IrfanView中点击[show plugin information],od断了下来。Alt+F9,回到ldf的领空。
我这里断在 100012B1 |. FF15 0CA00410
代码:
1000129A |. 51 push ecx ; /pBufSize 1000129B |. 8D5424 14 lea edx, dword ptr [esp+14] ; | 1000129F |. 55 push ebp ; |Buffer 100012A0 |. 52 push edx ; |pValueType 100012A1 |. 6A 00 push 0 ; |Reserved = NULL 100012A3 |. 68 90900510 push 10059090 ; |luratechldf 100012A8 |. 50 push eax ; |hKey 100012A9 |. C74424 24 000>mov dword ptr [esp+24], 100 ; | 100012B1 |. FF15 0CA00410 call dword ptr [<&ADVAPI32.RegQueryVa>; \RegQueryValueExA 100012B7 |. 85C0 test eax, eax ; 断在这里 100012B9 |. 74 16 je short 100012D1 ; 判断长度是否为0 100012BB |. 8B4C24 08 mov ecx, dword ptr [esp+8] 100012BF |. 51 push ecx ; /hKey 100012C0 |. FF15 10A00410 call dword ptr [<&ADVAPI32.RegCloseKe>; \RegCloseKey 100012C6 |. 5F pop edi 100012C7 |. 33C0 xor eax, eax 100012C9 |. 5D pop ebp 100012CA |. 81C4 0C010000 add esp, 10C 100012D0 |. C3 retn 100012D1 |> 8B5424 08 mov edx, dword ptr [esp+8] 100012D5 |. 53 push ebx 100012D6 |. 56 push esi 100012D7 |. 52 push edx ; /hKey 100012D8 |. FF15 10A00410 call dword ptr [<&ADVAPI32.RegCloseKe>; \RegCloseKey 100012DE |. 55 push ebp 100012DF |. E8 92820400 call 10049576 ; 这里面判断不能有小写字符 100012E4 |. 8BFD mov edi, ebp 100012E6 |. 83C9 FF or ecx, FFFFFFFF 100012E9 |. 33C0 xor eax, eax 100012EB |. 83C4 04 add esp, 4 100012EE |. 33D2 xor edx, edx 100012F0 |. BE 04000000 mov esi, 4 100012F5 |. F2:AE repne scas byte ptr es:[edi] 100012F7 |. F7D1 not ecx 100012F9 |. 49 dec ecx 100012FA |. 3BCE cmp ecx, esi ; 必须大于4位 100012FC |. 7E 22 jle short 10001320 100012FE |. 8D5C24 1C lea ebx, dword ptr [esp+1C] 10001302 |. 2BDE sub ebx, esi 10001304 |> 8A042E /mov al, byte ptr [esi+ebp] ; 取得第一段的长度 10001307 |. 3C 2D |cmp al, 2D 10001309 |. 74 15 |je short 10001320 1000130B |. 880433 |mov byte ptr [ebx+esi], al 1000130E |. 42 |inc edx 1000130F |. 8BFD |mov edi, ebp 10001311 |. 83C9 FF |or ecx, FFFFFFFF 10001314 |. 33C0 |xor eax, eax 10001316 |. 46 |inc esi 10001317 |. F2:AE |repne scas byte ptr es:[edi] 10001319 |. F7D1 |not ecx 1000131B |. 49 |dec ecx 1000131C |. 3BF1 |cmp esi, ecx 1000131E |.^ 7C E4 \jl short 10001304 10001320 |> 8D4424 1C lea eax, dword ptr [esp+1C] 10001324 |. C64414 1C 00 mov byte ptr [esp+edx+1C], 0 10001329 |. 50 push eax ; 这里要注意的是他是取第5位字符到后一个 '-' 的字符串。 1000132A |. E8 81EB0300 call 1003FEB0 ; 要进去,把字符串转换到数字 1000132F |. 8B9C24 280100>mov ebx, dword ptr [esp+128] 10001336 |. 83C4 04 add esp, 4 10001339 |. 8BFD mov edi, ebp 1000133B |. 83C9 FF or ecx, FFFFFFFF 1000133E |. 8903 mov dword ptr [ebx], eax ; 后面要的赋值 10001340 |. 33C0 xor eax, eax 10001342 |. 46 inc esi 10001343 |. 33D2 xor edx, edx 10001345 |. F2:AE repne scas byte ptr es:[edi] 10001347 |. F7D1 not ecx 10001349 |. 49 dec ecx 1000134A |. 3BF1 cmp esi, ecx 1000134C |. 7D 19 jge short 10001367 1000134E |> 8A0C2E /mov cl, byte ptr [esi+ebp] ; 后一段 复制 10001351 |. 8BFD |mov edi, ebp 10001353 |. 884C14 1C |mov byte ptr [esp+edx+1C], cl 10001357 |. 42 |inc edx 10001358 |. 83C9 FF |or ecx, FFFFFFFF 1000135B |. 33C0 |xor eax, eax 1000135D |. 46 |inc esi 1000135E |. F2:AE |repne scas byte ptr es:[edi] 10001360 |. F7D1 |not ecx 10001362 |. 49 |dec ecx 10001363 |. 3BF1 |cmp esi, ecx 10001365 |.^ 7C E7 \jl short 1000134E 10001367 |> C64414 1C 00 mov byte ptr [esp+edx+1C], 0 1000136C |. 8D5424 1C lea edx, dword ptr [esp+1C] 10001370 |. 52 push edx 10001371 |. E8 3AEB0300 call 1003FEB0 ; 要进去,把字符串转换到数字 10001376 |. 83C4 04 add esp, 4 10001379 |. 8943 04 mov dword ptr [ebx+4], eax ; 保存值 1000137C |. B8 01000000 mov eax, 1 10001381 |. 5E pop esi 10001382 |. 5B pop ebx 10001383 |. 5F pop edi 10001384 |. 5D pop ebp 10001385 |. 81C4 0C010000 add esp, 10C 1000138B \. C3 retn
代码:
1003FEB0 /$ 53 push ebx 1003FEB1 |. 55 push ebp 1003FEB2 |. 56 push esi 1003FEB3 |. 57 push edi 1003FEB4 |. 8B7C24 14 mov edi, dword ptr [esp+14] 1003FEB8 |> 833D CC080610>/cmp dword ptr [100608CC], 1 1003FEBF |. 7E 0F |jle short 1003FED0 1003FEC1 |. 0FB607 |movzx eax, byte ptr [edi] 1003FEC4 |. 6A 08 |push 8 1003FEC6 |. 50 |push eax 1003FEC7 |. E8 F2220000 |call 100421BE 1003FECC |. 59 |pop ecx 1003FECD |. 59 |pop ecx 1003FECE |. EB 0F |jmp short 1003FEDF 1003FED0 |> 0FB607 |movzx eax, byte ptr [edi] 1003FED3 |. 8B0D C0060610 |mov ecx, dword ptr [100606C0] ; LDF.100606CA 1003FED9 |. 8A0441 |mov al, byte ptr [ecx+eax*2] 1003FEDC |. 83E0 08 |and eax, 8 1003FEDF |> 85C0 |test eax, eax 1003FEE1 |. 74 03 |je short 1003FEE6 1003FEE3 |. 47 |inc edi 1003FEE4 |.^ EB D2 \jmp short 1003FEB8 1003FEE6 |> 0FB637 movzx esi, byte ptr [edi] 1003FEE9 |. 47 inc edi 1003FEEA |. 83FE 2D cmp esi, 2D ; '-' 1003FEED |. 8BEE mov ebp, esi 1003FEEF |. 74 05 je short 1003FEF6 1003FEF1 |. 83FE 2B cmp esi, 2B ; '+' 1003FEF4 |. 75 04 jnz short 1003FEFA 1003FEF6 |> 0FB637 movzx esi, byte ptr [edi] 1003FEF9 |. 47 inc edi 1003FEFA |> 33DB xor ebx, ebx ; ebx 清0 1003FEFC |> 833D CC080610>/cmp dword ptr [100608CC], 1 1003FF03 |. 7E 0C |jle short 1003FF11 1003FF05 |. 6A 04 |push 4 1003FF07 |. 56 |push esi 1003FF08 |. E8 B1220000 |call 100421BE 1003FF0D |. 59 |pop ecx 1003FF0E |. 59 |pop ecx 1003FF0F |. EB 0B |jmp short 1003FF1C 1003FF11 |> A1 C0060610 |mov eax, dword ptr [100606C0] 1003FF16 |. 8A0470 |mov al, byte ptr [eax+esi*2] 1003FF19 |. 83E0 04 |and eax, 4 1003FF1C |> 85C0 |test eax, eax 1003FF1E |. 74 0D |je short 1003FF2D 1003FF20 |. 8D049B |lea eax, dword ptr [ebx+ebx*4] 1003FF23 |. 8D5C46 D0 |lea ebx, dword ptr [esi+eax*2-30] 1003FF27 |. 0FB637 |movzx esi, byte ptr [edi] 1003FF2A |. 47 |inc edi 1003FF2B |.^ EB CF \jmp short 1003FEFC 1003FF2D |> 83FD 2D cmp ebp, 2D 1003FF30 |. 8BC3 mov eax, ebx 1003FF32 |. 75 02 jnz short 1003FF36 1003FF34 |. F7D8 neg eax 1003FF36 |> 5F pop edi 1003FF37 |. 5E pop esi 1003FF38 |. 5D pop ebp 1003FF39 |. 5B pop ebx 1003FF3A \. C3 retn
1003FED3 |. 8B0D C0060610 |mov ecx, dword ptr [100606C0] ; LDF.100606CA
LDF.100606CA 这里放了一个表,我以前是没有见过。内容如下
代码:
100606CA 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . . 100606DA 20 00 28 00 28 00 28 00 28 00 28 00 20 00 20 00 .(.(.(.(.(. . . 100606EA 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . . 100606FA 20 00 20 00 20 00 20 00 20 00 20 00 20 00 20 00 . . . . . . . . 1006070A 48 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00 H........ 1006071A 10 00 10 00 10 00 10 00 10 00 10 00 10 00 10 00 ........ 1006072A 84 00 84 00 84 00 84 00 84 00 84 00 84 00 84 00 ???????? 1006073A 84 00 84 00 10 00 10 00 10 00 10 00 10 00 10 00 ??...... 1006074A 10 00 81 00 81 00 81 00 81 00 81 00 81 00 01 00 .??????. 1006075A 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 ........ 1006076A 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 ........ 1006077A 01 00 01 00 01 00 10 00 10 00 10 00 10 00 10 00 ........ 1006078A 10 00 82 00 82 00 82 00 82 00 82 00 82 00 02 00 .??????. 1006079A 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 ........ 100607AA 02 00 02 00 02 00 02 00 02 00 02 00 02 00 02 00 ........ 100607BA 02 00 02 00 02 00 10 00 10 00 10 00 10 00 20 00 ....... .
代码:
100606CA 20(00)20 20 20 20 20 20 20 84 & 8 = 0 100606DA 20 28 28 28 28 28 20 20 10 & 8 = 0 100606EA 20 20 20 20 20 20 20 20 81 & 8 = 0 100606FA 20 20 20 20 20 20 20 20 01 & 8 = 0 1006070A 48 sp 10 ! 10 " 10 # 10 $ 10 % 10 & 10 ' 48 & 8 = 8 1006071A 10 ( 10 ) 10 * 10 + 10 , 10 - 10 . 10 / 1006072A 84 0 84 1 84 2 84 3 84 4 84 5 84 6 84 7 1006073A 84 8 84 9 10 : 10 ; 10 < 10 = 10 > 10 ? 1006074A 10 @ 81 A 81 B 81 C 81 D 81 E 81 F 01 G 1006075A 01 H 01 I 01 J 01 K 01 L 01 M 01 N 01 O 1006076A 01 P 01 Q 01 R 01 S 01 T 01 U 01 V 01 W 1006077A 01 X 01 Y 01 Z 10 [ 10 \ 10 ] 10 ^ 10 _ 1006078A 10 ` 82 a 82 b 82 c 82 d 82 e 82 f 02 g 1006079A 02 h 02 i 02 j 02 k 02 l 02 m 02 n 02 o 100607AA 02 p 02 q 02 r 02 s 02 t 02 u 02 v 02 w 100607BA 02 x 02 y 02 z 10 { 10 | 10 } 10 ~ 20
代码:
1003FF16 |. 8A0470 |mov al, byte ptr [eax+esi*2] 1003FF19 |. 83E0 04 |and eax, 4 1003FF1C |> 85C0 |test eax, eax 1003FF1E |. 74 0D |je short 1003FF2D
代码:
1003FF20 |. 8D049B |lea eax, dword ptr [ebx+ebx*4] 1003FF23 |. 8D5C46 D0 |lea ebx, dword ptr [esi+eax*2-30]
=============================================================================
从上面的代码返回后来到主要的地方了。
代码:
100015EC . E8 5FFCFFFF call 10001250 ; 从注册表读取注册码,并初步计算 100015F1 . 8A4424 1C mov al, byte ptr [esp+1C] 100015F5 . 83C4 08 add esp, 8 100015F8 . 3C 4C cmp al, 4C ; L 100015FA . 75 64 jnz short 10001660 100015FC . 807C24 15 44 cmp byte ptr [esp+15], 44 ; D 10001601 . 75 5D jnz short 10001660 10001603 . 807C24 16 46 cmp byte ptr [esp+16], 46 ; F 10001608 . 75 56 jnz short 10001660 1000160A . 8D4C24 0C lea ecx, dword ptr [esp+C] 1000160E . 51 push ecx 1000160F . E8 FCE40300 call 1003FB10 ; 算法比较 10001614 . 83C4 04 add esp, 4 10001617 . 83F8 01 cmp eax, 1 ; 判断是否注册 1000161A . 75 44 jnz short 10001660
X,Y都是数字。从 call 1003FB10这里进去。
代码:
1003FB10 /$ 8B4C24 04 mov ecx, dword ptr [esp+4] 1003FB14 |. 83EC 08 sub esp, 8 1003FB17 |. 8D4424 00 lea eax, dword ptr [esp] 1003FB1B |. 68 84060610 push 10060684 1003FB20 |. 50 push eax 1003FB21 |. 51 push ecx 1003FB22 |. E8 19000000 call 1003FB40 ; 进去 1003FB27 |. 8B4C24 10 mov ecx, dword ptr [esp+10] 1003FB2B |. 33C0 xor eax, eax 1003FB2D |. 85C9 test ecx, ecx 1003FB2F |. 0F94C0 sete al ; 根据ecx是否为0 ; 这里设置al,在上面的代码处比较 1003FB32 |. 83C4 14 add esp, 14 1003FB35 \. C3 retn
代码:
1003FB40 /$ 83EC 08 sub esp, 8 1003FB43 |. 53 push ebx 1003FB44 |. 55 push ebp 1003FB45 |. 56 push esi 1003FB46 |. 8B7424 20 mov esi, dword ptr [esp+20] 1003FB4A |. 8B4424 18 mov eax, dword ptr [esp+18] 1003FB4E |. 57 push edi 1003FB4F |. 8B3E mov edi, dword ptr [esi] 1003FB51 |. BA 2037EFC6 mov edx, C6EF3720 1003FB56 |. 8B08 mov ecx, dword ptr [eax] ; ecx 赋值 第一段数值 1003FB58 |. 8B40 04 mov eax, dword ptr [eax+4] ; eax 赋值 第二段数值 1003FB5B |. 897C24 14 mov dword ptr [esp+14], edi 1003FB5F |. 8B7E 04 mov edi, dword ptr [esi+4] 1003FB62 |. 897C24 10 mov dword ptr [esp+10], edi 1003FB66 |. 8B7E 08 mov edi, dword ptr [esi+8] 1003FB69 |. 8B76 0C mov esi, dword ptr [esi+C] 1003FB6C |. 897C24 24 mov dword ptr [esp+24], edi 1003FB70 |. 897424 1C mov dword ptr [esp+1C], esi 1003FB74 |. BF 20000000 mov edi, 20 1003FB79 |> 8B5C24 1C mov ebx, dword ptr [esp+1C] ; 高位 1003FB7D |. 8B6C24 24 mov ebp, dword ptr [esp+24] ; 低位 1003FB81 |. 8BF1 mov esi, ecx 1003FB83 |. C1EE 05 shr esi, 5 1003FB86 |. 03F3 add esi, ebx 1003FB88 |. 8BD9 mov ebx, ecx 1003FB8A |. C1E3 04 shl ebx, 4 1003FB8D |. 03DD add ebx, ebp 1003FB8F |. 8B6C24 14 mov ebp, dword ptr [esp+14] ; 低位 1003FB93 |. 33F3 xor esi, ebx 1003FB95 |. 8D1C0A lea ebx, dword ptr [edx+ecx] 1003FB98 |. 33F3 xor esi, ebx 1003FB9A |. 8B5C24 10 mov ebx, dword ptr [esp+10] ; 高位 1003FB9E |. 2BC6 sub eax, esi ; 1003FBA0 |. 8BF0 mov esi, eax 1003FBA2 |. C1EE 05 shr esi, 5 1003FBA5 |. 03F3 add esi, ebx 1003FBA7 |. 8BD8 mov ebx, eax 1003FBA9 |. C1E3 04 shl ebx, 4 1003FBAC |. 03DD add ebx, ebp 1003FBAE |. 33F3 xor esi, ebx 1003FBB0 |. 8D1C02 lea ebx, dword ptr [edx+eax] 1003FBB3 |. 33F3 xor esi, ebx 1003FBB5 |. 81C2 4786C861 add edx, 61C88647 1003FBBB |. 2BCE sub ecx, esi 1003FBBD |. 4F dec edi 1003FBBE |.^ 75 B9 jnz short 1003FB79 1003FBC0 |. 8B5424 20 mov edx, dword ptr [esp+20] 1003FBC4 |. 5F pop edi 1003FBC5 |. 5E pop esi 1003FBC6 |. 5D pop ebp 1003FBC7 |. 890A mov dword ptr [edx], ecx 1003FBC9 |. 8942 04 mov dword ptr [edx+4], eax 1003FBCC |. 5B pop ebx 1003FBCD |. 83C4 08 add esp, 8 1003FBD0 \. C3 retn
这四个是四个常数,对不同的插件有不同。
1003FB51 |. BA 2037EFC6 mov edx, C6EF3720
1003FBB5 |. 81C2 4786C861 add edx, 61C88647
也有两个常数。
1003FB56 |. 8B08 mov ecx, dword ptr [eax] ; ecx 赋值 第一段数值
1003FB58 |. 8B40 04 mov eax, dword ptr [eax+4] ; eax 赋值 第二段数值
ecx,eax的值就是上面LDF-XXXXXXX-YYYYYYYY,中xxx and yyyy分别的值。
我一开始就搞不清楚,主要显示的是16经制。在寄存器窗口双击对应的值可以看到。不过要注意上面提到的数值溢出问题。
上面代码的主要流程如下
代码:
int data = consNumber1; int firstInt = (int) firstNubmer; int secondInt = (int) secondNumber; int a = 0; int b = 0; for (int i = 32; i > 0; i--) { a = firstInt; a = a >>> 5; a = a + number4; b = firstInt; b = b << 4; b = b + number3; a = a ^ b; b = data + firstInt; a = a ^ b; secondInt = secondInt - a; // a = secondInt; a = a >>> 5; a = a + number2; b = secondInt; b = b << 4; b = b + number1; a = a ^ b; b = data + secondInt; a = a ^ b; data = data + consNumber2; firstInt = firstInt - a; } return (secondInt == 0); // 判断是不是为0,0的话就是注册的
需要再注意一点的是,反推出来得两个数字,如果是有符号的数,会出现负数,这个时候转换成相应的long型,就可以了
代码:
long result1 = number1 & 0xFFFFFFFFL;
声明:首发于看雪和龙族,如有转载,请注明。谢谢。