CrackMe160 学习笔记 之 024

前言

这个程序和023是一个作者。

说实话,这个作者是真的牛逼,能用汇编写出这样的程序。

每次调他写的程序就很头疼。

然而我还是差不多只花了一天就写出了注册机。

在这里插入图片描述

思路

这个程序没有明显的字符串,搜索字符串在这里不管用了。

那么从API入手。

和上个程序一样,找到获取name和获取key的函数。

因为是重复同样的步骤,我这里就不啰嗦了。

找到关键跳转。

虽然我这里写了注释,但是一开始可能并不那么容易看出来

004012E9   .^\74 EE         je      short 004012D9                   ;  关键跳转
004012EB   >  68 59304000   push    00403059                         ; /Text = "Your serial is not valid."
004012F0   .  FF35 5C314000 push    dword ptr [40315C]               ; |hWnd = 0133022C ('Your serial is not valid.',class='Edit',parent=01630166)
004012F6   .  E8 7D010000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA
004012FB   .  33C0          xor     eax, eax
004012FD   .  C9            leave
004012FE   .  C2 1000       retn    10
00401301   .  68 73 30 40 0>ascii   "hs0@",0                         ;  成功注册后的文本内容
00401306   .  FF35 5C314000 push    dword ptr [40315C]               ; |hWnd = 0133022C ('Your serial is not valid.',class='Edit',parent=01630166)
0040130C   .  E8 67010000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA

首先观察这一条指令。

00401301   .  68 73 30 40 0>ascii   "hs0@",0                         ;  成功注册后的文本内容

OD有点不智能,并不能分析出这条指令。

但比较上一条指令,就能得出 push 403073 才是真正的内容,而不是解释成数据。

如图。

在这里插入图片描述

还可以发现

004012BB   .  3105 D9124000 xor     dword ptr [4012D9], eax          ;  异或 ASCII “TEX.”
004012C1   .  C1E8 10       shr     eax, 10                          ;  右移0x10位
004012C4   .  66:2905 D9124>sub     word ptr [4012D9], ax

这个程序对0x004012D9处的四个字节进行了修改,这可是代码段啊。

也就是说,这个程序会修改自身的指令来完成验证

知道了这些,剩下来的就好分析了。

注册机是写的真的心累。

分析

整个程序很短小简洁。

