LYQingYe 发表于 2015-8-26 20:28

算法分析第一课 -- 超级视频合并软件 算法分析 回帖有钱

本帖最后由 LYQingYe 于 2015-8-27 18:35 编辑

{:6_205:}几天没法教程,手痒痒。{:5_121:}因为是假期 13天 ,所以我打算弄一个算法分析系列教程。现在是第一课,希望能得到大家的支持。{:5_124:}一边分析一天写帖的,所以难免会有些错误,希望大家指出,共同学习进步。{:6_208:}教程我就不隐藏了,回帖有钱领哦。我发教程只为共同学习不为什么,只求大家热心回复。中奖概率 50%每次5块钱,我是穷人
软件名称:超级视频合并软件 V2.20
编译器:貌似 Delphi6-7 {:6_207:} 无壳。

这个代码框让我数据丢失了两次,我又重新编过 效果不是很好,真失败。

正常情况下,打开弹出一个NAG窗口 要你注册还是试用,未注册版本合并视频后会有水印。下断点
MessageboxA 就可以找到关键 CALL 在这是 算法课,我就不说明了,很简单的。

从按钮事件开始_TFrm_Reg_Btn_RegClick proc near   0057EAC8
push    ebp
mov   ebp, esp
xor   ecx, ecx
push    ecx
push    ecx
push    ecx
push    ecx
push    ecx
push    ecx
push    ebx
mov   ebx, eax
xor   eax, eax
push    ebp
push    offset loc_57EC4F
push    dword ptr fs:
mov   fs:, esp
lea   edx,
mov   eax, ; this
call    @Controls@TControl@GetText$qqrv ;            TControl::GetText(void)
mov   eax,                                        EAX = 用户名   这里我们用 XUEPOJIE 来代替用户名
call    unknown_libname_81 ;                                 取用户名长度赋值给EAX
test    eax, eax                                                       判断 EAX 是否等于 0用TEST EAX,EAX 是常用的方法来判断一个寄存器内容是否为 0。
jnz   short loc_57EB2A                                          不为0 则跳转 到 LOC_57EB2A</font>loc_57EB2A:
lea   edx,
mov   eax, ; this
call    @Controls@TControl@GetText$qqrv ;        GetText(void)
mov   eax,                                     EAX = 假注册码   这里我们用 8888888888888888888888888代替注册码。
call    unknown_libname_81 ;                             取假码长度 给EAX
test    eax, eax                                                     判断假码长度是否为0
jnz   short loc_57EB70                                      不为0则跳,必须要跳走。</font>

static/image/hrline/5.gif
loc_57EBFB核心算法CALL下面接着分析
loc_57EBFB 里面有四个 CALLloc_004E0D24   loc_004E0B4C(包含全部算法代码)   loc_004047E8   loc_00403D04

004E0B66         push    ebp
004E0B67         push    004E0D0A
004E0B6C         push    dword ptr fs:
004E0B6F         mov   dword ptr fs:, esp
004E0B72         mov   eax,
004E0B75         call    004043C0
004E0B7A         lea   edx,
004E0B7D         mov   eax, edi
004E0B7F         call    004E0AE4
004E0B84         mov   eax,                                   ;EAX = 用户名
004E0B87         call    0040469C                                        ;计算的用户名长度
004E0B8C         mov   esi, eax
004E0B8E         test    esi, esi
004E0B90         jle   short 004E0BC2                                  ;判断 是否为 0
004E0B92         mov   ebx, 0x1                                        ;ebx 初始化 为0
004E0B97         lea   edx,
004E0B9A         mov   eax, edi
004E0B9C         call    004E0AE4
004E0BA1         mov   eax,                                  ;eax = 用户名地址
004E0BA4         movzx   eax, byte ptr          ;eax = 用户名第一位 ASICC值
004E0BA9         lea   ecx,
004E0BAC         xor   edx, edx
004E0BAE         call    00409528                                       ;需要分析

第一层算法
004093C8         or      cl, cl        判断cl是否为0 cl = 10固定的
004093CA         jnz   short 004093E3   不为0不跳
004093CC         or      eax, eax


004093CE         jns   short 004093DE
004093D0         neg   eax
004093D2         call    004093DE
004093D7         mov   al, 0x2D
004093D9         inc   ecx
004093DA         dec   esi
004093DB         mov   byte ptr , al
004093DD         retn
004093DE         mov   ecx, 0xA


