大管家通用人事工资管理系统的注册分析——F1(序列号)=F2(注册码)
【破解作者】 jsliyangsj
【作者邮箱】 sjcrack@yahoo.com.cn
【使用工具】 peid OllyDbg1.10
【破解平台】 Winxp
【软件名称】 大管家通用人事工资管理系统_专业版740
【软件地址】 http://www.lansom.com/
软件有壳,ASPack 2.12 -> Alexey Solodovnikov,脱壳后,点击“系统注册”,发现程序打开了新进程Hrms
在Hrms中查找字符串能直接找到错误提示“注册码错误……”
对于F1(序列号)=F2(注册码)的软件只要逆转一个就够了,这里逆转的是F1(序列号)就是用注册码得到序列号
分析:
08A0A2D2    .  8B>mov eax,dword ptr ds:[eax+2D8]
08A0A2D8    .  E8>call Hrms.087C7A28                   ;  得到序列号
08A0A2DD    .  8B>mov eax,dword ptr ss:[ebp-14]
08A0A2E0    .  E8>call Hrms.0879425C                   ;  得到序列号的位数
08A0A2E5    .  83>cmp eax,4                            ;  位数一定要大于等于4
08A0A2E8    .  7D>jge short Hrms.08A0A318
08A0A2EA    .  6A>push 10
08A0A2EC    .  B9>mov ecx,Hrms.08A0A610
08A0A2F1    .  BA>mov edx,Hrms.08A0A618
08A0A2F6    .  A1>mov eax,dword ptr ds:[8A19470]
08A0A2FB    .  8B>mov eax,dword ptr ds:[eax]
08A0A2FD    .  E8>call Hrms.087E7400                   ;  如果小于4,到这里出错了!!
08A0A302    .  8B>mov eax,dword ptr ss:[ebp-4]
………………省略……………………
08A0A32C    .  8B>mov eax,dword ptr ds:[eax+2DC]
08A0A332    .  E8>call Hrms.087C7A28                   ;  得到第1个注册码返回注册码1的位数
08A0A337    .  8D>lea eax,dword ptr ss:[ebp-18]
08A0A33A    .  50 push eax
08A0A33B    .  8D>lea edx,dword ptr ss:[ebp-1C]
08A0A33E    .  8B>mov eax,dword ptr ss:[ebp-4]
08A0A341    .  8B>mov eax,dword ptr ds:[eax+2E0]
08A0A347    .  E8>call Hrms.087C7A28                   ;  得到第2个注册码返回注册码2的位数
08A0A34C    .  8B>mov edx,dword ptr ss:[ebp-1C]
08A0A34F    .  58 pop eax
08A0A350    .  E8>call Hrms.08794264                   ;  把1,2注册码组合,共8位先放后几位注册码2,前几位不足用注册码填,多余去掉注册码1前面的
08A0A355    .  8B>mov edx,dword ptr ss:[ebp-18]
08A0A358    .  A1>mov eax,dword ptr ds:[8A1977C]
08A0A35D    .  8B>mov eax,dword ptr ds:[eax]
08A0A35F    .  E8>call Hrms.089F0E64                   ;  取合并后的注册码的前8位当做16进制(不是转化)
08A0A364    .  89>mov dword ptr ss:[ebp-C],eax         ;  储存在EBP-C
08A0A367    .  8D>lea edx,dword ptr ss:[ebp-20]
08A0A36A    .  8B>mov eax,dword ptr ss:[ebp-4]
08A0A36D    .  8B>mov eax,dword ptr ds:[eax+2E4]
08A0A373    .  E8>call Hrms.087C7A28                   ;  得到第3个注册码返回注册码3的位数
08A0A378    .  8D>lea eax,dword ptr ss:[ebp-20]
08A0A37B    .  50 push eax
08A0A37C    .  8D>lea edx,dword ptr ss:[ebp-24]
08A0A37F    .  8B>mov eax,dword ptr ss:[ebp-4]
08A0A382    .  8B>mov eax,dword ptr ds:[eax+2EC]
08A0A388    .  E8>call Hrms.087C7A28                   ;  得到第4个注册码返回注册码4的位数
08A0A38D    .  8B>mov edx,dword ptr ss:[ebp-24]
08A0A390    .  58 pop eax
08A0A391    .  E8>call Hrms.08794264                   ;  把3,4注册码组合,共8位先放后几位注册码4,前几位不足用注册码3填,多余去掉注册码3前面的
08A0A396    .  8B>mov edx,dword ptr ss:[ebp-20]
08A0A399    .  A1>mov eax,dword ptr ds:[8A1977C]
08A0A39E    .  8B>mov eax,dword ptr ds:[eax]
08A0A3A0    .  E8>call Hrms.089F0E64                   ;  取合并后的注册码的前8位当做16进制(不是转化)
08A0A3A5    .  89>mov dword ptr ss:[ebp-8],eax         ;  储存在EBP-8
08A0A3A8    .  33>xor eax,eax
………………………省略…………………………
08A0A3EA    .  E8>call Hrms.08793A08
08A0A3EF    >  8D>lea eax,dword ptr ss:[ebp-C]         ;  下面是关键
08A0A3F2    .  50 push eax
08A0A3F3    .  8D>lea edx,dword ptr ss:[ebp-28]
08A0A3F6    .  8B>mov eax,dword ptr ss:[ebp-4]
08A0A3F9    .  8B>mov eax,dword ptr ds:[eax+2D8]
08A0A3FF    .  E8>call Hrms.087C7A28                   ;  再次得到序列号
08A0A404    .  8B>mov edx,dword ptr ss:[ebp-28]
08A0A407    .  8D>lea ecx,dword ptr ss:[ebp-E]
08A0A40A    .  A1>mov eax,dword ptr ds:[8A1977C]
08A0A40F    .  8B>mov eax,dword ptr ds:[eax]
08A0A411    .  E8>call Hrms.089F0BDC                   ;  关键点, 进入

