【破解作者】 隐者无疆[BCG]
【使用工具】 Peid,OD
【破解平台】 WinXP SP2
【软件名称】 ipTicker v1.9h
【下载地址】 http://www.soft-trek.com.au
【软件简介】    
   ipTicker is a diagnostic utility to track IP traffic to and from        
   your PC in real time. Potential usages of ipTicker are:                 
                                                                           
      1. To measure the amount of traffic to and from your PC (grouped     
         by IP address and port)                                           
      2. To confirm if there are any unsolicited outbound activities       
         from your PC                                                      
      3. To detect possible Trojan activities                              
      4. To investigate IP activities                                     
【软件大小】 84.0k
【加壳方式】 无壳
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
--------------------------------------------------------------------------------
【破解内容】


好久没写破文了,今天灌上一篇。
1.老一套,Peid侦壳,显示"Microsoft Visual C++ 6.0 [Debug]",没壳。
  顺带着侦测一下加密算法,显示"No known crypto signatures found",不错,我喜欢。
2.OD加载 ipTicker.exe,F9运行。
  File--> Unlock,输入下列内容,试注册。
  Name:   warshon
  Email:  warshon@hotmail.com
  Unlock; 123456789
  点"OK"试一试。提示注册失败。
  就从这个出错对话框着手,搜索全部交互调用。对所有的 "MFC42.#1199_AfxMessageBox" 下断点。
  再次点"OK",程序被断下。
3.往上看,找到
  00408B70   .  call <jmp.&MFC42.#6334_CWnd::UpdateData>
从后面的跟踪我们可以知道这一个调用的作用是获得用户输入的Name和Email,在这个地方下一个断点。
  重新注册,程序在 UpdateData调用出被断下。F8单步运行。
  00408B7E   .  test eax,eax   和  
  00408BAC   .  test eax,eax   分别判断用户是否输入了Name和Email,若没有则报错。
  继续往下
  00408C24   .  push ecx                                          ;  Email
  00408C25   .  push edx                                          ;  Name
  00408C26   .  push ipTicker.0040E0F8                            ;  ASCII "%s::%s"
  00408C2B   .  push eax
  00408C2C   .  call <jmp.&MFC42.#2818_CString::Format>           ;  
  这一处Format调用根据输入的Email和Name生成形如字符串“$Name::$Email”的格式,例如根据我前面的输入,
  这里生成的字符串为"warshon::warshon@hotmail.com",记作 str_A
  往下走
  00408C39   .  5>push ecx                                        ; /Arg1 = 003746D8 ASCII "warshon::warshon@hotmail.com"
  00408C3A   .  8>lea ecx,dword ptr ss:[esp+10]                   ; |
  00408C3E   .  E>call ipTicker.00402060                          ; \
  可以看到上面生成的字符串str_A被压入了栈中。F7跟进call ipTicker.00402060
