• 标 题:IrfanView算法浅析-第一次贴算法文章,希望不会错得太离谱!
  • 作 者:xbb-NCG
  • 时 间:2003年11月28日 09:49
  • 链 接:http://bbs.pediy.com

IrfanView算法浅析

【软件简介】:IrfanView是非常优秀的看图工具,支持几十种格式(需插件)。它还能对不同文件格式进行转换,批量重命名等。甚至还支持mpg、mp3、mid等多媒体格式的播放。丝毫不逊色于ACDSEE。
  

【声    明】:刚学汇编不久,下面分析中难免有错误之处,敬请诸位大侠赐教!

【程 序 名】:i_view32.ExE
【版    本】:3.85
【大    小】:492KB
【语    言】:Visual C++
【运行平台】:W9x/NT/W2K/WXP
【保护方式】:telock0.98加壳+注册码
【分析方式】:追注册码+注册机
【难    度】:容易(明码比较)
【工    具】:PE-SCAN v3.31/WKTtElockDumper v1.2/W32dasm8.93+/TRW2000 v1.23
【程序下载】:http://www.irfanview.com

【作    者】:xbb_NCG

【分    析】:
      1、获取信息:安装后运行程序,我们可以在程序的帮助里看到注册选项,单击后知道仅需要用户名和注册码两条信息。
      2、脱壳:用PE-SCAN v3.31检测出该程序用telock0.98加壳。OK,我们用WKTtElockDumper v1.2(风飘雪的网站上有下载)脱掉它。  
      3、静态分析:用W32Dasm8.93+反汇编脱壳后的程序。查看字符串,找不到有用的。
      4、动态跟踪:运行TRW2000 v1.23,选择脱壳后的程序,点击Load。按G,让程序先运行。然后我们点 帮助>注册 ,在弹出的注册框中填入用户名和注册码。我填的是xbb_NCG和123456789,先不在按确定。按CTRL+N呼出TRW,键入bpx hmemcpy,回车,键入G,回到程序,现在我们按确定,程序会被TRW中断,输入pmodule回到程序的领空,按2次f12,再输入pmodule我们会在下面的代码入停住。
   
* Reference To: USER32.DialogBoxParamA, Ord:0093h
                                  |
:00455115 FF15F4844C00            Call dword ptr [004C84F4]
:0045511B 85C0                    test eaxeax  <-我们停在这里,检测用户名和注册码是否为空。
:0045511D 0F84AD000000            je 004551D0  <-为零则跳
:00455123 8DBC245C050000          lea edidword ptr [esp+0000055C]  <-将用户名读入EDI
:0045512A 83C9FF                  or ecx, FFFFFFFF
:0045512D 33C0                    xor eaxeax                       <-EAX清零
:0045512F F2                      repnz  
:00455130 AE                      scasb                              <-扫描用户名位数
:00455131 F7D1                    not ecx                            <-ECX取反
:00455133 49                      dec ecx                            <-ECX减1
:00455134 83F902                  cmp ecx, 00000002                  <-ECX的值和2比较
:00455137 0F825C010000            jb 00455299                        <-用户名小于2位则跳
:0045513D 8DBC245C050000          lea edidword ptr [esp+0000055C]
:00455144 83C9FF                  or ecx, FFFFFFFF
:00455147 F2                      repnz
:00455148 AE                      scasb
:00455149 F7D1                    not ecx
:0045514B 49                      dec ecx
:0045514C 83F955                  cmp ecx, 00000055                  <-ECX的值和55比较
:0045514F 0F8744010000            ja 00455299                        <-用户名大于55位则跳
:00455155 8DBC245C060000          lea edidword ptr [esp+0000065C]
:0045515C 83C9FF                  or ecx, FFFFFFFF
:0045515F 33D2                    xor edxedx                       <-EDX置0
:00455161 F2                      repnz
:00455162 AE                      scasb
:00455163 F7D1                    not ecx
:00455165 49                      dec ecx
:00455166 85C9                    test ecxecx                      <-检测ECX是否为0.
:00455168 7E75                    jle 004551DF                       <-不小于0则跳到计算注册码Call

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00455192(C)
|
:0045516A 8A84145C060000          mov albyte ptr [esp+edx+0000065C]-----  <-取注册码的第一位
:00455171 3C30                    cmp al, 30     <-是否小于0                
:00455173 7C04                    jl 00455179                               
:00455175 3C39                    cmp al, 39     <-是否大于9                  
:00455177 7E05                    jle 0045517E                                
                                                                               