…………………………………………………………………………………………………………………………
进入08A0A411    .  E8>call Hrms.089F0BDC 
…………………………………………………………………………………………………………………………
089F0C0E   |.  64>mov dword ptr fs:[eax],esp           ;  下面是判断用哪个字符串作为参数用的!
089F0C11   |.  A1>mov eax,dword ptr ds:[8A1C468]       ;  固定值9DD
089F0C16   |.  B9>mov ecx,3E8                          ;  固定的3E8
089F0C1B   |.  99 cdq
089F0C1C   |.  F7>idiv ecx                             ;  9DD除以3E8
089F0C1E   |.  48 dec eax                              ;  减1; Switch (cases 1..4)
089F0C1F   |.  74>je short Hrms.089F0C2C
089F0C21   |.  48 dec eax                              ;  再减1必为0
089F0C22   |.  74>je short Hrms.089F0C3B
089F0C24   |.  48 dec eax
089F0C25   |.  74>je short Hrms.089F0C4A
089F0C27   |.  48 dec eax
089F0C28   |.  74>je short Hrms.089F0C59
089F0C2A   |.  EB>jmp short Hrms.089F0C66
089F0C2C   |>  8D>lea eax,dword ptr ss:[ebp-18]        ;  Case 1 of switch 089F0C1E
089F0C2F   |.  BA>mov edx,Hrms.089F0DD4                ;  ASCII "Oh,You are fat pig!"
089F0C34   |.  E8>call Hrms.08794074
089F0C39   |.  EB>jmp short Hrms.089F0C66
089F0C3B   |>  8D>lea eax,dword ptr ss:[ebp-18]        ;  Case 2 of switch 089F0C1E
089F0C3E   |.  BA>mov edx,Hrms.089F0DF0                ;  字符串作为参数Ha...ha,You arefat pig!
089F0C43   |.  E8>call Hrms.08794074
089F0C48   |.  EB>jmp short Hrms.089F0C66
089F0C4A   |>  8D>lea eax,dword ptr ss:[ebp-18]        ;  Case 3 of switch 089F0C1E
089F0C4D   |.  BA>mov edx,Hrms.089F0E14                ;  ASCII "Oh,grandeur for company!"
089F0C52   |.  E8>call Hrms.08794074
089F0C57   |.  EB>jmp short Hrms.089F0C66
089F0C59   |>  8D>lea eax,dword ptr ss:[ebp-18]        ;  Case 4 of switch 089F0C1E
089F0C5C   |.  BA>mov edx,Hrms.089F0E38                ;  ASCII "Oh,grandeur for rsglpro!"
089F0C61   |.  E8>call Hrms.08794074
089F0C66   |>  8B>mov eax,dword ptr ss:[ebp-8]         ;  取出序列号地址; Default case of switch 089F0C1E
089F0C69   |.  E8>call Hrms.0879425C                   ;  得到序列号的位数
089F0C6E   |.  25>and eax,80000007                     ;  与7相乘
089F0C73   |.  79>jns short Hrms.089F0C7A
089F0C75   |.  48 dec eax
089F0C76   |.  83>or eax,FFFFFFF8
089F0C79   |.  40 inc eax
089F0C7A   |>  85>test eax,eax
089F0C7C   |.  74>je short Hrms.089F0CAA
089F0C7E   |.  8D>lea eax,dword ptr ss:[ebp-8]
089F0C81   |.  BA>mov edx,Hrms.089F0E5C                ;  得到固定值1234567
089F0C86   |.  E8>call Hrms.08794264                   ;  把序列号与固定值合并73065321234567
089F0C8B   |.  8B>mov eax,dword ptr ss:[ebp-8]         ;  得到地址
089F0C8E   |.  E8>call Hrms.0879425C                   ;  得到合并之后的位数
089F0C93   |.  85>test eax,eax
089F0C95   |.  79>jns short Hrms.089F0C9A
089F0C97   |.  83>add eax,7
089F0C9A   |>  C1>sar eax,3
089F0C9D   |.  8B>mov edx,eax
089F0C9F   |.  C1>shl edx,3                            ;  左移动3
089F0CA2   |.  8D>lea eax,dword ptr ss:[ebp-8]         ;  合并后的地址
089F0CA5   |.  E8>call Hrms.08794590                   ;  将第9位0  上面一段的意思是:如果你输入的小于8的倍数则后面不足的就用1234567补足。取8的倍数位
089F0CAA   |>  33>xor esi,esi
089F0CAC   |.  8D>lea eax,dword ptr ss:[ebp-8]
089F0CAF   |.  E8>call Hrms.0879442C
089F0CB4   |.  8B>mov edi,eax
089F0CB6   |.  8D>lea eax,dword ptr ss:[ebp-18]
089F0CB9   |.  E8>call Hrms.0879442C                   ;  得到字符串参数的Ha...ha,You arefat pig!的地址
089F0CBE   |.  8B>mov ebx,eax
089F0CC0   |.  EB>jmp short Hrms.089F0CF5
089F0CC2   |>  8B>/mov eax,dword ptr ds:[edi+esi*4]    ;  得到合并取前8位的前4位的ASCII码反过来放的
089F0CC5   |.  89>|mov dword ptr ss:[ebp-20],eax       ;  储存
089F0CC8   |.  8B>|mov eax,dword ptr ds:[edi+esi*4+4]  ;  取后四位反着放
089F0CCC   |.  89>|mov dword ptr ss:[ebp-1C],eax       ;  储存
089F0CCF   |.  8B>|mov ecx,ebx                         ;  得到字符串
089F0CD1   |.  8D>|lea edx,dword ptr ss:[ebp-20]
089F0CD4   |.  8B>|mov eax,dword ptr ss:[ebp-4]
089F0CD7   |.  E8>|call Hrms.089F0B74                  ;  循环处理序列号的地方    进入关键点
089F0CDC   |.  8B>|mov eax,dword ptr ds:[ebx]
089F0CDE   |.  89>|mov dword ptr ds:[ebx+8],eax
089F0CE1   |.  8B>|mov eax,dword ptr ds:[ebx+4]
089F0CE4   |.  89>|mov dword ptr ds:[ebx+C],eax
089F0CE7   |.  8B>|mov eax,dword ptr ss:[ebp-20]       ;  取刚才计算出来的数据
089F0CEA   |.  89>|mov dword ptr ds:[ebx],eax
089F0CEC   |.  8B>|mov eax,dword ptr ss:[ebp-1C]       ;  
089F0CEF   |.  89>|mov dword ptr ds:[ebx+4],eax
089F0CF2   |.  83>|add esi,2
089F0CF5   |>  8B> mov eax,dword ptr ss:[ebp-8]
089F0CF8   |.  E8>|call Hrms.0879425C                  ;  得到序列号处理后8倍数的位数
089F0CFD   |.  85>|test eax,eax
089F0CFF   |.  79>|jns short Hrms.089F0D04
089F0D01   |.  83>|add eax,3
089F0D04   |>  C1>|sar eax,2
089F0D07   |.  3B>|cmp esi,eax
089F0D09   |.^ 72>\jb short Hrms.089F0CC2              ;  上面一段意思:用来计算序列号的,每次取8位计算,以最后一次8位序列号计算为最后结果
089F0D0B   |.  8B>mov eax,dword ptr ss:[ebp-14]        ;  得到前2个注册码合并后的
089F0D0E   |.  33>xor edx,edx                          ;  下面2段用来处理注册码的
089F0D10   |.  52 push edx                             ; /Arg6 => 00000000
089F0D11   |.  50 push eax                             ; |Arg5
089F0D12   |.  FF>push dword ptr ds:[8A18C8C]          ; |Arg4 = 00000000
089F0D18   |.  FF>push dword ptr ds:[8A18C88]          ; |Arg3 = 3F17DC15
089F0D1E   |.  FF>push dword ptr ds:[8A18C94]          ; |Arg2 = 00000000
089F0D24   |.  FF>push dword ptr ds:[8A18C90]          ; |Arg1 = 758F0581
089F0D2A   |.  8B>mov eax,dword ptr ss:[ebp-4]         ; |
089F0D2D   |.  E8>call Hrms.089F0AB0                   ; \关键点2  进入  处理注册码1与注册码2合并后的
089F0D32   |.  83>sub eax,2                            ;  结果减2
089F0D35   |.  89>mov dword ptr ss:[ebp-28],eax
089F0D38   |.  8B>mov eax,dword ptr ss:[ebp-10]
089F0D3B   |.  33>xor edx,edx
089F0D3D   |.  52 push edx                             ; /Arg6 => 00000000
089F0D3E   |.  50 push eax                             ; |Arg5
089F0D3F   |.  FF>push dword ptr ds:[8A18C8C]          ; |Arg4 = 00000000
089F0D45   |.  FF>push dword ptr ds:[8A18C88]          ; |Arg3 = 3F17DC15
089F0D4B   |.  FF>push dword ptr ds:[8A18C94]          ; |Arg2 = 00000000
089F0D51   |.  FF>push dword ptr ds:[8A18C90]          ; |Arg1 = 758F0581
089F0D57   |.  8B>mov eax,dword ptr ss:[ebp-4]         ; |
089F0D5A   |.  E8>call Hrms.089F0AB0                   ; \关键点3  进入  处理注册码3与注册码4合并后的
089F0D5F   |.  83>sub eax,2                            ;  结果减2
089F0D62   |.  89>mov dword ptr ss:[ebp-24],eax
089F0D65   |.  C1>shl dword ptr ss:[ebp-28],2          ;  用注册码1、2处理后的结果左移2得到结果1
089F0D69   |.  8D>lea ecx,dword ptr ss:[ebp-28]
089F0D6C   |.  8B>mov eax,dword ptr ds:[ecx]           ;  得到处理后的结果1
089F0D6E   |.  8B>mov edx,dword ptr ds:[ecx+4]         ;  得到注册码3、4处理后的数据
089F0D71   |.  0F>shrd eax,edx,2                       ;  双精度数右移
089F0D75   |.  C1>shr edx,2                            ;  得到注册码3、4处理后的数据右移2得到结果2
089F0D78   |.  89>mov dword ptr ds:[ecx],eax
089F0D7A   |.  89>mov dword ptr ds:[ecx+4],edx
089F0D7D   |.  8B>mov eax,dword ptr ss:[ebp-28]
089F0D80   |.  3B>cmp eax,dword ptr ss:[ebp-20]        ;  比较   用注册码双精度数右移后的结果与序列号处理后的结果比较
089F0D83   |.  74>je short Hrms.089F0D89               ;  相等后再去计算终端数
089F0D85   |.  33>xor ebx,ebx
089F0D87   |.  EB>jmp short Hrms.089F0D9A
089F0D89   |>  66>mov ax,word ptr ss:[ebp-24]          ;  取结果2
089F0D8D   |.  66>and ax,0FFFF                         ;  取注册码3、4处理后的结果2的后16进制后4位作为终端数
089F0D91   |.  8B>mov edx,dword ptr ss:[ebp-C]
089F0D94   |.  66>mov word ptr ds:[edx],ax
089F0D97   |.  83>or ebx,FFFFFFFF
089F0D9A   |>  33>xor eax,eax
089F0D9C   |.  5A pop edx
089F0D9D   |.  59 pop ecx
089F0D9E   |.  59 pop ecx
089F0D9F   |.  64>mov dword ptr fs:[eax],edx
089F0DA2   |.  68>push Hrms.089F0DBF
089F0DA7   |>  8D>lea eax,dword ptr ss:[ebp-18]
089F0DAA   |.  E8>call Hrms.08793FDC
089F0DAF   |.  8D>lea eax,dword ptr ss:[ebp-8]
089F0DB2   |.  E8>call Hrms.08793FDC
089F0DB7   \.  C3 retn
……………………………………………………………………………………………………………………
进入089F0CD7   |.  E8>|call Hrms.089F0B74        ;  循环处理序列号的地方 是可逆的!!
……………………………………………………………………………………………………………………
089F0B74   /$  53 push ebx
089F0B75   |.  56 push esi
089F0B76   |.  57 push edi
089F0B77   |.  51 push ecx
089F0B78   |.  89>mov dword ptr ss:[esp],edx
089F0B7B   |.  BA>mov edx,20                           ;  参数20要循环20(16进制)次
089F0B80   |.  8B>mov eax,dword ptr ss:[esp]
089F0B83   |.  8B>mov eax,dword ptr ds:[eax]           ;  得到前4位ASCII码反  36303337
089F0B85   |.  8B>mov ebx,dword ptr ss:[esp]
089F0B88   |.  8B>mov ebx,dword ptr ds:[ebx+4]         ;  得到后四位ASCII码反  31323335
089F0B8B   |.  33>xor esi,esi
089F0B8D   |>  4A /dec edx                             ;  参数减1
089F0B8E       03>add esi,dword ptr ds:[8A18C84]       ;  固定脂9E3779B9
089F0B94       8B>mov edi,ebx
089F0B96   |.  C1>|shl edi,4                           ;  结果左移4位
089F0B99       03>add eax,edi                          ;  与前4位相加
089F0B9B   |.  8B>|mov edi,dword ptr ds:[ecx]          ;  取固定字符串的前4位ASCII码  2E2E6148
089F0B9D   |.  33>|xor edi,ebx                         ;  取固定字符串的前4位ASCII码与后4位XOR
089F0B9F       03>add eax,edi                          ;  再加到上面的和
089F0BA1   |.  8B>|mov edi,ebx
089F0BA3   |.  C1>|shr edi,5                           ;  后4位再右移5
089F0BA6   |.  33>|xor edi,esi                         ;  后4位再右移5与固定值XOR
089F0BA8       03>add eax,edi                          ;  再加上取
089F0BAA       03>add eax,dword ptr ds:[ecx+4]         ;  加上固定字符串的5到8位   2C61682E
089F0BAD   |.  8B>|mov edi,eax
089F0BAF   |.  C1>|shl edi,4                           ;  得到的结果左移4
089F0BB2       03>add ebx,edi                          ;  加上后4位
089F0BB4       8B>mov edi,dword ptr ds:[ecx+8]         ;  再取固定字符串的ASCII20756F59
089F0BB7   |.  33>|xor edi,eax                         ;  固定字符串的ASCII码与计算好的EAXXOR
089F0BB9       03>add ebx,edi                          ;  结果加在EBX上 改变EBX
089F0BBB   |.  8B>|mov edi,eax
089F0BBD   |.  C1>|shr edi,5                           ;  把上面计算好的EAX右移5位
089F0BC0   |.  33>|xor edi,esi                         ;  结果与9E3779B9累加(每次这个数加自己)XOR
089F0BC2       03>add ebx,edi                          ;  计算的结果加在EBX上
089F0BC4       03>add ebx,dword ptr ds:[ecx+C]         ;  EBX再加上固定字符串的ASCII20657261
089F0BC7   |.  85>|test edx,edx
089F0BC9   |.^ 77>\ja short Hrms.089F0B8D
089F0BCB   |.  8B>mov edx,dword ptr ss:[esp]
089F0BCE   |.  89>mov dword ptr ds:[edx],eax           ;  储存了上面计算结果一半
089F0BD0   |.  8B>mov eax,dword ptr ss:[esp]
089F0BD3   |.  89>mov dword ptr ds:[eax+4],ebx         ;  储存了上面计算结果
089F0BD6   |.  5A pop edx
089F0BD7   |.  5F pop edi
089F0BD8   |.  5E pop esi
089F0BD9   |.  5B pop ebx
089F0BDA   \.  C3 retn
 