004093E3         push    edx
004093E4         push    esi
004093E5         xor   edx, edx                                        ;edx 清零
004093E7         div   ecx                                             ;此时 eax =X的ASCII 值 58 eax / ecx 商在 eax 余数在 edx
004093E9         dec   esi                                             ;esi - 1
004093EA         add   dl, 0x30                                       ;余数 + 0x30
004093ED         cmp   dl, 0x3A                                    ;小于则跳转
004093F0         jb      short 004093F5
004093F2         add   dl, 0x7
004093F5         mov   byte ptr , dl                        处理后的数据放到 esi指向的内存空间
004093F7         or      eax, eax                                       判断 eax是否为0 为0不跳
004093F9         jnz   short 004093E5
第一次循环 : eax = 58 = 'X'   ecx = 10    eax/ecx商=eax = 5 余数 = 8 =edx余数+30 = 8+30= 38放入 esi指向空间

第二次循环 eax = 5ecx = 10 eax /ecx 商 = 0 =eax循环可以跳走了余数 =edx = 5 余数 +30 =35esi-1 放入 前一个字节的空间
相当于3538 我们在内存看下   是不是感到很奇怪 这个数值 刚到 等于 一个 字符串 '58' 这个字符串 刚到等于 我们用户名第一个 字符的 ASCII值, 所以 第一层算法 只是将用户名的 ASCII值 转化为 字符串
ASCII "585545504F4A4945"


004E0BB3      mov   edx,                                  ;edx 等于 处理 后的 字符串
004E0BB6      lea   eax,
004E0BB9         call    004046A4
004E0BBE      inc   ebx
004E0BBF         dec   esi
004E0BC0         jnz   short 004E0B97