* Referenced by a (U)nconditional or (C)onditional Jump at Address:             
|:00455173(C)                                                                    |
|                                                                                |
                                                                                 |
* Possible Ref to Menu: IRFANVIEW, Item: "黣r(M)"                              |
                                  |                                              |
:00455179 BB01000000              mov ebx, 00000001  <-EBX置1                    |--这一段是将我们输入的
                                                                                 |假注册码转换为16进制
* Referenced by a (U)nconditional or (C)onditional Jump at Address:              |
|:00455177(C)                                                                    |
|                                                                                |
:0045517E 8DBC245C060000          lea edidword ptr [esp+0000065C]              |
:00455185 83C9FF                  or ecx, FFFFFFFF                               |
:00455188 33C0                    xor eaxeax                                  /
:0045518A 42                      inc edx       <-循环记数器,EDX加1           /
:0045518B F2                      repnz                                       /
:0045518C AE                      scasb                                      /
:0045518D F7D1                    not ecx                                   /
:0045518F 49                      dec ecx       <-假注册码位数,ECX减1     /
:00455190 3BD1                    cmp edxecx  <-比较EDX和ECX的值        /
:00455192 7CD6                    jl 0045516A  __________________________/   <-循环记数小于注册码位数则跳
:00455194 85DB                    test ebxebx <-EBX是否为0?
:00455196 7447                    je 004551DF   <-为0就跳到注册码计算处。
:00455198 8B0D4C394F00            mov ecxdword ptr [004F394C]
:0045519E 6804010000              push 00000104
:004551A3 6860C84F00              push 004FC860

....................

***********************************

    我们由上面代码中的455192处跳来此处:
    
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00455168(C), :00455196(C)
|
:004551DF 8D84245C060000          lea eaxdword ptr [esp+0000065C]  <-用户名入EAX
:004551E6 8D8C245C050000          lea ecxdword ptr [esp+0000055C]  <-注册码入ECX
:004551ED 50                      push eax                           <-EAX入堆栈
:004551EE 51                      push ecx                           <-ECX入堆栈
:004551EF E8CC16FEFF              call 004368C0                      <-关键Call,计算注册码处,后面分析。
:004551F4 83C408                  add esp, 00000008                  <-在这里D EAX可以见到真的注册码
:004551F7 85C0                    test eaxeax  
:004551F9 7533                    jne 0045522E                       <-不=0则跳,到注册成功处。
:004551FB 8B154C394F00            mov edxdword ptr [004F394C]
:00455201 6804010000              push 00000104
:00455206 6860C84F00              push 004FC860

....................

:00455211 FF15A0834C00            Call dword ptr [004C83A0]
:00455217 A188CB4F00              mov eaxdword ptr [004FCB88]
:0045521C 6830200000              push 00002030
:00455221 6800DF4F00              push 004FDF00
:00455226 6860C84F00              push 004FC860
:0045522B 50                      push eax
:0045522C EB9C                    jmp 004551CA                       <-这里跳到出错提示

***********************************

4551EF处关键Call,我们进入。
* Referenced by a CALL at Addresses:
|:00436D8E   , :004550A4   , :004551EF   
|
:004368C0 8B442408                mov eaxdword ptr [esp+08]
:004368C4 83EC14                  sub esp, 00000014
:004368C7 53                      push ebx---
:004368C8 55                      push ebp    
:004368C9 56                      push esi     |--各寄存入栈
:004368CA 57                      push edi    /
:004368CB 50                      push eax___/
:004368CC 33DB                    xor ebxebx   <-EBX清零
:004368CE E82AFF0700              call 004B67FD  <-此Call将我们输入的注册码即123456789转为16进制为75BCD15
                                                   EDX=4ED99A 这个数在后的要用到。
