【文章标题】: ActArp算法分析
【文章作者】: Monster
【作者邮箱】: suphack@vip.qq.com
【作者主页】: http://www.hackerm.com.cn/
【作者QQ号】: 389264167
【软件名称】: ActArp
【软件大小】: 319 KB
【下载地址】: 自己搜索下载
【加壳方式】: UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo
【保护方式】: 注册码
【编写语言】: Borland Delphi 6.0 - 7.0
【使用工具】: OD+IDA+Dede
【操作平台】: WinXp
【软件介绍】: 就是一个Arp工具
【作者声明】: 原文地址:http://www.hackerm.com.cn/read.php/28.htm
--------------------------------------------------------------------------------
【详细过程】
  虽然在住院,可是今天还是收到黑X第三期的样刊,心里那个高兴啊,嘿嘿,打开光盘看了一下,有个叫ActArp(ARP扫描检测程序)的工具,打开看了一下,还不错,可是需要注册(要钱),郁闷,这可不是我的作风,偶给你破了,看你还要钱不。
  先用PEID检查一下,结果是UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo,嘿嘿,UPX的壳还是很好脱地,用OD载入,遇到pushad指令后直接hr esp就可以搞定,这不是本文的重点,就不具体讲了。脱完后再使用PEID检查一下,结果是Borland Delphi 6.0 - 7.0,嘿嘿,不是VB就好,最讨厌搞VB的了。
  先随便注册一下看看,输入用户名,序列号,注册码后按“确定”,就会弹出一个提示错误的对话框。
  既然是Delphi的,那我们可以对他进行反编译一下,我们打开Dede,把目标程序加载进去,现在我们找到了“确定”按钮的“Click”事件的RVA,是00466B30。
  现在我们再打开OD来分析,把脱壳后的程序载入OD,按Ctrl+G后会弹出一个小框,我们输入刚才得到的“确定”按钮的“Click”事件的RVA,按确定后就会来到00466B30所指的代码处,我们在这里按F2下一个断点。
  我们在OD中按F9让程序运行起来,还是输入刚才的用户名,序列号,注册码后按“确定”,程序就会被断在了我们刚才下断的地方,我们按F8往下跟踪几步就会看到一个jnz指令,代码如下:
  

代码:
00466B88    84C0            test    al, al                           ; 比较语句
  00466B8A    75 25           jnz     short 00466BB1                   ; 注册成功则跳
  00466B8C    6A 10           push    10
  00466B8E    B9 606C4600     mov     ecx, 00466C60                    ; 错误
  00466B93    BA 686C4600     mov     edx, 00466C68                    ; 无效的注册码,请与销售人员联系。
  00466B98    A1 E4B24600     mov     eax, dword ptr [46B2E4]
  00466B9D    8B00            mov     eax, dword ptr [eax]
  00466B9F    E8 0070FFFF     call    0045DBA4                         ; 弹出错误对话框
 
 我们可以看到,00466B8A外的jnz就是关键跳转,也就是我们常说的暴点,我们现在只要把这里修改成jmp就可以实现暴破了,可我们的目标不是暴破,我们来看看他的注册算法。
  全段代码如下:
  
