• 标 题:公文写作助手 V1.0
  • 作 者:cndave
  • 时 间:2003/05/24 11:05am 
  • 链 接:http://bbs.pediy.com

前几天收到一封垃圾邮件叫什么公文写作助手,但是需要注册才能使用,看着挺来气的,
就想把它做了,因为自己本就是菜鸟一个,现学现卖到看雪这里学习了一下,用了俩天
时间终于搞定了。不敢独享,从这里学的再返回到这里,也算是对给和我一样的菜鸟一
些鼓励吧。


【软件名称】:公文写作助手 V1.0

【下载页面】:http://hn-http.skycn.net/down/gongwen.exe

【软件大小】:1647 KB

【软件语言】:简体中文

【应用平台】:WIN9X/WINNT/WIN2K/WINXP

【软件简介】:
办公司,当文秘,一刻也离不开写文章。可是许多人,却因为写不出文章而发愁。其实,
写文章也有很多诀窍,其中最关键的,就是要先学会模仿,而后才能熟中生巧,写出一
手漂亮文章来。 本电子书积累类作者多年写文章的经验,既提供了各种行政、经济、法律、
礼仪、事物、新闻类文章的写作要点,又提供了各种公文的例文和范本。即使你没有任何写
作经验,对着范本来个照本宣科,马上就会写出一手漂亮文章来。特别提示:本书提供了数
百篇例文,对于初学者,可以利用复制、粘帖的办法,快速写出称心的文章.正所谓:有此软
件做助手,从此写作不再愁。

【软件限制】:只有注册后才能使用。

【作者声明】:本人发表这篇文章只是为了学习!!!请不用于商业用途或是将本文方法制作的
注册机任意传播,读者看了文章后所做的事情与我无关,我也不会负责,请读者看了文章后三思
而后行!最后希望大家在经济基础好的时候,支持共享软件!

【破解工具】fileinfo2.45a UnAspack DeDe3.20.04 vc6.0(没办法,水平太菜,softice不太会用)

【破解平台】W2K ADV SERVER

【过    程】:

先说一下此软件的注册方式,它是自己先根据机器信息生成一个每台机器独立的10位代码,然后
经过对其进行运算后生成所谓的解锁码。经过跟踪找出解锁码跟容易,我们的目标就是找出它的
计算解锁码的算法。

先用fi查看是用Aspack加的壳,于是用UnAspack脱掉后再看,是delphi写的。于是用DeDe处理。根
据处理的结果可以看出在注册界面点确定后会进入如下函数调用:

0047876C   call  dword ptr [edx+0F0h]

所以用VC打开程序,F10进入调试模式,断点下在0047876C。按F5运行程序后,进入注册界面随便输入
一个解锁码,点确定后程序中断,按F11跟进:
-------------------------------------------------------------------------------------
第一步:

00478698   push        ebp
00478699   mov         ebp,esp
0047869B   push        0
0047869D   push        0
0047869F   push        ebx
004786A0   mov         ebx,eax
004786A2   xor         eax,eax
004786A4   push        ebp
004786A5   push        4786FAh
004786AA   push        dword ptr fs:[eax]
004786AD   mov         dword ptr fs:[eax],esp
004786B0   lea         edx,[ebp-4]
004786B3   mov         eax,ebx
004786B5   mov         ecx,dword ptr [eax]
004786B7   call        dword ptr [ecx+0E0h]
004786BD   mov         eax,dword ptr [ebp-4]
004786C0   push        eax                 <-这里是输入的解锁码压栈
004786C1   lea         edx,[ebp-8]
004786C4   mov         eax,ebx
004786C6   mov         ecx,dword ptr [eax]
004786C8   call        dword ptr [ecx+0E4h]
004786CE   mov         eax,dword ptr [ebp-8] <-这里eax的值是机器生成的10位代码
004786D1   mov         ecx,dword ptr [ebx+2F8h]
004786D7   pop         edx
004786D8   call        00477DFC   <-eax是输入的解锁码,edx是机器算出的10位代码,进入函数
004786DD   mov         ebx,eax
004786DF   xor         eax,eax
004786E1   pop         edx
004786E2   pop         ecx
004786E3   pop         ecx
004786E4   mov         dword ptr fs:[eax],edx
004786E7   push        478701h
004786EC   lea         eax,[ebp-8]
004786EF   mov         edx,2
004786F4   call        00403BC8
004786F9   ret
------------------------------------------------------------------------
第二步: 接上一步的 004786D8   call   00477DFC 调用

