首页
社区
课程
招聘
[旧帖] [原创]MFC实战--Hex Workshop V4.2破解笔记(一) 0.00雪花
发表于: 2009-1-29 20:41 10246

[旧帖] [原创]MFC实战--Hex Workshop V4.2破解笔记(一) 0.00雪花

2009-1-29 20:41
10246
【文章标题】: MFC实战--Hex Workshop V4.2破解笔记(一)
【文章作者】: frank
【软件名称】: Hex Workshop
【下载地址】: 看雪站
【加壳方式】: 无
【保护方式】: 序列号
【编写语言】: MFC
【使用工具】: IDA,OLLYICE, EXESCOPE
【软件介绍】: 著名的16进制编辑工具
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  引言
    Hex Workshop是小弟破解的第一个MFC程序,特将过程整理出来希望帮助像我一样的小菜鸟找到门径。
  如果你已经使用注册机注册过了的话,将附件中的注册表文件直接导入注册表即可将程序变成未注册。
  具体实现下面正文会分析。废话不再表,直接进入正题。
  
  1、查壳
  ========
  首先、PEID打开文件--无壳:),MS VC7。
  
  
2、查找注册对话框
  
  使用:Exescope, OllyIce
  ===========
    Exescope打开hworks32.exe查找注册对话框--未果。
    OllyIce载入Ctrl+N进入输入输出函数表,查找Dialog创建相关的函数并全部下断点。点击注册按钮,注册对话框正常弹出。
  尝试用CreateWindow函数断依然正常弹出对话框。--到这里猜测注册相关实现应该不在hworks32.exe模块中。
    Alt+E查看所有模块,软件载入的自己的模块共有bpsregwd.dll,hwapi.dll,bp_da.dll,diffeng.dll。
    ExeScope逐个打开查看对话框资源,果然在第一个模块bpsregwd.dll中就发现了注册对话框。对话框ID--1002,Name对应Edit控件ID-1000,
  Company对应Edit控件ID-1001,Key对应Edit控件ID-1002,OK按钮ID-1(使用默认的OK按钮)。
  
  3、查找注册对话框类虚函数表
  
  使用:IDA Pro
  ============
    IDA Pro加载bpsregwd.dll, Ctrl+S 选择.rdata来到只读数据段--类虚函数表、MFC AFX_MSG_ENTRY均在该段。
    虚函数表即一个函数指针数组,每个元素都指向一个虚函数。IDA已经帮我们分析出来了部分MFC库函数,没有分析出来的应该
  是开发者重载过的。通过观察会发现只读段中包含不止一个虚函数表,那么哪个才是注册对话框类使用的呢?要解答这个问题就
  需要知道虚函数表被初始化的时机。有虚函数的类在实例化时会调用构造函数完成以下三个工作:调用基类构造函数、初始化虚函数表指针、
  初始化各数据成员。因此我们或许可以通过其他两个功能确定具体是哪个类的构造函数,进而确定对应的虚函数。
    注册对话框基类CDialog基于资源的构造函数:CDialog::CDialog(uint,CWnd *)。 其中第一个参数即为指向对话框资源名字的指针或者其
  ID值。具体如下例所示:
  push    eax
  push    3EAh ==>1002,注册对话框ID
  mov     esi, ecx
  call    CDialog::CDialog(uint,CWnd *)
   0x3EA是对话框资源ID,转换为10进制即为1002,因此可以确定该虚函数表地址即为注册对话框虚函数表。
  
  
  4、 查找注册按钮事件处理函数
  
  使用:IDA Pro
  ============
    一般按钮(除ID为1、2外)事件处理函数在AFX_MSG_ENTRY中指定,查找各AFX_MSG_ENTRY的地址需要找到GetMessageMap函数。
  本例中OK按钮为默认OK按钮(ID为1),其事件处理函数为注册对话框虚函数OnOK。
    通过查看已经被IDA分析出的虚函数CDialog::DoModal(void)位置,结合MFC源代码可以发现OnOK函数被重载后即sub_10003DE0.
    注意:虚函数表各虚函数相对位置在静态链接和共享MFC dll时是不同的,原因在于MFC源代码中用宏_AFXDLL控制。
  本例中采用的就是静态链接,其虚函数个数比动态链接时要少。--可以自己用两种方式编译简单事例,对比发现区别。
  下表是我整理出来的虚函数表:
  rdata:1001C9F8 70 94 01 10             off_1001C9F8 dd offset sub_10019470
  .rdata:1001C9F8                                                       ; DATA XREF: sub_10003BD0+42o ==》引用
  .rdata:1001C9F8                                                       ; @@@注册对话框虚函数表@@@
  .rdata:1001C9FC C0 3D 00 10             dd offset sub_10003DC0
  .rdata:1001CA00 90 1B 00 10             dd offset nullsub_3
  .rdata:1001CA04 D4 29 01 10             dd offset unknown_libname_25  ; MFC 3.1/4.0/4.2/8.0 32bit
  .rdata:1001CA08 CD 31 01 10             dd offset CWnd::OnFinalRelease(void)
  .rdata:1001CA0C 37 25 01 10             dd offset sub_10012537
  .rdata:1001CA10 8B 25 01 10             dd offset sub_1001258B
  .rdata:1001CA14 FA 3B 01 10             dd offset sub_10013BFA
  .rdata:1001CA18 FA 3B 01 10             dd offset sub_10013BFA
  .rdata:1001CA1C 3D 25 01 10             dd offset CCmdTarget::GetTypeLib(ulong,ITypeLib * *)
  .rdata:1001CA20 B0 33 00 10             dd offset sub_100033B0 ==>GetMessageMap
  .....
  .rdata:1001CB38 34 2F 01 10             dd offset CDialog::DoModal(void) ==>已经被分析出的虚函数
  .rdata:1001CB3C 70 37 00 10             dd offset sub_10003770
  .rdata:1001CB40 9F 34 01 10             dd offset nullsub_5
  .rdata:1001CB44 E0 3D 00 10             dd offset sub_10003DE0        ; OnOk注册按钮事件处理函数
  .rdata:1001CB48 20 29 01 10             dd offset sub_10012920
  .rdata:1001CB4C CC 31 01 10             dd offset nullsub_4
  .rdata:1001CB50 6C CB 01 10             off_1001CB50 dd offset s_Cwinapp

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
【文章标题】: MFC实战--Hex Workshop V4.2破解笔记(二)
【文章作者】: frankbai
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  通过上文的分析已经找到了OK按钮事件的处理函数sub_10003DE0,以下是对该函数的解析:
  ...
  push    1
  mov     ecx, esi     ;==>注册对话框this指针
  mov     byte ptr [esp+108h+var_4], 1
  call    CWnd::UpdateData(int) ; ==>取得用户名,公司,Key信息
                          ; sub_10003650
  lea     edi, [esi+80h]  ; CString
                          ; name ==》用户名
  mov     ecx, edi
  call    sub_10003B80
  mov     ecx, eax
  call    loc_10003A20
  lea     ebp, [esi+78h]  ; CString
                          ; company ==》公司名
  mov     ecx, ebp
  call    sub_10003B80
  mov     ecx, eax
  call    loc_10003A20
  lea     ebx, [esi+7Ch]  ; CString
                          ; key ==》用户输入的Key
  mov     ecx, ebx
  call    sub_10003B80
  mov     ecx, eax
  call    loc_10003A20
  lea     ecx, [esi+84h]  ; CString==>暂时未知的字符串,后经分析可以得出,也可以动态跟踪得出为"Hex Workshop"
  call    sub_10003B80
  mov     ecx, eax
  call    loc_10003A20
  mov     eax, [edi]      ; name
  lea     ecx, [esp+104h+name_buf]
  sub     ecx, eax
  
  函数通过CWnd::UpdateData取得用户输入信息。让我们来看看这个函数:
  
  BOOL CWnd::UpdateData(BOOL bSaveAndValidate)
  {
          ASSERT(::IsWindow(m_hWnd)); // calling UpdateData before DoModal?
  
          CDataExchange dx(this, bSaveAndValidate);
  
          // prevent control notifications from being dispatched during UpdateData
          _AFX_THREAD_STATE* pThreadState = AfxGetThreadState();
          HWND hWndOldLockout = pThreadState->m_hLockoutNotifyWindow;
          ASSERT(hWndOldLockout != m_hWnd);   // must not recurse
          pThreadState->m_hLockoutNotifyWindow = m_hWnd;
  
          BOOL bOK = FALSE;       // assume failure
          TRY
          {
                  DoDataExchange(&dx);  ==>关键函数,注册对话框类会重载该函数
                  bOK = TRUE;         // it worked
          }
          CATCH(CUserException, e)
          {
                  // validation failed - user already alerted, fall through
                  ASSERT(!bOK);
                  // Note: DELETE_EXCEPTION_(e) not required
          }
          AND_CATCH_ALL(e)
          {
                  // validation failed due to OOM or other resource failure
                  e->ReportError(MB_ICONEXCLAMATION, AFX_IDP_INTERNAL_FAILURE);
                  ASSERT(!bOK);
                  DELETE_EXCEPTION(e);
          }
          END_CATCH_ALL
  
          pThreadState->m_hLockoutNotifyWindow = hWndOldLockout;
          return bOK;
  }
  
  要解释这个过程最好还是自己建一个基于对话框的应用程序,拖几个Edit控件在面板上,然后用类向导Ctrl+W针对该Edit控件
  增加值型数据成员,最后查看对话框类的DoDataExchange函数的具体实现。我所建事例该函数如下:
  void CSampDlg::DoDataExchange(CDataExchange* pDX)
  {
          CDialog::DoDataExchange(pDX);
          //{{AFX_DATA_MAP(CSampDlg)
          DDX_Text(pDX, IDC_EDIT1, m_edit1); ==>将控件与数据成员联系起来的函数
          //}}AFX_DATA_MAP
  }
  
  DDX_Text函数通过控件ID更新与其相关的成员数据。因此我们只要找到被重载后的DoDataExchange既可以得到存放Name, Company,
  Key值的具体数据成员。通过分析虚函数表可以发现,DoDataExchange被重载后为sub_10003650。以下是该函数实现:
  sub_10003650 proc near
  
  arg_0= dword ptr  0Ch
  
  push    esi
  push    edi
  mov     edi, [esp+arg_0]
  mov     esi, ecx        ; this指针
  lea     eax, [esi+78h]  ; Company Edit控件对应数据成员
  push    eax             ; int
  push    3E9h            ; nIDDlgItem==>1001, Company Edit控件ID
  push    edi             ; int
  call    sub_100182F4
  lea     ecx, [esi+7Ch]  ; Key Edit控件对应数据成员
  push    ecx             ; int
  push    3EAh            ; nIDDlgItem==>1002,Key Edit控件ID
  push    edi             ; int
  call    sub_100182F4
  add     esi, 80h        ; [esi+80h] Name Edit控件对应数据成员
  push    esi             ; int
  push    3E8h            ; nIDDlgItem==>1000,Name Edit控件ID
  push    edi             ; int
  call    sub_100182F4
  pop     edi
  pop     esi
  retn    4
  sub_10003650 endp
  
  因此通过分析可以得到与我们输入的各字符串对应的数据成员:[esi+80h]-name; [esi+78h]-company; [esi+7Ch]/key。

  下面继续分析按钮事件函数sub_10003DE0:
  
  .text:10003E32 6A 01                   push    1
  .text:10003E34 8B CE                   mov     ecx, esi
  .text:10003E36 C6 84 24 04 01 00 00 01 mov     byte ptr [esp+108h+var_4], 1
  .text:10003E3E E8 4B 00 01 00          call    CWnd::UpdateData(int) ; 取得用户名,公司,密码信息
  .text:10003E3E                                                       ; sub_10003650
  .text:10003E3E
  .text:10003E43 8D BE 80 00 00 00       lea     edi, [esi+80h]        ; CString
  .text:10003E43                                                       ; name
  .text:10003E49 8B CF                   mov     ecx, edi
  .text:10003E4B E8 30 FD FF FF          call    sub_10003B80
  .text:10003E4B
  .text:10003E50 8B C8                   mov     ecx, eax
  .text:10003E52 E8 C9 FB FF FF          call    loc_10003A20
  .text:10003E52
  .text:10003E57 8D 6E 78                lea     ebp, [esi+78h]        ; CString
  .text:10003E57                                                       ; company
  .text:10003E5A 8B CD                   mov     ecx, ebp
  .text:10003E5C E8 1F FD FF FF          call    sub_10003B80
  .text:10003E5C
  .text:10003E61 8B C8                   mov     ecx, eax
  .text:10003E63 E8 B8 FB FF FF          call    loc_10003A20
  .text:10003E63
  .text:10003E68 8D 5E 7C                lea     ebx, [esi+7Ch]        ; CString
  .text:10003E68                                                       ; key
  .text:10003E6B 8B CB                   mov     ecx, ebx
  .text:10003E6D E8 0E FD FF FF          call    sub_10003B80
  .text:10003E6D
  .text:10003E72 8B C8                   mov     ecx, eax
  .text:10003E74 E8 A7 FB FF FF          call    loc_10003A20
  .text:10003E74
  .text:10003E79 8D 8E 84 00 00 00       lea     ecx, [esi+84h]        ; CString
  .text:10003E7F E8 FC FC FF FF          call    sub_10003B80
  .text:10003E7F
  .text:10003E84 8B C8                   mov     ecx, eax
  .text:10003E86 E8 95 FB FF FF          call    loc_10003A20
  .text:10003E86
  .text:10003E8B 8B 07                   mov     eax, [edi]            ; name
  .text:10003E8D 8D 8C 24 A8 00 00 00    lea     ecx, [esp+104h+name_buf]
  .text:10003E94 2B C8                   sub     ecx, eax
  .text:10003E94
  .text:10003E96
  .text:10003E96                         loc_10003E96:                 ; CODE XREF: sub_10003DE0+BEj
  .text:10003E96 8A 10                   mov     dl, [eax]             ; strcpy(namebuf, name)
  .text:10003E98 88 14 01                mov     [ecx+eax], dl
  .text:10003E9B 40                      inc     eax
  .text:10003E9C 84 D2                   test    dl, dl
  .text:10003E9E 75 F6                   jnz     short loc_10003E96
  .text:10003E9E
  .text:10003EA0 8B 45 00                mov     eax, [ebp+0]          ; company
  .text:10003EA3 8D 54 24 58             lea     edx, [esp+104h+company_buf]
  .text:10003EA7 2B D0                   sub     edx, eax
  .text:10003EA9 8D A4 24 00 00 00 00    lea     esp, [esp+0]
  .text:10003EA9
  .text:10003EB0
  .text:10003EB0                         loc_10003EB0:                 ; CODE XREF: sub_10003DE0+D8j
  .text:10003EB0 8A 08                   mov     cl, [eax]             ; strcpy(company_buf, company)
  .text:10003EB2 88 0C 02                mov     [edx+eax], cl
  .text:10003EB5 40                      inc     eax
  .text:10003EB6 84 C9                   test    cl, cl
  .text:10003EB8 75 F6                   jnz     short loc_10003EB0
  .text:10003EB8
  .text:10003EBA 8B 03                   mov     eax, [ebx]            ; key
  .text:10003EBC 8D 54 24 18             lea     edx, [esp+104h+key_buf]
  .text:10003EC0 2B D0                   sub     edx, eax
  .text:10003EC0
  .text:10003EC2
  .text:10003EC2                         loc_10003EC2:                 ; CODE XREF: sub_10003DE0+EAj
  .text:10003EC2 8A 08                   mov     cl, [eax]             ; strcpy(key_buf, key)
  .text:10003EC4 88 0C 02                mov     [edx+eax], cl
  .text:10003EC7 40                      inc     eax
  .text:10003EC8 84 C9                   test    cl, cl
  .text:10003ECA 75 F6                   jnz     short loc_10003EC2
  .text:10003ECA
  .text:10003ECC 8B 86 84 00 00 00       mov     eax, [esi+84h]
  .text:10003ED2 8D 54 24 38             lea     edx, [esp+104h+var_CC]
  .text:10003ED6 2B D0                   sub     edx, eax
  .text:10003ED6
  .text:10003ED8
  .text:10003ED8                         loc_10003ED8:                 ; CODE XREF: sub_10003DE0+100j
  .text:10003ED8 8A 08                   mov     cl, [eax]             ; strcpy(unk_buf, unk_string)
  .text:10003EDA 88 0C 02                mov     [edx+eax], cl
  .text:10003EDD 40                      inc     eax
  .text:10003EDE 84 C9                   test    cl, cl
  .text:10003EE0 75 F6                   jnz     short loc_10003ED8
  .text:10003EE0
  .text:10003EE2 E8 20 55 01 00          call    AfxGetModuleState(void)
  .text:10003EE2
  .text:10003EE7 8B 40 04                mov     eax, [eax+4]
  .text:10003EEA 8B 10                   mov     edx, [eax]
  .text:10003EEC 6A 01                   push    1
  .text:10003EEE 8B C8                   mov     ecx, eax
  .text:10003EF0 FF 92 9C 00 00 00       call    dword ptr [edx+9Ch]
  .text:10003EF6 8B 3D 54 C2 01 10       mov     edi, ds:Sleep
  .text:10003EFC 68 D0 07 00 00          push    7D0h                  ; dwMilliseconds
  .text:10003F01 FF D7                   call    edi ; Sleep
  .text:10003F03 E8 FF 54 01 00          call    AfxGetModuleState(void)
  .text:10003F03
  .text:10003F08 8B 40 04                mov     eax, [eax+4]
  .text:10003F0B 8B 10                   mov     edx, [eax]
  .text:10003F0D 6A FF                   push    0FFFFFFFFh
  .text:10003F0F 8B C8                   mov     ecx, eax
  .text:10003F11 FF 92 9C 00 00 00       call    dword ptr [edx+9Ch]   ; DoWaitCursor
  .text:10003F11                                                       ;  0 => restore, 1=> begin, -1=> end
  .text:10003F17 8D 44 24 18             lea     eax, [esp+10Ch+var_F4] ; [esp+104h+key_buf]
  .text:10003F1B 50                      push    eax                   ; key
  .text:10003F1C 8B 86 88 02 00 00       mov     eax, [esi+288h]
  .text:10003F22 8D 4C 24 5C             lea     ecx, [esp+110h+var_B4] ; [esp+104h+company_buf]
  .text:10003F26 51                      push    ecx                   ; company
  .text:10003F27 8B 4E 70                mov     ecx, [esi+70h]
  .text:10003F2A 8D 94 24 B0 00 00 00    lea     edx, [esp+114h+var_64] ; [esp+104h+name_buf]
  .text:10003F31 52                      push    edx                   ; name
  .text:10003F32 33 D2                   xor     edx, edx
  .text:10003F34 8A 56 74                mov     dl, [esi+74h]
  .text:10003F37 50                      push    eax
  .text:10003F38 51                      push    ecx
  .text:10003F39 8D 44 24 4C             lea     eax, [esp+120h+var_D4] ; [esp+104h+unk_buf]
  .text:10003F3D 52                      push    edx
  .text:10003F3E 50                      push    eax                   ; pProgramFile
  .text:10003F3F E8 5C EC FF FF          call    key_verify            ; 参数:1/pProgramFile
  .text:10003F3F                                                       ; 2/m_data74: 04,
  .text:10003F3F                                                       ; 3/m_data70: 07,
  .text:10003F3F                                                       ; 4/m_data288: 0x40800000
  .text:10003F3F                                                       ; 5/pName, 6/pCom, 7/pKey
  .text:10003F3F                                                       ;
  .text:10003F3F                                                       ; 返回值: 0/成功, 非0/失败
  .text:10003F3F
  .text:10003F44 83 C4 1C                add     esp, 1Ch
  .text:10003F47 85 C0                   test    eax, eax
  .text:10003F49 75 4A                   jnz     short loc_10003F95
  .text:10003F49
  .text:10003F4B 6A 0D                   push    0Dh                   ; Thank you!  Your product has been unlocked.
  .text:10003F4B                                                       ;
  .text:10003F4D E8 92 28 01 00          call    AfxFindStringResourceHandle(uint)
  .text:10003F4D
  .text:10003F52 85 C0                   test    eax, eax
  .text:10003F54 74 0C                   jz      short loc_10003F62
  .text:10003F54
  .text:10003F56 6A 0D                   push    0Dh
  .text:10003F58 50                      push    eax
  .text:10003F59 8D 4C 24 1C             lea     ecx, [esp+114h+var_F8]
  .text:10003F5D E8 4E F9 FF FF          call    loc_100038B0
  .text:10003F5D
  .text:10003F62
  .text:10003F62                         loc_10003F62:                 ; CODE XREF: sub_10003DE0+174j
  .text:10003F62 6A 0B                   push    0Bh                   ; Success
  .text:10003F64 E8 7B 28 01 00          call    AfxFindStringResourceHandle(uint)
  .text:10003F64
  .text:10003F69 85 C0                   test    eax, eax
  .text:10003F6B 74 0C                   jz      short loc_10003F79
  .text:10003F6B
  .text:10003F6D 6A 0B                   push    0Bh
  .text:10003F6F 50                      push    eax
  .text:10003F70 8D 4C 24 18             lea     ecx, [esp+11Ch+var_104]
  .text:10003F74 E8 37 F9 FF FF          call    loc_100038B0
  .text:10003F74
  .text:10003F79
  .text:10003F79                         loc_10003F79:                 ; CODE XREF: sub_10003DE0+18Bj
  .text:10003F79 8B 4C 24 10             mov     ecx, [esp+11Ch+var_10C]
  .text:10003F7D 8B 54 24 14             mov     edx, [esp+11Ch+lpText]
  .text:10003F81 6A 40                   push    40h                   ; uType
  .text:10003F83 51                      push    ecx                   ; int
  .text:10003F84 52                      push    edx                   ; lpText
  .text:10003F85 8B CE                   mov     ecx, esi
  .text:10003F87 E8 A4 FE 00 00          call    sub_10013E30
  .text:10003F87
  .text:10003F8C 8B CE                   mov     ecx, esi
  .text:10003F8E E8 74 E9 00 00          call    CDialog::OnOK(void)
  .text:10003F8E
  .text:10003F93 EB 70                   jmp     short loc_10004005
  .text:10003F93
  .text:10003F95                         ; ---------------------------------------------------------------------------
  .text:10003F95
  .text:10003F95                         loc_10003F95:                 ; CODE XREF: sub_10003DE0+169j
  .text:10003F95 6A 0E                   push    0Eh
  .text:10003F97 E8 48 28 01 00          call    AfxFindStringResourceHandle(uint)
  .text:10003F97
  .text:10003F9C 85 C0                   test    eax, eax
  .text:10003F9E 74 0C                   jz      short loc_10003FAC
  .text:10003F9E
  .text:10003FA0 6A 0E                   push    0Eh                   ; Please check your key and try again.
  .text:10003FA0                                                       ; If this problem persists, please contact service@bpsoft.com.
  .text:10003FA0                                                       ;
  .text:10003FA2 50                      push    eax
  .text:10003FA3 8D 4C 24 1C             lea     ecx, [esp+114h+var_F8]
  .text:10003FA7 E8 04 F9 FF FF          call    loc_100038B0
  .text:10003FA7
  .text:10003FAC
  .text:10003FAC                         loc_10003FAC:                 ; CODE XREF: sub_10003DE0+1BEj
  .text:10003FAC 6A 0C                   push    0Ch                   ; Invalid Key
  .text:10003FAC                                                       ;
  .text:10003FAE E8 31 28 01 00          call    AfxFindStringResourceHandle(uint)
  .text:10003FAE
  .text:10003FB3 85 C0                   test    eax, eax
  .text:10003FB5 74 0C                   jz      short loc_10003FC3
  .text:10003FB5
  .text:10003FB7 6A 0C                   push    0Ch
  .text:10003FB9 50                      push    eax
  .text:10003FBA 8D 4C 24 18             lea     ecx, [esp+11Ch+var_104]
  .text:10003FBE E8 ED F8 FF FF          call    loc_100038B0
  .text:10003FBE
  .text:10003FC3
  .text:10003FC3                         loc_10003FC3:                 ; CODE XREF: sub_10003DE0+1D5j
  .text:10003FC3 8B 44 24 10             mov     eax, [esp+11Ch+var_10C]
  .text:10003FC7 8B 4C 24 14             mov     ecx, [esp+11Ch+lpText]
  .text:10003FCB 6A 40                   push    40h                   ; uType
  .text:10003FCD 50                      push    eax                   ; int
  .text:10003FCE 51                      push    ecx                   ; lpText
  .text:10003FCF 8B CE                   mov     ecx, esi
  .text:10003FD1 E8 5A FE 00 00          call    sub_10013E30
  .text:10003FD1
  .text:10003FD6 E8 2C 54 01 00          call    AfxGetModuleState(void)
  .text:10003FD6
  .text:10003FDB 8B 40 04                mov     eax, [eax+4]
  .text:10003FDE 8B 10                   mov     edx, [eax]
  .text:10003FE0 6A 01                   push    1
  .text:10003FE2 8B C8                   mov     ecx, eax
  .text:10003FE4 FF 92 9C 00 00 00       call    dword ptr [edx+9Ch]
  .text:10003FEA 68 D0 07 00 00          push    7D0h                  ; dwMilliseconds
  .text:10003FEF FF D7                   call    edi ; Sleep
  .text:10003FF1 E8 11 54 01 00          call    AfxGetModuleState(void)
  .text:10003FF1
  .text:10003FF6 8B 40 04                mov     eax, [eax+4]
  .text:10003FF9 8B 10                   mov     edx, [eax]
  .text:10003FFB 6A FF                   push    0FFFFFFFFh
  .text:10003FFD 8B C8                   mov     ecx, eax
  .text:10003FFF FF 92 9C 00 00 00       call    dword ptr [edx+9Ch]
  
  基本分析我都已经在注释中写明,其中name_buf, company_buf, ke_buf, key_verify是我根据分析重新命名的结果,读者可参照地址自行命名。
  这里要说明的是:弹出出错以及正确对话框均在函数sub_10013E30中完成。该函数共三个参数:lpText, lpCaption, type。其中
  lpText, lpCaption由loc_100038B0函数通过调用LoadResource载入字符串资源。
  具体载入哪两个字串资源也即弹出哪个对话框(正确或错误)由key_verify的返回值决定,即10003F3F处调用的函数。由此我们找到了
  真正关键的函数,这也是我把其命名为key_verify的原因所在。观察得到该函数共有7个参数,返回值分为0和非0--0/成功,软件成功注册;
  非0/失败,弹出出错对话框。
  该函数声明如注释中所述:
  .text:10003F3E 50                      push    eax                   ; pProgramFile
  .text:10003F3F E8 5C EC FF FF          call    key_verify            ; 参数:1/pProgramFile
  .text:10003F3F                                                       ; 2/m_data74: 04,
  .text:10003F3F                                                       ; 3/m_data70: 07,
  .text:10003F3F                                                       ; 4/m_data288: 0x40800000
  .text:10003F3F                                                       ; 5/pName, 6/pCom, 7/pKey
  .text:10003F3F                                                       ;
  .text:10003F3F                                                       ; 返回值: 0/成功, 非0/失败
  
  其中各参数可以通过动态调试得到,也可以静态分析得到。在这里我用的是静态分析,动态调试只是作为验证想法的辅助手段。
  静态分析得到的信息是:参数1-未知字符串指针,参数2~4-注册对话框实例数据成员,参数5-Name字符串指针,参数6-Company字符串指针,
  参数7-Key字符串指针。
  
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月29日 11:19:19
2009-1-29 20:43
0
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
【文章标题】: MFC实战--Hex Workshop V4.2破解笔记(三)
【文章作者】: frank
【下载地址】: 自己搜索下载
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
  下面来解析函数:key_verify
  
  .text:10002BA0                         key_verify proc near          ; CODE XREF: _102+2Ep
  .text:10002BA0                                                       ; sub_10003DE0+15Fp
  .text:10002BA0
  .text:10002BA0                         var_1D8= dword ptr -1D8h
  .text:10002BA0                         var_1C8= byte ptr -1C8h
  .text:10002BA0                         var_1C7= dword ptr -1C7h
  .text:10002BA0                         var_1C0= dword ptr -1C0h
  .text:10002BA0                         var_1BC= dword ptr -1BCh
  .text:10002BA0                         var_1B8= dword ptr -1B8h
  .text:10002BA0                         var_1B4= dword ptr -1B4h
  .text:10002BA0                         var_1B0= dword ptr -1B0h
  .text:10002BA0                         var_190= dword ptr -190h
  .text:10002BA0                         var_140= dword ptr -140h
  .text:10002BA0                         var_F0= byte ptr -0F0h
  .text:10002BA0                         var_D0= dword ptr -0D0h
  .text:10002BA0                         var_B0= dword ptr -0B0h
  .text:10002BA0                         var_AC= dword ptr -0ACh
  .text:10002BA0                         var_A8= dword ptr -0A8h
  .text:10002BA0                         var_A4= dword ptr -0A4h
  .text:10002BA0                         var_A0= dword ptr -0A0h
  .text:10002BA0                         var_9C= dword ptr -9Ch
  .text:10002BA0                         var_98= dword ptr -98h
  .text:10002BA0                         var_94= dword ptr -94h
  .text:10002BA0                         var_90= dword ptr -90h
  .text:10002BA0                         var_8C= dword ptr -8Ch
  .text:10002BA0                         var_88= dword ptr -88h
  .text:10002BA0                         pProgramFile= dword ptr  8
  .text:10002BA0                         arg_4= dword ptr  0Ch
  .text:10002BA0                         arg_8= dword ptr  10h
  .text:10002BA0                         arg_C= dword ptr  14h
  .text:10002BA0                         pName= dword ptr  18h
  .text:10002BA0                         pCompany= dword ptr  1Ch
  .text:10002BA0                         pKey= dword ptr  20h
  .text:10002BA0
  .text:10002BA0 55                      push    ebp
  .text:10002BA1 8B EC                   mov     ebp, esp
  .text:10002BA3 83 E4 F8                and     esp, 0FFFFFFF8h
  .text:10002BA6 81 EC CC 01 00 00       sub     esp, 1CCh
  .text:10002BAC 53                      push    ebx
  .text:10002BAD 56                      push    esi
  .text:10002BAE 57                      push    edi
  .text:10002BAF 6A 00                   push    0
  .text:10002BB1 E8 6C 35 00 00          call    __time64  =》生成随机变量
  .text:10002BB1
  .text:10002BB6 8B 5D 20                mov     ebx, [ebp+pKey]
  .text:10002BB9 83 C4 04                add     esp, 4
  .text:10002BBC 8B FB                   mov     edi, ebx
  .text:10002BBE 8B F0                   mov     esi, eax
  .text:10002BC0 89 54 24 24             mov     [esp+1D8h+var_1B4], edx
  .text:10002BC4 E8 E7 F9 FF FF          call    sub_100025B0
  .text:10002BC4
  .text:10002BC9 84 C0                   test    al, al
  .text:10002BCB 0F 85 0E 02 00 00       jnz     loc_10002DDF
  .text:10002BCB
  .text:10002BD1 8D 44 24 12             lea     eax, [esp+1D8h+var_1C7+1]
  .text:10002BD5 50                      push    eax                   ; int
  .text:10002BD6 8D 4C 24 14             lea     ecx, [esp+14h]        ; [esp+1DCh+var_1C8]
  .text:10002BDA 51                      push    ecx                   ; int
  .text:10002BDB 8D 54 24 1B             lea     edx, [esp+1E0h+var_1C7+2]
  .text:10002BDF 52                      push    edx                   ; int
  .text:10002BE0 8D 44 24 20             lea     eax, [esp+1E4h+var_1C7+3] ; [esp+1E4h+var_1C4]
  .text:10002BE4 50                      push    eax                   ; int
  .text:10002BE5 8D 4C 24 21             lea     ecx, [esp+1E8h+var_1C7]
  .text:10002BE9 51                      push    ecx                   ; int
  .text:10002BEA 8D 54 24 2C             lea     edx, [esp+1ECh+var_1C0]
  .text:10002BEE 52                      push    edx                   ; int
  .text:10002BEF 8D 44 24 34             lea     eax, [esp+1F0h+var_1BC]
  .text:10002BF3 50                      push    eax                   ; int
  .text:10002BF4 53                      push    ebx                   ; char *
  .text:10002BF5 E8 36 F7 FF FF          call    sub_10002330          ; Byte func(pKey, pInt, pInt, pByte,
  .text:10002BF5                                                       ;         pInt, pByte, pByte, pByte);
  .text:10002BF5                                                       ;
  .text:10002BF5                                                       ; 参数:1/pKey
  .text:10002BF5                                                       ;
  .text:10002BF5                                                       ; 返回值:0/失败,非0/成功
  .text:10002BF5
  .text:10002BFA 83 C4 20                add     esp, 20h
  .text:10002BFD 84 C0                   test    al, al
  .text:10002BFF 0F 84 F2 01 00 00       jz      loc_10002DF7
  .text:10002BFF
  .text:10002C05 8B 4D 0C                mov     ecx, [ebp+arg_4]      ; 04
  .text:10002C08 38 4C 24 11             cmp     byte ptr [esp+1D8h+var_1C7], cl
  .text:10002C0C 0F 85 C1 01 00 00       jnz     loc_10002DD3
  .text:10002C0C
  .text:10002C12 8B 44 24 14             mov     eax, [esp+1D8h+var_1C7+3] ; [esp+1D8h+var_1C4]
  .text:10002C12                                                       ; 0b***00111
  .text:10002C16 8B 7D 10                mov     edi, [ebp+arg_8]
  .text:10002C19 3B C7                   cmp     eax, edi
  .text:10002C1B 0F 8C B2 01 00 00       jl      loc_10002DD3
  .text:10002C1B
  .text:10002C21 8D 54 24 28             lea     edx, [esp+1D8h+var_1B0]
  .text:10002C25 52                      push    edx
  .text:10002C26 50                      push    eax                   ; 2722
  .text:10002C27 8B 45 08                mov     eax, [ebp+pProgramFile] ; Hex WorkShop
  .text:10002C2A 51                      push    ecx                   ; 04->BE
  .text:10002C2B 50                      push    eax
  .text:10002C2C E8 0F F1 FF FF          call    sub_10001D40          ; 注册表键值变形
  .text:10002C2C                                                       ; 并将结果存入
  .text:10002C2C                                                       ; 参数4所指地址
  .text:10002C2C
  .text:10002C31 83 C4 10                add     esp, 10h
  .text:10002C34 84 C0                   test    al, al
  .text:10002C36 75 10                   jnz     short loc_10002C48
  .text:10002C36
  .text:10002C38 B9 6B 00 00 00          mov     ecx, 6Bh
  .text:10002C3D 33 C0                   xor     eax, eax
  .text:10002C3F 8D 7C 24 28             lea     edi, [esp+1D8h+var_1B0]
  .text:10002C43 F3 AB                   rep stosd                     ; 函数返回值为0时
  .text:10002C43                                                       ; 使用_time64函数
  .text:10002C43                                                       ; 返回值低32bit填充缓冲区
  .text:10002C45 8B 7D 10                mov     edi, [ebp+arg_8]
  .text:10002C45
  .text:10002C48
  .text:10002C48                         loc_10002C48:                 ; CODE XREF: key_verify+96j
  .text:10002C48 8D 54 24 28             lea     edx, [esp+1D8h+var_1B0]
  .text:10002C4C 8B C3                   mov     eax, ebx              ; pKey
  .text:10002C4E 2B D3                   sub     edx, ebx
  .text:10002C4E
  .text:10002C50
  .text:10002C50                         loc_10002C50:                 ; CODE XREF: key_verify+B8j
  .text:10002C50 8A 08                   mov     cl, [eax]
  .text:10002C52 88 0C 02                mov     [edx+eax], cl
  .text:10002C55 40                      inc     eax
  .text:10002C56 84 C9                   test    cl, cl
  .text:10002C58 75 F6                   jnz     short loc_10002C50
  .text:10002C58
  .text:10002C5A 8B 45 18                mov     eax, [ebp+pName]      ; pName
  .text:10002C5D 8D 54 24 48             lea     edx, [esp+1D8h+var_190]
  .text:10002C61 2B D0                   sub     edx, eax
  .text:10002C61
  .text:10002C63
  .text:10002C63                         loc_10002C63:                 ; CODE XREF: key_verify+CBj
  .text:10002C63 8A 08                   mov     cl, [eax]
  .text:10002C65 88 0C 02                mov     [edx+eax], cl
  .text:10002C68 40                      inc     eax
  .text:10002C69 84 C9                   test    cl, cl
  .text:10002C6B 75 F6                   jnz     short loc_10002C63
  .text:10002C6B
  .text:10002C6D 8B 45 1C                mov     eax, [ebp+pCompany]   ; pComapany
  .text:10002C70 8D 94 24 98 00 00 00    lea     edx, [esp+1D8h+var_140]
  .text:10002C77 2B D0                   sub     edx, eax
  .text:10002C79 8D A4 24 00 00 00 00    lea     esp, [esp+0]
  .text:10002C79
  .text:10002C80
  .text:10002C80                         loc_10002C80:                 ; CODE XREF: key_verify+E8j
  .text:10002C80 8A 08                   mov     cl, [eax]
  .text:10002C82 88 0C 02                mov     [edx+eax], cl
  .text:10002C85 40                      inc     eax
  .text:10002C86 84 C9                   test    cl, cl
  .text:10002C88 75 F6                   jnz     short loc_10002C80
  .text:10002C88
  .text:10002C8A 8B 4C 24 1C             mov     ecx, [esp+1D8h+var_1BC]
  .text:10002C8E 51                      push    ecx                   ; ****04$$-******-****
  .text:10002C8E                                                       ; $$:0b***00111
  .text:10002C8E                                                       ; field1-field2-field3
  .text:10002C8E                                                       ; =>field2
  .text:10002C8F 8D 94 24 EC 00 00 00    lea     edx, [esp+1DCh+var_F0]
  .text:10002C96 68 B4 C9 01 10          push    offset s_06d          ; "%06d"
  .text:10002C9B 52                      push    edx                   ; char *
  .text:10002C9C E8 B3 28 00 00          call    _sprintf
  .text:10002C9C
  .text:10002CA1 8B 5D 08                mov     ebx, [ebp+pProgramFile]
  .text:10002CA4 8D 94 24 14 01 00 00    lea     edx, [esp+1E4h+var_D0]
  .text:10002CAB 83 C4 0C                add     esp, 0Ch
  .text:10002CAE 8B C3                   mov     eax, ebx
  .text:10002CB0 2B D3                   sub     edx, ebx
  .text:10002CB0
  .text:10002CB2
  .text:10002CB2                         loc_10002CB2:                 ; CODE XREF: key_verify+11Aj
  .text:10002CB2 8A 08                   mov     cl, [eax]             ; strcpy(var_D0, pProgramFile)
  .text:10002CB4 88 0C 02                mov     [edx+eax], cl
  .text:10002CB7 40                      inc     eax
  .text:10002CB8 84 C9                   test    cl, cl
  .text:10002CBA 75 F6                   jnz     short loc_10002CB2
  .text:10002CBA
  .text:10002CBC 8B 44 24 18             mov     eax, [esp+1D8h+var_1C0] ; ****04$$-******-****
  .text:10002CBC                                                       ; $$:0b***00111
  .text:10002CBC                                                       ; field1-field2-field3
  .text:10002CBC                                                       ; =>*pArg3
  .text:10002CC0 8B 4D 14                mov     ecx, [ebp+arg_C]      ; [esi+288h]
  .text:10002CC3 89 84 24 28 01 00 00    mov     [esp+1D8h+var_B0], eax
  .text:10002CCA 8A 44 24 10             mov     al, [esp+1D8h+var_1C8] ; *pArg7
  .text:10002CCE 84 C0                   test    al, al
  .text:10002CD0 89 8C 24 50 01 00 00    mov     [esp+1D8h+var_88], ecx
  .text:10002CD7 74 7C                   jz      short loc_10002D55
  .text:10002CD7
  .text:10002CD9 8B 8C 24 38 01 00 00    mov     ecx, [esp+1D8h+var_A0]
  .text:10002CE0 85 C9                   test    ecx, ecx
  .text:10002CE2 B8 01 00 00 00          mov     eax, 1
  .text:10002CE7 89 84 24 2C 01 00 00    mov     [esp+1D8h+var_AC], eax
  .text:10002CEE 0F 85 B7 00 00 00       jnz     loc_10002DAB
  .text:10002CEE
  .text:10002CF4 6A 00                   push    0
  .text:10002CF6 6A 00                   push    0
  .text:10002CF8 6A 00                   push    0
  .text:10002CFA 6A 0F                   push    0Fh
  .text:10002CFC 8D 4C 24 30             lea     ecx, [esp+1E8h+var_1B8]
  .text:10002D00 C7 84 24 40 01 00 00 00+mov     [esp+1E8h+var_A8], 0
  .text:10002D0B 89 84 24 44 01 00 00    mov     [esp+1E8h+var_A4], eax
  .text:10002D12 89 84 24 48 01 00 00    mov     [esp+1E8h+var_A0], eax
  .text:10002D19 C7 84 24 4C 01 00 00 0F+mov     [esp+1E8h+var_9C], 0Fh
  .text:10002D24 89 B4 24 50 01 00 00    mov     [esp+1E8h+var_98], esi
  .text:10002D2B 89 B4 24 54 01 00 00    mov     [esp+1E8h+var_94], esi
  .text:10002D32 E8 69 FB FF FF          call    sub_100028A0
  .text:10002D32
  .text:10002D37 8B 08                   mov     ecx, [eax]
  .text:10002D39 8B 50 04                mov     edx, [eax+4]
  .text:10002D3C 8B 45 0C                mov     eax, [ebp+arg_4]
  .text:10002D3F 03 CE                   add     ecx, esi
  .text:10002D41 57                      push    edi
  .text:10002D42 50                      push    eax
  .text:10002D43 89 54 24 2C             mov     [esp+1E0h+var_1B4], edx
  .text:10002D47 89 8C 24 50 01 00 00    mov     [esp+1E0h+var_90], ecx
  .text:10002D4E E8 8D EE FF FF          call    sub_10001BE0
  .text:10002D4E
  .text:10002D53 EB 53                   jmp     short loc_10002DA8
  .text:10002D53
  .text:10002D55                         ; ---------------------------------------------------------------------------
  .text:10002D55
  .text:10002D55                         loc_10002D55:                 ; CODE XREF: key_verify+137j
  .text:10002D55 8B 4D 0C                mov     ecx, [ebp+arg_4]
  .text:10002D58 33 C0                   xor     eax, eax
  .text:10002D5A 57                      push    edi
  .text:10002D5B 51                      push    ecx
  .text:10002D5C 89 84 24 34 01 00 00    mov     [esp+1E0h+var_AC], eax
  .text:10002D63 89 84 24 38 01 00 00    mov     [esp+1E0h+var_A8], eax
  .text:10002D6A 89 84 24 3C 01 00 00    mov     [esp+1E0h+var_A4], eax
  .text:10002D71 C7 84 24 40 01 00 00 01+mov     [esp+1E0h+var_A0], 1
  .text:10002D7C C7 84 24 44 01 00 00 FF+mov     [esp+1E0h+var_9C], 0FFFFFFFFh
  .text:10002D87 89 B4 24 48 01 00 00    mov     [esp+1E0h+var_98], esi
  .text:10002D8E 89 B4 24 4C 01 00 00    mov     [esp+1E0h+var_94], esi
  .text:10002D95 89 B4 24 50 01 00 00    mov     [esp+1E0h+var_90], esi
  .text:10002D9C 89 84 24 54 01 00 00    mov     [esp+1E0h+var_8C], eax
  .text:10002DA3 E8 A8 EE FF FF          call    sub_10001C50
  .text:10002DA3
  .text:10002DA8
  .text:10002DA8                         loc_10002DA8:                 ; CODE XREF: key_verify+1B3j
  .text:10002DA8 83 C4 08                add     esp, 8
  .text:10002DA8
  .text:10002DAB
  .text:10002DAB                         loc_10002DAB:                 ; CODE XREF: key_verify+14Ej
  .text:10002DAB 8B 45 0C                mov     eax, [ebp+arg_4]
  .text:10002DAE 8D 54 24 28             lea     edx, [esp+1D8h+var_1B0]
  .text:10002DB2 52                      push    edx
  .text:10002DB3 57                      push    edi
  .text:10002DB4 50                      push    eax
  .text:10002DB5 53                      push    ebx
  .text:10002DB6 E8 E5 F1 FF FF          call    sub_10001FA0          ; 返回值:0/失败, 1/成功
  .text:10002DB6
  .text:10002DBB 83 C4 10                add     esp, 10h
  .text:10002DBE F6 D8                   neg     al
  .text:10002DC0 1B C0                   sbb     eax, eax
  .text:10002DC2 25 FF FE FF FF          and     eax, 0FFFFFEFFh
  .text:10002DC7 05 01 01 00 00          add     eax, 101h             ; 最后返回值:0/成功, 非0/失败
  .text:10002DC7                                                       ; 非0:0x101, 5, 2
  .text:10002DCC 5F                      pop     edi
  .text:10002DCD 5E                      pop     esi
  .text:10002DCE 5B                      pop     ebx
  .text:10002DCF 8B E5                   mov     esp, ebp
  .text:10002DD1 5D                      pop     ebp
  .text:10002DD2 C3                      retn
  .text:10002DD2
  .text:10002DD3                         ; ---------------------------------------------------------------------------
  .text:10002DD3
  .text:10002DD3                         loc_10002DD3:                 ; CODE XREF: key_verify+6Cj
  .text:10002DD3                                                       ; key_verify+7Bj
  .text:10002DD3 B8 05 00 00 00          mov     eax, 5
  .text:10002DD8 5F                      pop     edi
  .text:10002DD9 5E                      pop     esi
  .text:10002DDA 5B                      pop     ebx
  .text:10002DDB 8B E5                   mov     esp, ebp
  .text:10002DDD 5D                      pop     ebp
  .text:10002DDE C3                      retn
  .text:10002DDE
  .text:10002DDF                         ; ---------------------------------------------------------------------------
  .text:10002DDF
  .text:10002DDF                         loc_10002DDF:                 ; CODE XREF: key_verify+2Bj
  .text:10002DDF 8B 3D 54 C2 01 10       mov     edi, ds:Sleep
  .text:10002DE5 BE 0A 00 00 00          mov     esi, 0Ah
  .text:10002DEA 8D 9B 00 00 00 00       lea     ebx, [ebx+0]
  .text:10002DEA
  .text:10002DF0
  .text:10002DF0                         loc_10002DF0:                 ; CODE XREF: key_verify+255j
  .text:10002DF0 6A 64                   push    64h                   ; dwMilliseconds
  .text:10002DF2 FF D7                   call    edi ; Sleep
  .text:10002DF4 4E                      dec     esi
  .text:10002DF5 75 F9                   jnz     short loc_10002DF0
  .text:10002DF5
  .text:10002DF7
  .text:10002DF7                         loc_10002DF7:                 ; CODE XREF: key_verify+5Fj
  .text:10002DF7 5F                      pop     edi
  .text:10002DF8 5E                      pop     esi
  .text:10002DF9 B8 02 00 00 00          mov     eax, 2
  .text:10002DFE 5B                      pop     ebx
  .text:10002DFF 8B E5                   mov     esp, ebp
  .text:10002E01 5D                      pop     ebp
  .text:10002E02 C3                      retn
  .text:10002E02
  .text:10002E02                         key_verify endp
  .text:10002E02
  
  该函数同样分支众多,我们来一一解析。

  第一部分