代码:
CODE:00466B35                 push    ecx
  CODE:00466B36                 push    ecx
  CODE:00466B37                 push    ecx
  CODE:00466B38                 push    ecx
  CODE:00466B39                 push    ecx
  CODE:00466B3A                 push    ebx
  CODE:00466B3B                 push    esi
  CODE:00466B3C                 mov     ebx, eax
  CODE:00466B3E                 xor     eax, eax
  CODE:00466B40                 push    ebp
  CODE:00466B41                 push    offset loc_466C50
  CODE:00466B46                 push    dword ptr fs:[eax]
  CODE:00466B49                 mov     fs:[eax], esp
  CODE:00466B4C                 lea     edx, [ebp+var_4]
  CODE:00466B4F                 mov     eax, [ebx+34Ch]
  CODE:00466B55                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取用户名
  CODE:00466B5A                 mov     eax, [ebp+var_4]
  CODE:00466B5D                 push    eax
  CODE:00466B5E                 lea     edx, [ebp+var_8]
  CODE:00466B61                 mov     eax, [ebx+344h]
  CODE:00466B67                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取序列号
  CODE:00466B6C                 mov     eax, [ebp+var_8]
  CODE:00466B6F                 push    eax
  CODE:00466B70                 lea     edx, [ebp+var_C]
  CODE:00466B73                 mov     eax, [ebx+33Ch]
  CODE:00466B79                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取注册码
  CODE:00466B7E                 mov     eax, [ebp+var_C]
  CODE:00466B81                 pop     edx
  CODE:00466B82                 pop     ecx
  CODE:00466B83                 call    sub_466024
  CODE:00466B88                 test    al, al
  CODE:00466B8A                 jnz     short loc_466BB1
  CODE:00466B8C                 push    10h             ; uType
  CODE:00466B8E                 mov     ecx, offset dword_466C60
  CODE:00466B93                 mov     edx, offset dword_466C68 ; lpText
  CODE:00466B98                 mov     eax, off_46B2E4
  CODE:00466B9D                 mov     eax, [eax]      ; int
  CODE:00466B9F                 call    @Forms@TApplication@MessageBox$qqrpxct1i ; Forms::TApplication::MessageBox(char *,char *,int)
  CODE:00466BA4                 xor     eax, eax
  CODE:00466BA6                 mov     [ebx+24Ch], eax
  CODE:00466BAC                 jmp     loc_466C35
  CODE:00466BB1 ; ---------------------------------------------------------------------------
  CODE:00466BB1
  CODE:00466BB1 loc_466BB1:                             ; CODE XREF: _TAboutBox_OKButtonClick+5A j
  CODE:00466BB1                 lea     edx, [ebp+var_10]
  CODE:00466BB4                 mov     eax, [ebx+33Ch]
  CODE:00466BBA                 call    @Controls@TControl@GetText$qqrv ; Controls::TControl::GetText(void)
  CODE:00466BBF                 mov     edx, [ebp+var_10]
  CODE:00466BC2                 mov     eax, off_46B360
  CODE:00466BC7                 call    @System@@LStrAsg$qqrpvpxv ; System::__linkproc__ LStrAsg(void *,void *)
  CODE:00466BCC                 lea     edx, [ebp+var_14]
  CODE:00466BCF                 mov     eax, [ebx+34Ch]
  CODE:00466BD5                 call    @Controls@TControl@GetText$qqrv ; Controls::TControl::GetText(void)
  CODE:00466BDA                 mov     edx, [ebp+var_14]
  CODE:00466BDD                 mov     eax, off_46B150
  CODE:00466BE2                 call    @System@@LStrAsg$qqrpvpxv ; System::__linkproc__ LStrAsg(void *,void *)
  CODE:00466BE7                 mov     dl, 1
  CODE:00466BE9                 mov     eax, off_465E40
  CODE:00466BEE                 call    sub_4664DC
  CODE:00466BF3                 mov     ebx, eax
  CODE:00466BF5                 mov     eax, off_46B360
  CODE:00466BFA                 mov     eax, [eax]
  CODE:00466BFC                 push    eax
  CODE:00466BFD                 mov     ecx, offset _str_User.Text
  CODE:00466C02                 mov     edx, offset _str_Register.Text
  CODE:00466C07                 mov     eax, ebx
  CODE:00466C09                 mov     esi, [eax]
  CODE:00466C0B                 call    dword ptr [esi+4]
  CODE:00466C0E                 mov     eax, off_46B150
  CODE:00466C13                 mov     eax, [eax]
  CODE:00466C15                 push    eax
  CODE:00466C16                 mov     ecx, offset _str_RegCode.Text
  CODE:00466C1B                 mov     edx, offset _str_Register.Text
  CODE:00466C20                 mov     eax, ebx
  CODE:00466C22                 mov     esi, [eax]
  CODE:00466C24                 call    dword ptr [esi+4]
  CODE:00466C27                 mov     eax, ebx
  CODE:00466C29                 mov     edx, [eax]
  CODE:00466C2B                 call    dword ptr [edx+54h]
  CODE:00466C2E                 mov     eax, ebx
  CODE:00466C30                 call    @System@TObject@Free$qqrv ; System::TObject::Free(void)
  CODE:00466C35
  CODE:00466C35 loc_466C35:                             ; CODE XREF: _TAboutBox_OKButtonClick+7C j
  CODE:00466C35                 xor     eax, eax
  CODE:00466C37                 pop     edx
  CODE:00466C38                 pop     ecx
  CODE:00466C39                 pop     ecx
  CODE:00466C3A                 mov     fs:[eax], edx
  CODE:00466C3D                 push    offset loc_466C57
  CODE:00466C42
  CODE:00466C42 loc_466C42:                             ; CODE XREF: _TAboutBox_OKButtonClick+125 j
  CODE:00466C42                 lea     eax, [ebp+var_14]
  CODE:00466C45
  CODE:00466C45 ; __fastcall Ibdatabaseinfo::TIBDatabaseInfo::GetReads(void)
  CODE:00466C45 @Ibdatabaseinfo@TIBDatabaseInfo@GetReads$qqrv:
  CODE:00466C45                 mov     edx, 5
  CODE:00466C4A                 call    @System@@LStrArrayClr$qqrpvi ; System::__linkproc__ LStrArrayClr(void *,int)
  CODE:00466C4F                 retn
      可以看出00466B83处的call    sub_466024就是算法,我们看一下上面的几句:
  