此函数是可逆的!!也可以直接在OD中改代码达到目的!循环32次!
……………………………………………………………………………………………………………………
进入处理注册码1、2的地方 注册码3、4同一个函数!,089F0D2D   |.  E8>call Hrms.089F0AB0  ; \关键点2  进入  
……………………………………………………………………………………………………………………
089F0AB9   |.  C7>mov dword ptr ss:[ebp-8],1
089F0AC0   |.  C7>mov dword ptr ss:[ebp-4],0
089F0AC7   |.  E9>jmp Hrms.089F0B4C
089F0ACC   |>  6A>/push 0
089F0ACE   |.  6A>|push 2
089F0AD0   |.  8B>|mov eax,dword ptr ss:[ebp+10]       ;  参数之一 最初3F17DC15 以后的值已经修改
089F0AD3   |.  8B>|mov edx,dword ptr ss:[ebp+14]       ;  参数之2  最初为0
089F0AD6   |.  E8>|call Hrms.087978A5                  ;  得到了EAX除以2的余数
089F0ADB   |.  83>|cmp edx,0                           ;  固定不为0
089F0ADE   |.  75>|jnz short Hrms.089F0B1B
089F0AE0   |.  83>|cmp eax,0
089F0AE3   |.  75>|jnz short Hrms.089F0B1B             ;  余数不为0 就跳,就是说奇数就跳另一种计算
089F0AE5   |.  6A>|push 0                              ;  偶数到这里  压入0
089F0AE7   |.  6A>|push 2                              ;  压入2
089F0AE9   |.  8B>|mov eax,dword ptr ss:[ebp+10]       ;  又得到参数3F17DC14
089F0AEC   |.  8B>|mov edx,dword ptr ss:[ebp+14]       ;  0
089F0AEF   |.  E8>|call Hrms.087977B2                  ;  得到3F17DC14除以2的商
089F0AF4   |.  89>|mov dword ptr ss:[ebp+10],eax       ;  得到3F17DC14除以2的商保存在原来覆盖
089F0AF7   |.  89>|mov dword ptr ss:[ebp+14],edx       ;  必为0
089F0AFA   |.  FF>|push dword ptr ss:[ebp+1C]          ; /Arg6
089F0AFD   |.  FF>|push dword ptr ss:[ebp+18]          ; |Arg5
089F0B00   |.  FF>|push dword ptr ss:[ebp+1C]          ; |Arg4
089F0B03   |.  FF>|push dword ptr ss:[ebp+18]          ; |Arg3
089F0B06   |.  FF>|push dword ptr ss:[ebp+C]           ; |Arg2
089F0B09   |.  FF>|push dword ptr ss:[ebp+8]           ; |Arg1
089F0B0C   |.  8B>|mov eax,ebx                         ; |
089F0B0E   |.  E8>|call Hrms.089F0A58                  ; \这个CALL就是为了改变EBP+18和EBP+1C
089F0B13   |.  89>|mov dword ptr ss:[ebp+18],eax
089F0B16   |.  89>|mov dword ptr ss:[ebp+1C],edx
089F0B19   |.  EB>|jmp short Hrms.089F0B4C
089F0B1B   |>  8B>|mov eax,dword ptr ss:[ebp+10]       ;  再次得到参数之一 最初3F17DC15
089F0B1E   |.  8B>|mov edx,dword ptr ss:[ebp+14]       ;  参数之2  最初为0
089F0B21   |.  83>|sub eax,1                           ;  减1 变成了偶数
089F0B24   |.  83>|sbb edx,0
089F0B27   |.  89>|mov dword ptr ss:[ebp+10],eax       ;  储存刚才被减1后的参数3F17DC14偶数了
089F0B2A   |.  89>|mov dword ptr ss:[ebp+14],edx       ;  还是0
089F0B2D   |.  FF>|push dword ptr ss:[ebp+1C]          ; /Arg6
089F0B30   |.  FF>|push dword ptr ss:[ebp+18]          ; |我的前两位输入码开始为11112222
089F0B33   |.  FF>|push dword ptr ss:[ebp-4]           ; |Arg4
089F0B36   |.  FF>|push dword ptr ss:[ebp-8]           ; |第一次是上面05290AB9压入的1  此后固定为11112222
089F0B39   |.  FF>|push dword ptr ss:[ebp+C]           ; |参数0
089F0B3C   |.  FF>|push dword ptr ss:[ebp+8]           ; |参数758F0581
089F0B3F   |.  8B>|mov eax,ebx                         ; |
089F0B41   |.  E8>|call Hrms.089F0A58                  ; \Hrms.08A50A58
089F0B46   |.  89>|mov dword ptr ss:[ebp-8],eax        ;  用相乘的结果覆盖了第一次EBP-8固定值1
089F0B49   |.  89>|mov dword ptr ss:[ebp-4],edx        ;  
089F0B4C   |>  83> cmp dword ptr ss:[ebp+14],0         ;  压入参数的地方,第一次为0
089F0B50   |.  75>|jnz short Hrms.089F0B5E
089F0B52   |.  83>|cmp dword ptr ss:[ebp+10],0         ;  第2个参数 是052B8C88地址处的值不为0
089F0B56   |.^ 0F>|ja Hrms.089F0ACC                    ;  大于0
089F0B5C   |.  EB>|jmp short Hrms.089F0B64
089F0B5E   |>^ 0F>\jg Hrms.089F0ACC
………………………………………………………………………………………………………………………………
这里处理注册码的函数中总共包含两个不同算法(依赖与固定值参数初始值0x3F17DC15):
每次固定值除以2如果没有余数(也就是偶数)并把固定值除以2覆盖原来:
输入的注册码(合并后)乘以自己(也就是平方),然后再进行循环处理,
如果固定值除以2没有余数(也就是奇数)则固定值-1:
输入的注册码(合并后)乘以上一次这里计算出来的值,然后再进行循环处理
这里的乘法要涉及到大数相乘。!

