【文章标题】: ***软件算法分析--新手第一次
【文章作者】: 一休
【作者邮箱】:
【作者主页】:
【作者QQ号】:
【软件名称】: ***装修软件
【软件大小】: 356M
【下载地址】: 自己搜索下载
【加壳方式】: 无
【保护方式】: 序列号+功能限制
【编写语言】: Delphi 7.0
【使用工具】: OD
【操作平台】: WindowsXP-SP2
【软件介绍】:
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
先用PointH.exe找到那个断点,下断。一路F8下来,来到这里:
0073B2E6 |. 8B55 F8 mov edx, [ebp-8] ;机器码[edx]="4910825475137942" 注册码
0073B2E9 |. 8B45 FC mov eax, [ebp-4] ;注册码[eax]="4935906723251451" 机器玛
0073B2EC |. E8 F7EEF7FF call 006BA1E8
进入注册码验证函数
006BA144 > /BB 04000000 mov ebx, 4
006BA149 . |8B45 E4 mov eax, dword ptr [ebp-1C]
006BA14C . |8BF0 mov esi, eax
006BA14E . |8B45 E0 mov eax, dword ptr [ebp-20]
006BA151 . |8945 DC mov dword ptr [ebp-24], eax
006BA154 . |8B45 D8 mov eax, dword ptr [ebp-28]
006BA157 . |8945 D4 mov dword ptr [ebp-2C], eax
006BA15A > /8A06 mov al, byte ptr [esi] ;al=机器码第一位
006BA15C . |8B55 DC mov edx, dword ptr [ebp-24]
006BA15F . |2A02 sub al, byte ptr [edx] ;[edx]=注册码第一位,这里用机器码的第一位减去注册码的第一位。
006B9FF4 /$ 8BC8 mov ecx, eax
006B9FF6 |. 84C9 test cl, cl
006B9FF8 |. 7D 13 jge short 006BA00D ;如果cl>=o,转移到006BA00D
006B9FFA |. 0FBEC1 movsx eax, cl
006B9FFD |. 05 2C010000 add eax, 12C
006BA002 |. B9 0A000000 mov ecx, 0A
006BA007 |. 99 cdq
006BA008 |. F7F9 idiv ecx ;用(DX,AX)除以 ecx
006BA00A |. 8BC2 mov eax, edx ;把上面除法的余数赋值给eax
006BA00C |. C3 retn
006BA00D |> 80F9 0A cmp cl, 0A
006BA010 |. 7C 0F jl short 006BA021
006BA012 |. 0FBEC1 movsx eax, cl
006BA015 |. B9 0A000000 mov ecx, 0A
006BA01A |. 99 cdq
006BA01B |. F7F9 idiv ecx
006BA01D |. 8BC2 mov eax, edx
006BA01F |. EB 02 jmp short 006BA023
006BA021 |> 8BC1 mov eax, ecx
006BA023 \> C3 retn ;从006B9FF4到006BA023这个函数过程,把前面减法运算结果作为输入,如果al中结果大于等于零则直接返回这个值,反之用0Ah减去(-al),把结果输出。
006BA166 . 8B55 D4 mov edx, dword ptr [ebp-2C]
006BA169 . 8802 mov byte ptr [edx], al
006BA16B . FF45 D4 inc dword ptr [ebp-2C]
006BA16E . FF45 DC inc dword ptr [ebp-24] ;指针指向注册码的下一位
006BA171 . 46 inc esi ;指针指向机器码的下一位
006BA172 . 4B dec ebx
006BA173 .^ 75 E5 jnz short 006BA15A
006BA175 . 8345 D8 04 add dword ptr [ebp-28], 4
006BA179 . 8345 E0 04 add dword ptr [ebp-20], 4
006BA17D . 8345 E4 04 add dword ptr [ebp-1C], 4 ;指针移动到下一组数据
006BA181 . 4F dec edi
006BA182 .^ 75 C0 jnz short 006BA144
006BA184 . 33C0 xor eax, eax
006BA186 . BF 04000000 mov edi, 4
006BA18B . 8D55 9C lea edx, dword ptr [ebp-64] "把上面用机器码减去注册码生成的新数列的指针给edx
006BA18E > BB 04000000 mov ebx, 4
006BA193 . 8BF2 mov esi, edx
006BA195 > 0206 add al, byte ptr [esi]
006BA197 . 46 inc esi
006BA198 . 4B dec ebx
006BA199 .^ 75 FA jnz short 006BA195
006BA19B . 83C2 04 add edx, 4
006BA19E . 4F dec edi
006BA19F .^ 75 ED jnz short 006BA18E ;把新数列的所有位加起来给al
006BA1A1 . 0FBED0 movsx edx, al
006BA1A4 . 8B0D 18057800 mov ecx, dword ptr [780518] ;ecx=781db8
006BA1AA . 8911 mov dword ptr [ecx], edx
006BA1AC . 24 0F and al, 0F ;只保留个位,去掉其它位
006BA1AE . 0FBED0 movsx edx, al
006BA1B1 . 8BCA mov ecx, edx ;把用机器码减去注册码生成的新数列的每一位累加后的个位赋值给ecx
006BA1B3 . 85C9 test ecx, ecx
006BA1B5 . 79 03 jns short 006BA1BA
006BA1B7 . 83C1 03 add ecx, 3
006BA1BA > C1F9 02 sar ecx, 2 ;右移两位,相当于用ecx除以4取商给ecx
inc ecx ;最新版本这里多了一句;在研究上一个版本时,就是这里把我卡住了。因为没有这一句,逆运算就不是百分之百可进行的。
006BA1BD . 894D F0 mov dword ptr [ebp-10], ecx ;把商加一后的结果保存在[ebp-10]这个地方,后面变换数列要用到
006BA1C0 . 81E2 03000080 and edx, 80000003 ;取末两位,相当于用上面ecx除以4取余数给edx
006BA1C6 . 79 05 jns short 006BA1CD
006BA1C8 . 4A dec edx
006BA1C9 . 83CA FC or edx, FFFFFFFC
006BA1CC . 42 inc edx
006BA1CD > 42 inc edx ;余数加一
006BA1CE . BF 04000000 mov edi, 4
006BA1D3 . 8D45 9C lea eax, dword ptr [ebp-64]
006BA1D6 . 8945 D0 mov dword ptr [ebp-30], eax
006BA1D9 > BB 04000000 mov ebx, 4
006BA1DE . 8B45 D0 mov eax, dword ptr [ebp-30]
006BA1E1 > 8B4D F0 mov ecx, dword ptr [ebp-10] ;商加一后的结果
006BA1E4 . 8D4C8D 8C lea ecx, dword ptr [ebp+ecx*4-74] ;新的结果保存地址为从ebp-74到ebp-64
006BA1E8 . 8D7411 FB lea esi, dword ptr [ecx+edx-5] ;其实,结果保存地址=ebp-74+(商×4)+余数
006BA1EC . 8A08 mov cl, byte ptr [eax] ;按顺序取出用机器码减去注册码生成的新数列的值
006BA1EE . 880E mov byte ptr [esi], cl ;从“ebp-74+(商×4)+余数”开始写入新的数列
006BA1F0 . 42 inc edx
006BA1F1 . 83FA 04 cmp edx, 4
006BA1F4 . 7E 08 jle short 006BA1FE
006BA1F6 . BA 01000000 mov edx, 1
006BA1FB . FF45 F0 inc dword ptr [ebp-10]
006BA1FE > 837D F0 04 cmp dword ptr [ebp-10], 4
006BA202 . 7E 07 jle short 006BA20B
006BA204 . C745 F0 01000>mov dword ptr [ebp-10], 1
006BA20B > 40 inc eax
006BA20C . 4B dec ebx
006BA20D .^ 75 D2 jnz short 006BA1E1
006BA20F . 8345 D0 04 add dword ptr [ebp-30], 4
006BA213 . 4F dec edi
006BA214 .^ 75 C3 jnz short 006BA1D9 "循环,把原来的数列按照一定的顺序写到从[ebp-74]开始的16个字节
006BA216 . BB 04000000 mov ebx, 4
006BA21B . 8D45 90 lea eax, dword ptr [ebp-70]
006BA21E . 8945 CC mov dword ptr [ebp-34], eax
006BA221 > BF 03000000 mov edi, 3
006BA226 . 8B45 CC mov eax, dword ptr [ebp-34]
006BA229 . 8BF0 mov esi, eax
006BA22B > 8A06 mov al, byte ptr [esi]
006BA22D . 2A46 FC sub al, byte ptr [esi-4] "用上面变换后的数列的第五个数减去第一个数,然后依次做减法直到最后一个数。
006B9FF4 /$ 8BC8 mov ecx, eax
006B9FF6 |. 84C9 test cl, cl
006B9FF8 |. 7D 13 jge short 006BA00D
006B9FFA |. 0FBEC1 movsx eax, cl
006B9FFD |. 05 2C010000 add eax, 12C
006BA002 |. B9 0A000000 mov ecx, 0A
006BA007 |. 99 cdq
006BA008 |. F7F9 idiv ecx
006BA00A |. 8BC2 mov eax, edx
006BA00C |. C3 retn
006BA00D |> 80F9 0A cmp cl, 0A
006BA010 |. 7C 0F jl short 006BA021
006BA012 |. 0FBEC1 movsx eax, cl
006BA015 |. B9 0A000000 mov ecx, 0A
006BA01A |. 99 cdq
006BA01B |. F7F9 idiv ecx
006BA01D |. 8BC2 mov eax, edx
006BA01F |. EB 02 jmp short 006BA023
006BA021 |> 8BC1 mov eax, ecx
006BA023 \> C3 retn ;从006B9FF4到006BA023这个函数过程,把前面减法运算结果作为输入,如果al中结果大于等于零则直接返回这个值,反之用0Ah减去(-al),把结果输出。
006BA235 . 8806 mov byte ptr [esi], al ;把结果保存回去
006BA237 . 83C6 04 add esi, 4
006BA23A . 4F dec edi
006BA23B .^ 75 EE jnz short 006BA22B
006BA23D . FF45 CC inc dword ptr [ebp-34]
006BA240 . 4B dec ebx
006BA241 .^ 75 DE jnz short 006BA221 ;经过12次循环,得到新的数列
006BA243 . BF 04000000 mov edi, 4
006BA248 . 8D45 8D lea eax, dword ptr [ebp-73]
006BA24B . 8945 CC mov dword ptr [ebp-34], eax
006BA24E > BB 03000000 mov ebx, 3
006BA253 . 8B45 CC mov eax, dword ptr [ebp-34]
006BA256 . 8BF0 mov esi, eax
006BA258 > 8A06 mov al, byte ptr [esi]
006BA25A . 2A46 FF sub al, byte ptr [esi-1] "用上面新数列的第二位减去第一位。
006B9FF4 /$ 8BC8 mov ecx, eax
006B9FF6 |. 84C9 test cl, cl
006B9FF8 |. 7D 13 jge short 006BA00D
006B9FFA |. 0FBEC1 movsx eax, cl
006B9FFD |. 05 2C010000 add eax, 12C
006BA002 |. B9 0A000000 mov ecx, 0A
006BA007 |. 99 cdq
006BA008 |. F7F9 idiv ecx
006BA00A |. 8BC2 mov eax, edx
006BA00C |. C3 retn
006BA00D |> 80F9 0A cmp cl, 0A
006BA010 |. 7C 0F jl short 006BA021
006BA012 |. 0FBEC1 movsx eax, cl
006BA015 |. B9 0A000000 mov ecx, 0A
006BA01A |. 99 cdq
006BA01B |. F7F9 idiv ecx
006BA01D |. 8BC2 mov eax, edx
006BA01F |. EB 02 jmp short 006BA023
006BA021 |> 8BC1 mov eax, ecx
006BA023 \> C3 retn ;从006B9FF4到006BA023这个函数过程,把前面减法运算结果作为输入,如果al中结果大于等于零则直接返回这个值,反之用0Ah减去(-al),把结果输出。
006BA262 . 8806 mov byte ptr [esi], al ;结果赋值回去
006BA264 . 46 inc esi
006BA265 . 4B dec ebx
006BA266 .^ 75 F0 jnz short 006BA258
006BA268 . 8345 CC 04 add dword ptr [ebp-34], 4
006BA26C . 4F dec edi
006BA26D .^ 75 DF jnz short 006BA24E ;循环12次又得到新的数列
006BA26F . BF 04000000 mov edi, 4
006BA274 . 8D45 8C lea eax, dword ptr [ebp-74]
006BA277 . 8945 CC mov dword ptr [ebp-34], eax
006BA27A > BB 04000000 mov ebx, 4
006BA27F . 8B45 CC mov eax, dword ptr [ebp-34]
006BA282 > B2 09 mov dl, 9
006BA284 . 2A10 sub dl, byte ptr [eax]
006BA286 . 8810 mov byte ptr [eax], dl "把新数列各位用9减去后从新赋值
006BA288 . 40 inc eax
006BA289 . 4B dec ebx
006BA28A .^ 75 F6 jnz short 006BA282
006BA28C . 8345 CC 04 add dword ptr [ebp-34], 4
006BA290 . 4F dec edi
006BA291 .^ 75 E7 jnz short 006BA27A ;循环16次,更新数列
006BA293 . BF 01000000 mov edi, 1
006BA298 . 8D85 7CFFFFFF lea eax, dword ptr [ebp-84]
006BA29E . 8945 CC mov dword ptr [ebp-34], eax
006BA2A1 > BB 04000000 mov ebx, 4
006BA2A6 . 8D45 90 lea eax, dword ptr [ebp-70]
006BA2A9 . 8B55 CC mov edx, dword ptr [ebp-34]
006BA2AC > B9 05000000 mov ecx, 5
006BA2B1 . 2BCF sub ecx, edi
006BA2B3 . 8A4C08 FB mov cl, byte ptr [eax+ecx-5]
006BA2B7 . 880A mov byte ptr [edx], cl "把上面的数列中,从每(4个)组里的第四位(从四位到一位)数依次付值到新数列的第一个(从一组到四组)组数里(例:1234 5678 6587 2143->4873 3784 2651 1562)
006BA2B9 . 42 inc edx
006BA2BA . 83C0 04 add eax, 4
006BA2BD . 4B dec ebx
006BA2BE .^ 75 EC jnz short 006BA2AC
006BA2C0 . 47 inc edi
006BA2C1 . 8345 CC 04 add dword ptr [ebp-34], 4
006BA2C5 . 83FF 05 cmp edi, 5
006BA2C8 .^ 75 D7 jnz short 006BA2A1 ;循环16次
006BA2CA . BF 04000000 mov edi, 4
006BA2CF . 8D45 BC lea eax, dword ptr [ebp-44]
006BA2D2 . 8945 CC mov dword ptr [ebp-34], eax
006BA2D5 . 8D85 7CFFFFFF lea eax, dword ptr [ebp-84]
006BA2DB . 8945 D0 mov dword ptr [ebp-30], eax
006BA2DE > BB 04000000 mov ebx, 4
006BA2E3 . 8B45 CC mov eax, dword ptr [ebp-34] ;[eax]=上面经过种种变换后的数列
006BA2E6 . 8B55 D0 mov edx, dword ptr [ebp-30] ;[edx]=软件机器码
006BA2E9 > 8A08 mov cl, byte ptr [eax]
006BA2EB 3A0A cmp cl, byte ptr [edx] "比较上面计算出来的数列与软件本身的机器码是否相同.
006BA2ED . 74 0C je short 006BA2FB "如果不同则转到 "序列号输入错误"
006BA2EF . 64:8F05 00000>pop dword ptr fs:[0]
006BA2F6 . 83C4 08 add esp, 8
006BA2F9 EB 40 jmp short 006BA33B
006BA2FB > 42 inc edx
006BA2FC . 40 inc eax
006BA2FD . 4B dec ebx
006BA2FE .^ 75 E9 jnz short 006BA2E9
006BA300 . 8345 D0 04 add dword ptr [ebp-30], 4
006BA304 . 8345 CC 04 add dword ptr [ebp-34], 4
006BA308 . 4F dec edi
006BA309 .^ 75 D3 jnz short 006BA2DE "如果相同,继续比较下一位,然后就进入已注册软件了,哈哈!
为了能更好的理解这个算法,下面写一个例子:
机器码:4935 9067 2325 1451
你输入的注册码:4910 8254 7513 7942 随便输入的16个数字
机器码减注册码:0025 1813 5812 4519 各个位之和=37h,个位数除以4得1余3,1×4+3=7,所以下行从第(7+1)位开始按顺序写入
重新排序:8124 5190 0251 8135 用第五个数减去第一个数,得出下一行
更新数列:8124 7076 3285 5950 每一组用后一个数减去前一个数,得出下一行
更新数列:8395 7342 3996 5419 用9减去每一位,得出下一行
更新数列:1604 2657 6003 4580 由每组的第四位开始,重新组成下一列数据
生成与机器码比较数列:4730 0508 6605 1264 这时,如果生成与机器码比较数列与机器码完全相同,那么软件就被注册了。
前面那些汇编语言就是实现上面这些功能的,明白了验证注册码的算法,相信大家都能很容易写出他的逆运算的程序啦。
--------------------------------------------------------------------------------
【经验总结】
对于这种简单的数据变换,就不总结什么了吧。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年07月17日 13:57:44
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)