00477DFC   push        ebp
00477DFD   mov         ebp,esp
00477DFF   add         esp,0FFFFFEFCh
00477E05   push        ebx
00477E06   push        esi
00477E07   push        edi
00477E08   xor         ebx,ebx
00477E0A   mov         dword ptr [ebp-4],ebx
00477E0D   mov         edi,ecx
00477E0F   mov         esi,edx  <-输入的解锁码
00477E11   mov         ebx,eax  <-机器算出的10位代码
00477E13   xor         eax,eax
00477E15   push        ebp
00477E16   push        477E63h
00477E1B   push        dword ptr fs:[eax]
00477E1E   mov         dword ptr fs:[eax],esp
00477E21   lea         ecx,[ebp-104h]
00477E27   mov         edx,edi
00477E29   mov         eax,ebx
00477E2B   call        00477C94  <-eax:机器算出的10位代码,esi:输入的解锁码,进入函数
00477E30   lea         edx,[ebp-104h]
00477E36   lea         eax,[ebp-4]
00477E39   call        00403DC8
00477E3E   mov         eax,dword ptr [ebp-4]
00477E41   mov         edx,esi
00477E43   call        00403F34
00477E48   sete        al
00477E4B   mov         ebx,eax
00477E4D   xor         eax,eax
00477E4F   pop         edx
00477E50   pop         ecx
00477E51   pop         ecx
00477E52   mov         dword ptr fs:[eax],edx
00477E55   push        477E6Ah
00477E5A   lea         eax,[ebp-4]
00477E5D   call        00403BA4
00477E62   ret
-------------------------------------------------------------------------------
第三步:接上一步的00477E2B   call   00477C94调用

00477C94   push        ebp
00477C95   mov         ebp,esp
00477C97   add         esp,0E0h
00477C9A   push        ebx
00477C9B   push        esi
00477C9C   push        edi
00477C9D   xor         ebx,ebx
00477C9F   mov         dword ptr [ebp-20h],ebx
00477CA2   mov         dword ptr [ebp-1Ch],ebx
00477CA5   mov         dword ptr [ebp-18h],ebx
00477CA8   mov         edi,ecx
00477CAA   mov         dword ptr [ebp-8],edx
00477CAD   mov         dword ptr [ebp-4],eax
00477CB0   mov         eax,dword ptr [ebp-4]
00477CB3   call        00403FD8
00477CB8   mov         eax,dword ptr [ebp-8]
00477CBB   call        00403FD8
00477CC0   xor         eax,eax
00477CC2   push        ebp
00477CC3   push        477DEDh
00477CC8   push        dword ptr fs:[eax]
00477CCB   mov         dword ptr fs:[eax],esp
00477CCE   cmp         dword ptr [ebp-4],0
00477CD2   je          00477D43
00477CD4   mov         ebx,1
00477CD9   lea         esi,[ebp-11h]
00477CDC   mov         eax,dword ptr [ebp-4]
00477CDF   call        00403E24
00477CE4   push        eax
00477CE5   mov         eax,ebx
00477CE7   dec         eax
00477CE8   pop         edx
00477CE9   mov         ecx,edx
00477CEB   cdq
00477CEC   idiv        eax,ecx
00477CEE   mov         eax,dword ptr [ebp-4]
00477CF1   mov         al,byte ptr [eax+edx]<-分别取出10位机器码放入al中
00477CF4   push        eax
00477CF5   mov         eax,dword ptr [ebp-4]
00477CF8   call        00403E24
00477CFD   pop         edx
00477CFE   xor         dl,al                <-先与al进行xor运算,al值为0x0a
00477D00   xor         dl,bl                <-再与bl进行xor运算,bl为从1开始每次递增1
00477D02   mov         byte ptr [esi],dl    <-运算结果放进ESI
00477D04   inc         ebx
00477D05   inc         esi
00477D06   cmp         ebx,0Ah              <-循环记数
00477D09   jne         00477CDC
00477D0B   mov         eax,dword ptr [ebp-4]
00477D0E   call        00403E24
00477D13   mov         esi,eax
00477D15   test        esi,esi
00477D17   jle         00477D43
00477D19   mov         ebx,1
00477D1E   mov         eax,dword ptr [ebp-4]
00477D21   call        00403E24
00477D26   sub         eax,ebx
00477D28   mov         edx,dword ptr [ebp-4]
00477D2B   mov         cl,byte ptr [edx+eax] <-每次一个反序取出机器码
00477D2E   mov         eax,ebx
00477D30   dec         eax
00477D31   push        ecx
00477D32   mov         ecx,9
00477D37   cdq
00477D38   idiv        eax,ecx
00477D3A   pop         ecx
00477D3B   xor         byte ptr [ebp+edx-11h],cl <-取出的内容与上面的结果进行xor操作
                                                <-循环共9次,所以最后一位要和第一
                                                <-次的计算结果进行运算