………………………………………………………………………………………………………………………………
再进入上面算法的call Hrms.089F0A58 
……………………………………………………………………………………
089F0A58   /$  55 push ebp
089F0A59   |.  8B>mov ebp,esp
089F0A5B   |.  83>add esp,-10
089F0A5E   |.  8B>mov eax,dword ptr ss:[ebp+18]        ;  得到我的输入码
089F0A61   |.  89>mov dword ptr ss:[ebp-10],eax        ;  储存
089F0A64   |.  8B>mov eax,dword ptr ss:[ebp+1C]
089F0A67   |.  89>mov dword ptr ss:[ebp-C],eax
089F0A6A   |.  FF>push dword ptr ss:[ebp+14]
089F0A6D   |.  FF>push dword ptr ss:[ebp+10]           ;  第一次为1
089F0A70   |.  8B>mov eax,dword ptr ss:[ebp-10]
089F0A73   |.  8B>mov edx,dword ptr ss:[ebp-C]         ;  0
089F0A76   |.  E8>call Hrms.0879776C                   ;  是相乘的函数(大数相乘)EAX中放积,EDX中放相乘的进位
089F0A7B   |.  89>mov dword ptr ss:[ebp-10],eax        ;  相乘的结果储存覆盖原来的
089F0A7E   |.  89>mov dword ptr ss:[ebp-C],edx         ;  如果数据过大 相乘超过了8位,则进位
089F0A81   |.  FF>push dword ptr ss:[ebp+C]            ;  0
089F0A84   |.  FF>push dword ptr ss:[ebp+8]            ;  得到另一个参数758F0581
089F0A87   |.  8B>mov eax,dword ptr ss:[ebp-10]        ;  得到相乘的结果
089F0A8A   |.  8B>mov edx,dword ptr ss:[ebp-C]         ;  进位的 数据
089F0A8D   |.  E8>call Hrms.087978A5                   ;  这里可能要进行循环(如果上面的大数相乘有进位的话)
089F0A92   |.  89>mov dword ptr ss:[ebp-10],eax
089F0A95   |.  89>mov dword ptr ss:[ebp-C],edx
089F0A98   |.  8B>mov eax,dword ptr ss:[ebp-10]
089F0A9B   |.  89>mov dword ptr ss:[ebp-8],eax
089F0A9E   |.  8B>mov eax,dword ptr ss:[ebp-C]
089F0AA1   |.  89>mov dword ptr ss:[ebp-4],eax
089F0AA4   |.  8B>mov eax,dword ptr ss:[ebp-8]         ;  取出循环的结果
089F0AA7   |.  8B>mov edx,dword ptr ss:[ebp-4]         ;  取出循环的结果
089F0AAA   |.  8B>mov esp,ebp
089F0AAC   |.  5D pop ebp
089F0AAD   \.  C2>retn 18
………………………………………………………………………………………………………………………………
上面循环的CALL
……………………………………………………………………………………………………………………