:004368D3 8B74242C                mov esidword ptr [esp+2C]
:004368D7 8BE8                    mov ebpeax
:004368D9 8BFE                    mov ediesi
:004368DB 83C9FF                  or ecx, FFFFFFFF
:004368DE 33C0                    xor eaxeax
:004368E0 83C404                  add esp, 00000004
:004368E3 33D2                    xor edxedx
:004368E5 F2                      repnz
:004368E6 AE                      scasb
:004368E7 F7D1                    not ecx
:004368E9 49                      dec ecx
:004368EA 85C9                    test ecxecx
:004368EC 7E17                    jle 00436905

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436903(C)
|
:004368EE 0FBE0C32                movsx ecxbyte ptr [edx+esi]-
:004368F2 03D9                    add ebxecx                   
:004368F4 8BFE                    mov ediesi                    
:004368F6 83C9FF                  or ecx, FFFFFFFF                 
:004368F9 33C0                    xor eaxeax                      |将用户名的ASCII码逐位相加,和放入EBX
:004368FB 42                      inc edx                           |
:004368FC F2                      repnz                            / 
:004368FD AE                      scasb                           /
:004368FE F7D1                    not ecx                        /
:00436900 49                      dec ecx                       /
:00436901 3BD1                    cmp edxecx                 /<-比较EDX和ECX的值
:00436903 7CE9                    jl 004368EE  _______________/ <-小于则跳

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:004368EC(C)
|
:00436905 B804010000              mov eax, 00000104                    <-104放入EAX

* Possible Reference to Dialog: DialogID_0402, CONTROL_ID:000A, ""
                                  |
:0043690A 6A0A                    push 0000000A                        <-A入栈
:0043690C 2BC3                    sub eaxebx                         
:0043690E 99                      cdq                                  <-扩展EAX
:0043690F 33C2                    xor eaxedx                         
:00436911 2BC2                    sub eaxedx                        
:00436913 054C010000              add eax, 0000014C                    
:00436918 8D14C500000000          lea edxdword ptr [8*eax+00000000]  
:0043691F 2BD0                    sub edxeax                        
:00436921 8D0C90                  lea ecxdword ptr [eax+4*edx]      
:00436924 8D542414                lea edxdword ptr [esp+14]
:00436928 52                      push edx
:00436929 8D3448                  lea esidword ptr [eax+2*ecx]       <-ESI=A119
:0043692C C1E603                  shl esi, 03                          <-A119做逻辑左移
:0043692F 56                      push esi
:00436930 E851B00800              call 004C1986                        <-令ESP+10=关键数,此关
                                                                         键数根据用户名的不同而不同。
