【文章标题】: 海天屏幕广播 算法分析 + 注册机代码
【文章作者】: Here
【作者邮箱】: Here.Zhou@gmail.com
【软件名称】: 海天屏幕广播 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,"烂鎈xxx/xxx/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 [ebp+128]            ; |
  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 [esi]
  00402B72   .  57            push    edi
  00402B73   .  51            push    ecx
  00402B74   .  E8 77F8FFFF   call    004023F0
  00402B79   .  8945 74       mov     dword ptr [ebp+74], eax
  00402B7C   .  8B15 28E74000 mov     edx, dword ptr [40E728]
  00402B82   .  8B3D 2CE74000 mov     edi, dword ptr [40E72C]
  00402B88   .  A1 30E74000   mov     eax, dword ptr [40E730]
  00402B8D   .  83C4 08       add     esp, 8
  00402B90   .  894424 18     mov     dword ptr [esp+18], eax
  00402B94   .  A1 50E74000   mov     eax, dword ptr [40E750]
  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 [esp+14], edx
  00402BA7   .  74 11         je      short 00402BBA
  00402BA9   .  C74424 1C 010>mov     dword ptr [esp+1C], 1
  00402BB1   .  8B48 20       mov     ecx, dword ptr [eax+20]
  00402BB4   .  894C24 20     mov     dword ptr [esp+20], ecx
  00402BB8   .  EB 08         jmp     short 00402BC2
  00402BBA   >  897C24 1C     mov     dword ptr [esp+1C], edi
  00402BBE   .  897C24 20     mov     dword ptr [esp+20], edi
  00402BC2   >  8B15 3CE74000 mov     edx, dword ptr [40E73C]
  00402BC8   .  8D4424 14     lea     eax, dword ptr [esp+14]
  00402BCC   .  50            push    eax
  00402BCD   .  895424 28     mov     dword ptr [esp+28], 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 [40E744]
  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 [esi]
  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 [ebp+78], eax
  00402C0D   .  5B            pop     ebx
  00402C0E   .  75 31         jnz     short 00402C41                      ;  注册成功则跳
  00402C10   .  8D4424 7C     lea     eax, dword ptr [esp+7C]
  00402C14   .  66:893D 4CE74>mov     word ptr [40E74C], di
  00402C1B   .  A3 48E74000   mov     dword ptr [40E748], eax
  ---------------------------------------------------------------------------------------------------
  下面代码略
  ====================================================================================================
  
  
  【关键CALL代码】
  ---------------------------------------------------------------------------------------------------
  00402740  /$  8B4C24 04     mov     ecx, dword ptr [esp+4]              ;  ecx=机器码
  00402744  |.  64:A1 0000000>mov     eax, dword ptr fs:[0]
  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:[0], 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 [esp+1C]             ;  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 [esp+18]
  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 [esp+1C]
  0040279D  |.  68 00D24000   push    0040D200                            ;  ASCII "%u"
  004027A2  |.  50            push    eax
  004027A3  |.  C74424 1C 000>mov     dword ptr [esp+1C], 0
  004027AB  |.  E8 1C750000   call    <jmp.&MFC42.#2818_CString::Format>  ;  esi值格式化
  004027B0  |.  83C4 0C       add     esp, 0C
  004027B3  |.  8D4C24 1C     lea     ecx, dword ptr [esp+1C]
  004027B7  |.  6A 08         push    8
  004027B9  |.  51            push    ecx
  004027BA  |.  8D4C24 20     lea     ecx, dword ptr [esp+20]
  004027BE  |.  E8 55740000   call    <jmp.&MFC42.#4129_CString::Left>    ;  取左边8位作为注册码
  004027C3  |.  50            push    eax
  004027C4  |.  8D4C24 1C     lea     ecx, dword ptr [esp+1C]
  004027C8  |.  C64424 14 01  mov     byte ptr [esp+14], 1
  004027CD  |.  E8 40740000   call    <jmp.&MFC42.#858_CString:perator=>
  004027D2  |.  8D4C24 1C     lea     ecx, dword ptr [esp+1C]
  004027D6  |.  C64424 10 00  mov     byte ptr [esp+10], 0
  004027DB  |.  E8 DE730000   call    <jmp.&MFC42.#800_CString::~CString>
  004027E0  |.  8B5424 18     mov     edx, dword ptr [esp+18]
  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 [esp+18]
  004027F6  |.  C74424 10 FFF>mov     dword ptr [esp+10], -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 [esp+8]
  0040280C  |.  64:890D 00000>mov     dword ptr fs:[0], 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 [esp+18]
  00402822  |.  F7E7          mul     edi
  00402824  |.  D1EA          shr     edx, 1
  00402826  |.  C74424 10 FFF>mov     dword ptr [esp+10], -1
  0040282E  |.  8D42 03       lea     eax, dword ptr [edx+3]
  00402831  |.  3BC2          cmp     eax, edx
  00402833  |.  E8 86730000   call    <jmp.&MFC42.#800_CString::~CString>
  00402838  |>  8B4C24 08     mov     ecx, dword ptr [esp+8]
  0040283C  |.  5F            pop     edi
  0040283D  |.  33C0          xor     eax, eax                            ;  eax=0
  0040283F  |.  64:890D 00000>mov     dword ptr fs:[0], 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);                       // 真正注册码
  
  ====================================================================================================
  
  好,就分析到这里。文章可能有很多错误的地方,敬请见谅。并给予指出问题。
  
--------------------------------------------------------------------------------
【经验总结】
  算法分析还是从简单的开始分析好,不然对自己的信心会大大打击。