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  处的方法,这里主要的目的是把字符串转换成数字。但是其中要注意的是 由于 里面用到了 4字节 的长度。所以字符串的数值会溢出。

代码:
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  ....... .
经过分析,发现是一个判断ascii字符的表。我标记了一部分。内容如下
代码:
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  
里面数字是84。。。
代码:
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]
同时可以看到,超过4字节的数值都丢了。那么数值就是最大 4294967295。在调试的时候不要大过这个数
=============================================================================

从上面的代码返回后来到主要的地方了。
代码:
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                  
到这里我们可以看到注册码的格式  LDF-XXXXXXXXX-YYYYYYYYYY
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
 1003FB22  |.  E8 19000000   call    1003FB40  就是具体的算法比较了。
代码:
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
dword ptr [esp+1C], dword ptr [esp+24],dword ptr [esp+14] ,dword ptr [esp+10] 
这四个是四个常数,对不同的插件有不同。
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;
最后附带一个算好的 sn :  LDF-39301713-2160942820

声明:首发于看雪和龙族,如有转载,请注明。谢谢。