087978A5   /$  55 push ebp
087978A6   |.  53 push ebx
087978A7   |.  56 push esi
087978A8   |.  57 push edi
087978A9   |.  33>xor edi,edi
087978AB   |.  8B>mov ebx,dword ptr ss:[esp+14]        ;  固定值758F0581
087978AF   |.  8B>mov ecx,dword ptr ss:[esp+18]        ;  固定值0
087978B3   |.  0B>or ecx,ecx
087978B5   |.  75>jnz short Hrms.087978BF              ;  ECX必为0   此必不跳
087978B7   |.  0B>or edx,edx                           ;  也就是进位
087978B9   |.  74>je short Hrms.08797918               ;  进位为0 就跳   第一次不跳它乘以1
087978BB   |.  0B>or ebx,ebx
087978BD   |.  74>je short Hrms.08797918
087978BF   |>  0B>or edx,edx
087978C1   |.  79>jns short Hrms.087978CD
087978C3   |.  F7>neg edx                              ;  这里必不经过
087978C5   |.  F7>neg eax                              ;  这里必不经过
087978C7   |.  83>sbb edx,0                            ;  这里必不经过
087978CA   |.  83>or edi,1                             ;  这里必不经过
087978CD   |>  0B>or ecx,ecx
087978CF   |.  79>jns short Hrms.087978D8
087978D1   |.  F7>neg ecx                              ;  这里必不经过
087978D3   |.  F7>neg ebx                              ;  这里必不经过
087978D5   |.  83>sbb ecx,0                            ;  这里必不经过
087978D8   |>  8B>mov ebp,ecx
087978DA   |.  B9>mov ecx,40                           ;  循环64次
087978DF   |.  57 push edi                             ;  必为0
087978E0   |.  33>xor edi,edi
087978E2   |.  33>xor esi,esi
087978E4   |>  D1>/shl eax,1                           ;  乘以2   11110C84
087978E6   |.  D1>|rcl edx,1                           ;  乘以2加1  012347AE(是否加1依赖余是否有进位标志位C)
087978E8   |.  D1>|rcl esi,1                           ;  开始都是0 后来会变成1 当EDX RCL有进位时,此时ESI加1
087978EA   |.  D1>|rcl edi,1                           ;  EDI必等于0 不可能等于1 因为上面不可能有进位
087978EC   |.  3B>|cmp edi,ebp                         ;  EDI与0 比较
087978EE   |.  72>|jb short Hrms.087978FB
087978F0   |.  77>|ja short Hrms.087978F6
087978F2   |.  3B>|cmp esi,ebx                         ;  ESI与固定值758F0581比较
087978F4   |.  72>|jb short Hrms.087978FB              ;  小于则跳过
087978F6   |>  2B>|sub esi,ebx                         ;  当ESI超过固定值758F0581时,就减去758F0581
087978F8   |.  1B>|sbb edi,ebp
087978FA   |.  40 |inc eax                             ;  EAX加1
087978FB   |>^ E2>\loopd short Hrms.087978E4
087978FD   |.  8B>mov eax,esi
087978FF   |.  8B>mov edx,edi
08797901   |.  5B pop ebx                              ;  必为0
08797902   |.  F7>test ebx,1
08797908   |.  74>je short Hrms.08797911               ;  必跳
0879790A   |.  F7>neg edx                              ;  这里必不经过
0879790C   |.  F7>neg eax                              ;  这里必不经过
0879790E   |.  83>sbb edx,0                            ;  这里必不经过
08797911   |>  5F pop edi
08797912   |.  5E pop esi
08797913   |.  5B pop ebx
08797914   |.  5D pop ebp
08797915   |.  C2>retn 8
08797918   |>  F7>div ebx                              ;  如果进位为0把固定值3F17DC15除以2
0879791A   |.  92 xchg eax,edx                         ;  交换EAX与EDX  为了得到余数
0879791B   |.  33>xor edx,edx                          ;  把商清零
0879791D   \.^ EB>jmp short Hrms.08797911
…………………………………………………………………………………………………………………………
发现处理注册码的函数不可逆!函数出来后到了这里:比较终端数目!
…………………………………………………………………………………………………………………………
08A0A416    .  85>test eax,eax
08A0A418    .  75>jnz short Hrms.08A0A448              ;  如果EAX等于0 就错误
08A0A41A    .  6A>push 10
08A0A41C    .  B9>mov ecx,Hrms.08A0A610
08A0A421    .  BA>mov edx,Hrms.08A0A624
08A0A426    .  A1>mov eax,dword ptr ds:[8A19470]
08A0A42B    .  8B>mov eax,dword ptr ds:[eax]
08A0A42D    .  E8>call Hrms.087E7400                   ;  错误窗口!
08A0A432    .  8B>mov eax,dword ptr ss:[ebp-4]
……………………省略……………………
08A0A454    .  E8>call Hrms.087C7A28                   ;  得到输入的终端数 返回位数
08A0A459    .  8B>mov eax,dword ptr ss:[ebp-30]
08A0A45C    .  8D>lea edx,dword ptr ss:[ebp-2C]
08A0A45F    .  E8>call Hrms.08799DE4
08A0A464    .  83>cmp dword ptr ss:[ebp-2C],0          ;  比较看有没有输入数据
08A0A468    .  74>je short Hrms.08A0A48B
08A0A46A    .  8D>lea edx,dword ptr ss:[ebp-34]
08A0A46D    .  8B>mov eax,dword ptr ss:[ebp-4]
08A0A470    .  8B>mov eax,dword ptr ds:[eax+2FC]
08A0A476    .  E8>call Hrms.087C7A28                   ;  得到输入的终端数 返回位数
08A0A47B    .  8B>mov eax,dword ptr ss:[ebp-34]
08A0A47E    .  E8>call Hrms.0879A138                   ;  将终端数转化为16进制数
08A0A483    .  0F>movzx edx,word ptr ss:[ebp-E]        ;  取前面计算出来的结果2的16进制后4位
08A0A487    .  3B>cmp eax,edx                          ;  与输入的终端数比较
08A0A489    .  74>je short Hrms.08A0A4B9
…………………………………………………………………………………………………………………………
由上面可以知道只能逆转处理序列号的函数了,这里发现可以直接在OD中逆循环只要改变一下代码
如果你已经到了089F0D80   |.  3B>cmp eax,dword ptr ss:[ebp-20]        ;  比较   用注册码双精度数右移后的结果与序列号处理后的结果比较
看到了处理序列号的应该的值,就可以逆转了   修改代码:089F0B74   /$  53 push ebx段的代码:
…………………………………………………………………………………………………………………………
08BA0B8D   |> /4A /dec edx                           ;  
08BA0B8E      |2B>sub esi,dword ptr ds:[8BC8C84]     ;  注意这里走过这个代码后修改把ESI改成C6EF3720
08BA0B94      |8B>mov edi,ebx
08BA0B96   |. |C1>|shl edi,4                         ;  
08BA0B99      |2B>sub eax,edi                        ;  
08BA0B9B   |. |8B>|mov edi,dword ptr ds:[ecx]        ;  
08BA0B9D   |. |33>|xor edi,ebx                       ;  
08BA0B9F      |2B>sub eax,edi                        ;  
08BA0BA1   |. |8B>|mov edi,ebx
08BA0BA3   |. |C1>|shr edi,5                         ;  
08BA0BA6   |. |33>|xor edi,esi                       ;  
08BA0BA8      |2B>sub eax,edi                        ;  
08BA0BAA      |2B>sub eax,dword ptr ds:[ecx+4]       ;  
08BA0BAD   |. |8B>|mov edi,eax
08BA0BAF   |. |C1>|shl edi,4                         ;  
08BA0BB2      |2B>sub ebx,edi                        ;  
08BA0BB4      |8B>mov edi,dword ptr ds:[ecx+8]       ;  
08BA0BB7   |. |33>|xor edi,eax
08BA0BB9      |2B>sub ebx,edi
08BA0BBB   |. |8B>|mov edi,eax
08BA0BBD   |. |C1>|shr edi,5
08BA0BC0   |. |33>|xor edi,esi
08BA0BC2      |2B>sub ebx,edi
08BA0BC4      |2B>sub ebx,dword ptr ds:[ecx+C]
08BA0BC7   |. |85>|test edx,edx
08BA0BC9   |.^\77>\ja short Hrms.08BA0B8D
08BA0BCB   |.  8B>mov edx,dword ptr ss:[esp]


