首页
论坛
课程
招聘
[原创]一个窗口隐藏工具的注册验证流程分析(一)
2009-11-14 21:27 5421

[原创]一个窗口隐藏工具的注册验证流程分析(一)

2009-11-14 21:27
5421
【文章标题】: 一个窗口隐藏工具的注册验证流程分析
【文章作者】: FishSeeWater
【软件名称】: 为支持看雪老大,自己找找吧:)
【软件大小】: 264K
【下载地址】: 自己搜索下载
【加壳方式】: ASPack
【保护方式】: Aspack+RSA
【编写语言】: Delphi
【使用工具】: OllyIce IDA RSATool BigIntCalc
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  一款窗口隐藏的工具,可定制性很高,是本人目前见过的窗口隐藏类软件中比较不错的。
  
  这款软件在04年就打过他的主意,不过那时功力尚浅,分析了一个通宵给爆掉了,之后就一直再没动过它,爆破之后也
  不用它。最近由于工作需要(想在工作时做点休闲的事:))上网找窗口隐藏软件,又把它给找着了(有缘呀:)),
  忍不住旧情复燃,重新分析一下。
  好开工:
  1、当然是查看软件的母亲,这容易,由于以前分析过,知道它是Delphi生的,穿ASPack衣服(好朴素呀,我喜欢:))。
  2、脱衣服,5年了,现在VMP大行其道,而她还穿戴着Aspack,真是让人倍感亲切:),ASPackDie轻松搞定。
   有一个form.dll文件没有加壳。
  3、运行脱壳后的程序,会发现出错,连Explorer都崩了。分析了好长时间,都没有发现什么原因退出的。只好带壳调试,
   OD载入,运行,这里会发现系统假死,鼠标点任何东东都不反应,但系统级按键还是有反应的,估计是钩子问题。
  经过分析,在程序运行时会调用form.dll中的过程在系统中安装 Shell Mouse 等钩子。OK为了一劳永逸,先把Hook干掉:
  一:Patch掉Hook
  
  003A8718     .  A1 00A83>mov     eax, dword ptr ds:[3AA800]                                  ; |
  003A871D     .  50       push    eax                                                         ; |hWnd => 00030044 (class='Shell_TrayWnd')
  003A871E     .  E8 F1BFF>call    <jmp.&user32.GetWindowThreadProcessId>                      ; \GetWindowThreadProcessId
  003A8723     .  8BD8     mov     ebx, eax
  003A8725        EB 43    jmp     short form.003A876A                                         //这里向下会安装3个HOOK,直接JMP到Hook末尾
  003A8727        90       nop
  003A8728        90       nop
  003A8729        8C90 506>mov     word ptr ds:[eax+83346850], ss
  003A872F     ?  3A00     cmp     al, byte ptr ds:[eax]
  003A8731     .  6A 0D    push    0D                                                          ; |HookType = 13.
  003A8733     .  E8 0CC0F>call    <jmp.&user32.SetWindowsHookExA>                             ; \SetWindowsHookExA
  003A8738     .  A3 F4A73>mov     dword ptr ds:[3AA7F4], eax
  003A873D     .  6A 00    push    0
  003A873F     .  A1 60A63>mov     eax, dword ptr ds:[3AA660]
  003A8744     .  50       push    eax
  003A8745     .  68 80843>push    form.003A8480
  003A874A     .  0D 09E8F>or      eax, BFF3E809
  003A874F        FF       db      FF
  003A8750     .  FFA3 F8A>jmp     dword ptr ds:[ebx+3AA7F8]
  003A8756     .  6A 00    push    0                                                           ; /ThreadID = 0
  003A8758     .  A1 60A63>mov     eax, dword ptr ds:[3AA660]                                  ; |
  003A875D     .  50       push    eax                                                         ; |hModule => 003A0000 (form)
  003A875E     .  68 34863>push    form.003A8634                                               ; |Hookproc = form.003A8634
  003A8763     .  6A 0D    push    0D                                                          ; |HookType = 13.
  003A8765     .  E8 DABFF>call    <jmp.&user32.SetWindowsHookExA>                             ; \SetWindowsHookExA
  003A876A     .  A3 FCA73>mov     dword ptr ds:[3AA7FC], eax
  003A876F     .  833D F4A>cmp     dword ptr ds:[3AA7F4], 0
  003A8776     .  0F95C0   setne   al
  003A8779     .  F6D8     neg     al
  

  Patch后,备份下一原文件,保存可执行文件。好了,这样系统就不会再卡死了。
  用DeDe找到 “导入许可文件”按钮事件的入口,在OD中下断。然后用IDA把 脱壳的程序给拆了,生成Map文件,
  在OD中导入。由于按导入许可文件后,会程序会要你导入*.lic文件,所以我们先构建一个假Lic文件,在里面输入
  两行文字:
    UserName:FishSeeWater
    LicNum:HelloWorld
  二:分析“导入许可文件”事件
  
  004949D1    |.  55       push    ebp
  004949D2    |.  68 064D4>push    <HideHelp.loc_494D06>
  004949D7    |.  64:FF30  push    dword ptr fs:[eax]
  004949DA    |.  64:8920  mov     dword ptr fs:[eax], esp
  004949DD    |.  8D45 F4  lea     eax, [local.3]
  004949E0    |.  BA 1C4D4>mov     edx, <HideHelp.aYw08f8h4tkwt_0>                             ;  yw08f8h4tkwt6gotdbsnrgo3xnvgwp=qwyurhgxwcyymp5pkcu4gonsvqdbxzz10+jrspozkmpm3bv=ydi18zlynllezjbodicfln1glb28o99ulxhquaguv9m
  004949E5    |.  E8 86FDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  004949EA    |.  8D45 F0  lea     eax, [local.4]
  004949ED    |.  BA A04D4>mov     edx, <HideHelp.aP8rvf1agdmfo_0>                             ;  p8rvf1agdmfowqiewfdr4pj=snyqk7irbepjhi=fz+sm24be22f2ditz4ub=+bet7bmgshs8q6dmzfhwge9a+2bfmnavp2elasj1xu50+rhcy3qjjuqlx5wrgu
  004949F2    |.  E8 79FDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  004949F7    |.  8D45 EC  lea     eax, [local.5]
  004949FA    |.  BA 244E4>mov     edx, <HideHelp.a81orb447y3he_0>                             ;  81orb447y3he0fnlyfswtuepqcnr1qppib83fh+jrdze5c53tzf=iyipol0xpcdpmlopz2loryh9akb=vtwfe4ojofuxgo2cgmuqndkgqp15obgznbbpgtv+au
  004949FF    |.  E8 6CFDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A04    |.  8D45 E8  lea     eax, [local.6]
  00494A07    |.  BA A84E4>mov     edx, <HideHelp.aAet7r0zhomst_0>                             ;  aet7r0zhomsteemprkk8bfdtsat2syhhxoiwnbwtj61kn2cnkf3rg7mzwbi1om5r1o++ryh5p6wss=ylweo1ija+oejg9greslomk36p3remajaw3mbwfiqbhf
  00494A0C    |.  E8 5FFDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A11    |.  8D45 E4  lea     eax, [local.7]
  00494A14    |.  BA 2C4F4>mov     edx, <HideHelp.a7txt1bvikexp_0>                             ;  7txt1bvikexpqg+xmmjzi8khgxchsbbyozexm9m=cubh4h1i1kxroxb6dm9rbznfejjrqgscrzbid1cke4mg58=insd+wufkforjqotevz8ooc3ueg4mx7djcr=4o8cywem6ehy
  00494A19    |.  E8 52FDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A1E    |.  8D45 E0  lea     eax, [local.8]
  00494A21    |.  BA BC4F4>mov     edx, <HideHelp.aHxzm402e5t5q_0>                             ;  hxzm402e5t5qzjtoaji2vthqmk7fxcjoeadsgkry7baihvhefhgqtrwznipx0wh0gi+jk9ss9tbz8bcd4e+9bpc7ms1it9c2vqqzs1hiazkj+i04915tce0dy6wsrfzfzryvqrnou1bblzfopoaamwq=ey9sus93m5lrq
  00494A26    |.  E8 45FDF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A2B    |.  FF75 F4  push    [local.3]
  00494A2E    |.  FF75 F0  push    [local.4]
  00494A31    |.  FF75 EC  push    [local.5]
  00494A34    |.  FF75 E8  push    [local.6]
  00494A37    |.  FF75 E4  push    [local.7]
  00494A3A    |.  FF75 E0  push    [local.8]
  00494A3D    |.  8D45 DC  lea     eax, [local.9]                                              ;  将上面的串连接起来
  00494A40    |.  BA 06000>mov     edx, 6
  00494A45    |.  E8 2A00F>call    <HideHelp.System::__linkproc__ LStrCatN(void)>
  00494A4A    |.  BE F3F05>mov     esi, 59F0F3
  00494A4F    |.  8D55 DC  lea     edx, [local.9]
  00494A52    |.  8B45 DC  mov     eax, [local.9]
  00494A55    |.  E8 F272F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>      ; Base编码处理一下
  00494A5A    |.  8D4D 9C  lea     ecx, [local.25]
  00494A5D    |.  8BD6     mov     edx, esi
  00494A5F    |.  8B45 DC  mov     eax, [local.9]
  00494A62    |.  E8 91F1F>call    <HideHelp.subN_111111_Decrypt>                              ;经过这个Call后,字符串变成了10进制的串了。
  00494A67    |.  8B55 9C  mov     edx, [local.25]
  00494A6A    |.  8D45 DC  lea     eax, [local.9]
  00494A6D    |.  E8 FEFCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A72    |.  8D45 D8  lea     eax, [local.10]
  00494A75    |.  BA 6C504>mov     edx, <HideHelp.aZnznshe3uswk_0>                             ;  znznshe3uswkxyfshxsc1vysc8ar3huo6hs4coiiametdexdsqfc+gzd5p+a5byhzn0oljin6v+olnoz060duzdrznrnws7ebikrqb6nlcjnp+mtdlk4easn3f
  00494A7A    |.  E8 F1FCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A7F    |.  8D45 D4  lea     eax, [local.11]
  00494A82    |.  BA F0504>mov     edx, <HideHelp.aRfvG30qI5ou6_0>                             ;  rfv+g30q+i5ou6upkf7rbt07pxrvaupf88dyb4me6okcpoxastrrwiifci26rt82tx4bnfhxoxxum=dih5p+ga9k=cxamo5dqqwqvkvrzdw9c6n1rtwtxwryli
  00494A87    |.  E8 E4FCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A8C    |.  8D45 D0  lea     eax, [local.12]
  00494A8F    |.  BA 74514>mov     edx, <HideHelp.aSbaffnknyl2f_0>                             ;  sbaffnknyl2fuqmlhpza0s40wclm5acw4smlslhajwxdgekhjf8kahzk+nqovfdk7ycapfum2=6il2prn9oogq9mrr2d+f6m+w2trena9ryhx1hv5pd+dpaaaf
  00494A94    |.  E8 D7FCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494A99    |.  8D45 CC  lea     eax, [local.13]
  00494A9C    |.  BA F8514>mov     edx, <HideHelp.aDuqu5qwlwhx6_0>                             ;  duqu5qwlwhx6bozkir2tp0+sxz+hkedbjpzlk+ucojgzscjtzy2m=aqf9rei1=sex4znk1aqlwmoesfn8qwd4i3jkgnri12nof=dxhfvvhmqfcixkca2z3ypbx
  00494AA1    |.  E8 CAFCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494AA6    |.  8D45 C8  lea     eax, [local.14]
  00494AA9    |.  BA 7C524>mov     edx, <HideHelp.aErlkefd9pnrg_0>                             ;  erlkefd9pnrg9awpwmoafg6zc+mqc0fcrouiattiudiuntuvt+tj+k1wevevzp0rkmx7zvch6oukkqgqile=k=htdwvejsambvfkowjoi5iq6oconwqr3rtfi=5bcxebbfto0epzk
  00494AAE    |.  E8 BDFCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494AB3    |.  8D45 C4  lea     eax, [local.15]
  00494AB6    |.  BA 10534>mov     edx, <HideHelp.aIma63sqrvi6C_0>                             ;  ima63sqrvi6+ciemwfzaf0x6ebiblgz1lqwmadqekx5sfzjnwnn9dg0xsa2cb5ymea5oqb3dboyv+w=zm+iwerztyhuu2pspzfo=vdqzqwslehadgrxn4ut1lm+nzjamwk3ihzfifb8awzcofxxu=weo5yujosztkff
  00494ABB    |.  E8 B0FCF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494AC0    |.  FF75 D8  push    [local.10]
  00494AC3    |.  FF75 D4  push    [local.11]
  00494AC6    |.  FF75 D0  push    [local.12]
  00494AC9    |.  FF75 CC  push    [local.13]
  00494ACC    |.  FF75 C8  push    [local.14]
  00494ACF    |.  FF75 C4  push    [local.15]
  00494AD2    |.  8D45 C0  lea     eax, [local.16]                                             ;  处理过程同上
  00494AD5    |.  BA 06000>mov     edx, 6
  00494ADA    |.  E8 95FFF>call    <HideHelp.System::__linkproc__ LStrCatN(void)>
  00494ADF    |.  8D55 C0  lea     edx, [local.16]
  00494AE2    |.  8B45 C0  mov     eax, [local.16]
  00494AE5    |.  E8 6272F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>
  

  看到上面两个恐怖的串,估计是碰到密码学算法了。继续向下看(中间打开文件对话框 省略N行 )
  
  00494BA7    |. /0F84 DC0>je      <HideHelp.loc_494C89>
  00494BAD    |. |8D55 84  lea     edx, [local.31]
  00494BB0    |. |8BC3     mov     eax, ebx
  00494BB2    |. |E8 99B9F>call    <HideHelp.Dialogs::TOpenDialog::GetFileName(void)>
  00494BB7    |. |8B45 84  mov     eax, [local.31]
  00494BBA    |. |8D55 A4  lea     edx, [local.23]
  00494BBD    |. |E8 72F1F>call    <HideHelp.sub_483D34>                                       ;  读第一行:UserName....
  00494BC2    |. |837D A4 >cmp     [local.23], 0
  00494BC6    |. |0F84 D70>je      <HideHelp.loc_494CA3>                                       ;  失败跳走
  00494BCC    |. |8D55 80  lea     edx, [local.32]
  00494BCF    |. |8BC3     mov     eax, ebx
  00494BD1    |. |E8 7AB9F>call    <HideHelp.Dialogs::TOpenDialog::GetFileName(void)>
  00494BD6    |. |8B45 80  mov     eax, [local.32]
  00494BD9    |. |8D55 A0  lea     edx, [local.24]
  00494BDC    |. |E8 FBF1F>call    <HideHelp.sub_483DDC>
  00494BE1    |. |8D55 F8  lea     edx, [local.2]
  00494BE4    |. |8B45 A0  mov     eax, [local.24]                                             ;  读第二行:LicNum....
  00494BE7    |. |E8 6071F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>      ;  将用户名Base64解码
  00494BEC    |. |8D55 B8  lea     edx, [local.18]  
  00494BEF    |. |8B45 DC  mov     eax, [local.9]                                              ;  转换第一个长串为十进制大数
  00494BF2    |. |E8 4975F>call    <HideHelp.FGInt_Base10StringToFGInt>
  00494BF7    |. |8D55 B0  lea     edx, [local.20]
  00494BFA    |. |8B45 C0  mov     eax, [local.16]                                             ;  转换第二个长串为十进制大数
  00494BFD    |. |E8 3E75F>call    <HideHelp.FGInt_Base10StringToFGInt>
  00494C02    |. |8D45 A8  lea     eax, [local.22]
  00494C05    |. |50       push    eax
  00494C06    |. |8D45 A8  lea     eax, [local.22]
  00494C09    |. |50       push    eax
  00494C0A    |. |8D45 A8  lea     eax, [local.22]
  00494C0D    |. |50       push    eax
  00494C0E    |. |8D45 A8  lea     eax, [local.22]
  00494C11    |. |50       push    eax
  00494C12    |. |8D45 FC  lea     eax, [local.1]
  00494C15    |. |50       push    eax
  00494C16    |. |8D4D B0  lea     ecx, [local.20]                                             ;  第二个大数N
  00494C19    |. |8D55 B8  lea     edx, [local.18]                                             ;  第一个大数D
  00494C1C    |. |8B45 F8  mov     eax, [local.2]                                              ;  编码后的LicNum
  00494C1F    |. |E8 B89BF>call    <HideHelp.RSADecrypt(AnsiString,TFGInt &,TFGInt &,TFGInt &,>;  RSA解密函数
  00494C24    |. |8D55 FC  lea     edx, [local.1]
  00494C27    |. |8B45 FC  mov     eax, [local.1]
  00494C2A    |. |E8 1D71F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>      ;  解密结果Base64解码
  00494C2F    |. |8D8D 7CF>lea     ecx, [local.33]
  00494C35    |. |8BD6     mov     edx, esi
  00494C37    |. |8B45 FC  mov     eax, [local.1]
  00494C3A    |. |E8 B9EFF>call    <HideHelp.subN_111111_Decrypt>                              ;自定义函数解密LicNum
  00494C3F    |. |8B95 7CF>mov     edx, [local.33]
  00494C45    |. |8D45 FC  lea     eax, [local.1]
  00494C48    |. |E8 23FBF>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00494C4D    |. |8D85 78F>lea     eax, [local.34]
  00494C53    |. |E8 D4E8F>call    <HideHelp.ReadHardWare>                                     ;  读硬盘指纹,并生成机器码。
  00494C58    |. |8B85 78F>mov     eax, [local.34]                                             ;  (初始 cpu 选择)
  00494C5E    |. |8B55 FC  mov     edx, [local.1]
  00494C61    |. |E8 9200F>call    <HideHelp.System::__linkproc__ LStrPos(void)>               ; 关键比较,如果成功则保存许可文件路径到Config.ini
  00494C66    |. |85C0     test    eax, eax
  00494C68    |. |74 1F    je      short <HideHelp.loc_494C89>
  00494C6A    |. |8D95 74F>lea     edx, [local.35]
  00494C70    |. |8BC3     mov     eax, ebx
  00494C72    |. |E8 D9B8F>call    <HideHelp.Dialogs::TOpenDialog::GetFileName(void)>
  00494C77    |. |8B95 74F>mov     edx, [local.35]
  00494C7D    |. |33C9     xor     ecx, ecx
  00494C7F    |. |B8 18544>mov     eax, <HideHelp.aFilepath_0>                                 ;  filepath
  00494C84    |. |E8 D7F7F>call    <HideHelp.sub_484460>
  00494C89 <H>|> \8B87 A00>mov     eax, dword ptr ds:[edi+3A0]                                 ;  loc_494C89
  00494C8F    |.  8A50 38  mov     dl, byte ptr ds:[eax+38]
  00494C92    |.  A1 B4AE4>mov     eax, dword ptr ds:[<dword_49AEB4>]
  00494C97    |.  E8 F4F4F>call    <HideHelp.sub_484190>                                       ;  界面更新
  00494C9C    |.  8BC3     mov     eax, ebx
  00494C9E    |.  E8 A5ECF>call    <HideHelp.System::TObject::Free(void)>
  00494CA3 <H>|>  33C0     xor     eax, eax                                                    ;  loc_494CA3
  00494CA5    |.  5A       pop     edx
  00494CA6    |.  59       pop     ecx
  00494CA7    |.  59       pop     ecx
  00494CA8    |.  64:8910  mov     dword ptr fs:[eax], edx
  00494CAB    |.  68 0D4D4>push    <HideHelp.loc_494D0D>
  

  OK到此,导入许可证文件的过程的主线基本分析完成
  关键点:
  1、程序先将两个长串进行Base64解码,然后再用他自己的解密过程处理,长串被还原成两个十进制数串 D,N。
  2、程序读入Lic文件中的用户名与序列号,对序列号进行Base64解码生成 M。
  3、调用RSADecrypt函数 参数为 M,D ,N 对M解密。
  4、对解密后的M进行Base64解码 后成 M1。
  5、程序读硬盘序列号,生成机器码。
  6、比较:M1字串中是否包含机器码,如果是,则将Lic文件的路径写进config.ini的filepath字段中。
  
  导入是导入了,那么程序是不是在启动的时候还会验证呢,答案是肯定的,不然怎么限制我们使用呢:)
  怎样才能快速在程序的启动验证过程中下断呢?通过上面的分析,估计上面的部分函数肯定还会被调用,
  那么就在RSA的关键解密函数的入口 0x0047E7DC 上下断。
  Ctrl+F2重启软件,这时会提示一些断点被禁用,Yes 。在OEP处下断,运行程序,OEP处断下后 VLT+B,
  打开0x0047E7DC 的断点。F9运行,软件一会就被断下来了。哈哈,我们分析的一点没错:
三:分析启动验证流程
  
  0048A30A     .  68 E2A64>push    <HideHelp.loc_48A6E2>
  0048A30F     .  64:FF30  push    dword ptr fs:[eax]
  0048A312     .  64:8920  mov     dword ptr fs:[eax], esp
  0048A315     .  8D4D 94  lea     ecx, dword ptr ss:[ebp-6C]
  0048A318     .  33D2     xor     edx, edx
  0048A31A     .  B8 F8A64>mov     eax, <HideHelp.aFilepath>                                   ;  filepath
  0048A31F     .  E8 5CA0F>call    <HideHelp.sub_484380>                                       ;  读Config.ini中的filepath字段,如果没有则跳走
  0048A324     .  8B45 94  mov     eax, dword ptr ss:[ebp-6C]                                  ;  filepath字段保存的就是Lic文件的路径。
  0048A327     .  8D55 98  lea     edx, dword ptr ss:[ebp-68]
  0048A32A     .  E8 45E7F>call    <HideHelp.Sysutils::Trim(System::AnsiString)>
  0048A32F     .  8B45 98  mov     eax, dword ptr ss:[ebp-68]
  0048A332     .  BA 0CA74>mov     edx, <HideHelp.aNull_5>                                     ;  null
  0048A337     .  E8 C4A7F>call    <HideHelp.System::__linkproc__ LStrCmp(void)>
  0048A33C     .  74 20    je      short <HideHelp.loc_48A35E>
  (..........省略N行 省略代码与步骤二相同)
  0048A52F     .  8D4D AC  lea     ecx, dword ptr ss:[ebp-54]
  0048A532     .  8D55 B4  lea     edx, dword ptr ss:[ebp-4C]
  0048A535     .  8B45 F4  mov     eax, dword ptr ss:[ebp-C]
  0048A538     .  E8 9F42F>call    <HideHelp.RSADecrypt(AnsiString,TFGInt &,TFGInt &,TFGInt &,>;  同步骤二
  0048A53D     .  8D55 F8  lea     edx, dword ptr ss:[ebp-8]
  0048A540     .  8B45 F8  mov     eax, dword ptr ss:[ebp-8]
  0048A543     .  E8 0418F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>
  0048A548     .  8D8D 78F>lea     ecx, dword ptr ss:[ebp-88]
  0048A54E     .  8BD3     mov     edx, ebx
  0048A550     .  8B45 F8  mov     eax, dword ptr ss:[ebp-8]
  0048A553     .  E8 A096F>call    <HideHelp.subN_111111_Decrypt>
  0048A558     .  8B95 78F>mov     edx, dword ptr ss:[ebp-88]
  0048A55E     .  8D45 F8  lea     eax, dword ptr ss:[ebp-8]
  0048A561     .  E8 0AA2F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  0048A566     .  8D85 74F>lea     eax, dword ptr ss:[ebp-8C]
  0048A56C     .  E8 BB8FF>call    <HideHelp.ReadHardWare>
  0048A571     .  8B85 74F>mov     eax, dword ptr ss:[ebp-8C]
  0048A577     .  8B55 F8  mov     edx, dword ptr ss:[ebp-8]
  0048A57A     .  E8 79A7F>call    <HideHelp.System::__linkproc__ LStrPos(void)>               ;  同步骤二
  0048A57F     .  85C0     test    eax, eax
  0048A581     .  75 65    jnz     short <HideHelp.loc_48A5E8>                                 ;  如果序列号比较成功,跳
  0048A583     .  BA 38AF4>mov     edx, offset <HideHelp.dword_49AF38>
  0048A588     .  8B45 9C  mov     eax, dword ptr ss:[ebp-64]
  0048A58B     .  E8 BC17F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>      
  0048A590     .  8D8D 70F>lea     ecx, dword ptr ss:[ebp-90]
  0048A596     .  8BD3     mov     edx, ebx
  0048A598     .  A1 38AF4>mov     eax, dword ptr ds:[<dword_49AF38>]
  0048A59D     .  E8 5696F>call    <HideHelp.subN_111111_Decrypt>                              ;  解密用户名
  0048A5A2     .  8B95 70F>mov     edx, dword ptr ss:[ebp-90]
  0048A5A8     .  B8 38AF4>mov     eax, offset <HideHelp.dword_49AF38>
  0048A5AD     .  E8 7AA1F>call    <HideHelp.System::__linkproc__ LStrAsg(void *,void *)>
  0048A5B2     .  B8 38AF4>mov     eax, offset <HideHelp.dword_49AF38>
  0048A5B7     .  E8 1CA1F>call    <HideHelp.System::__linkproc__ LStrClr(void *)>
  0048A5BC     .  C605 B4A>mov     byte ptr ds:[<byte_49AFB4>], 0
  0048A5C3     .  8B45 FC  mov     eax, dword ptr ss:[ebp-4]
  0048A5C6     .  8B90 D00>mov     edx, dword ptr ds:[eax+4D0]
  0048A5CC     .  8B45 FC  mov     eax, dword ptr ss:[ebp-4]
  0048A5CF     .  8B80 540>mov     eax, dword ptr ds:[eax+454]
  0048A5D5     .  E8 F66FF>call    <HideHelp.Comctrls::TPageControl::SetActivePage(Comctrls::T>;  如果是试用版,则程序启动后默认显示最后一页选项卡
  0048A5DA     .  33D2     xor     edx, edx
  0048A5DC     .  B8 F8A64>mov     eax, <HideHelp.aFilepath>                                   ;  filepath
  0048A5E1     .  E8 769FF>call    <HideHelp.sub_48455C>
  0048A5E6     .  EB 4A    jmp     short <HideHelp.loc_48A632>
  0048A5E8 <H> >  BA 38AF4>mov     edx, offset <HideHelp.dword_49AF38>                         ;  loc_48A5E8
  0048A5ED     .  8B45 A0  mov     eax, dword ptr ss:[ebp-60]
  0048A5F0     .  E8 5717F>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>      ;  解码用户名
  0048A5F5     .  8D8D 6CF>lea     ecx, dword ptr ss:[ebp-94]
  0048A5FB     .  8BD3     mov     edx, ebx
  0048A5FD     .  A1 38AF4>mov     eax, dword ptr ds:[<dword_49AF38>]
  0048A602     .  E8 F195F>call    <HideHelp.subN_111111_Decrypt>                              ;  解密用户名
  0048A607     .  8B95 6CF>mov     edx, dword ptr ss:[ebp-94]
  0048A60D     .  B8 38AF4>mov     eax, offset <HideHelp.dword_49AF38>
  0048A612     .  E8 15A1F>call    <HideHelp.System::__linkproc__ LStrAsg(void *,void *)>
  0048A617     .  8B45 FC  mov     eax, dword ptr ss:[ebp-4]
  0048A61A     .  8B80 180>mov     eax, dword ptr ds:[eax+518]
  0048A620     .  8B15 B89>mov     edx, dword ptr ds:[<off_4997B8>]                            ;  <HideHelp.dword_489028>
  0048A626     .  E8 FDE9F>call    <HideHelp.Controls::TControl::SetText(System::AnsiString)>  ;  显示软件授权给“用户名”
  0048A62B     .  C605 B4A>mov     byte ptr ds:[<byte_49AFB4>], 1
  0048A632 <H> >  8D85 68F>lea     eax, dword ptr ss:[ebp-98]                                  ;  loc_48A632
  

  OK总结一下启动验证
  关键点:
  1、程序首先读config.ini文件中的filepath字段,如果没有则跳失败
  2、从filepath指向的许可文件中读入用户名与序列号
  3、进行序列号验证,验证过程同步骤二
  4、如果通过序列号验证,则将读出的用户名用自定义的解密函数进行解密,将解密后的用户名显示在程序界面上,
   如果没有通过验证,则设置默认选项卡为最后一页,然后运行程序。
  
  好了,导入验证与启动验证都分析过了,但当我们关闭程序时,发现他会提示我们还有XX次试用机会,这说明还有
  一个地方需要我们分析。经过测试,发现如果我们只是运行程序,然后再关闭时,并不会提示我们。只有我们在
  切换选项卡后,程序才会认为我们用过一次,然后提示。也就是说,我们只要在程序运行时切换一下选项卡,那么
  程序就会增加一次使用记录,好,我们继续:
  四:分析试用次数限制:
  我们还是在RSA的关键解密函数的入口 0x0047E7DC 上下断。OD载入,在OEP处下断,运行程序,OEP处断下后 VLT+B,
  打开0x0047E7DC 的断点。F9运行,然后切换选项卡,然而我们期望中断不没有出现,这说明程序在试用次数的检查
  上没有使用RSA函数。那么我们就用别的函数试试,在以上分析中多次出现过 ConvertBase64to256 那么我们就用这个
  函数试试,找到ConvertBase64to256 入口点,下断,重启程序....多次中断后,程序界面出现,我们切换一下选项卡,
  哈哈,断下来了:
  
  00489254    |.  8BFA     mov     edi, edx
  00489256    |.  8BF0     mov     esi, eax
  00489258    |.  33C0     xor     eax, eax
  0048925A    |.  55       push    ebp
  0048925B    |.  68 FA934>push    <HideHelp.loc_4893FA>
  00489260    |.  64:FF30  push    dword ptr fs:[eax]
  00489263    |.  64:8920  mov     dword ptr fs:[eax], esp
  00489266    |.  8D45 FC  lea     eax, [local.1]
  00489269    |.  BA 10944>mov     edx, <HideHelp.aXyxue4kfs0g4sj>                                    ;  xyxue+4kfs0g4sjnsewvyx1hkk5folj8mgnghlgawqnwolumwkrpvy
  0048926E    |.  E8 FDB4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>            ;  键路径密文
  00489273    |.  8D45 F8  lea     eax, [local.2]
  00489276    |.  BA 50944>mov     edx, <HideHelp.aS20eelxpba>                                        ;  s20eelxpba
  0048927B    |.  E8 F0B4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>            ;  键名密文
  00489280    |.  8D55 FC  lea     edx, [local.1]
  00489283    |.  8B45 FC  mov     eax, [local.1]
  00489286    |.  E8 C12AF>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>             ;  Base64解码
  0048928B    |.  8D4D F0  lea     ecx, [local.4]
  0048928E    |.  BA F3F05>mov     edx, 59F0F3
  00489293    |.  8B45 FC  mov     eax, [local.1]
  00489296    |.  E8 5DA9F>call    <HideHelp.subN_111111_Decrypt>                                     ;  解密键路径
  0048929B    |.  8B55 F0  mov     edx, [local.4]
  0048929E    |.  8D45 FC  lea     eax, [local.1]
  004892A1    |.  E8 CAB4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  004892A6    |.  8D55 F8  lea     edx, [local.2]
  004892A9    |.  8B45 F8  mov     eax, [local.2]
  004892AC    |.  E8 9B2AF>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>
  004892B1    |.  8D4D EC  lea     ecx, [local.5]
  004892B4    |.  BA F3F05>mov     edx, 59F0F3
  004892B9    |.  8B45 F8  mov     eax, [local.2]
  004892BC    |.  E8 37A9F>call    <HideHelp.subN_111111_Decrypt>                                     ;  解密键名
  004892C1    |.  8B55 EC  mov     edx, [local.5]
  004892C4    |.  8D45 F8  lea     eax, [local.2]
  004892C7    |.  E8 A4B4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  004892CC    |.  B2 01    mov     dl, 1
  004892CE    |.  A1 EC844>mov     eax, dword ptr ds:[<off_4384EC>]
  004892D3    |.  E8 14F3F>call    <HideHelp.Registry::TRegistry::TRegistry(void)>
  004892D8    |.  8BD8     mov     ebx, eax
  004892DA    |.  BA 00000>mov     edx, 80000000
  004892DF    |.  8BC3     mov     eax, ebx
  004892E1    |.  E8 A6F3F>call    <HideHelp.Registry::TRegistry::SetRootKey(uint)>
  004892E6    |.  8B55 FC  mov     edx, [local.1]
  004892E9    |.  8BC3     mov     eax, ebx
  004892EB    |.  E8 B4F7F>call    <HideHelp.Registry::TRegistry::KeyExists(System::AnsiString)>      ;  判断键是否存在
  004892F0    |.  84C0     test    al, al
  004892F2    |.  74 1B    je      short <HideHelp.loc_48930F>
  004892F4    |.  33C9     xor     ecx, ecx
  004892F6    |.  8B55 FC  mov     edx, [local.1]
  004892F9    |.  8BC3     mov     eax, ebx
  004892FB    |.  E8 F0F3F>call    <HideHelp.Registry::TRegistry::OpenKey(System::AnsiString,bool)>
  00489300    |.  8D4D F4  lea     ecx, [local.3]
  00489303    |.  8B55 F8  mov     edx, [local.2]
  00489306    |.  8BC3     mov     eax, ebx
  00489308    |.  E8 ABF5F>call    <HideHelp.Registry::TRegistry::ReadString(System::AnsiString)>     ;  如果存在,则读出键值
  0048930D    |.  EB 19    jmp     short <HideHelp.loc_489328>
  0048930F <H>|>  B1 01    mov     cl, 1                                                              ;  如果不存在,则创建并设置值为"y4o"
  00489311    |.  8B55 FC  mov     edx, [local.1]
  00489314    |.  8BC3     mov     eax, ebx
  00489316    |.  E8 D5F3F>call    <HideHelp.Registry::TRegistry::OpenKey(System::AnsiString,bool)>
  0048931B    |.  8D45 F4  lea     eax, [local.3]
  0048931E    |.  BA 64944>mov     edx, <HideHelp.dword_489464>                                       ;  y4o
  00489323    |.  E8 48B4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  00489328 <H>|>  8D55 F4  lea     edx, [local.3]                                                     ;  loc_489328
  0048932B    |.  8B45 F4  mov     eax, [local.3]
  0048932E    |.  E8 192AF>call    <HideHelp.ConvertBase64to256(AnsiString,AnsiString &)>             ;  读出的值解码
  00489333    |.  8D4D E8  lea     ecx, [local.6]
  00489336    |.  BA F3F05>mov     edx, 59F0F3
  0048933B    |.  8B45 F4  mov     eax, [local.3]
  0048933E    |.  E8 B5A8F>call    <HideHelp.subN_111111_Decrypt>                                     ;  解密读出的值
  00489343    |.  8B55 E8  mov     edx, [local.6]
  00489346    |.  8D45 F4  lea     eax, [local.3]
  00489349    |.  E8 22B4F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  0048934E    |.  8B45 F4  mov     eax, [local.3]
  00489351    |.  E8 C2FAF>call    <HideHelp.Sysutils::StrToInt(System::AnsiString)>
  00489356    |.  48       dec     eax                                                                ;  值转换为int后减1,如果结果为0则 退出程序
  00489357    |.  79 24    jns     short <HideHelp.loc_48937D>
  00489359    |.  E8 DEFCF>call    <HideHelp.DisableHook>                                             ;  jmp 到 form.DisableHook
  0048935E    |.  68 C4AE4>push    offset <HideHelp.Data>                                             ;  x
  00489363    |.  6A 02    push    2
  00489365    |.  E8 E65BF>call    <HideHelp.Shell_NotifyIconA>                                       ;  jmp 到 shell32.Shell_NotifyIconA
  0048936A    |.  8BC6     mov     eax, esi
  0048936C    |.  E8 AFFDF>call    <HideHelp.sub_489120>
  00489371    |.  A1 B89B4>mov     eax, dword ptr ds:[<off_499BB8>]
  00489376    |.  8B00     mov     eax, dword ptr ds:[eax]
  00489378    |.  E8 4F0AF>call    <HideHelp.Forms::TApplication::Terminate(void)>
  0048937D <H>|>  8B45 F4  mov     eax, [local.3]                                                     ;  loc_48937D
  00489380    |.  E8 93FAF>call    <HideHelp.Sysutils::StrToInt(System::AnsiString)>
  00489385    |.  48       dec     eax
  00489386    |.  8BD7     mov     edx, edi
  00489388    |.  E8 4FF9F>call    <HideHelp.Sysutils::IntToStr(int)>
  0048938D    |.  8B45 F4  mov     eax, [local.3]
  00489390    |.  E8 83FAF>call    <HideHelp.Sysutils::StrToInt(System::AnsiString)>
  00489395    |.  48       dec     eax
  00489396    |.  8D55 E0  lea     edx, [local.8]
  00489399    |.  E8 3EF9F>call    <HideHelp.Sysutils::IntToStr(int)>
  0048939E    |.  8B45 E0  mov     eax, [local.8]
  004893A1    |.  8D4D E4  lea     ecx, [local.7]
  004893A4    |.  BA F3F05>mov     edx, 59F0F3
  004893A9    |.  E8 AAA7F>call    <HideHelp.subN_222222_Encrypt>                                     ;  结果减1后,转为string,加密
  004893AE    |.  8B55 E4  mov     edx, [local.7]
  004893B1    |.  8D45 F4  lea     eax, [local.3]
  004893B4    |.  E8 B7B3F>call    <HideHelp.System::__linkproc__ LStrLAsg(void *,void *)>
  004893B9    |.  8D55 F4  lea     edx, [local.3]
  004893BC    |.  8B45 F4  mov     eax, [local.3]
  004893BF    |.  E8 0828F>call    <HideHelp.ConvertBase256to64(AnsiString,AnsiString &)>             ;  编码,保存到注册表
  004893C4    |.  8B4D F4  mov     ecx, [local.3]
  004893C7    |.  8B55 F8  mov     edx, [local.2]
  004893CA    |.  8BC3     mov     eax, ebx
  004893CC    |.  E8 BBF4F>call    <HideHelp.Registry::TRegistry::WriteString(System::AnsiString,Syst>
  004893D1    |.  8BC3     mov     eax, ebx
  004893D3    |.  E8 84F2F>call    <HideHelp.subN_RegClose_Flush>
  004893D8    |.  8BC3     mov     eax, ebx
  004893DA    |.  E8 69A5F>call    <HideHelp.System::TObject::Free(void)>
  004893DF    |.  33C0     xor     eax, eax
  004893E1    |.  5A       pop     edx
  

  整理一下:
  软件作者保密意识很好,在软件中没有出现任何明码信息。软件的试用次数是保存在注册表中的,然后注册表路径,
  作者对其进行了加密存放,这样分析者在静态分析软件时,看到的只是一串串乱七八糟的密文。
  试用次数验证的关键:
  1、解码,解密注册表的路径与键名。
  2、判断键名是否存在,如果没有,则新建键名,并赋值为:y4o
  3、读出的键值,解码,解密,转换为数值并减1。
  4、如果结果为0了,则程序退出(试用次数没啦)
  5、将减1后的结果转换为字串,并加密,编码后存入注册表。
  
  
  到此这款软件的注册验证流程全部分析完,如果要想去掉试用次数限制,那么只要在 004892F2 的JZ改为JMP
  就可以使试用次数永远为30次。
  如果想要暴破,那么可以在0048A581 JNZ改为JMP就可以实现了,但前提是要在config.ini中建一个filepath中键名,并
  做一个Lic文件,在里面输入两行字串(当然也可以把这些检测全Patch掉),不过有一点就是授权用户那里为乱码。
  
  由于先们对RSA加密方法不熟悉,费了好大劲分析,把Base64的编码差不多全逆出来时,才在网上发现老罗大侠Base算法
  以及用FGint库做的Sig文件,真晕了。
  国产软件,大家都不容易,补丁就不发了,如果有想用的兄弟,自己动手吧,这样也可以锻炼一下:)

  好了,这次先分析到这里,在下一篇中,将为这个软件做一个注册机。
  
  
  
  
  
  
  
  
  
  
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年11月14日 21:25:08

[2022冬季班]《安卓高级研修班(网课)》月薪三万班招生中~

收藏
点赞0
打赏
分享
最新回复 (2)
雪    币: 291
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
leking 活跃值 2009-11-14 22:32
2
0
文章写的层次清晰,收藏
雪    币: 200
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
zhonggq 活跃值 2009-11-15 08:58
3
0
收藏备用了!贴子很不错
游客
登录 | 注册 方可回帖
返回