========
  首先第一个可能导致函数返回非零值的分支出现在对函数sub_100025B0返回值的检查上--0/继续执行, 非0/sleep会儿然后返回2.
  跟进函数sub_100025B0为:
  .text:100025B0                         sub_100025B0 proc near        ; CODE XREF: key_verify+24p
  .text:100025B0
  .text:100025B0                         var_4= dword ptr -4
  .text:100025B0
  .text:100025B0 53                      push    ebx
  .text:100025B1 32 DB                   xor     bl, bl
  .text:100025B3 E8 B8 FF FF FF          call    sub_10002570
  .text:100025B3
  .text:100025B8 A1 A8 31 02 10          mov     eax, off_100231A8
  .text:100025BD 85 C0                   test    eax, eax
  .text:100025BF 74 35                   jz      short loc_100025F6
  .text:100025BF
  .text:100025C1 B8 A8 31 02 10          mov     eax, offset off_100231A8
  .text:100025C6 56                      push    esi
  .text:100025C7 8B F0                   mov     esi, eax
  .text:100025C9 8D A4 24 00 00 00 00    lea     esp, [esp+0]
  .text:100025C9
  .text:100025D0
  .text:100025D0                         loc_100025D0:                 ; CODE XREF: sub_100025B0+3Aj
  .text:100025D0 8B 00                   mov     eax, [eax]
  .text:100025D2 50                      push    eax                   ; char *
  .text:100025D3 57                      push    edi                   ; char *
  .text:100025D4 E8 87 38 00 00          call    _strstr
  .text:100025D4
  .text:100025D9 83 C4 08                add     esp, 8
  .text:100025DC 85 C0                   test    eax, eax
  .text:100025DE 75 11                   jnz     short loc_100025F1
  .text:100025DE
  .text:100025E0 8B 4E 04                mov     ecx, [esi+4]
  .text:100025E3 83 C6 04                add     esi, 4
  .text:100025E6 85 C9                   test    ecx, ecx
  .text:100025E8 8B C6                   mov     eax, esi
  .text:100025EA 75 E4                   jnz     short loc_100025D0
  .text:100025EA
  .text:100025EC 5E                      pop     esi
  .text:100025ED 8A C3                   mov     al, bl
  .text:100025EF 5B                      pop     ebx
  .text:100025F0 C3                      retn
  .text:100025F0
  .text:100025F1                         ; ---------------------------------------------------------------------------
  .text:100025F1
  .text:100025F1                         loc_100025F1:                 ; CODE XREF: sub_100025B0+2Ej
  .text:100025F1 5E                      pop     esi
  .text:100025F2 B0 01                   mov     al, 1
  .text:100025F4 5B                      pop     ebx
  .text:100025F5 C3                      retn
  .text:100025F5
  .text:100025F6                         ; ---------------------------------------------------------------------------
  .text:100025F6
  .text:100025F6                         loc_100025F6:                 ; CODE XREF: sub_100025B0+Fj
  .text:100025F6 8A C3                   mov     al, bl
  .text:100025F8 5B                      pop     ebx
  .text:100025F9 C3                      retn
  .text:100025F9
  .text:100025F9                         sub_100025B0 endp
  .text:100025F9
  .text:100025F9                         ; ---------------------------------------------------------------------------
  可以看出函数在对一个字符串数组进行循环比对,如果用户输入的key值是该数组某个元素的字串的话返回非0,如果都不是则返回0.
  那么这个数组是什么呢?进一步跟进发现该数组是个全局变量(在.data段中),数组每个元素所指的字符串也是全局变量,但均为乱码!!
  这说明程序启动以后还会对该乱码进行变化以使其变为正常的字符串。那么必然有函数引用该全局数组!!果然我们看到除函数sub_100025B0
  引用概述组外,还有一个函数sub_10002570对其进行了引用!
  .data:100231A7 00                      align 4
  .data:100231A8 5C 31 02 10             off_100231A8 dd offset s_LmlmmkoN
  .data:100231A8                                                       ; DATA XREF: sub_10002570+9r
  .data:100231A8                                                       ; sub_10002570+19o
  .data:100231A8                                                       ; sub_100025B0+8r
  .data:100231A8                                                       ; sub_100025B0+11o
  .data:100231A8                                                       ; "媽媽寠廂嵑"
  .data:100231AC 68 31 02 10             dd offset s_Lmlmmkokn         ; "媽媽寠帄嵑"
  .data:100231B0 74 31 02 10             dd offset s_Lkoknckilkglc     ; "媻帄崡妶媻儖楕偤"
  .data:100231B4 88 31 02 10             dd offset s_Lkoknckilgolc     ; "媻帄崡妶媰帇楟孇嫼"
  .data:100231B8 9C 31 02 10             dd offset s_Lmlmnkoknk        ; "媽媽崐帄崐"
  
  跳到该函数为:
  .text:10002570                         sub_10002570 proc near        ; CODE XREF: sub_100025B0+3p
  .text:10002570 A0 80 49 02 10          mov     al, byte_10024980     ; xor
  .text:10002575 84 C0                   test    al, al
  .text:10002577 75 35                   jnz     short locret_100025AE
  .text:10002577
  .text:10002579 A1 A8 31 02 10          mov     eax, off_100231A8
  .text:1000257E 85 C0                   test    eax, eax
  .text:10002580 C6 05 80 49 02 10 01    mov     byte_10024980, 1
  .text:10002587 74 25                   jz      short locret_100025AE
  .text:10002587
  .text:10002589 B8 A8 31 02 10          mov     eax, offset off_100231A8
  .text:1000258E 8B C8                   mov     ecx, eax
  .text:1000258E
  .text:10002590
  .text:10002590                         loc_10002590:                 ; CODE XREF: sub_10002570+3Cj
  .text:10002590 8B 00                   mov     eax, [eax]
  .text:10002592 80 38 00                cmp     byte ptr [eax], 0
  .text:10002595 74 0B                   jz      short loc_100025A2
  .text:10002595
  .text:10002597
  .text:10002597                         loc_10002597:                 ; CODE XREF: sub_10002570+30j
  .text:10002597 80 30 BA                xor     byte ptr [eax], 0BAh
  .text:1000259A 8A 50 01                mov     dl, [eax+1]
  .text:1000259D 40                      inc     eax
  .text:1000259E 84 D2                   test    dl, dl
  .text:100025A0 75 F5                   jnz     short loc_10002597
  .text:100025A0
  .text:100025A2
  .text:100025A2                         loc_100025A2:                 ; CODE XREF: sub_10002570+25j
  .text:100025A2 8B 51 04                mov     edx, [ecx+4]
  .text:100025A5 83 C1 04                add     ecx, 4
  .text:100025A8 85 D2                   test    edx, edx
  .text:100025AA 8B C1                   mov     eax, ecx
  .text:100025AC 75 E2                   jnz     short loc_10002590
  .text:100025AC
  .text:100025AE
  .text:100025AE                         locret_100025AE:              ; CODE XREF: sub_10002570+7j
  .text:100025AE                                                       ; sub_10002570+17j
  .text:100025AE C3                      retn
  .text:100025AE
  .text:100025AE                         sub_10002570 endp
  .text:100025AE
  
  该函数比较简单,不再做详细解释。以下是我对该函数的逆向源代码:
  #define FILTER_MAX 5
  
  Byte g_byte1[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8C, 0x8A, 0x8E, 0xFB, 0x8D, 0xBA, 0x00};
  Byte g_byte2[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8C, 0x8A, 0x8E, 0x8A, 0x8D, 0XBA, 0x00};
  Byte g_byte3[] = {0x8B, 0x8A, 0x8E, 0x8A, 0x8D, 0x97, 0x8A, 0x88, 0x8B, 0x8A, 0x83,
               0x8B, 0x97, 0xF8, 0xF8, 0xFE, 0x82, 0xBA, 0x00};
  Byte g_byte4[] = {0x8B, 0x8A, 0x8E, 0x8A, 0x8D, 0x97, 0x8A, 0x88, 0x8B, 0x83, 0x8E,
               0x8B, 0x97, 0xFE, 0x8B, 0xFE, 0x00};
  Byte g_byte5[] = {0x8B, 0x8C, 0x8B, 0x8C, 0x8D, 0x8A, 0x8E, 0x8A, 0x8D, 0x8A, 0x00};
  
  PBYTE g_strArray[] = {g_byte1, g_byte2, g_byte3, g_byte4, g_byte5, 0};
  
  static void SetFilter()
  {
      int i=0, j=0;
      PBYTE temp = NULL;
  
          while (temp = g_strArray[i]) {
  #ifdef _DEBUG
                  printf("Original value: ");
  
                  j = 0;
                  while (temp[j]) {
                    printf("0x%02X ", temp[j]);
                    j++;
                  }
  
                  printf("\n");
   #endif      
                  j = 0;
                  while (temp[j]) {
                temp[j] ^= 0xBA;
                    j++;
                  }
  #ifdef _DEBUG
                  printf("New value: %s\n\n", temp);
  #endif
                  i++;
          }
     
          return;
  }
  
  通过运行该函数可以得到个字符串为:
  Original value: 0x8B 0x8C 0x8B 0x8C 0x8C 0x8A 0x8E 0xFB 0x8D 0xBA
  New value: 1616604A7
  
  Original value: 0x8B 0x8C 0x8B 0x8C 0x8C 0x8A 0x8E 0x8A 0x8D 0xBA
  New value: 161660407
  
  Original value: 0x8B 0x8A 0x8E 0x8A 0x8D 0x97 0x8A 0x88 0x8B 0x8A 0x83 0x8B 0x97
   0xF8 0xF8 0xFE 0x82 0xBA
  New value: 10407-021091-BBD8
  
  Original value: 0x8B 0x8A 0x8E 0x8A 0x8D 0x97 0x8A 0x88 0x8B 0x83 0x8E 0x8B 0x97
   0xFE 0x8B 0xFE
  New value: 10407-021941-D1D
  
  Original value: 0x8B 0x8C 0x8B 0x8C 0x8D 0x8A 0x8E 0x8A 0x8D 0x8A
  New value: 1616704070
  
  因此输入的key值切不可为以上5个字符串中任何一个的字串!!!--不过话说回来真正想命中这些字串还是比较有难度的,所以我们可以不必
  太在乎这个纸老虎。
  
  第二部份
  ========
  第二个分支发生在对函数sub_10002330调用完毕后进行返回值检查时:0/失败--返回2,非0/成功--继续执行。
  下面对该函数进行详细讲解(其实该函数才是真正对Key进行变换验证的地方):
  函数共有8个参数:除参数1为用户输入的key以外,其余参数均为局部变量地址--说明该函数需要将解析所得值填入这些局部变量!!
  7个局部变量参数中,除参数2、3、5为指向DWORD型指针外,其余均为指向BYTE型指针!!
  返回值只检查al--说明返回值类型也为BYTE型。
  据此我们可以写出函数原型为:
  call    sub_10002330    ; Byte sub_10002330(pKey, pInt, pInt, pByte,
                          ;         pInt, pByte, pByte, pByte);
                          ;
                          ; 参数:1/pKey
                          ;
                          ; 返回值:0/失败,非0/成功
  
  2.1 key_parse函数逆向
  
  sub_10002330函数同样也是个拥有众多分支的函数,限于篇幅我把关键的几个地方的分析贴出来供大家参考:
  
  .text:10002350 8D 54 24 64             lea     edx, [esp+164h+field3]
  .text:10002354 52                      push    edx                   ; field3
  .text:10002355 8D 84 24 A8 00 00 00    lea     eax, [esp+168h+field2]
  .text:1000235C 50                      push    eax                   ; field2
  .text:1000235D 8D 4C 24 2C             lea     ecx, [esp+16Ch+field1]
  .text:10002361 51                      push    ecx                   ; field1
  .text:10002362 8D 94 24 F0 00 00 00    lea     edx, [esp+170h+key]
  .text:10002369 52                      push    edx                   ; char *
  .text:1000236A E8 E1 FE FF FF          call    key_parse             ; 解析参数1所指字符串:****0407-******-****
  .text:1000236A
  同样key_parse也是我重命名的结果,大家可以参考地址找到原函数。该函数的作用是把用户输入的Key值按'-'字符分隔开,并把
  每段字串地址的指针付给三个输入的指针参数。比如输入Key为10000407-123456-0512,分割后会变成"10000407","123456","0512"。
  注意:该函数还对段数以及每段字串长度做了检查--第一段长度不得小于5,第二段长度必须为6,第三段长度必须为4!
  以下是我对该函数的逆向源代码:
  Byte key_parse (char *pKey, char *field1, char *field2, char *field3)
  {
    char *temp = NULL;
  
    /* Field1 parse */
    temp = strtok(pKey, "-");
  
    if(temp==NULL || strlen(temp) < FIELD1_LEN_MIN)
      return 0;
    else
          strcpy(field1, temp);
  
  #ifdef _DEBUG
    printf("\nfield1: %s", field1);
  #endif
  
    /* Field2 parse */
    temp = strtok(NULL, "-");
  
    if(temp==NULL || strlen(temp) != FIELD2_LEN)
      return 0;
    else
          strcpy(field2, temp);
  
  #ifdef _DEBUG
    printf("\nfield2: %s", field2);
  #endif
  
    /* Field3 parse */
    temp = strtok(NULL, "-");
  
    if(temp==NULL || strlen(temp) != FIELD3_LEN)
      return 0;
    else
          strcpy(field3, temp);
  
  #ifdef _DEBUG
    printf("\nfield3: %s", field3);
  #endif
  
    return 1;
  }
  
  2.2 sub_10002330函数逆向
  
  经过上述解析后sub_10002330函数的逆向工作变得简单起来,重点部分我已经在注释中说明了:
  
  .text:1000237A 8D 44 24 18             lea     eax, [esp+158h+field1]
  .text:1000237E 8D 50 01                lea     edx, [eax+1]
  .text:1000237E
  .text:10002381
  .text:10002381                         loc_10002381:                 ; CODE XREF: sub_10002330+56j
  .text:10002381 8A 08                   mov     cl, [eax]
  .text:10002383 40                      inc     eax
  .text:10002384 84 C9                   test    cl, cl
  .text:10002386 75 F9                   jnz     short loc_10002381
  .text:10002386
  .text:10002388 2B C2                   sub     eax, edx
  .text:1000238A 83 F8 05                cmp     eax, 5                ; 再次比较field1长度>=5
  .text:1000238D 0F 8C B0 01 00 00       jl      loc_10002543
  .text:1000238D
  .text:10002393 56                      push    esi
  .text:10002394 8D 74 04 18             lea     esi, [esp+eax+15Ch+var_144]
  .text:10002398 8D 54 24 0C             lea     edx, [esp+15Ch+var_150]
  .text:1000239C 8B C6                   mov     eax, esi
  .text:1000239E 2B D6                   sub     edx, esi
  .text:1000239E
  .text:100023A0
  .text:100023A0                         loc_100023A0:                 ; CODE XREF: sub_10002330+78j
  .text:100023A0 8A 08                   mov     cl, [eax]             ; field最后4个字节copy到var_150变量中去
  .text:100023A2 88 0C 02                mov     [edx+eax], cl
  .text:100023A5 40                      inc     eax
  .text:100023A6 84 C9                   test    cl, cl
  .text:100023A8 75 F6                   jnz     short loc_100023A0
  .text:100023A8
  .text:100023AA 88 0E                   mov     [esi], cl
  .text:100023AC 80 7C 24 1C 2A          cmp     byte ptr [esp+15Ch+field1], 2Ah ; '*'
  .text:100023B1 75 0F                   jnz     short loc_100023C2
  .text:100023B1
  .text:100023B3 8B 84 24 68 01 00 00    mov     eax, [esp+15Ch+arg_8]
  .text:100023BA C7 00 FF FF FF FF       mov     dword ptr [eax], 0FFFFFFFFh
  .text:100023C0 EB 1D                   jmp     short loc_100023DF
  .text:100023C0
  .text:100023C2                         ; ---------------------------------------------------------------------------
  .text:100023C2
  .text:100023C2                         loc_100023C2:                 ; CODE XREF: sub_10002330+81j
  .text:100023C2 6A 0A                   push    0Ah                   ; int
  .text:100023C4 8D 4C 24 0C             lea     ecx, [esp+160h+var_154]
  .text:100023C8 51                      push    ecx                   ; char **
  .text:100023C9 8D 54 24 24             lea     edx, [esp+164h+field1]
  .text:100023CD 52                      push    edx                   ; char *
  .text:100023CE E8 2F 39 00 00          call    _strtol               ; field1头4个字节转为long
  .text:100023CE
  .text:100023D3 8B 8C 24 74 01 00 00    mov     ecx, [esp+168h+arg_8]
  .text:100023DA 83 C4 0C                add     esp, 0Ch
  .text:100023DD 89 01                   mov     [ecx], eax            ; 结果赋值参数3所指变量
  .text:100023DD
  .text:100023DF
  .text:100023DF                         loc_100023DF:                 ; CODE XREF: sub_10002330+90j
  .text:100023DF 8A 54 24 0C             mov     dl, byte ptr [esp+15Ch+var_150]
  .text:100023E3 8A 44 24 0D             mov     al, byte ptr [esp+15Ch+var_150+1]
  .text:100023E7 6A 10                   push    10h                   ; int
  .text:100023E9 8D 4C 24 0C             lea     ecx, [esp+160h+var_154]
  .text:100023ED 88 54 24 1C             mov     [esp+160h+var_144], dl
  .text:100023F1 51                      push    ecx                   ; char **
  .text:100023F2 8D 54 24 20             lea     edx, [esp+164h+var_144]
  .text:100023F6 52                      push    edx                   ; char *
  .text:100023F7 88 44 24 25             mov     [esp+25h], al         ; field1倒数第3个字节
  .text:100023F7                                                       ; 存放到栈变量中
  .text:100023FB C6 44 24 26 00          mov     byte ptr [esp+26h], 0
  .text:10002400 E8 14 39 00 00          call    _strtoul              ; field1倒数第4,3个字节
  .text:10002400                                                       ; 按16进制转为long
  .text:10002400
  .text:10002405 8B 8C 24 78 01 00 00    mov     ecx, [esp+168h+arg_C]
  .text:1000240C 8B 54 24 14             mov     edx, [esp+168h+var_154]
  .text:10002410 88 01                   mov     [ecx], al             ; 结果赋值参数4所指变量
  .text:10002412 8A 02                   mov     al, [edx]
  .text:10002414 83 C4 0C                add     esp, 0Ch
  .text:10002417 84 C0                   test    al, al
  .text:10002419 0F 85 2E 01 00 00       jnz     loc_1000254D
  .text:10002419
  .text:1000241F 8A 44 24 0E             mov     al, byte ptr [esp+15Ch+var_150+2] ; field1倒数第2个字节
  .text:10002423 8A 4C 24 0F             mov     cl, byte ptr [esp+15Ch+var_150+3] ; 最后个
  .text:10002427 6A 10                   push    10h                   ; int
  .text:10002429 8D 54 24 0C             lea     edx, [esp+160h+var_154]
  .text:1000242D 88 44 24 18             mov     [esp+160h+var_148], al
  .text:10002431 52                      push    edx                   ; char **
  .text:10002432 8D 44 24 1C             lea     eax, [esp+164h+var_148]
  .text:10002436 50                      push    eax                   ; char *
  .text:10002437 88 4C 24 21             mov     [esp+21h], cl         ; 最后个字节存放栈变量
  .text:1000243B C6 44 24 22 00          mov     byte ptr [esp+22h], 0
  .text:10002440 E8 D4 38 00 00          call    _strtoul              ; 倒数后2个字节按16进制long
  .text:10002440
  .text:10002445 8B 4C 24 14             mov     ecx, [esp+168h+var_154]
  .text:10002449 8A 11                   mov     dl, [ecx]
  .text:1000244B 83 C4 0C                add     esp, 0Ch
  .text:1000244E 84 D2                   test    dl, dl
  .text:10002450 0F 85 F7 00 00 00       jnz     loc_1000254D
  .text:10002450
  .text:10002456 8B B4 24 70 01 00 00    mov     esi, [esp+15Ch+arg_10] ; 参数5
  .text:1000245D 8B 9C 24 7C 01 00 00    mov     ebx, [esp+15Ch+arg_1C] ; 参数8
  .text:10002464 33 D2                   xor     edx, edx
  .text:10002466 8A D0                   mov     dl, al
  .text:10002468 8A C8                   mov     cl, al
  .text:1000246A 80 E1 20                and     cl, 20h
  .text:1000246D 55                      push    ebp
  .text:1000246E 8B AC 24 7C 01 00 00    mov     ebp, [esp+160h+arg_18] ; 参数7
  .text:10002475 57                      push    edi
  .text:10002476 8B BC 24 7C 01 00 00    mov     edi, [esp+164h+arg_14] ; 参数6
  .text:1000247D 83 E2 1F                and     edx, 1Fh
  .text:10002480 80 F9 20                cmp     cl, 20h
  .text:10002483 89 16                   mov     [esi], edx            ; 转换结果&0x1F
  .text:10002483                                                       ; 存放到参数5所指变量
  .text:10002485 0F 94 C2                setz    dl
  .text:10002488 8A C8                   mov     cl, al
  .text:1000248A 80 E1 40                and     cl, 40h
  .text:1000248D 88 17                   mov     [edi], dl             ; 转换结果与&0x20
  .text:1000248D                                                       ; 结果赋值参数6所指变量
  .text:1000248F 80 F9 40                cmp     cl, 40h
  .text:10002492 0F 94 C2                setz    dl
  .text:10002495 24 80                   and     al, 80h
  .text:10002497 88 55 00                mov     [ebp+0], dl           ; 转换结果与&0x40
  .text:10002497                                                       ; 结果赋值参数7所指变量
  .text:1000249A 6A 0A                   push    0Ah                   ; int
  .text:1000249C 8D 4C 24 14             lea     ecx, [esp+168h+var_154]
  .text:100024A0 3C 80                   cmp     al, 80h
  .text:100024A2 51                      push    ecx                   ; char **
  .text:100024A3 8D 94 24 AC 00 00 00    lea     edx, [esp+16Ch+field2]
  .text:100024AA 0F 94 C0                setz    al
  .text:100024AD 52                      push    edx                   ; char *
  .text:100024AE 88 03                   mov     [ebx], al             ; 转换结果与&0x80
  .text:100024AE                                                       ; 结果赋值参数8所指变量
  .text:100024AE                                                       ;
  .text:100024B0 E8 4D 38 00 00          call    _strtol               ; field2按10进制转为long
  .text:100024B0
  .text:100024B5 8B 8C 24 78 01 00 00    mov     ecx, [esp+170h+arg_4]
  .text:100024BC 8B 54 24 1C             mov     edx, [esp+170h+var_154]
  .text:100024C0 89 01                   mov     [ecx], eax            ; 结果赋值参数2所指变量
  .text:100024C2 8A 02                   mov     al, [edx]
  .text:100024C4 83 C4 0C                add     esp, 0Ch
  .text:100024C7 84 C0                   test    al, al
  .text:100024C9 0F 85 89 00 00 00       jnz     loc_10002558
  .text:100024C9
  .text:100024CF 6A 10                   push    10h                   ; int
  .text:100024D1 8D 44 24 14             lea     eax, [esp+168h+var_154]
  .text:100024D5 50                      push    eax                   ; char **
  .text:100024D6 8D 4C 24 6C             lea     ecx, [esp+16Ch+field3]
  .text:100024DA 51                      push    ecx                   ; char *
  .text:100024DB E8 39 38 00 00          call    _strtoul              ; field3转为16进制
  .text:100024DB
  .text:100024E0 8B 54 24 1C             mov     edx, [esp+170h+var_154]
  .text:100024E4 89 44 24 20             mov     [esp+170h+var_150], eax ; 结果赋值变量var_150
  .text:100024E8 8A 02                   mov     al, [edx]
  .text:100024EA 83 C4 0C                add     esp, 0Ch
  .text:100024ED 84 C0                   test    al, al
  .text:100024EF 75 67                   jnz     short loc_10002558
  .text:100024EF
  .text:100024F1 33 C0                   xor     eax, eax
  .text:100024F3 8A 03                   mov     al, [ebx]             ; 原参数8所指字节
  .text:100024F5 33 C9                   xor     ecx, ecx
  .text:100024F7 8A 4D 00                mov     cl, [ebp+0]           ; 原参数7所指字节
  .text:100024FA 33 D2                   xor     edx, edx
  .text:100024FC 8A 17                   mov     dl, [edi]             ; 原参数6所指字节
  .text:100024FE 50                      push    eax
  .text:100024FF 8B 06                   mov     eax, [esi]
  .text:10002501 51                      push    ecx
  .text:10002502 8B 8C 24 7C 01 00 00    mov     ecx, [esp+16Ch+arg_C]
  .text:10002509 52                      push    edx
  .text:1000250A 33 D2                   xor     edx, edx
  .text:1000250C 8A 11                   mov     dl, [ecx]
  .text:1000250E 50                      push    eax                   ; 原参数5所指Int
  .text:1000250F 8B 84 24 80 01 00 00    mov     eax, [esp+174h+arg_8]
  .text:10002516 8B 08                   mov     ecx, [eax]
  .text:10002518 52                      push    edx                   ; 原参数4所指字节
  .text:10002519 8B 94 24 80 01 00 00    mov     edx, [esp+178h+arg_4]
  .text:10002520 8B 02                   mov     eax, [edx]
  .text:10002522 51                      push    ecx                   ; 原参数3所指Int
  .text:10002522                                                       ; field1头4个字节
  .text:10002522                                                       ; strtol转换结果
  .text:10002523 50                      push    eax                   ; 原参数2所指Int
  .text:10002523                                                       ; strtol(field2)
  .text:10002524 E8 97 FC FF FF          call    sub_100021C0          ; func(arg2, arg3, arg4, arg5, arg6, arg7, arg8)
  .text:10002524
  .text:10002529 83 C4 1C                add     esp, 1Ch
  .text:1000252C 0F B7 C8                movzx   ecx, ax
  .text:1000252F 8B 44 24 14             mov     eax, [esp+164h+var_150]
  .text:10002533 5F                      pop     edi
  .text:10002534 5D                      pop     ebp
  .text:10002535 3B C1                   cmp     eax, ecx
  .text:10002537 5E                      pop     esi
  .text:10002538 0F 94 C0                setz    al
  .text:1000253B 5B                      pop     ebx
  .text:1000253C 81 C4 54 01 00 00       add     esp, 154h
  .text:10002542 C3                      retn
  .text:10002542
  .text:10002543                         ; ---------------------------------------------------------------------------
  .text:10002543
  .text:10002543                         loc_10002543:                 ; CODE XREF: sub_10002330+5Dj
  .text:10002543 32 C0                   xor     al, al
  .text:10002545 5B                      pop     ebx
  .text:10002546 81 C4 54 01 00 00       add     esp, 154h
  .text:1000254C C3                      retn
  .text:1000254C
  .text:1000254D                         ; ---------------------------------------------------------------------------
  .text:1000254D
  .text:1000254D                         loc_1000254D:                 ; CODE XREF: sub_10002330+E9j
  .text:1000254D                                                       ; sub_10002330+120j
  .text:1000254D 5E                      pop     esi
  .text:1000254E 32 C0                   xor     al, al
  .text:10002550 5B                      pop     ebx
  .text:10002551 81 C4 54 01 00 00       add     esp, 154h
  .text:10002557 C3                      retn
  .text:10002557
  .text:10002558                         ; ---------------------------------------------------------------------------
  .text:10002558
  .text:10002558                         loc_10002558:                 ; CODE XREF: sub_10002330+199j
  .text:10002558                                                       ; sub_10002330+1BFj
  .text:10002558 5F                      pop     edi
  .text:10002559 5D                      pop     ebp
  .text:1000255A 5E                      pop     esi
  .text:1000255B 32 C0                   xor     al, al
  .text:1000255D 5B                      pop     ebx
  .text:1000255E 81 C4 54 01 00 00       add     esp, 154h
  .text:10002564 C3                      retn
  .text:10002564
  .text:10002565                         ; ---------------------------------------------------------------------------
  .text:10002565
  .text:10002565                         loc_10002565:                 ; CODE XREF: sub_10002330+44j
  .text:10002565 8A C3                   mov     al, bl
  .text:10002567 5B                      pop     ebx
  .text:10002568 81 C4 54 01 00 00       add     esp, 154h
  .text:1000256E C3                      retn
  .text:1000256E
  .text:1000256E                         sub_10002330 endp
  .text:1000256E
  
  下面给出该函数的逆向源代码:
  
  #define KEYBUF_LEN 0x80
  #define FIELD_BUF_LEN 0x40
  #define OTHER_BUF_LEN 0x08
  
  Byte sub_10002330(char *pKey, int *pArg2, int *pArg3,
                  PBYTE pArg4, int *pArg5, PBYTE pArg6, PBYTE pArg7, PBYTE pArg8)
  {
    char key_buf[KEYBUF_LEN], field1_buf[FIELD_BUF_LEN];
    char field2_buf[FIELD_BUF_LEN], field3_buf[FIELD_BUF_LEN];
    int  var_144=0, var_148=0;
    char other_buf[OTHER_BUF_LEN], *pEndPtr;
    int len = 0;
    Byte rc = 0, tmp = 0;
  
    strncpy(key_buf, pKey, KEYBUF_LEN);
  
    if (key_parse(key_buf, field1_buf, field2_buf, field3_buf) == 0) {
          /* key_parse failed: return 0 */
      return rc;
    }
   
    if ((len = strlen(field1_buf)) < 5) {
      return rc;
    }
  
    strcpy(other_buf, &field1_buf[len-4]);
    field1_buf[len-4] = '\0';
  
    if (field1_buf[0] == '*')
          *pArg3 = -1;
    else {
          *pArg3 = strtol(field1_buf, &pEndPtr, 0x0A);
    }
  
    ((char *)&var_144)[0] = other_buf[0];
    ((char *)&var_144)[1] = other_buf[1];
    *pArg4 = (Byte) strtol((char *)&var_144, &pEndPtr, 0x10);
  
    if (*pArg4 == 0)
          return rc;
  
    ((char *)&var_148)[0] = other_buf[2];
    ((char *)&var_148)[1] = other_buf[3];
    tmp = (Byte) strtol((char *)&var_148, &pEndPtr, 0x10);
  
    if (*pEndPtr != NULL)
          return rc;
  
    *pArg5 = tmp & 0x1F;
    *pArg6 = tmp & 0x20;
    *pArg7 = tmp & 0x40;
    *pArg8 = tmp & 0x80;
  
    *pArg2 = strtol(field2_buf, &pEndPtr, 0x0A);
    if (*pEndPtr != NULL)
          return rc;
  
    var_144 = strtol(field3_buf, &pEndPtr, 0x10);
    if(*pEndPtr != NULL)
          return rc;
   
    var_148 = sub_100021C0(*pArg2, *pArg3, *pArg4, *pArg5, *pArg6, *pArg7, *pArg8);
  
    if ((var_148 & 0xFFFF) == var_144)
          rc = 1;
  
  #ifdef _DEBUG
    printf("%s(%d): return value %d\n", rc);
  #endif
  
    return rc;
  }
  
  声明:其中几个变量使用没有严格按照汇编代码翻译,而是做了多用途使用:var_144, var_148。
  
  2.3 sub_100021C0函数逆向
  
  该函数是函数sub_10002330调用的最后一个函数,其返回值直接决定sub_10002330函数的最后成败。
  下面给出对该函数的分析:
  返回值:ax--WORD型值
  参数:共7个,观察得到为sub_10002330函数参数2-8指针所指向的变量值!
  这些变量在调用sub_100021C0函数之前已经被赋予了值--具体参见2.2。
  
  下面给出对该函数的逆向:
  #define BUF_LEN 9
  
  unsigned sub_100021C0 (int arg1, int arg2, Byte arg3, int arg4, Byte arg5, Byte arg6, Byte arg7)
  {
    unsigned buf[BUF_LEN] = {
          arg1, ~arg1, arg2, ~arg2,
          (unsigned)arg3, arg4,
          (unsigned)arg5, (unsigned)arg6,
          (unsigned)arg7
    };
  
    unsigned result;
  
    result = sub_10004070((PBYTE)buf, sizeof(buf));
  
    result = (result >> 16) ^ result;
  
  #ifdef _DEBUG
    printf("%s(%d)--result=%08X\n", __FILE__, __LINE__, result);
  #endif
  
    return result;
  }
  
  其中sub_10004070函数在程序中多处用到(后面注册表键值修改时还要用到),这里也给出对其的逆向:
  
  #define XOR_SEED 0x1021
  #define INNER_LOOP_MAX 7
  
  int sub_10004070 (PBYTE buf, unsigned len)
  {
    int result=0xB0BAB0BA, temp = 0;
    unsigned i=0, j=0;
  
    if (len <= 0 )
          return result;
  
    while (i<len) {
      temp = (int) (char)buf[i];
          result ^= (temp << 8);
      
          j = 0;
          while (j++ < INNER_LOOP_MAX) {
        if (result < 0) {
              result = (result << 1) ^ XOR_SEED;
            }
            else
              result <<= 1;
          }
  
          i++;
    }
  
  #ifdef _DEBUG
    printf("\n%s(%d)--result=%08X\n", __FILE__, __LINE__, result);
  #endif  
  
    return result;
  }
  
  2.4 计算返回值
  
  就像2.2给出的源代码所示,程序用field3字段转化后的结果与sub_100021C0函数返回值比较--相等返回1(成功),不相等返回0(失败)。
  
  第三部分--修改注册表键值
  ===========
  上述两部分都正确执行以后就可以正确注册了,key_verify函数剩下的工作就是修改注册表以便下次启动能判断出是否已经注册过了。
  本部分工作相对不这么重要,读者可自行分析。下面给出相关的几个函数逆向:
  
  #ifdef _DEBUG
  #define COLUM_LEN 8
  
  static void DebugPrint(char *pTitle, PBYTE pData, int nDataLen)
  {
    int i = 0, j,  temp;
  
    printf("\n%s\n", pTitle);
  
    printf("=====\n");
  
    for (; i<nDataLen/COLUM_LEN; i++) {
          printf("%08x: ", i);
  
          temp = i<<3;
          for (j=0; j<COLUM_LEN; j++)
            printf("%02X ", pData[temp+j]);
  
          printf("\n");
    }
   
    if (nDataLen % COLUM_LEN) {
      printf("%08x: ", i);
  
      temp = i<<3;
          for (temp = i<<3; temp<nDataLen; temp++)
            printf("%02X ", pData[temp]);
  
          printf("\n");
    }
  
  }
  #endif
  
  static void RegKeyProcess(PBYTE pData, int nDataLen, DWORD seed)
  {
    int i=0, temp;
  
    if (nDataLen<=0)
          return;
  
    for (; i<nDataLen; i+=4) {
      temp = seed >> 31;
          seed += seed;
          temp |= seed;
          seed = (i >> 2) ^ temp;
          *(DWORD *)&pData[i] ^= seed;
    }
  #ifdef _DEBUG
    DebugPrint("RegValue after process", (PBYTE)pData, nDataLen);
  #endif
  
    return;
  }
  
  #define VALUE_BUF_LEN 0x80
  #define REGDATA_LEN 0x1AC
  
  Byte sub_10001D40 (char *pProgramFile, int arg2, int arg3, char *pOutPut)
  {
    char ValueName[VALUE_BUF_LEN];
    HGLOBAL pData;
    HKEY hKey;
    DWORD cbData = REGDATA_LEN, type = 3;
    LONG rc = ERROR_SUCCESS;
    int temp;
    Byte result = 0;
  
    sprintf(ValueName, "%s (%d-%02X)", pProgramFile,
            (arg3 ^ (~0x55A) & 0XFFF), (arg2 ^ 0xBA));
   
    temp = sub_10004070((PBYTE)ValueName, strlen(ValueName));
  #ifdef _DEBUG
    printf("\nValueName: %s, len=%d\n", ValueName, strlen(ValueName));
  #endif
  
    pData = GlobalAlloc(0, REGDATA_LEN);
  
    RegOpenKeyEx(HKEY_CURRENT_USER, BREAK_LICENSE_MANAGER, 0, 0x20019, &hKey);
  
    RegQueryValueEx(hKey, ValueName, 0, &type, (PBYTE)pData, &cbData);
  #ifdef _DEBUG
    DebugPrint(ValueName, (PBYTE)pData, cbData);
  #endif
  
    if (cbData == REGDATA_LEN) {
      RegKeyProcess((PBYTE)pData, cbData, temp);
  
          memcpy(pOutPut, pData, REGDATA_LEN);
  
          temp = *(DWORD *)&pOutPut[0x1A8];
          *(DWORD *)&pOutPut[0x1A8] = 0x0AC1DBA5E;
          rc = sub_10004070((PBYTE)pOutPut, REGDATA_LEN);
      *(DWORD *)&pOutPut[0x1A8] = temp;
  
          if (temp == rc)
            result = 1;
  #ifdef _DEBUG
          printf("%s(%d): result is %d\n", __FILE__, __LINE__, result);
  #endif
    }
  
    RegCloseKey(hKey);
    GlobalFree(pData);
  
    return result;
  }
  
  到这里Hex Workshop V4.2加密算法部分的逆向基本完成了。注册表部分还是很有乐趣的,我这里限于篇幅没有做过多介绍--其实因为
  文笔是在太烂了:).
  
  