也就是把加改成减,而且把最后要进行比较的值放在EBX中,EAX中的数据随便填。
并把计算的参数前八位与后8位交换变成:
59 6F 75 20 61 72 65 20  You are
48 61 2E 2E 2E 68 61 2C  Ha...ha,
66 61 74 20 70 69 67 21  fat pig!
当然最后的结果要稍微处理一下。
………………………………………………………………………………………………………………
附注册程序代码:


unsigned long int xiangx(shuru,b,p)
unsigned long int shuru,b,*p;
{
unsigned long int jie[8],c,d,e=0xffffffff,jinwei=0,qian8=0,i,g,j,k,h,hou8;
static long int a[8];
unsigned static long int carry[8];

for(i=1;i<=8;i++)
{
k=shuru<<(32-i*4);
k=k>>(32-i*4);
a[8-i]=k>>((i-1)*4);
}

for(i=0;i<8;i++)
{
h=b;
jinwei=0;
for(j=1;j<a[7-i];j++)
{
if((e-h)<=b)
{jinwei++;
h=h+b;
}
else
h=h+b;
}
d=jinwei;
carry[i]=d;
jie[i]=b*a[7-i];
}

for(i=1;i<8;i++)
{
carry[i]=carry[i]<<(i*4);
g=jie[i]>>(32-i*4);
carry[i]=carry[i]|g;
}

for(i=0;i<8;i++)
{qian8=qian8+carry[i]; }

jinwei=0;
for(i=1;i<8;i++)
{
if((e-jie[0])<=(jie[i]<<(4*i)))
{
jinwei++;
jie[0]=jie[0]+(jie[i]<<(4*i));
}
else
jie[0]=jie[0]+(jie[i]<<(4*i));
}
qian8=qian8+jinwei;
hou8=jie[0];
*p=qian8;
return(hou8);
}