00477D3F   inc         ebx
00477D40   dec         esi
00477D41   jne         00477D1E
00477D43   cmp         dword ptr [ebp-8],0
00477D47   je          00477D82
00477D49   mov         ebx,1
00477D4E   lea         esi,[ebp-11h]
00477D51   mov         eax,dword ptr [ebp-8]
00477D54   call        00403E24
00477D59   push        eax
00477D5A   mov         eax,ebx
00477D5C   dec         eax
00477D5D   pop         edx
00477D5E   mov         ecx,edx
00477D60   cdq
00477D61   idiv        eax,ecx
00477D63   mov         eax,dword ptr [ebp-8]
00477D66   mov         al,byte ptr [eax+edx]
00477D69   xor         al,byte ptr [esi]
00477D6B   push        eax
00477D6C   mov         eax,dword ptr [ebp-8]
00477D6F   call        00403E24
00477D74   pop         edx
00477D75   xor         dl,al
00477D77   xor         dl,bl
00477D79   mov         byte ptr [esi],dl
00477D7B   inc         ebx
00477D7C   inc         esi
00477D7D   cmp         ebx,0Ah
00477D80   jne         00477D51
00477D82   lea         eax,[ebp-18h]
00477D85   call        00403BA4
00477D8A   mov         ebx,9
00477D8F   lea         esi,[ebp-11h]
00477D92   lea         eax,[ebp-1Ch]
00477D95   mov         dl,byte ptr [esi]
00477D97   call        00403D4C
00477D9C   mov         edx,dword ptr [ebp-1Ch]
00477D9F   lea         eax,[ebp-18h]
00477DA2   call        00403E2C
00477DA7   inc         esi
00477DA8   dec         ebx
00477DA9   jne         00477D92
00477DAB   lea         edx,[ebp-20h]
00477DAE   mov         eax,dword ptr [ebp-18h]
00477DB1   call        00477B50              <--10位代码经过运算后进入调用
00477DB6   mov         edx,dword ptr [ebp-20h]
00477DB9   mov         eax,edi
00477DBB   mov         ecx,0FFh
00477DC0   call        00403E00
00477DC5   xor         eax,eax
00477DC7   pop         edx
00477DC8   pop         ecx
00477DC9   pop         ecx
00477DCA   mov         dword ptr fs:[eax],edx
00477DCD   push        477DF4h
00477DD2   lea         eax,[ebp-20h]
00477DD5   mov         edx,3
00477DDA   call        00403BC8
00477DDF   lea         eax,[ebp-8]
00477DE2   mov         edx,2
00477DE7   call        00403BC8
00477DEC   ret

这里对此过程进入调用之前的分析说明,它是这样处理的,假设10位解锁码为c1-c10;
运算如下:

--------------------------------------------------------------
    c1    c2    c3    c4    c5    c6    c7    c8    c9    c10
xor  0x0a  0x0a  0x0a  0x0a  0x0a  0x0a  0x0a  0x0a  0x0a  0x0a 分别与0x0a进行xor运算
---------------------------------------------------------------
    cc1   cc2   cc3   cc4   cc5   cc6   cc7   cc8   cc9        得到的结果
xor  1     2     3     4     5     6     7     8     9          然后前9个分别从1到9进行xor运算
---------------------------------------------------------------
    ccc1  ccc2  ccc3  ccc4  ccc5  ccc6  ccc7  ccc8  ccc9       得到的结果
xor  c10   c9    c8    c7    c6    c5    c4    c3    c2         10位解锁码反序与前面结果xor运算
---------------------------------------------------------------
    cccc1                                                      最后一位也就是代码的第一个与