--------------------------------------------------------------------------------
【经验总结】
  1、关于本软件
  用户输入Key值需如下格式:****04$7-******-****
  其中第一个字段必须长度>=5(我采用了8个字节长), 第二、三字段长度分为6,4。
  
  字段1会被解析成6个值,字段2按照16进制转为long型,字段3按照10进制转为long型。
  字段1的6个值和字段2的值作为参数经过函数sub_100021C0运算后的返回值与字段3比较,相等则认为输入的Key正确,否则
  返回错误。
  
  2、关于MFC程序
  
  1- 查找注册资源(如果有该资源的话)
  2- 通过基类构造函数判断出正确的虚函数表
  3- 通过相关虚函数或者AFX_MSG_ENTRY找到相应按钮处理函数
  4- 如果有输入,可以通过重载的DoDataExchange静态分析出相应数据成员
  
  进而可以进行算法分析了。
  
  最后我采用的注册码为:10000407-123456-5162
  
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2009年01月29日 13:11:59
2009-1-29 20:47
0
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
因为本人帖子数量不够所以没有办法上传附件,特把此文件内容贴出来。各位只要把以下内容粘贴到注册表文件后,直接导入注册表即可将软件变为未注册。

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\BreakPoint License Manager]
"Hex Workshop (2722-BE)"=hex:b9,ef,4d,d9,9f,0a,6c,6c,f7,d5,3b,34,67,0f,fd,e0,\
  cb,1e,fa,c1,92,3d,f4,83,23,7b,e8,07,41,f6,d0,0f,df,82,d3,7a,7a,b0,30,4b,55,\
  c0,e2,1a,6b,64,0f,fd,db,c8,1e,fa,ba,91,3d,f4,7b,23,7b,e8,f8,46,f6,d0,e1,8d,\
  ec,a1,d2,1b,d9,43,b6,37,b2,87,7e,6f,64,0f,e8,de,c8,1e,c5,bd,91,3d,9c,7b,23,\
  7b,2f,f7,46,f6,47,ee,8d,ec,96,dc,1b,d9,37,b9,37,b2,74,72,6f,64,a1,8a,ac,ad,\
  93,a0,ce,e5,92,e1,1e,47,f1,27,f7,46,c2,4f,ee,8d,a4,9f,dc,1b,6a,3f,b9,37,f7,\
  7e,72,6f,ca,fd,e4,de,b0,fb,c9,bd,47,f7,93,7b,a9,ee,27,f7,7b,dd,4f,ee,de,ba,\
  9f,dc,97,75,3f,b9,04,eb,7e,72,24,d6,fd,e4,64,ac,fb,c9,e7,58,f7,93,e0,b1,ee,\
  27,b4,26,90,00,d1,c7,ba,9f,91,8f,75,3f,11,1f,eb,7e,16,3e,d6,fd,18,7c,ac,fb,\
  07,f8,58,f7,38,f0,b1,ee,01,85,1b,fd,fd,af,b5,d1,1c,e9,e0,05,e5,02,1f,eb,f7,\
  05,3e,d6,d2,0b,7c,ac,9b,17,f8,58,09,2f,f0,b1,53,5e,e0,63,e6,bc,c0,c7,8d,79,\
  81,8f,58,f3,02,1f,f4,e6,05,3e,8f,cd,0b,7c,72,fb,6b,b1,0b,56,53,b9,5b,e8,f4,\
  a9,23,d9,bc,c0,0f,b2,f9,c1,54,64,f3,02,e4,c8,e6,05,85,91,cd,0b,44,23,9b,17,\
  c7,46,36,2f,de,8d,6c,5e,ed,1b,d9,bc,89,37,b2,79,41,6f,64,f3,d7,de,c8,e6,fa,\
  bd,91,cd,a3,7b,23,9b,10,f7,46,36,78,ee,8d,6c,a9,dc,1b,d9,09,b9,37,b2,48,72,\
  6f,64,cc,e4,de,c8,c4,c9,bd,91,d7,93,7b,23,f1,27,f7,46,82,4f,ee,8d,64,9f,dc,\
  1b,aa,3e,b9,37,37,7d,72,6f,0a,fa,e4,de,70,f4,c9,bd,87,e8,93,7b,69,d1,27,f7,\
  bb,a2,4f,ee,1e,45,9f,dc,6a,b5,0b,56