unsigned long int chuli2(jie,jinwei,gud)
unsigned long int jie,jinwei,gud;
{
unsigned long int jieguo=0,i,e=0xffffffff,c;
if(jinwei==0)
jieguo=jie%gud;
else
{
  for(i=64;i>0;i--)
 {
    if((e-jie)<=jie)
   {c=1;
   jie=jie+jie;
   }
   else
   {c=0;
   jie=jie+jie;
   }

   if((e-jinwei)<=jinwei)
   {
   jinwei=2*jinwei+c;
   c=1;
   }
   else
   {
   jinwei=2*jinwei+c;
   c=0;
   }

   jieguo=2*jieguo+c;

   if(jieguo>gud)
   {
   jieguo=jieguo-gud;
   jie++;
   }
 }

}
return(jieguo);

}


unsigned long int fun(x,y,z)
unsigned long int x,y,z;
{
unsigned long int jie,jinwei,*p=&jinwei,jieguo;
jie=xiangx(x,y,p);
jieguo=chuli2(jie,jinwei,z);
return(jieguo);
}



unsigned long int zong(shuru)
unsigned long int shuru;
{
unsigned long int xunh=0x3f17dc15,gud=0x758f0581,bchenji=1;

for(;xunh>0;)
{
if((xunh%2)==0)
{xunh=xunh/2;
shuru=fun(shuru,shuru,gud);

}
else
{
xunh--;
bchenji=fun(shuru,bchenji,gud);
}
}
return(bchenji);
}