xor  c1                                                         执行结果的第一项继续运算
---------------------------------------------------------------
    b1    b2     b3    b4    b5   b6     b7    b8    b9        这里为最终生成的结果
---------------------------------------------------------------

上面就是对本段进入注名的函数调用之前的分析,其中cc[n],ccc[n],cccc[n]为中间结果,b[n]为最终结果


-------------------------------------------------------------------------------------------
第四步: 接00477DB1   call   00477B50调用

00477B50   push        ebp
00477B51   mov         ebp,esp
00477B53   add         esp,0F0h
00477B56   push        ebx
00477B57   push        esi
00477B58   push        edi
00477B59   xor         ecx,ecx
00477B5B   mov         dword ptr [ebp-10h],ecx
00477B5E   mov         edi,edx
00477B60   mov         dword ptr [ebp-4],eax
00477B63   mov         eax,dword ptr [ebp-4]
00477B66   call        00403FD8
00477B6B   xor         eax,eax
00477B6D   push        ebp
00477B6E   push        477C84h
00477B73   push        dword ptr fs:[eax]
00477B76   mov         dword ptr fs:[eax],esp
00477B79   mov         eax,edi
00477B7B   call        00403BA4
00477B80   jmp         00477C5C
00477B85   mov         eax,dword ptr [ebp-4]
00477B88   call        00403E24
00477B8D   mov         ecx,eax
00477B8F   mov         eax,ecx
00477B91   mov         ebx,3
00477B96   cdq
00477B97   idiv        eax,ebx
00477B99   test        eax,eax
00477B9B   jle         00477BA4
00477B9D   mov         ebx,3
00477BA2   jmp         00477BA6
00477BA4   mov         ebx,ecx
00477BA6   lea         eax,[ebp-7]
00477BA9   xor         ecx,ecx
00477BAB   mov         edx,3
00477BB0   call        00402B68
00477BB5   lea         eax,[ebp-0Bh]
00477BB8   mov         ecx,40h
00477BBD   mov         edx,4
00477BC2   call        00402B68
00477BC7   lea         eax,[ebp-4]
00477BCA   call        00403FF4
00477BCF   lea         edx,[ebp-7]
00477BD2   mov         ecx,ebx
00477BD4   call        00402890
00477BD9   cmp         ebx,3
00477BDC   jl          00477BE6
                                            <-此段代码循环三次,每次都把前面计算出的9个数取出三个
00477BDE   mov         al,byte ptr [ebp-5]   <-取第三个数
00477BE1   and         al,3Fh                <-和3F进行AND运算
00477BE3   mov         byte ptr [ebp-8],al   <-保存结果
00477BE6   cmp         ebx,2
00477BE9   jl          00477C00
00477BEB   mov         al,byte ptr [ebp-6]   <-取第二个数
00477BEE   shl         eax,2                 <-左移2位
00477BF1   xor         edx,edx      
00477BF3   mov         dl,byte ptr [ebp-5]   <-取第三个数
00477BF6   shr         edx,6                 <-右移动6位
00477BF9   or          al,dl                 <-俩个结果进行or运算
00477BFB   and         al,3Fh                <-运算结果再与3F进行and运算
00477BFD   mov         byte ptr [ebp-9],al   <-保存结果
00477C00   mov         al,byte ptr [ebp-7]   <-取第一个数
00477C03   mov         edx,eax
00477C05   shl         edx,4                 <-左移4位
00477C08   xor         ecx,ecx
00477C0A   mov         cl,byte ptr [ebp-6]   <-取第二个数
00477C0D   shr         ecx,4                 <-右移4位
00477C10   or          dl,cl                 <-俩个结果进行or运算
00477C12   and         dl,3Fh                <-运算结果再与3F进行and运算
00477C15   mov         byte ptr [ebp-0Ah],dl <-保存结果
00477C18   and         eax,0FFh              <-第一个数与ff进行and运算
00477C1D   shr         eax,2                 <-结果右移2位
00477C20   and         al,3Fh                <-运算结果再与3F进行and运算
00477C22   mov         byte ptr [ebp-0Bh],al <-保存结果
00477C25   lea         eax,[ebp-4]
00477C28   mov         ecx,ebx
00477C2A   mov         edx,1
00477C2F   call        0040406C
00477C34   mov         esi,4
00477C39   lea         ebx,[ebp-0Bh]
00477C3C   lea         eax,[ebp-10h]
00477C3F   xor         edx,edx
00477C41   mov         dl,byte ptr [ebx]          <-这里循环四次,就是每此分别取出上面计算出的四个数
00477C43   mov         dl,byte ptr [edx+47E49Dh]  <-47e490d处保存了一个用来生成解琐码的长字符串,根据                        

                                                 <-前面计算出的四个数的位置取出四个字符,就是解锁码的
                                                 <-四位