代码:
CODE:00466B30                 push    ebp
  CODE:00466B31                 mov     ebp, esp
  CODE:00466B33                 xor     ecx, ecx
  CODE:00466B35                 push    ecx
  CODE:00466B36                 push    ecx
  CODE:00466B37                 push    ecx
  CODE:00466B38                 push    ecx
  CODE:00466B39                 push    ecx
  CODE:00466B3A                 push    ebx
  CODE:00466B3B                 push    esi
  CODE:00466B3C                 mov     ebx, eax
  CODE:00466B3E                 xor     eax, eax
  CODE:00466B40                 push    ebp
  CODE:00466B41                 push    offset loc_466C50
  CODE:00466B46                 push    dword ptr fs:[eax]
  CODE:00466B49                 mov     fs:[eax], esp
  CODE:00466B4C                 lea     edx, [ebp+var_4]
  CODE:00466B4F                 mov     eax, [ebx+34Ch]
  CODE:00466B55                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取用户名
  CODE:00466B5A                 mov     eax, [ebp+var_4]
  CODE:00466B5D                 push    eax
  CODE:00466B5E                 lea     edx, [ebp+var_8]
  CODE:00466B61                 mov     eax, [ebx+344h]
  CODE:00466B67                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取序列号
  CODE:00466B6C                 mov     eax, [ebp+var_8]
  CODE:00466B6F                 push    eax
  CODE:00466B70                 lea     edx, [ebp+var_C]
  CODE:00466B73                 mov     eax, [ebx+33Ch]
  CODE:00466B79                 call    @Controls@TControl@GetText$qqrv ; 从输入框中获取注册码
  CODE:00466B7E                 mov     eax, [ebp+var_C] ; 取用户名到eax
  CODE:00466B81                 pop     edx             ; 取注册码到edx
  CODE:00466B82                 pop     ecx             ; 取序列号到ecx
  CODE:00466B83                 call    sub_466024
  CODE:00466B88                 test    al, al
  CODE:00466B8A                 jnz     short loc_466BB1
 
     用OD跟到00466B83处的call    sub_466024里看看:
  