[HKEY_LOCAL_MACHINE\SOFTWARE\BreakPoint\Licenses]
"Hex Workshop (2722-BE)"=hex:b9,ef,4d,d9,9f,0a,6c,6c,f7,d5,3b,34,67,0f,fd,e0,\
  cb,1e,fa,c1,92,3d,f4,83,23,7b,e8,07,41,f6,d0,0f,df,82,d3,7a,7a,b0,30,4b,55,\
  c0,e2,1a,6b,64,0f,fd,db,c8,1e,fa,ba,91,3d,f4,7b,23,7b,e8,f8,46,f6,d0,e1,8d,\
  ec,a1,d2,1b,d9,43,b6,37,b2,87,7e,6f,64,0f,e8,de,c8,1e,c5,bd,91,3d,9c,7b,23,\
  7b,2f,f7,46,f6,47,ee,8d,ec,96,dc,1b,d9,37,b9,37,b2,74,72,6f,64,a1,8a,ac,ad,\
  93,a0,ce,e5,92,e1,1e,47,f1,27,f7,46,c2,4f,ee,8d,a4,9f,dc,1b,6a,3f,b9,37,f7,\
  7e,72,6f,ca,fd,e4,de,b0,fb,c9,bd,47,f7,93,7b,a9,ee,27,f7,7b,dd,4f,ee,de,ba,\
  9f,dc,97,75,3f,b9,04,eb,7e,72,24,d6,fd,e4,64,ac,fb,c9,e7,58,f7,93,e0,b1,ee,\
  27,b4,26,90,00,d1,c7,ba,9f,91,8f,75,3f,11,1f,eb,7e,16,3e,d6,fd,18,7c,ac,fb,\
  07,f8,58,f7,38,f0,b1,ee,01,85,1b,fd,fd,af,b5,d1,1c,e9,e0,05,e5,02,1f,eb,f7,\
  05,3e,d6,d2,0b,7c,ac,9b,17,f8,58,09,2f,f0,b1,53,5e,e0,63,e6,bc,c0,c7,8d,79,\
  81,8f,58,f3,02,1f,f4,e6,05,3e,8f,cd,0b,7c,72,fb,6b,b1,0b,56,53,b9,5b,e8,f4,\
  a9,23,d9,bc,c0,0f,b2,f9,c1,54,64,f3,02,e4,c8,e6,05,85,91,cd,0b,44,23,9b,17,\
  c7,46,36,2f,de,8d,6c,5e,ed,1b,d9,bc,89,37,b2,79,41,6f,64,f3,d7,de,c8,e6,fa,\
  bd,91,cd,a3,7b,23,9b,10,f7,46,36,78,ee,8d,6c,a9,dc,1b,d9,09,b9,37,b2,48,72,\
  6f,64,cc,e4,de,c8,c4,c9,bd,91,d7,93,7b,23,f1,27,f7,46,82,4f,ee,8d,64,9f,dc,\
  1b,aa,3e,b9,37,37,7d,72,6f,0a,fa,e4,de,70,f4,c9,bd,87,e8,93,7b,69,d1,27,f7,\
  bb,a2,4f,ee,1e,45,9f,dc,6a,b5,0b,56