00477C49   call        00403D4C      
00477C4E   mov         edx,dword ptr [ebp-10h]  
00477C51   mov         eax,edi
00477C53   call        00403E2C  
00477C58   inc         ebx
00477C59   dec         esi
00477C5A   jne         00477C3C
00477C5C   cmp         dword ptr [ebp-4],0
00477C60   jne         00477B85                 <-此处循环三次,计算出12位的解锁码
00477C66   xor         eax,eax
00477C68   pop         edx
00477C69   pop         ecx
00477C6A   pop         ecx
00477C6B   mov         dword ptr fs:[eax],edx
00477C6E   push        477C8Bh
00477C73   lea         eax,[ebp-10h]
00477C76   call        00403BA4
00477C7B   lea         eax,[ebp-4]
00477C7E   call        00403BA4
00477C83   ret

对本段分析如下:

注:b1-b9为前面生成的结果,m,n,k为计算中间结果,N1-N12为最后的结果

取出三个数:b1   b2   b3  
1,  b3 and 3f    =N1(生成第一个数)  
2,  b2 shl 2     =m
   b3 shr 6     =n  
   m  or  n     =k
   k  and 3f    =N2(生成第二个数)  
3,  b1 shl 4     =m
   b2 shr 4     =n
   m  or  n     =k
   k  and 3f    =N3(生成第三个数)
4, b1 and 0ff   =m
   m  shr 2     =n
   n  and 3f    =N4(生成第四个数)  

取三个数:b4  b5  b6  
   与前面三个数执行同样的运算
取三个数:b7  b8  b9
   与前面三个数执行同样的运算

最后生成12个数从N1-N12

现在从47E49Dh处保存的数据分别从N1到N12位置取出12个字符,就是最终的解锁码了。


第一次写这样的东西,可能看起来很乱,看起来步骤很简单,但是实际跟踪的时候乱
七八糟的CALL搞的头都晕,也许对于高手来手很简单,但是谁让咱菜呢,要是表达不
清楚,还请海涵。对于软件作者在这里也说声抱歉,算是对他乱发垃圾邮件的一个小
小的惩罚吧。不知道帖子发完会不会变形,就这些吧。


下面附上注册机代码:
VC的对话框程序:m_machine_code和m_register_code分别为俩个EDIT控件的变量


void CGwxzDlg::OnOK()
{
// TODO: Add extra validation here
char BaseCode[]="此处为生成的解锁码的字串,这里就不给出了";
       char MachineCode[10];
char RegisterCode[12];
int MidData[9];
int i,a,b;

UpdateData(true);

strncpy(MachineCode,m_machine_code,10);
MachineCode[10]=0;

for(i=0;i<9;i++)
{
MidData[i]=MachineCode[i]^10;
MidData[i]^=i+1;
MidData[i]^=MachineCode[9-i];
}

MidData[0]^=MachineCode[0];


       for(i=1;i<4;i++)
{
  a=MidData[3*i-1];
  a&=0x3f;
 
  RegisterCode[4*i-1]=a;

  a=MidData[3*i-2];
  a<<=2;
  b=MidData[3*i-1];
  b>>=6;
  a|=b;
  a&=0x3f;
     
  RegisterCode[4*i-2]=a;

          a=MidData[3*i-3];
  a<<=4;
  b=MidData[3*i-2];
  b>>=4;
  a|=b;
  a&=0x3f;

      RegisterCode[4*i-3]=a;
 
      a=MidData[3*i-3];
      a&=0xff;
      a>>=2;
      a&=0x3f;

      RegisterCode[4*i-4]=a;
}

for(i=0;i<12;i++)
{
   RegisterCode[i]=BaseCode[RegisterCode[i]];
}

RegisterCode[12]=0;

m_register_code=RegisterCode;

UpdateData(false);
}