代码:
CODE:00466024                 push    ebp
  CODE:00466025                 mov     ebp, esp
  CODE:00466027                 add     esp, 0FFFFFFE4h
  CODE:0046602A                 push    ebx
  CODE:0046602B                 push    esi
  CODE:0046602C                 push    edi
  CODE:0046602D                 xor     ebx, ebx
  CODE:0046602F                 mov     [ebp+var_4], ebx
  CODE:00466032                 mov     [ebp+var_18], ebx
  CODE:00466035                 mov     [ebp+var_1C], ebx
  CODE:00466038                 mov     edi, ecx        ; 取注册码到edi
  CODE:0046603A                 mov     esi, edx        ; 取序列号到esi
  CODE:0046603C                 mov     ebx, eax        ; 取用户名到ebx
  CODE:0046603E                 xor     eax, eax        ; 清零eax
  CODE:00466040                 push    ebp
  CODE:00466041                 push    offset loc_4660B0
  CODE:00466046                 push    dword ptr fs:[eax]
  CODE:00466049                 mov     fs:[eax], esp
  CODE:0046604C                 push    offset _str_ACTIVEARP_0.Text ; 压入字符串“activearp”
  CODE:00466051                 push    ebx             ; 压入用户名
  CODE:00466052                 push    esi             ; 压入序列号
  CODE:00466053                 lea     eax, [ebp+var_1C]
  CODE:00466056                 mov     edx, 3
  CODE:0046605B                 call    @System@@LStrCatN$qqrv ; 连接字符串“activearp+用户名+序列号”
  CODE:00466060                 mov     eax, [ebp+var_1C] ; 将得到的字符串放到eax的
  CODE:00466063                 lea     edx, [ebp+var_18]
  CODE:00466066                 call    @Sysutils@UpperCase$qqrx17System@AnsiString ; 将刚才得到的字符串转为大写
  CODE:0046606B                 mov     eax, [ebp+var_18] ; 将转换后到的字符串放到eax的
  CODE:0046606E                 lea     edx, [ebp+var_14]
  CODE:00466071                 call    sub_466624      ; 计算注册码
  CODE:00466076                 lea     eax, [ebp+var_14]
  CODE:00466079                 lea     edx, [ebp+var_4]
  CODE:0046607C                 call    sub_466584      ; 将生成的注册码转换为字符串
  CODE:00466081                 mov     eax, [ebp+var_4] ; 放正确序列号到eax
  CODE:00466084                 mov     edx, edi        ; 放我们输入的序列号到edx
  CODE:00466086                 call    unknown_libname_111 ; 比较注册码
  CODE:0046608B                 mov     ebx, eax
  CODE:0046608D                 xor     eax, eax
  CODE:0046608F                 pop     edx
  CODE:00466090                 pop     ecx
  CODE:00466091                 pop     ecx
  CODE:00466092                 mov     fs:[eax], edx
  CODE:00466095                 push    offset loc_4660B7
  CODE:0046609A
  CODE:0046609A loc_46609A:                             ; CODE XREF: sub_466024+91 j
  CODE:0046609A                 lea     eax, [ebp+var_1C]
  CODE:0046609D                 mov     edx, 2
  CODE:004660A2                 call    @System@@LStrArrayClr$qqrpvi ; System::__linkproc__ LStrArrayClr(void *,int)
  CODE:004660A7                 lea     eax, [ebp+var_4]
  CODE:004660AA                 call    @System@@LStrClr$qqrpv ; System::__linkproc__ LStrClr(void *)
  CODE:004660AF                 retn
      我们可以看到CODE:00466071处的call    sub_466624就是计算注册码的地方,其实就是将上面得到的长字符串加密成32位的MD5。
      算法就是这样,现在来写个注册机吧。
      下面给出关键代码:
      
代码:
    CMd5 md5;
      UpdateData(true);
      string key("");
      string temp("");
      key.append("activearp");
      key.append(m_user);
      key.append(m_sn);
      m_key=key.data();
      m_key.MakeUpper();
      md5.TargetStr(m_key.GetBuffer(0));
      temp=md5.GetDigestKey();
      m_key=temp.data();
      UpdateData(false);

下载地址:http://www.hackerm.com.cn/attachment/arpkeygen.rar

--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年03月22日 23:12:14