unsigned long int xlh(qian4,hou4,p)
unsigned long int qian4,hou4,*p;
{
unsigned long int lei,guding1,guding2,guding3,guding4,guding5;
int i;
guding1=0x20756f59;
guding2=0x20657261;
guding3=0x2e2e6148;
guding4=0x2c61682e;
guding5=0x9e3779b9;
lei=0xC6EF3720;

for(i=0;i<0x20;i++)
{
hou4=hou4-(qian4<<4);
hou4=hou4-(qian4^guding1);
hou4=hou4-((qian4>>5)^lei);
hou4=hou4-guding2;

qian4=qian4-(hou4<<4);
qian4=qian4-(hou4^guding3);
qian4=qian4-((hou4>>5)^lei);
qian4=qian4-guding4;

lei=lei-guding5;

}
*p=hou4;
return(qian4);
}


unsigned long int jianpan(p)
unsigned long int *p;
{unsigned long int shuru1=0,shuru2=0;
int n,i,zj;
char zifu1[20],zifu2[20],zifu3[20],zifu4[20];
scanf("%s",zifu1);
scanf("%s",zifu2);
scanf("%s",zifu3);
scanf("%s",zifu4);
strcat(zifu1,zifu2);
strcat(zifu3,zifu4);
n=strlen(zifu1);
for(i=0;i<n;i++)
{
if((zifu1[i]>0x29)&(zifu1[i]<0x40))
{
zj=zifu1[i]-0x30;
shuru1=(shuru1<<4)|zj;
}
else if((zifu1[i]>0x40)&(zifu1[i]<0x47))
{
zj=zifu1[i]-0x37;
shuru1=(shuru1<<4)|zj;
}
else if((zifu1[i]>0x60)&(zifu1[i]<0x67))
{
zj=zifu1[i]-0x57;
shuru1=(shuru1<<4)|zj;
}
else
{
shuru1=0;
break;
}
}


n=strlen(zifu3);
for(i=0;i<n;i++)
{
if((zifu3[i]>0x29)&(zifu3[i]<0x40))
{
zj=zifu3[i]-0x30;
shuru2=(shuru2<<4)|zj;
}
else if((zifu3[i]>0x40)&(zifu3[i]<0x47))
{
zj=zifu3[i]-0x37;
shuru2=(shuru2<<4)|zj;
}
else if((zifu3[i]>0x60)&(zifu3[i]<0x67))
{
zj=zifu3[i]-0x57;
shuru2=(shuru2<<4)|zj;
}
else
{
shuru2=0;
break;
}
}

*p=shuru2;
return(shuru1);
}



main()
{
unsigned long int shuru1,shuru2,jieguo1,jieguo2,f=0x0000000f,d,xulihao1,xulihao2,*p=&xulihao2,b;
unsigned long int g=0x000000ff,h=0x0000ff00,i=0x00ff0000,j=0xff000000,zhduan,k=0x0000ffff,shu[4];
unsigned long int *zhizhen=&shuru2;
char ascii[12];
int a;
shuru1=jianpan(zhizhen);
b=0x235678;
jieguo1=zong(shuru1);
jieguo2=zong(shuru2);
jieguo1=jieguo1-2;
jieguo2=jieguo2-2;
jieguo1=jieguo1<<2;
jieguo1=jieguo1>>2;
d=f&jieguo2;
d=d<<2;
d=d&f;
d=d<<28;
jieguo1=jieguo1+d;
jieguo2=jieguo2>>2;
zhduan=jieguo2&k;
for(a=0;a<200;a++)
{
xulihao1=xlh(jieguo1,b,p);
ascii[0]=xulihao1&g;
ascii[1]=(xulihao1&h)>>8;
ascii[2]=(xulihao1&i)>>16;
ascii[3]=(xulihao1&j)>>24;
ascii[4]=xulihao2&g;
ascii[5]=(xulihao2&h)>>8;
ascii[6]=(xulihao2&i)>>16;
ascii[7]=(xulihao2&j)>>24;
ascii[8]='\0';
ascii[9]='\0';
ascii[10]='\0';
ascii[11]='\0';
printf("%s\n",ascii);
b++;
}
printf("zhong duan shu mu:");
printf("%d\n",zhduan);
}

输入4个注册码;
里面有200个序列号可选择,但有些没有用,
因为字符无法显示,也就无法输入,自己选择一下,最后的数据就是终端数目。