call ipTicker.00402060中:
  开始又是一段检验str_A长度的代码。
  下面有一处 sprintf 的调用。
  00402092  |.  5>push edx                                          ; /<%s> = str_A
  00402093  |.  F>rep stos dword ptr es:[edi]                       ; |
  00402095  |.  6>push ipTicker.0040B630                            ; |<%s> = "STIT"
  0040209A  |.  8>lea eax,dword ptr ss:[esp+C]                      ; |
  0040209E  |.  6>push ipTicker.0040E104                            ; |format = "%s+%s"
  004020A3  |.  5>push eax                                          ; |s
  004020A4  |.  F>call dword ptr ds:[<&MSVCRT.sprintf>]             ; \sprintf
  这一处生成形如"STIT+$str_A"的字符串,本例中为"STIT+warshon::warshon@hotmail.com",记作str_B
  
  004020B8  |.  push ecx                                          ;  str_B的长度
  004020B9  |.  lea ecx,dword ptr ss:[esp+18]             
  004020BD  |.  push ecx                                          ;  str_B
  004020BE  |.  call ipTicker.00401560                            ;  处理str_B
  这一个call是对str_B的处理,F7跟进。

  00401560  /$  mov ecx,dword ptr ss:[esp+8]                      ;  ecx = str_B 的长度
  00401564  |.  mov edx,dword ptr ss:[esp+4]                      ;  edx = str_B
  00401568  |.  xor eax,eax                                       ;  eax = 0
  0040156A  |.  test ecx,ecx
  0040156C  |.  jle short ipTicker.0040159C
  0040156E  |.  push esi
  0040156F  |.  push edi
  00401570  |.  mov edi,ecx                                       ;  edi = 尚未处理的字符数目
  00401572  |>  /xor ecx,ecx
  00401574  |.  |mov esi,8                                        ;  esi = 8
  00401579  |.  |mov ch,byte ptr ds:[edx]                         ;  edx = 当前字符;ch !
  0040157B  |.  |xor eax,ecx
  0040157D  |.  |inc edx
  0040157E  |>  |/mov ecx,eax
  00401580  |.  ||and ecx,8000
  00401586  |.  ||shl eax,1
  00401588  |.  ||cmp cx,8000
  0040158D  |.  ||jnz short ipTicker.00401594
  0040158F  |.  ||xor eax,8005
  00401594  |>  ||dec esi
  00401595  |.^ |\jnz short ipTicker.0040157E
  00401597  |.  |dec edi
  00401598  |.^ \jnz short ipTicker.00401572
  0040159A  |.  pop edi
  0040159B  |.  pop esi
  0040159C  \>  retn
  这一段代码主要是对 str_B 中的字符做一些位运算,就不详细分析了。不过需要指出,最后对我们有用的结果存
  放在 eax 中。

  处理结束以后,程序返回。
  00408C43   .  mov edi,eax                                       ;  ! edi<== eax
  这里我们看到,处理str_B 的结果被保存到 edi 寄存器中!!!
  00408C45   .  mov eax,dword ptr ds:[esi+B0]
  00408C4B   .  push eax                                          ; /Arg1 = 输入的注册码
  00408C4C   .  lea ecx,dword ptr ss:[esp+10]                     ; |
  00408C50   .  call ipTicker.00402190                            ; \ 关键call,F7跟进
  00408C55   .  cmp ax,di                                         ;  !关键比较
  00408C58   .  pop edi
  00408C59   .  je short ipTicker.00408C81

  跟进 call ipTicker.00402190。
  00402190  /$  mov edx,dword ptr ss:[esp+4]                      ;  edx <== str_B
  00402194  |.  sub esp,100
  0040219A  |.  or ecx,FFFFFFFF
  0040219D  |.  xor eax,eax
  0040219F  |.  push edi                                          ;  !
  004021A0  |.  mov edi,edx
  004021A2  |.  repne scas byte ptr es:[edi]
  004021A4  |.  not ecx
  004021A6  |.  dec ecx
  004021A7  |.  jnz short ipTicker.004021B7                       ;  ecx = len of regcode
  004021A9  |.  mov ax,2
  004021AD  |.  pop edi                                           ;  !
  004021AE  |.  add esp,100
  004021B4  |.  retn 4
  004021B7  |>  mov ecx,40
  004021BC  |.  xor eax,eax
  004021BE  |.  lea edi,dword ptr ss:[esp+4]
  004021C2  |.  push ebx
  004021C3  |.  rep stos dword ptr es:[edi]
  004021C5  |.  mov edi,edx
  004021C7  |.  or ecx,FFFFFFFF
  004021CA  |.  repne scas byte ptr es:[edi]
  004021CC  |.  not ecx                                           ;  ecx = len of str_B +1
  004021CE  |.  sub edi,ecx
  004021D0  |.  push esi                                          ;  esi = str_B
  004021D1  |.  lea ebx,dword ptr ss:[esp+C]                      ;  ebx = ptr to block
  004021D5  |.  mov eax,ecx
  004021D7  |.  mov esi,edi
  004021D9  |.  mov edi,ebx
  004021DB  |.  shr ecx,2
  004021DE  |.  rep movs dword ptr es:[edi],dword ptr ds:[esi]    ;  store part1 of regcode to block 
  004021E0  |.  mov ecx,eax
  004021E2  |.  and ecx,3
  004021E5  |.  rep movs byte ptr es:[edi],byte ptr ds:[esi]      ;  store part2 of regcode to block
  004021E7  |.  lea ecx,dword ptr ss:[esp+C]
  004021EB  |.  push ecx                                          ;  ecx = ptr to regcode
  004021EC  |.  call ipTicker.00401680                            ;  !!! ax = ?
  004021F1  |.  add esp,4
  004021F4  |.  pop esi
  004021F5  |.  pop ebx
  004021F6  |.  pop edi
  004021F7  |.  add esp,100
  004021FD  \.  retn 4

  可以看到,在4021EB处,我们输入的注册码被压入栈中,由call ipTicker.00401680进行处理。跟进
  00401680  /$  sub esp,58
  00401683  |.  push ebx
  00401684  |.  xor edx,edx
  00401686  |.  push esi
  00401687  |.  mov esi,dword ptr ss:[esp+64]                     ;  esi = regcode
  0040168B  |.  push edi
  0040168C  |.  mov dword ptr ss:[esp+C],edx
  00401690  |.  xor ecx,ecx
  00401692  |.  mov eax,ipTicker.0040E088                         ;  eax = 0x40e088
  00401697  |>  mov edi,dword ptr ds:[eax]                        ;  分别取注册码的第4、15、9、11位,存于ss:12e87c
  00401699  |.  add eax,4
  0040169C  |.  inc ecx
  0040169D  |.  cmp eax,ipTicker.0040E098                         ;  ASCII "44"
  004016A2  |.  mov bl,byte ptr ds:[edi+esi]
  004016A5  |.  mov byte ptr ss:[esp+ecx+F],bl
  004016A9  |.^ jl short ipTicker.00401697
  004016AB  |.  lea eax,dword ptr ss:[esp+C]
  004016AF  |.  mov byte ptr ss:[esp+ecx+10],dl
  004016B3  |.  push eax
  004016B4  |.  lea ecx,dword ptr ss:[esp+14]                     ;  ecx 指向提取出来的4位注册码
  004016B8  |.  push ipTicker.0040E0AC                            ; |format = "%X"
  004016BD  |.  push ecx                                          ; |s
  004016BE  |.  call dword ptr ds:[<&MSVCRT.sscanf>]              ; \sscanf
  004016C4  |.  mov ax,word ptr ss:[esp+18]                       ;  !!! ax = 4位注册码的对应的八进制 !重要
  004016C9  |.  add esp,0C
  004016CC  |.  pop edi
  004016CD  |.  pop esi
  004016CE  |.  pop ebx
  004016CF  |.  add esp,58
  004016D2  \.  retn
  这个call的作用是分别将注册码的第4、15、9、11位对应的十六进制数由低位到高位存入ax中,重要。
  一直运行到408655处。
  00408C55   .  cmp ax,di                                         ;  !关键比较
  00408C58   .  pop edi
  00408C59   .  je short ipTicker.00408C81
  比较 ax 和 di 的值,若相等则注册成功

4.兜了那么一大圈子,下面总结一下注册算法。
  首先,根据输入的 Name 和 Email,计算得到一个十六进制值(存放在di中)
  然后,将注册码的第4、15、9、11位对应的十六进制数由低位到高位存入ax中
  最后,比较di和ax的值。若相等则为合法注册码

5.注册算法知道了,要编写注册机也不难了。


--------------------------------------------------------------------------------
【版权声明】 本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!