2009-1-29 20:53
0
雪    币: 419
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
很好,学习中
2009-1-29 20:55
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
6
鼠标滚轮跑偏了
2009-1-29 21:26
0
雪    币: 6092
活跃值: (654)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
7
牛年的犇。。。。
很不错啊,学习。
2009-1-30 10:41
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
8
能不能不用马甲发呀。。。。。
2009-1-30 10:44
0
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
楼上,你认错人了。我是新人,一直潜水,做了点东西出来才注册号发出来跟大家分享一下。。
不过好像发错地方了,没什么人认真看:(
2009-1-30 18:54
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
支持一下,楼主很强啊。
2009-1-30 19:14
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
收藏了
2009-1-30 22:22
0
雪    币: 200
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
不会吧,辛辛苦苦写的东西居然要被找师傅之类的帖子给沉了?
另外:找师傅那位,与其找师傅的空你不如把看雪上的资料看了呢。保证比找谁都好使。。
我建议你先看看PE文件格式,当然了对着个真正的应用软件看。
2009-1-31 15:20
0
雪    币: 485
活跃值: (12)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
13
帖子沉了不要紧
我保证这帖子很多人都看了,只是没人顶。
看雪里的人大部人不喜欢看完后无意义的随便顶一句。
有疑义或值得讨论的地方,大家肯定会提出来的。
所以,继续学知识,继续发帖吧,就当是学习的时候记了笔记。
2009-1-31 16:15
0
雪    币: 1844
活跃值: (35)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
14
我就来顶一下,不错了,解密的乐趣和专注都在你的文章中体现了,PF
2009-1-31 21:36
0
游客
登录 | 注册 方可回帖
返回
//