JackyChou 发表于 2008-9-27 22:24:40

海天屏幕广播 算法分析 + 注册机代码

【文章标题】: 海天屏幕广播 算法分析 + 注册机代码
【文章作者】: JackyChou
【作者邮箱】: [email protected]
【软件名称】: 海天屏幕广播 V4.1
【软件大小】: 76K
【下载地址】: 自己搜索下载
【加壳方式】: 无壳
【保护方式】: 算法保护
【编写语言】: VC
【使用工具】: OD、PEID
【操作平台】: XP SP2正版
【软件介绍】: 海天屏幕广播软件是将局域网内一台电脑的屏幕画面广播到其他电脑上的软件,采用虚拟显示驱动,实时性好,CPU占用低,在局域网内能取得很好的效果。可以直接广播视频画面。本软件为绿色软件,仅服务端需要安装一个虚拟显示驱动程序,无需设置,操作简单。同时具备语音广播,远程锁定,短消息,电子教鞭,远程关机等功能,可应用于学校,企事业单位教学,培训,演示等场合。
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
      前段时间由于项目问题以及杂七杂八的事情,没有什么时间学习算法分析。不过本人算法分析也是相当的菜,难的还
在学习当中,正好遇到一个简单的算法程序,拿来和大家一起分享。网上也好像有内存注册机,不过注册码不对。

      算法关键位置查找过程:
1、运行程序,点击【注册】菜单。
   注册对话框信息:机器码为【1551133666】。

   随便输入注册码【123456】,点击【注册(R)】按钮,没有任何反应。不过程序文件夹内,产生一个文件【sset.ini】。
打开一看,发现注册码是存放在这个文件内的。(regnum=123456)。
   尝试了几次,都没有任何提示,所以软件可能是重启验证的。后来发现,如果软件提示注册成功,其实是假注册成功
现象。真正注册成功是没有任何提示,并且软件重新启动才验证的。成功注册后,菜单中不会再出现【注册】菜单项目了。

2、对于INI小型文件,一般用API函数【GetPrivateProfileStringA】进行读取的。如果文件超大,最好自己进行解析。
因为这个API会重复进行文件的打开和关闭,效率较低。
   OD载入程序,下断GetPrivateProfileStringA,运行F9。当进行项【regnum】读取时,去除断点,Alt + F9返回。