00401273   .  6A 00         push    0                                ; /IsSigned = FALSE
00401275   .  8D45 FC       lea     eax, dword ptr [ebp-4]           ; |
00401278   .  50            push    eax                              ; |pSuccess
00401279   .  6A 64         push    64                               ; |ControlID = 64 (100.)
0040127B   .  FF35 50314000 push    dword ptr [403150]               ; |hWnd = 01630166 ('TEXme v2.0',class='CTEX')
00401281   .  E8 BC010000   call    <jmp.&USER32.GetDlgItemInt>      ; \GetDlgItemInt
00401286   .  837D FC 00    cmp     dword ptr [ebp-4], 0             ;  返回key的int值
0040128A   .  74 5F         je      short 004012EB
0040128C   .  50            push    eax
0040128D   .  6A 14         push    14                               ; /Count = 14 (20.)
0040128F   .  68 6C314000   push    0040316C                         ; |Buffer = Chafe_2.0040316C
00401294   .  FF35 54314000 push    dword ptr [403154]               ; |hWnd = 00A2020E (class='Edit',parent=01630166)
0040129A   .  E8 AF010000   call    <jmp.&USER32.GetWindowTextA>     ; \GetWindowTextA
0040129F   .  85C0          test    eax, eax                         ;  返回name的长度
004012A1   .  74 48         je      short 004012EB                   ;  为0则跳转,失败
004012A3   .  A1 0B304000   mov     eax, dword ptr [40300B]          ;  ASCII "CTEX"
004012A8   .  BB 6C314000   mov     ebx, 0040316C                    ;  获取输入字符串地址
004012AD   >  0303          add     eax, dword ptr [ebx]             ;  求和
004012AF   .  43            inc     ebx                              ;  指向下一个字符
004012B0   .  81FB 7C314000 cmp     ebx, 0040317C                    ;  将ebx和地址0x0040317C比较
004012B6   .^ 75 F5         jnz     short 004012AD                   ;  不相等则跳转
004012B8   .  5B            pop     ebx                              ;  弹出key的int值
004012B9   .  03C3          add     eax, ebx                         ;  求和
004012BB   .  3105 D9124000 xor     dword ptr [4012D9], eax          ;  异或 ASCII “TEX.”
004012C1   .  C1E8 10       shr     eax, 10                          ;  右移0x10位
004012C4   .  66:2905 D9124>sub     word ptr [4012D9], ax
004012CB   .  BE EC114000   mov     esi, 004011EC                    ;  esi初始化
004012D0   .  B9 3E000000   mov     ecx, 3E
004012D5   .  33DB          xor     ebx, ebx
004012D7   .  EB 04         jmp     short 004012DD
004012D9   >  A4            movs    byte ptr es:[edi], byte ptr [esi>
004012DA      6B            db      6B                               ;  CHAR 'k'
004012DB      1D            db      1D
004012DC      58            db      58                               ;  CHAR 'X'
004012DD   >  AD            lods    dword ptr [esi]                  ;  读取esi,esi+4
004012DE   .  33D8          xor     ebx, eax
004012E0   .  49            dec     ecx                              ;  计数器减一
004012E1   .^ 75 FA         jnz     short 004012DD
004012E3   .  81FB FBCFFCAF cmp     ebx, AFFCCFFB
004012E9   .^ 74 EE         je      short 004012D9                   ;  关键跳转
004012EB   >  68 59304000   push    00403059                         ; /Text = "Your serial is not valid."
004012F0   .  FF35 5C314000 push    dword ptr [40315C]               ; |hWnd = 0133022C ('Your serial is not valid.',class='Edit',parent=01630166)
004012F6   .  E8 7D010000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA
004012FB   .  33C0          xor     eax, eax
004012FD   .  C9            leave
004012FE   .  C2 1000       retn    10
00401301   .  68 73 30 40 0>ascii   "hs0@",0                         ;  成功注册后的文本内容
00401306   .  FF35 5C314000 push    dword ptr [40315C]               ; |hWnd = 0133022C ('Your serial is not valid.',class='Edit',parent=01630166)
0040130C   .  E8 67010000   call    <jmp.&USER32.SetWindowTextA>     ; \SetWindowTextA
00401311   .  33C0          xor     eax, eax
00401313   .  C9            leave
00401314   .  C2 1000       retn    10

注册机代码

用逆向的方法求出注册机。
如果用穷举法,那是真的蠢。
下面给出公式
懂的人自然都懂。

  58A91A69(name^计算出的固定值,这里只是举个例子)
+      KEY
  ----------------
  58??????  >>0x10 -> 58??
^ 00584554
  ----------------
  58??????
- 000058??
  ----------------
  585426EB
/*
  004011EC  55 8B EC 83 C4 FC 8B 45 0C 83 F8 10 75 0D 6A 00  U嬱兡鼖E.凐u.j.
  004011FC  E8 6B 02 00 00 33 C0 C9 C2 10 00 83 F8 0F 75 0E  鑛..3郎?.凐u
  0040120C  8B 45 08 E8 18 01 00 00 33 C0 C9 C2 10 00 83 F8  婨?..3郎?.凐
  0040121C  01 75 06 33 C0 C9 C2 10 00 3D 11 01 00 00 0F 85  u3郎?.=..
  0040122C  E7 00 00 00 8B 45 14 3B 05 60 31 40 00 75 1A 6A  ?..婨;`[email protected]j
  0040123C  00 68 96 30 40 00 68 A7 30 40 00 FF 75 08 E8 17  [email protected]?@.u?
  0040124C  02 00 00 33 C0 C9 C2 10 00 3B 05 58 31 40 00 74  ..3郎?.;[email protected]
  0040125C  0C 3B 05 54 31 40 00 0F 85 AE 00 00 00 C7 05 D9  .;T1@.叜...?
  0040126C  12 40 00 54 45 58 00 6A 00 8D 45 FC 50 6A 64 FF  @.TEX.j.岴黀jd
  0040127C  35 50 31 40 00 E8 BC 01 00 00 83 7D FC 00 74 5F  5P1@.杓..儅?t_
  0040128C  50 6A 14 68 6C 31 40 00 FF 35 54 31 40 00 E8 AF  Pjhl1@.5T1@.璇
  0040129C  01 00 00 85 C0 74 48 A1 0B 30 40 00 BB 6C 31 40  ..吚tH?0@.籰1@
  004012AC  00 03 03 43 81 FB 7C 31 40 00 75 F5 5B 03 C3 31  .C侞|[email protected]鮗?
  004012BC  05 D9 12 40 00 C1 E8 10 66 29 05 D9 12 40 00 BE  ?@.凌f)?@.
  004012CC  EC 11 40 00 B9 3E 00 00 00 33 DB EB 04 54 45 58  ?@.?...3垭TEX
  004012DC  00 AD 33 D8 49 75 FA 81 FB FB CF FC              .?豂u鷣宵痶頷
*/
int array[]={
  0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xFC, 0x8B, 0x45, 0x0C, 0x83, 0xF8, 0x10, 0x75, 0x0D, 0x6A, 0x00,
  0xE8, 0x6B, 0x02, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x83, 0xF8, 0x0F, 0x75, 0x0E,
  0x8B, 0x45, 0x08, 0xE8, 0x18, 0x01, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x83, 0xF8,
  0x01, 0x75, 0x06, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x3D, 0x11, 0x01, 0x00, 0x00, 0x0F, 0x85,
  0xE7, 0x00, 0x00, 0x00, 0x8B, 0x45, 0x14, 0x3B, 0x05, 0x60, 0x31, 0x40, 0x00, 0x75, 0x1A, 0x6A,
  0x00, 0x68, 0x96, 0x30, 0x40, 0x00, 0x68, 0xA7, 0x30, 0x40, 0x00, 0xFF, 0x75, 0x08, 0xE8, 0x17,
  0x02, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x3B, 0x05, 0x58, 0x31, 0x40, 0x00, 0x74,
  0x0C, 0x3B, 0x05, 0x54, 0x31, 0x40, 0x00, 0x0F, 0x85, 0xAE, 0x00, 0x00, 0x00, 0xC7, 0x05, 0xD9,
  0x12, 0x40, 0x00, 0x54, 0x45, 0x58, 0x00, 0x6A, 0x00, 0x8D, 0x45, 0xFC, 0x50, 0x6A, 0x64, 0xFF,
  0x35, 0x50, 0x31, 0x40, 0x00, 0xE8, 0xBC, 0x01, 0x00, 0x00, 0x83, 0x7D, 0xFC, 0x00, 0x74, 0x5F,
  0x50, 0x6A, 0x14, 0x68, 0x6C, 0x31, 0x40, 0x00, 0xFF, 0x35, 0x54, 0x31, 0x40, 0x00, 0xE8, 0xAF,
  0x01, 0x00, 0x00, 0x85, 0xC0, 0x74, 0x48, 0xA1, 0x0B, 0x30, 0x40, 0x00, 0xBB, 0x6C, 0x31, 0x40,
  0x00, 0x03, 0x03, 0x43, 0x81, 0xFB, 0x7C, 0x31, 0x40, 0x00, 0x75, 0xF5, 0x5B, 0x03, 0xC3, 0x31,
  0x05, 0xD9, 0x12, 0x40, 0x00, 0xC1, 0xE8, 0x10, 0x66, 0x29, 0x05, 0xD9, 0x12, 0x40, 0x00, 0xBE,
  0xEC, 0x11, 0x40, 0x00, 0xB9, 0x3E, 0x00, 0x00, 0x00, 0x33, 0xDB, 0xEB, 0x04, 0x54, 0x45, 0x58,/*start:0x54 end:0x00*/
  0x00, 0xAD, 0x33, 0xD8, 0x49, 0x75, 0xFA, 0x81
};// ???04 D833AD?
#include<stdio.h>
#define real_v(x)  (x)>len? (0):(name[x])
#define real_n(x)  (x)>len_array? (0):(array[x])
#define offset (0x4012D9-0x4011EC)
int main()
{
  char* name;
  unsigned int key=0xAFFCCFFB,rerverse_key;
  unsigned int key_1,key_2,key_3,key_4;
  int len=0,len_array=sizeof(array)/sizeof(int);
  int count=0x0;
  unsigned int ebx=0,eax='XETC';//CTEX
  printf("name:");
  scanf("%[^\n]",name);
  len=strlen(name);
  while(count< offset-4)
    {
      ebx^=real_n(count)+(real_n(count+1)<<8)+(real_n(count+2)<<16)+(real_n(count+3)<<24);
      count+=4;
    }
  //printf("ebx:%08X %8X\n",ebx,real_n(count)+(real_n(count+1)<<8)+(real_n(count+2)<<16)+(real_n(count+3)<<24));
  key^=0x81FA7549;
  //printf("key=%08X\n",key);
  key^=0xD833AD04;
  //printf("key=%08X\n",key);
  key^=ebx;
  //printf("key=%08X\n",key);
  //???04^D833AD?=D4501258
  array[offset]=key>>8&0xFF;
  array[offset+1]=key>>16&0xFF;
  array[offset+2]=key>>24&0xFF;
  array[offset+3]=key&0xFF;
  //printf("%02X %02X %02X %02X\n",array[offset],array[offset+1],array[offset+2],array[offset+3]);
  count=0;
  while(count< 0x40317c-0x40316c)
    {
      eax+=real_v(count)+(real_v(count+1)<<8)+(real_v(count+2)<<16)+(real_v(count+3)<<24);
      //printf("%x\n",eax);
      count++;
    }
  //  printf("eax=%x\n",eax);
  rerverse_key=array[offset]+(array[offset+1]<<8)+(array[offset+2]<<16)+(array[offset+3]<<24);
  key=0;
  //printf("reverse_key=%08X\n",rerverse_key);
  key_1=rerverse_key>>24&0xFF;
  key_2=(rerverse_key>>16&0xFF)^0x00^0x58;
  key_3=(rerverse_key>>8&0xFF)+0x58+((rerverse_key&0xFF)+key_2>0xFF?1:0)^0x45;
  key_4=((rerverse_key&0xFF)+key_2)%0x100^0x54;
  //printf("%x\n",(rerverse_key&0xFF)+0xc);
  //printf("key=%08X\n",key_1);
  //printf("key=%08X\n",key_2);
  //printf("key=%08X\n",key_3);
  //printf("key=%08X\n",key_4);
  printf("key=%u\n",(key_1<<24)+(key_2<<16)+(key_3<<8)+key_4-eax);
  return 0;
}

补充

调试这个程序的时候有一个坑。

断点会影响最后生成的值。如图。
在这里插入图片描述

真正的值。
在这里插入图片描述

只要不在0x4011EC到0x4012E4区间下断点就行了。或者下完直接取消。

这也是我注册机为什么写这么久的原因。

我还写了一个正向的程序用来验证。

/*
  004011EC  55 8B EC 83 C4 FC 8B 45 0C 83 F8 10 75 0D 6A 00  U嬱兡鼖E.凐u.j.
  004011FC  E8 6B 02 00 00 33 C0 C9 C2 10 00 83 F8 0F 75 0E  鑛..3郎?.凐u
  0040120C  8B 45 08 E8 18 01 00 00 33 C0 C9 C2 10 00 83 F8  婨?..3郎?.凐
  0040121C  01 75 06 33 C0 C9 C2 10 00 3D 11 01 00 00 0F 85  u3郎?.=..
  0040122C  E7 00 00 00 8B 45 14 3B 05 60 31 40 00 75 1A 6A  ?..婨;`[email protected]j
  0040123C  00 68 96 30 40 00 68 A7 30 40 00 FF 75 08 E8 17  [email protected]?@.u?
  0040124C  02 00 00 33 C0 C9 C2 10 00 3B 05 58 31 40 00 74  ..3郎?.;[email protected]
  0040125C  0C 3B 05 54 31 40 00 0F 85 AE 00 00 00 C7 05 D9  .;T1@.叜...?
  0040126C  12 40 00 54 45 58 00 6A 00 8D 45 FC 50 6A 64 FF  @.TEX.j.岴黀jd
  0040127C  35 50 31 40 00 E8 BC 01 00 00 83 7D FC 00 74 5F  5P1@.杓..儅?t_
  0040128C  50 6A 14 68 6C 31 40 00 FF 35 54 31 40 00 E8 AF  Pjhl1@.5T1@.璇
  0040129C  01 00 00 85 C0 74 48 A1 0B 30 40 00 BB 6C 31 40  ..吚tH?0@.籰1@
  004012AC  00 03 03 43 81 FB 7C 31 40 00 75 F5 5B 03 C3 31  .C侞|[email protected]鮗?
  004012BC  05 D9 12 40 00 C1 E8 10 66 29 05 D9 12 40 00 BE  ?@.凌f)?@.
  004012CC  EC 11 40 00 B9 3E 00 00 00 33 DB EB 04 54 45 58  ?@.?...3垭TEX
  004012DC  00 AD 33 D8 49 75 FA 81 FB FB CF FC              .?豂u鷣宵痶頷
*/

int array[]={
  0x55, 0x8B, 0xEC, 0x83, 0xC4, 0xFC, 0x8B, 0x45, 0x0C, 0x83, 0xF8, 0x10, 0x75, 0x0D, 0x6A, 0x00,
  0xE8, 0x6B, 0x02, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x83, 0xF8, 0x0F, 0x75, 0x0E,
  0x8B, 0x45, 0x08, 0xE8, 0x18, 0x01, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x83, 0xF8,
  0x01, 0x75, 0x06, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x3D, 0x11, 0x01, 0x00, 0x00, 0x0F, 0x85,
  0xE7, 0x00, 0x00, 0x00, 0x8B, 0x45, 0x14, 0x3B, 0x05, 0x60, 0x31, 0x40, 0x00, 0x75, 0x1A, 0x6A,
  0x00, 0x68, 0x96, 0x30, 0x40, 0x00, 0x68, 0xA7, 0x30, 0x40, 0x00, 0xFF, 0x75, 0x08, 0xE8, 0x17,
  0x02, 0x00, 0x00, 0x33, 0xC0, 0xC9, 0xC2, 0x10, 0x00, 0x3B, 0x05, 0x58, 0x31, 0x40, 0x00, 0x74,
  0x0C, 0x3B, 0x05, 0x54, 0x31, 0x40, 0x00, 0x0F, 0x85, 0xAE, 0x00, 0x00, 0x00, 0xC7, 0x05, 0xD9,
  0x12, 0x40, 0x00, 0x54, 0x45, 0x58, 0x00, 0x6A, 0x00, 0x8D, 0x45, 0xFC, 0x50, 0x6A, 0x64, 0xFF,
  0x35, 0x50, 0x31, 0x40, 0x00, 0xE8, 0xBC, 0x01, 0x00, 0x00, 0x83, 0x7D, 0xFC, 0x00, 0x74, 0x5F,
  0x50, 0x6A, 0x14, 0x68, 0x6C, 0x31, 0x40, 0x00, 0xFF, 0x35, 0x54, 0x31, 0x40, 0x00, 0xE8, 0xAF,
  0x01, 0x00, 0x00, 0x85, 0xC0, 0x74, 0x48, 0xA1, 0x0B, 0x30, 0x40, 0x00, 0xBB, 0x6C, 0x31, 0x40,
  0x00, 0x03, 0x03, 0x43, 0x81, 0xFB, 0x7C, 0x31, 0x40, 0x00, 0x75, 0xF5, 0x5B, 0x03, 0xC3, 0x31,
  0x05, 0xD9, 0x12, 0x40, 0x00, 0xC1, 0xE8, 0x10, 0x66, 0x29, 0x05, 0xD9, 0x12, 0x40, 0x00, 0xBE,
  0xEC, 0x11, 0x40, 0x00, 0xB9, 0x3E, 0x00, 0x00, 0x00, 0x33, 0xDB, 0xEB, 0x04, 0x54, 0x45, 0x58,
  0x00, 0xAD, 0x33, 0xD8, 0x49, 0x75, 0xFA, 0x81, 0xFB, 0xFB, 0xCF, 0xFC

};

#include<stdio.h>
#define real_v(x)  (x)>len? (0):(name[x])
#define real_n(x)  (x)>len_array? (0):(array[x])


#define offset (0x4012D9-0x4011EC)
int main(int argc, const char * argv[])
{
  char* name;
  unsigned int key=1234;
  int len=0,len_array=sizeof(array)/sizeof(int);
  int count=0;
  int sub_result=0;
  unsigned int eax='XETC';//CTEX

  printf("name:");
  name=malloc(100);
  scanf("%[^\n]",name);
  len=strlen(name);
  while(count< 0x40317c-0x40316c)
    {
      eax+=real_v(count)+(real_v(count+1)<<8)+(real_v(count+2)<<16)+(real_v(count+3)<<24);
      //printf("%x\n",eax);
      count++;
    }
  eax+=key;
  printf("eax=%0X\n",eax);
  printf("%02X %02X %02X %02X\n",array[offset],array[offset+1],array[offset+2],array[offset+3]);
  
  array[offset]  ^=eax&0xFF;
  array[offset+1]^=eax>>8&0xFF;
  array[offset+2]^=eax>>16&0xFF;
  array[offset+3]^=eax>>24&0xFF;
  
  printf("%02X %02X %02X %02X\n",array[offset],array[offset+1],array[offset+2],array[offset+3]);
  eax>>=0x10;
  sub_result=array[offset]+(array[offset+1]<<8)-eax;
  array[offset]=sub_result&0xFF;
  array[offset+1]=sub_result>>8;

  printf("argv[1] %02X %02X %02X %02X\n",array[offset],array[offset+1],array[offset+2],array[offset+3]);
  eax=0;
  count=0;
  while(count< 0x3E*4)
    {
      eax^=real_n(count)+(real_n(count+1)<<8)+(real_n(count+2)<<16)+(real_n(count+3)<<24);
      // printf("count=%d %08X %08X\n",count/4,eax,real_n(count)+(real_n(count+1)<<8)+(real_n(count+2)<<16)+(real_n(count+3)<<24));
      count+=4;
    }
  printf("count=%d %08X %08X\n",count/4,eax,real_n(count)+(real_n(count+1)<<8)+(real_n(count+2)<<16)+(real_n(count+3)<<24));
  //free(name);

  return 0;
}

//eax == 0xAFFCCFFB
发布了42 篇原创文章 · 获赞 2 · 访问量 7960

猜你喜欢

转载自blog.csdn.net/guaigle001/article/details/104247170
今日推荐