:00436935 83C40C                  add esp, 0000000C
:00436938 81FE3F420F00            cmp esi, 000F423F                    <-ESI与999999比较
:0043693E 0F87EF000000            ja 00436A33                          <-大于则跳走
:00436944 8A4C2414                mov clbyte ptr [esp+14]      <-cl=2----------------ESP+10是注册码第1位
:00436948 8A442415                mov albyte ptr [esp+15]      <-al=8-----------------  这几行是对上面
:0043694C 8A542413                mov dlbyte ptr [esp+13]      <-dl=9------------------关键数进行移位计
:00436950 884C2416                mov byte ptr [esp+16], cl      <-注册码第七位为ESP+16=2-算的,六位数移
:00436954 8A4C2411                mov clbyte ptr [esp+11]      <-cl=2--------------------位后成为九位数
:00436958 88442418                mov byte ptr [esp+18], al      <-注册码第九位为ESP+18=8--- 即注册码的位
:0043695C 8A442412                mov albyte ptr [esp+12]      <-al=9----------------------|数。但这不是
:00436960 88542415                mov byte ptr [esp+15], dl      <-注册码第六位为ESP+15=9----|真的注册码,
:00436964 884C2412                mov byte ptr [esp+12], cl      <-注册码第三位为ESP+12=2----|真注册码的第
:00436968 8B4C2414                mov ecxdword ptr [esp+14]    <-取注册码的第五位         /二、五、八位
:0043696C 81E1FF000000            and ecx, 000000FF              <-ECX=32                  /要通过这个九位
:00436972 88442413                mov byte ptr [esp+13], al      <-注册码第四位为ESP+13=9-/数来计算得出。
:00436976 8BC1                    mov eaxecx                   
:00436978 C1E005                  shl eax, 05                    
:0043697B 2BC1                    sub eaxecx                   
:0043697D 8B4C2418                mov ecxdword ptr [esp+18]    <-取注册码第9位数
:00436981 81E1FF000000            and ecx, 000000FF              
:00436987 8D1440                  lea edxdword ptr [eax+2*eax
:0043698A 8D0489                  lea eaxdword ptr [ecx+4*ecx
:0043698D C1E003                  shl eax, 03                    
:00436990 2BC1                    sub eaxecx                   
:00436992 2BC2                    sub eaxedx                  
:00436994 99                      cdq
:00436995 8BC8                    mov ecxeax                   
:00436997 33CA                    xor ecxedx                   
:00436999 2BCA                    sub ecxedx                  
:0043699B 8D0489                  lea eaxdword ptr [ecx+4*ecx
:0043699E C1E003                  shl eax, 03                    <-EAX的值左移3次
:004369A1 2BC1                    sub eaxecx                   

* Possible Ref to Menu: IRFANVIEW, Item: "?u JPM(J)"
                                  |

* Possible Reference to Dialog: DialogID_0402, CONTROL_ID:0009, ""
                                  |
:004369A3 B909000000              mov ecx, 00000009              <-ECX置9
:004369A8 99                      cdq
:004369A9 F7F9                    idiv ecx                       <-EAX/9 商为29BE,余数为0
:004369AB 8B442413                mov eaxdword ptr [esp+13]    <-取注册码的第四位
:004369AF 25FF000000              and eax, 000000FF              <-EAX=39
:004369B4 80C230                  add dl, 30                    
:004369B7 88542417                mov byte ptr [esp+17], dl      <-注册码第8位为ESP+17=0
:004369BB 8D1440                  lea edxdword ptr [eax+2*eax
:004369BE C1E204                  shl edx, 04                   
:004369C1 2BD0                    sub edxeax                   
:004369C3 8B442415                mov eaxdword ptr [esp+15]    <-取注册码的第六位
:004369C7 25FF000000              and eax, 000000FF              
:004369CC 8D0CC0                  lea ecxdword ptr [eax+8*eax
:004369CF 8D0488                  lea eaxdword ptr [eax+4*ecx
:004369D2 8D0442                  lea eaxdword ptr [edx+2*eax
:004369D5 99                      cdq
:004369D6 33C2                    xor eaxedx                  
:004369D8 2BC2                    sub eaxedx                   
:004369DA 8D0CC0                  lea ecxdword ptr [eax+8*eax
:004369DD 8D0488                  lea eaxdword ptr [eax+4*ecx

* Possible Ref to Menu: IRFANVIEW, Item: "?u JPM(J)"
                                  |

* Possible Reference to Dialog: DialogID_0402, CONTROL_ID:0009, ""
                                  |
:004369E0 B909000000              mov ecx, 00000009
:004369E5 D1E0                    shl eax, 1                     
:004369E7 99                      cdq
:004369E8 F7F9                    idiv ecx                       <-EAX/9 商为DD84 余数6
:004369EA 8B4C2410                mov ecxdword ptr [esp+10]    <-取注册码的第一位
:004369EE 81E1FF000000            and ecx, 000000FF              
:004369F4 8D0449                  lea eaxdword ptr [ecx+2*ecx
:004369F7 8D04C0                  lea eaxdword ptr [eax+8*eax
:004369FA D1E0                    shl eax, 1                     
:004369FC 2BC1                    sub eaxecx                   
:004369FE 80C230                  add dl, 30                     
:00436A01 88542414                mov byte ptr [esp+14], dl      <-注册码第五位为ESP+14=6
:00436A05 8B4C2411                mov ecxdword ptr [esp+11]    <-取注册码的第二位
:00436A09 81E1FF000000            and ecx, 000000FF
:00436A0F 8D14CD00000000          lea edxdword ptr [8*ecx+00000000]  
:00436A16 2BD1                    sub edxecx                   
:00436A18 8D1492                  lea edxdword ptr [edx+4*edx
:00436A1B 2BC2                    sub eaxedx                   
:00436A1D 99                      cdq
:00436A1E 8BC8                    mov ecxeax                   
:00436A20 33CA                    xor ecxedx                   
:00436A22 2BCA                    sub ecxedx                   
:00436A24 8D0449                  lea eaxdword ptr [ecx+2*ecx
:00436A27 8D04C0                  lea eaxdword ptr [eax+8*eax
:00436A2A D1E0                    shl eax, 1                    
:00436A2C 2BC1                    sub eaxecx                   
:00436A2E E9F5000000              jmp 00436B28

..................中间省略

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00436A2E(U)
|
:00436B28 99                      cdq

* Possible Ref to Menu: IRFANVIEW, Item: "?u JPM(J)"
                                  |

* Possible Reference to Dialog: DialogID_0402, CONTROL_ID:0009, ""
                                  |
:00436B29 B909000000              mov ecx, 00000009
:00436B2E C644241900              mov [esp+19], 00
:00436B33 F7F9                    idiv ecx                       <-商为15EC,余数为EDX=1
:00436B35 80C230                  add dl, 30                     <-dl=dl+30=31
:00436B38 88542411                mov byte ptr [esp+11], dl      <-注册码第2位为1
:00436B3C 8D542410                lea edxdword ptr [esp+10]    <-真注册码入EDX
:00436B40 52                      push edx                       <-EDX入栈
:00436B41 E8B7FC0700              call 004B67FD                  <-将真注册码转换为16进制,EBP为假注册码
:00436B46 83C404                  add esp, 00000004
:00436B49 33C9                    xor ecxecx                   <-ECX清零
:00436B4B 3BE8                    cmp ebpeax                   <-真假注册码比较
:00436B4D 5F                      pop edi
:00436B4E 5E                      pop esi
:00436B4F 0F94C1                  sete cl                        <-设置cl
:00436B52 5D                      pop ebp
:00436B53 8BC1                    mov eaxecx                   <-EAX清零
:00436B55 5B                      pop ebx
:00436B56 83C414                  add esp, 00000014
:00436B59 C3                      ret                            <-返回EAX值




***********************************

程序的注册信息保存在程序的安装目录里的i_view32.ini文件中。
取消注册只要把此文件中的[Registration]段下的name和code两行删除即可。


***********************************

注册算法总结:软件根据用户名算出一个六位关键数,再将其进行移位,形成一个九位数。然后用用这个九位数算出注册码。最后将真注册码转换为16进制数与假注册码的16进制数进行比较。

关键数与九位数关系如下:

关键数的第六位---------九位数的第九位
关键数的第五位---------九位数的第五、七位
关键数的第四位---------九位数的第六位
关键数的第三位---------九位数的第四位
关键数的第二位---------九位数的第二、三位
关键数的第一位---------九位数的第一位
                       九位数的第八位为空

九位数中除第二、五、八位需要由其它数计算得出外,第一、三、四、六、七、九位就是真注册码的相应位。

注册码的第二位由九位数中的第一、二位计算得出;
注册码的第五位由九位数中的第四、六位计算得出;
注册码的第八位由九位数中的第五、九位计算得出。

***********************************




    ..............................................
    .                 __         ___   ____  __  .
    .   / |    |    |   |   | |   | |    |   | .
    .  /  |    |    |   |   | |     |  __    | .
    .  /  |~~| |~~| |   |   | |     |    |   | .
    . /   |__| |__| |__ |   | |___| |____| __| .
    ..............................................
                             
                      2003.11.28 傍晚