【返回代码】
---------------------------------------------------------------------------------------------------
00402B41   .50            push    eax                                 ; /IniFileName => "C:\Documents and Settings\zhoujq\",D7,"烂鎈**\**\sset.ini"
00402B42   .6A 00         push    0                                 ; |Default = 0
00402B44   .68 28D34000   push    0040D328                            ; |Key = "regnum"
00402B49   .68 20D34000   push    0040D320                            ; |Section = "setting"
00402B4E   .FFD3          call    ebx                                 ; \GetPrivateProfileIntA
00402B50   .6A 00         push    0                                 ; /pFileSystemNameSize = NULL
00402B52   .6A 00         push    0                                 ; |pFileSystemNameBuffer = NULL
00402B54   .8DB5 28010000 lea   esi, dword ptr             ; |
00402B5A   .6A 00         push    0                                 ; |pFileSystemFlags = NULL
00402B5C   .6A 00         push    0                                 ; |pMaxFilenameLength = NULL
00402B5E   .56            push    esi                                 ; |pVolumeSerialNumber
00402B5F   .6A 00         push    0                                 ; |MaxVolumeNameSize = 0
00402B61   .6A 00         push    0                                 ; |VolumeNameBuffer = NULL
00402B63   .68 1CD34000   push    0040D31C                            ; |RootPathName = "c:\"
00402B68   .8BF8          mov   edi, eax                            ; |
00402B6A   .FF15 48B04000 call    dword ptr [<&KERNEL32.GetVolumeInfo>; \GetVolumeInformationA
00402B70   .8B0E          mov   ecx, dword ptr
00402B72   .57            push    edi
00402B73   .51            push    ecx
00402B74   .E8 77F8FFFF   call    004023F0
00402B79   .8945 74       mov   dword ptr , eax
00402B7C   .8B15 28E74000 mov   edx, dword ptr
00402B82   .8B3D 2CE74000 mov   edi, dword ptr
00402B88   .A1 30E74000   mov   eax, dword ptr
00402B8D   .83C4 08       add   esp, 8
00402B90   .894424 18   mov   dword ptr , eax
00402B94   .A1 50E74000   mov   eax, dword ptr
00402B99   .F7DA          neg   edx
00402B9B   .1BD2          sbb   edx, edx
00402B9D   .23D7          and   edx, edi
00402B9F   .33FF          xor   edi, edi
00402BA1   .3BC7          cmp   eax, edi
00402BA3   .895424 14   mov   dword ptr , edx
00402BA7   .74 11         je      short 00402BBA
00402BA9   .C74424 1C 010>mov   dword ptr , 1
00402BB1   .8B48 20       mov   ecx, dword ptr
00402BB4   .894C24 20   mov   dword ptr , ecx
00402BB8   .EB 08         jmp   short 00402BC2
00402BBA   >897C24 1C   mov   dword ptr , edi
00402BBE   .897C24 20   mov   dword ptr , edi
00402BC2   >8B15 3CE74000 mov   edx, dword ptr
00402BC8   .8D4424 14   lea   eax, dword ptr
00402BCC   .50            push    eax
00402BCD   .895424 28   mov   dword ptr , edx
00402BD1   .E8 54740000   call    <jmp.&HTSAPI.#1>
00402BD6   .3BC7          cmp   eax, edi
00402BD8   .74 0E         je      short 00402BE8
00402BDA   .50            push    eax
00402BDB   .68 0CD34000   push    0040D30C
00402BE0   .E8 1BF9FFFF   call    00402500
00402BE5   .83C4 08       add   esp, 8
00402BE8   >8B0D 44E74000 mov   ecx, dword ptr
00402BEE   .51            push    ecx
00402BEF   .57            push    edi
00402BF0   .68 28D34000   push    0040D328                            ;ASCII "regnum"
00402BF5   .68 20D34000   push    0040D320                            ;ASCII "setting"
00402BFA   .FFD3          call    ebx                                 ;eax=假码
00402BFC   .8B16          mov   edx, dword ptr
00402BFE   .50            push    eax                                 ;假码
00402BFF   .52            push    edx                                 ;机器码
00402C00   .E8 3BFBFFFF   call    00402740                            ;这边出现正码
00402C05   .83C4 08       add   esp, 8
00402C08   .3BC7          cmp   eax, edi
00402C0A   .8945 78       mov   dword ptr , eax
00402C0D   .5B            pop   ebx
00402C0E   .75 31         jnz   short 00402C41                      ;注册成功则跳
00402C10   .8D4424 7C   lea   eax, dword ptr
00402C14   .66:893D 4CE74>mov   word ptr , di
00402C1B   .A3 48E74000   mov   dword ptr , eax
---------------------------------------------------------------------------------------------------
下面代码略
====================================================================================================


【关键CALL代码】
---------------------------------------------------------------------------------------------------
00402740/$8B4C24 04   mov   ecx, dword ptr             ;ecx=机器码
00402744|.64:A1 0000000>mov   eax, dword ptr fs:
0040274A|.69C9 096EBA02 imul    ecx, ecx, 2BA6E09                   ;ecx=ecx*0x2BA6E09
00402750|.6A FF         push    -1
00402752|.68 00A34000   push    0040A300
00402757|.50            push    eax
00402758|.B8 25499224   mov   eax, 24924925                     ;eax=0x24924925
0040275D|.F7E1          mul   ecx                                 ;无符号乘eax*ecx->edx(高位)+eax(低位)
0040275F|.2BCA          sub   ecx, edx                            ;ecx=ecx -edx
00402761|.64:8925 00000>mov   dword ptr fs:, esp
00402768|.D1E9          shr   ecx, 1                              ;逻辑右移1位
0040276A|.03CA          add   ecx, edx                            ;ecx=ecx+edx
0040276C|.56            push    esi
0040276D|.C1E9 02       shr   ecx, 2                              ;逻辑右移2位
00402770|.8BC1          mov   eax, ecx                            ;eax = ecx
00402772|.57            push    edi
00402773|.69C0 FB3F9702 imul    eax, eax, 2973FFB                   ;eax=eax*0x2973FFB
00402779|.8B7C24 1C   mov   edi, dword ptr              ;edi=假码(123456)
0040277D|.F7D0          not   eax                                 ;eax取反
0040277F|.83C0 2F       add   eax, 2F                           ;eax=eax+0x2F
00402782|.3BC7          cmp   eax, edi
00402784|.0F84 AE000000 je      00402838                            ;如果跳则eax=0,因为后面xor eax,eax
0040278A|.8BF0          mov   esi, eax                            ;esi=eax
0040278C|.8D4C24 18   lea   ecx, dword ptr
00402790|.0FAFF0      imul    esi, eax                            ;esi=esi*eax
00402793|.E8 44740000   call    <jmp.&MFC42.#540_CString::CString>
00402798|.56            push    esi
00402799|.8D4424 1C   lea   eax, dword ptr
0040279D|.68 00D24000   push    0040D200                            ;ASCII "%u"
004027A2|.50            push    eax
004027A3|.C74424 1C 000>mov   dword ptr , 0
004027AB|.E8 1C750000   call    <jmp.&MFC42.#2818_CString::Format>;esi值格式化
004027B0|.83C4 0C       add   esp, 0C
004027B3|.8D4C24 1C   lea   ecx, dword ptr
004027B7|.6A 08         push    8
004027B9|.51            push    ecx
004027BA|.8D4C24 20   lea   ecx, dword ptr
004027BE|.E8 55740000   call    <jmp.&MFC42.#4129_CString::Left>    ;取左边8位作为注册码
004027C3|.50            push    eax
004027C4|.8D4C24 1C   lea   ecx, dword ptr
004027C8|.C64424 14 01mov   byte ptr , 1
004027CD|.E8 40740000   call    <jmp.&MFC42.#858_CString::operator=>
004027D2|.8D4C24 1C   lea   ecx, dword ptr
004027D6|.C64424 10 00mov   byte ptr , 0
004027DB|.E8 DE730000   call    <jmp.&MFC42.#800_CString::~CString>
004027E0|.8B5424 18   mov   edx, dword ptr
004027E4|.52            push    edx                                 ; /s
004027E5|.FF15 F0B24000 call    dword ptr [<&MSVCRT.atoi>]          ; \字符串到数值的转换
004027EB|.83C4 04       add   esp, 4
004027EE|.3BC7          cmp   eax, edi                            ;eax(真码)与输入码的比较
004027F0|.75 27         jnz   short 00402819                      ;跳,eax=0
004027F2|.8D4C24 18   lea   ecx, dword ptr
004027F6|.C74424 10 FFF>mov   dword ptr , -1
004027FE|.E8 BB730000   call    <jmp.&MFC42.#800_CString::~CString>
00402803|.B8 01000000   mov   eax, 1                              ;eax=1
00402808|.8B4C24 08   mov   ecx, dword ptr
0040280C|.64:890D 00000>mov   dword ptr fs:, ecx
00402813|.5F            pop   edi
00402814|.5E            pop   esi
00402815|.83C4 0C       add   esp, 0C
00402818|.C3            retn
00402819|>B8 398EE338   mov   eax, 38E38E39
0040281E|.8D4C24 18   lea   ecx, dword ptr
00402822|.F7E7          mul   edi
00402824|.D1EA          shr   edx, 1
00402826|.C74424 10 FFF>mov   dword ptr , -1
0040282E|.8D42 03       lea   eax, dword ptr
00402831|.3BC2          cmp   eax, edx
00402833|.E8 86730000   call    <jmp.&MFC42.#800_CString::~CString>
00402838|>8B4C24 08   mov   ecx, dword ptr
0040283C|.5F            pop   edi
0040283D|.33C0          xor   eax, eax                            ;eax=0
0040283F|.64:890D 00000>mov   dword ptr fs:, ecx
00402846|.5E            pop   esi
00402847|.83C4 0C       add   esp, 0C
0040284A\.C3            retn
---------------------------------------------------------------------------------------------------

通过关键CALL的分析,注册码的算法过程应该都明白了。


【注册机代码】
因为算法比较简单,所以用VC写代码时可以偷懒,直接可以嵌入ASM写代码
_asm
{
      mov ecx, dwMachine                        //机器码
      imul ecx, ecx, 0x2BA6E09
               
      xor edx, edx
      mov eax, 0x24924925
      mul ecx
               
      sub ecx, edx
      shr ecx, 1
      add ecx, edx
      shr ecx, 2
      mov eax, ecx
               
      imul eax, eax, 0x2973FFB
      not eax
      add eax, 0x2F
               
      xor edx, edx
      mov edx, eax
      imul edx, eax
               
      mov eax, edx
      mov dwOut, eax                        // 处理数据
}
   sKey.Format("%u", dwOut);
   sKey = sKey.Left(8);                     // 真正注册码

====================================================================================================

好,就分析到这里。文章可能有很多错误的地方,敬请见谅。并给予指出问题。

--------------------------------------------------------------------------------
【经验总结】
算法分析还是从简单的开始分析好,不然对自己的信心会大大打击。

--------------------------------------------------------------------------------
【版权声明】: 本文原创于飘云阁技术论坛, 转载请注明作者并保持文章的完整, 谢谢!

                                                       2008年09月27日 22:21:46

a13639875277 发表于 2008-9-28 10:58:37

学习了,支持一个,不过有些地方还是写的不清楚。

zsl01 发表于 2008-9-28 11:07:31

新手,学习一下,支持楼主。

jackzkm 发表于 2008-10-14 22:29:37

学习了,支持一个!谢谢楼主!

walili 发表于 2008-10-22 21:16:54

楼主强的一毛啊,佩服,不知道ecx=ecx*0x2BA6E09是什么意思是直接0x2BA6E09还是0x2BA6E09的值?

52computer 发表于 2008-10-28 23:22:38

学习了,支持一个!谢谢楼主

bhcjl 发表于 2008-10-29 16:48:07

好文章就得转/:017

939372735 发表于 2008-11-2 13:41:22

新手啊,看不懂,学习,懂了再回来看。
先顶。
页: [1]
查看完整版本: 海天屏幕广播 算法分析 + 注册机代码