一个国产文件夹锁的注册算法简单分析

主程序加了简单的壳:
ASPack 2.12 -> Alexey Solodovnikov

没想脱,直接搜索:
push 0
retn

然后在retn上下断,F9运行,然后再单步就到了程序的OEP了,呵呵

让程序运行起来,随意的输入假码,利用万能断点就能找到程序的算法关键所在!
这是一个典型的查表注册机制,代码如下:

00586D5B     8B45 FC       mov eax,dword ptr ss:[ebp-4]        ; 将EAX指向机器码
00586D5E     0FB64438 FF   movzx eax,byte ptr ds:[eax+edi-1]   ; 以EDI为索引逐一取机器码的ASCII值
00586D63     2B45 F0       sub eax,dword ptr ss:[ebp-10]
00586D66     03C7          add eax,edi
00586D68     8B55 F8       mov edx,dword ptr ss:[ebp-8]        ; 将EDX指向用户名
00586D6B     0FB6541A FF   movzx edx,byte ptr ds:[edx+ebx-1]   ; 以EBX不索引逐一取用户名的ASCII码值
00586D70     33C2          xor eax,edx                         ; 将两者进行或运算
00586D72     03C3          add eax,ebx                         ; 加上用户名的索引值(从1开始)
00586D74     99            cdq
00586D75     33C2          xor eax,edx
00586D77     2BC2          sub eax,edx
00586D79     8BF0          mov esi,eax
00586D7B     8BC6          mov eax,esi
00586D7D     B9 24000000   mov ecx,24
00586D82     99            cdq
00586D83     F7F9          idiv ecx                            ; 除以0x24求余
00586D85     8BF2          mov esi,edx
00586D87     8D45 E0       lea eax,dword ptr ss:[ebp-20]
00586D8A     8A96 90C75A00 mov dl,byte ptr ds:[esi+5AC790]     ; 将余数作为索引从字符表中取字符
00586D90     E8 07DEF8FF   call etdirloc.00514B9C
00586D95     8B55 E0       mov edx,dword ptr ss:[ebp-20]
00586D98     8D45 E4       lea eax,dword ptr ss:[ebp-1C]
00586D9B     E8 DCDEF8FF   call etdirloc.00514C7C
00586DA0     3B7D EC       cmp edi,dword ptr ss:[ebp-14]       ; 判断是否超出机器码长度
00586DA3     7D 03         jge short etdirloc.00586DA8
00586DA5     47            inc edi                             ; 不是则增1
00586DA6     EB 05         jmp short etdirloc.00586DAD
00586DA8     BB 01000000   mov ebx,1                           ; 否则将用户名的索引设为1,
00586DAD     3B5D E8       cmp ebx,dword ptr ss:[ebp-18]       ; 判断是否超出用户名长度
00586DB0     7D 03         jge short etdirloc.00586DB5
00586DB2     43            inc ebx                             ; 不是则增1
00586DB3     EB 05         jmp short etdirloc.00586DBA
00586DB5     BB 01000000   mov ebx,1
00586DBA     FF45 F0       inc dword ptr ss:[ebp-10]
00586DBD     837D F0 15    cmp dword ptr ss:[ebp-10],15
00586DC1   ^ 75 98         jnz short etdirloc.00586D5B


通过mov dl,byte ptr ds:[esi+5AC790] 这句,我们可以知道,所要查找表的是在位置5AC790处:

005AC790  30 43 4D 35 45 51 39 52 50 5A 36 44 56 34 42 33  0CM5EQ9RPZ6DV4B3
005AC7A0  55 4C 43 37 59 53 47 38 4B 46 4E 41 31 48 49 47  ULC7YSG8KFNA1HIG
005AC7B0  32 4A 4F 54 00 00 00 00                          2JOT....


存放在一个全局变量里,呵呵!
现在可以动手写注册机了,代码如下是:

#include
#include
using namespace std;

const char gString[]="0CM5EQ9RPZ6DV4B3ULC7YSG8KFNA1HIG2JOT";

int main()
{
  cout<<"不支持用户名中带空格!\n";
  char username[20]={0};
  cout<<"请输入你的用户名:";
  cin>>username;

  char strM[32]={0};
  cout<<"请输入你的机器码:";
  cin>>strM;

  cout<<"你的注册码是:(填写时请按5位一组填写)\n";
  char strCode[32]={0};
  
  int len=strlen(username);
  for(int i=0,j=0;i<20;i++){
    int tmp=strM[i] ^ username[j];
    tmp+=(j+1);
    tmp %= 0x24;
    strCode[i]=gString[tmp];
    j++;
    if(j>=len)
      j=0;
  }
  cout<
  return 0;
}


在我电脑上运行如下([color=#0000FF]注意是在命令行下运行[/color]):

G:\TDDOWNLOAD>keyGen
不支持用户名中带空格!
请输入你的用户名:iawen
请输入你的机器码:1412101181315857262915313
你的注册码是:(填写时请按5位一组填写)
L3C71C6CF176JFK8427Y


即注册码为:[color=#FF0000]L3C71-C6CF1-76JFK-8427Y[/color]

点击下载注册机:
keyGen.rar