004E0BB3      mov   edx,                                  ;edx 等于 处理后的字符串地址004E0BB6      lea   eax, 004E0BB9      call    004046A4004E0BBE      inc   ebx004E0BBF      dec   esi004E0BC0      jnz   short 004E0B97
下面就是第二层算法 ,其实没什么作用 004E0BC2      mov   eax,                                   ;将 运算的 东东 放到eax004E0BC5      call    0040469C                                        ;将 这字符串 前 4个 字节的 内容 给 eax004E0BCA      mov   esi, eax                                        ;eax 给 esi004E0BCC      test    esi, esi                                        ;判断 esi是否 为 0004E0BCE      jle   short 004E0BFC004E0BD0      mov   ebx, 0x1                                        ;ebx 给0x1貌似要 计数器004E0BD5      mov   eax,                                  ;运算后的 假吗 给 eax004E0BD8      call    0040469C                                       ;还是 刚才 那样 给前4个字节 数据 给 eax004E0BDD      sub   eax, ebx                                       ;eax- ebx004E0BDF      mov   edx,                                  ;假吗运算之 给 edx004E0BE2      mov   dl, byte ptr                          ;第一次 取最后 一位004E0BE5      lea   eax,                                  ;估计 又是 将此 东西 放入缓冲区004E0BE8      call    004045A8                                       004E0BED      mov   edx, 004E0BF0      lea   eax, 004E0BF3      call    004046A4004E0BF8      inc   ebx004E0BF9      dec   esi004E0BFA      jnz   short 004E0BD5第二层算法作用也就是 把第一层算法得出的字符串倒过来ASCII "5494A4F405545585"
004E0BFC      lea   eax,            将处理后的字符串 的二级指针给转化为 一级指针给eax 这个是第一层算法算出的004E0BFF      push    eax               压入栈,保存起来004E0C00      mov   ecx, 0x4            初始化变量 eax = 0x4004E0C05      mov   edx, 0x1            初始化变量 edx = 0x1004E0C0A      mov   eax,                                   ;将倒转后的字符串也就是第二层算法 后的字符串地址给eax 004E0C0D      call    004048FC            执行后 eax = 倒转字符串前四个字节 5494 字符串的二级指针004E0C12      lea   eax,            二级指针给eax 转换为 一级指针004E0C15      push    eax              指针入栈 保存004E0C16      mov   ecx, 0x4            初始化值004E0C1B      mov   edx, 0x5            初始化值 004E0C20      mov   eax,           倒转字符串地址给 eax   004E0C23      call    004048FC            执行后 eax = 倒转后字符串 接着在后四位 4AF4字符串的二级指针 004E0C28      mov   eax,           将前四位字符串地址给eax004E0C2B      call    0040469C            计算出他的长度004E0C30      cmp   eax, 0x4            判断长度是否等于 0x4 等于则跳,我先撤了。已经跳了004E0C33      jge   short 004E0C64004E0C35      mov   eax, 004E0C38      call    0040469C004E0C3D      mov   ebx, eax004E0C3F      cmp   ebx, 0x3004E0C42      jg      short 004E0C64004E0C44      /lea   ecx, 004E0C47      |mov   eax, ebx004E0C49      |shl   eax, 0x2004E0C4C      |xor   edx, edx004E0C4E      |call    00409528004E0C53      |mov   edx, 004E0C56      |lea   eax, 004E0C59      |call    004046A4004E0C5E      |inc   ebx004E0C5F      |cmp   ebx, 0x4004E0C62      \jnz   short 004E0C44004E0C64      mov   eax,       接着后四位的字符串地址给eax 4AF4
004E0C67      call    0040469C         计算器其长度004E0C6C      cmp   eax, 0x4         判断长度 跳了004E0C6F      jge   short 004E0CA0004E0C71      mov   eax, 004E0C74      call    0040469C004E0C79      mov   ebx, eax004E0C7B      cmp   ebx, 0x3004E0C7E      jg      short 004E0CA0004E0C80      /lea   ecx, 004E0C83      |mov   eax, ebx004E0C85      |shl   eax, 0x2004E0C88      |xor   edx, edx004E0C8A      |call    00409528004E0C8F      |mov   edx, 004E0C92      |lea   eax, 004E0C95      |call    004046A4004E0C9A      |inc   ebx004E0C9B      |cmp   ebx, 0x4004E0C9E      \jnz   short 004E0C80004E0CA0      lea   eax,         004E0CA3      push    eax004E0CA4      mov   eax, dword ptr     在这产生一个新的字符串 vj268v2013 不要奇怪这个字符串是固定的 就是这个软件的exe名称和版本 004E0CA7      mov   ecx, 0x4           004E0CAC      mov   edx, 0x1004E0CB1      call    004048FC             取前四位字符串 vj26004E0CB6      push    004E0CB9      push    004E0D20                                        ;UNICODE "-"004E0CBE      push    004E0CC1      lea   eax,            004E0CC4      push    eax004E0CC5      mov   eax, dword ptr 004E0CC8      mov   ecx, 0x5004E0CCD      mov   edx, 0x5004E0CD2      call    004048FC           取后 5位字符串 8v201004E0CD7      push    004E0CDA      push    004E0D20                                        ;UNICODE "-" 看到这 杠号是不是很熟悉啊,哈哈 你已经拆到了004E0CDF      push    004E0CE2      mov   eax, 004E0CE5      mov   edx, 0x6004E0CEA      call    0040475C004E0CEF      xor   eax, eax004E0CF1      pop   edx004E0CF2      pop   ecx004E0CF3      pop   ecx004E0CF4      mov   dword ptr fs:, edx004E0CF7      push    004E0D11004E0CFC      lea   eax, 004E0CFF      mov   edx, 0xA004E0D04      call    004043E4到最后就是 将前面出现过的字符串组装了,我就不废话了 vj26-54948v201-A4F4   5494是将用户名经过二层算法获得的前四个字节的字符串 A4F4是在后四位的字符串 其他的就是这个软件的 exe名称了 最后这个就是注册码了。。我们测试下。。
注册成功,哈哈,肚子太饿了,我就偷懒下,写这个帖子花了我三个小时,边分析边写帖子,大伙给我点动力把。一路 艰难险阻是不是都过来了?是否体验到算法带来的成就感?本次教程到此结束,我是 LYQingYe 我爱雪坡姐, 感谢大家支持。



Aniz 发表于 2015-8-26 20:30

沙发我速度怎么样

s768067871 发表于 2015-8-26 20:31

看到有钱我就来了谢谢楼主

泽杨 发表于 2015-8-26 20:36

我是来拿HB的

易木马 发表于 2015-8-26 20:50

嗯,领钱走人了。

旧虐 发表于 2015-8-26 21:06

回帖真的有钱吗。我是来蹭钱的。。

弦上云烟 发表于 2015-8-26 21:09

嘿嘿   我是来蹭钱的   

ningzhonghui 发表于 2015-8-26 21:18

膜拜算法牛,学习下怎么样的算法过程

LYQingYe 发表于 2015-8-26 21:20

ningzhonghui 发表于 2015-8-26 21:18
膜拜算法牛,学习下怎么样的算法过程

数据丢失两次了,分析得不是很全了。谢谢支持

JackDx 发表于 2015-8-26 21:25

不错。学习了。
页: [1] 2 3 4 5 6 7
查看完整版本: 算法分析第一课 -- 超级视频合并软件 算法分析 回帖有钱