且行且远

和上次看的那个计算机等级考试的模拟软件是同一个公司出的,而且都是同一个毛病,就是只有一个主程序,特别的大,很ft。仍然是用VB编的,而且没有加壳,上次因为是用SmartCheck看的,得到的信息很少,这次用Odbg载入分析了一下,原来注册码是用浮点运算计算得到的,而SmartCheck 没有检测到浮点运算,因此SmartCheck里面显示的数都不知道是怎么得到的。

VBExplorer先查看注册按钮的入口点,然后ODBG设断点,具体的程序懒得在这里写了,VB的程序太长太麻烦了,看了好久再加上一些猜测才弄明白点。这里就把最后注册码的计算过程写一下算了。

序列号分为两部分,前面是字符串,后面是一串数,把这串数提取出来,分别取得数的1、3、5、7位。分别在每位后面依次加上2、5、7、6。这样得到四个数。

下面再对每个数进行处理,看一下各个数是在什么区间内,分析的时候记录如下:

ds:[4026C0]=20 再加上ds:[4026B8]=97
ds:[4026B0]=29 再加上ds:[4026A8]=28
ds:[4026A0]=30 这步无意义,末位不可能是9或0
ds:[402698]=55 再加上ds:[402690]=35(相等也加)
ds:[402688]=56 这步比较无意义,小于等于55执行上面的加法,大于55直接和81判断
ds:[402680]=81 再加上ds:[402678]=41
ds:[402670]=82 再减去ds:[402668]=17
实际上也就是按上面的几个数划分了一下区间,数落在不同的区间内进行不同的处理,这样就又可以得到四个数。

把最初得到的四个数求和,判断和处于如下哪个区间内,然后注册码即可求得

属于区间[0,100]:注册码=zgx+第一位+第二位+gf8+第三位+第四位
属于区间(100,200]:注册码=第一位+ygp+第二位+第三位+tx6+第四位
属于区间(200,300]:注册码=第四位+gmu+第一位+第二位+hu6+第三位
属于区间(300,正无穷):注册码=第二位+fre+第一位+kmh+第三位+第四位

注意上面所说的第?位都是以最初得到的数为ASCII码求得的字符。

写的挺凌乱的,基本都是边分析边记录的,还把注册机做了,以后有空补上算法分析吧,最近忙于考试和试验报告,实在没那么多时间,5555


分类: 逆向手札 由 ssfighter 于 2006年5月24日 发表

看了水木Crack版上以前peansen学长发的一篇Flashget限制线程数的修改方法,尝试着自己用OllyDbg跟了一下,发现还不算很难, odbg对这种C++写的程序支持的很好,用起来很方便,这篇文章我希望自己尽量写的详细一点,以前的东西我都是不该详细的地方写的特别详细,该认真分析的地方都一笔带过了:(

首先,在默认下载属性的地方,把文件分成10同时下载的地方改成11,弹出一个窗口,显示”Please enter an integer between 1 and 10.”,先对FlashGet侦壳,发现无壳,直接用OllyICE载入,先找一下字符串参考,发现找不到,那就直接对API函数下断点bp MessageBoxA。
启动之后仍然把默认下载属性里面的10改为11,程序被断下,按Ctrl+F9从系统领空返回到程序领空来到这里:
004C4BD7 /$ 55 push ebp
004C4BD8 |. 8BEC mov ebp, esp
004C4BDA |. 81EC 14010000 sub esp, 114
004C4BE0 |. 53 push ebx
004C4BE1 |. 56 push esi
004C4BE2 |. 57 push edi
004C4BE3 |. 33DB xor ebx, ebx
004C4BE5 |. 8BF9 mov edi, ecx
004C4BE7 |. 53 push ebx
004C4BE8 |. 897D F0 mov ss:[ebp-10], edi
004C4BEB |. E8 B9FFFFFF call flashget.004C4BA9
004C4BF0 |. 8D45 FC lea eax, ss:[ebp-4]
004C4BF3 |. 50 push eax
004C4BF4 |. 53 push ebx
004C4BF5 |. E8 55010000 call flashget.004C4D4F
004C4BFA |. 33F6 xor esi, esi
004C4BFC |. 3BC3 cmp eax, ebx
004C4BFE |. 8945 F4 mov ss:[ebp-C], eax
004C4C01 |. 74 18 je short flashget.004C4C1B
004C4C03 |. 53 push ebx ; /lParam
004C4C04 |. 53 push ebx ; |wParam
004C4C05 |. 68 76030000 push 376 ; |Message = MSG(376)
004C4C0A |. FF75 FC push dword ptr ss:[ebp-4] ; |hWnd
004C4C0D |. FF15 6C574E00 call near ds:[<&USER32.SendMessageA>] ; \SendMessageA
004C4C13 |. 3BC3 cmp eax, ebx
004C4C15 |. 74 04 je short flashget.004C4C1B
004C4C17 |. 8BF0 mov esi, eax
004C4C19 |. EB 0A jmp short flashget.004C4C25
004C4C1B |> 3BFB cmp edi, ebx
004C4C1D |. 74 06 je short flashget.004C4C25
004C4C1F |. 8DB7 9C000000 lea esi, ds:[edi+9C]
004C4C25 |> 3BF3 cmp esi, ebx
004C4C27 |. 895D F8 mov ss:[ebp-8], ebx
004C4C2A |. 74 13 je short flashget.004C4C3F
004C4C2C |. 8B06 mov eax, ds:[esi]
004C4C2E |. 8945 F8 mov ss:[ebp-8], eax
004C4C31 |. 8B45 10 mov eax, ss:[ebp+10]
004C4C34 |. 3BC3 cmp eax, ebx
004C4C36 |. 74 07 je short flashget.004C4C3F
004C4C38 |. 05 00000300 add eax, 30000
004C4C3D |. 8906 mov ds:[esi], eax
004C4C3F |> 8B5D 0C mov ebx, ss:[ebp+C]
004C4C42 |. F6C3 F0 test bl, 0F0
004C4C45 |. 75 17 jnz short flashget.004C4C5E
004C4C47 |. 8BC3 mov eax, ebx
004C4C49 |. 83E0 0F and eax, 0F
004C4C4C |. 83F8 01 cmp eax, 1
004C4C4F |. 76 0A jbe short flashget.004C4C5B
004C4C51 |. 83F8 02 cmp eax, 2
004C4C54 |. 76 08 jbe short flashget.004C4C5E
004C4C56 |. 83F8 04 cmp eax, 4
004C4C59 |. 77 03 ja short flashget.004C4C5E
004C4C5B |> 83CB 30 or ebx, 30
004C4C5E |> 85FF test edi, edi
004C4C60 |. 74 05 je short flashget.004C4C67
004C4C62 |. 8B7F 78 mov edi, ds:[edi+78]
004C4C65 |. EB 1A jmp short flashget.004C4C81
004C4C67 |> 8D85 ECFEFFFF lea eax, ss:[ebp-114]
004C4C6D |. 68 04010000 push 104 ; /BufSize = 104 (260.)
004C4C72 |. 50 push eax ; |PathBuffer
004C4C73 |. 6A 00 push 0 ; |hModule = NULL
004C4C75 |. 8DBD ECFEFFFF lea edi, ss:[ebp-114] ; |
004C4C7B |. FF15 A8524E00 call near ds:[<&KERNEL32.GetModuleFil>; \GetModuleFileNameA
004C4C81 |> 53 push ebx ; /Style
004C4C82 |. 57 push edi ; |Title
004C4C83 |. FF75 08 push dword ptr ss:[ebp+8] ; |Text
004C4C86 |. FF75 F4 push dword ptr ss:[ebp-C] ; |hOwner
004C4C89 |. FF15 9C554E00 call near ds:[<&USER32.MessageBoxA>] ; \MessageBoxA
004C4C8F |. 85F6 test esi, esi ; flashget.00519B5C
004C4C91 |. 8BF8 mov edi, eax

原本以为这里会有判断的地方,但是没有找到,按照peansen说的,继续向上找调用这个模块的地方,具体跟踪的方法就是紧跟出错的字符串,从4C4BD7处可以看到,这个调用是来自于4C4CED,再来到这里:
004C4CBE /$ 55 push ebp
004C4CBF |. 8BEC mov ebp, esp
004C4CC1 |. E8 6DA10000 call flashget.004CEE33
004C4CC6 |. 8B40 04 mov eax, ds:[eax+4]
004C4CC9 |. 85C0 test eax, eax
004C4CCB |. 74 15 je short flashget.004C4CE2
004C4CCD |. FF75 10 push dword ptr ss:[ebp+10]
004C4CD0 |. 8B10 mov edx, ds:[eax]
004C4CD2 |. 8BC8 mov ecx, eax
004C4CD4 |. FF75 0C push dword ptr ss:[ebp+C]
004C4CD7 |. FF75 08 push dword ptr ss:[ebp+8]
004C4CDA |. FF92 8C000000 call near ds:[edx+8C]
004C4CE0 |. EB 10 jmp short flashget.004C4CF2
004C4CE2 |> FF75 10 push dword ptr ss:[ebp+10] ; /Arg3
004C4CE5 |. 33C9 xor ecx, ecx ; |
004C4CE7 |. FF75 0C push dword ptr ss:[ebp+C] ; |Arg2
004C4CEA |. FF75 08 push dword ptr ss:[ebp+8] ; |Arg1
004C4CED |. E8 E5FEFFFF call flashget.004C4BD7 ; \flashget.004C4BD7
004C4CF2 |> 5D pop ebp
004C4CF3 \. C2 0C00 retn 0C

对4C4CBE这里下断点,发现此时出错的字符串仍然是已经压入堆栈了,查看堆栈,返回到4C3B5D处,就是这里:
004C3AF5 /$ B8 A42B4E00 mov eax, flashget.004E2BA4
004C3AFA |. E8 5919FEFF call flashget.004A5458
004C3AFF |. 83EC 40 sub esp, 40
004C3B02 |. 57 push edi
004C3B03 |. 8B7D 08 mov edi, ss:[ebp+8]
004C3B06 |. 833F 00 cmp dword ptr ds:[edi], 0
004C3B09 |. 74 6E je short flashget.004C3B79
004C3B0B |. 56 push esi
004C3B0C |. 8B35 F0554E00 mov esi, ds:[<&USER32.wsprintfA>] ; USER32.wsprintfA
004C3B12 |. FF75 0C push dword ptr ss:[ebp+C]
004C3B15 |. 8D45 B4 lea eax, ss:[ebp-4C]
004C3B18 |. FF75 14 push dword ptr ss:[ebp+14] ; |Format
004C3B1B |. 50 push eax ; |s
004C3B1C |. FFD6 call near esi ; \wsprintfA
004C3B1E |. 83C4 0C add esp, 0C
004C3B21 |. 8D45 D4 lea eax, ss:[ebp-2C]
004C3B24 |. FF75 10 push dword ptr ss:[ebp+10]
004C3B27 |. FF75 14 push dword ptr ss:[ebp+14]
004C3B2A |. 50 push eax
004C3B2B |. FFD6 call near esi
004C3B2D |. A1 70545100 mov eax, ds:[515470]
004C3B32 |. 83C4 0C add esp, 0C
004C3B35 |. 8945 08 mov ss:[ebp+8], eax
004C3B38 |. 8D45 D4 lea eax, ss:[ebp-2C]
004C3B3B |. 8365 FC 00 and dword ptr ss:[ebp-4], 0
004C3B3F |. 50 push eax
004C3B40 |. 8D45 B4 lea eax, ss:[ebp-4C]
004C3B43 |. 50 push eax
004C3B44 |. 8D45 08 lea eax, ss:[ebp+8]
004C3B47 |. FF75 18 push dword ptr ss:[ebp+18]
004C3B4A |. 50 push eax
004C3B4B |. E8 33200000 call flashget.004C5B83
004C3B50 |. FF75 18 push dword ptr ss:[ebp+18] ; /Arg3
004C3B53 |. 6A 30 push 30 ; |Arg2 = 00000030
004C3B55 |. FF75 08 push dword ptr ss:[ebp+8] ; |Arg1
004C3B58 |. E8 61110000 call flashget.004C4CBE ; \flashget.004C4CBE

这里应该是对出错的字符串进行处理的地方,但是这并不是我们需要的,是判断线程数超过最大值之后出错来到的这里,因此还要往前返回,按堆栈的提示,回到4C3BAB出,来到这里:
004C3B88 /$ 55 push ebp
004C3B89 |. 8BEC mov ebp, esp
004C3B8B |. 8B45 0C mov eax, ss:[ebp+C]
004C3B8E |. 3B45 10 cmp eax, ss:[ebp+10]
004C3B91 |. 7C 05 jl short flashget.004C3B98
004C3B93 |. 3B45 14 cmp eax, ss:[ebp+14]
004C3B96 |. 7E 18 jle short flashget.004C3BB0
004C3B98 |> 68 12F10000 push 0F112
004C3B9D |. 68 B4E45000 push flashget.0050E4B4 ; ASCII “%ld”
004C3BA2 |. FF75 14 push dword ptr ss:[ebp+14]
004C3BA5 |. FF75 10 push dword ptr ss:[ebp+10]
004C3BA8 |. FF75 08 push dword ptr ss:[ebp+8]
004C3BAB |. E8 45FFFFFF call flashget.004C3AF5
004C3BB0 |> 5D pop ebp
004C3BB1 \. C2 1000 retn 10
这里就是判断添入的数值是否满足条件的地方,其中ss:[ebp+10]和ss:[ebp+14]分别是01和0A,也就是说添入的数值要介于1和10之间,如果不满足就会进入4C3BAB处的call,就会弹出那个对话框。我们不关心最小值1,我们关心的是最大值0A,我们希望知道知道这个ss: [ebp+14]是什么时候被压入堆栈的,因此还要继续返回到上层调用,观察堆栈,回到40CC34,来到这里:
0040CA90 . 6A FF push -1
0040CA92 . 68 C05E4D00 push flashget.004D5EC0 ; SE 处理程序安装
0040CA97 . 64:A1 0000000>mov eax, fs:[0]
0040CA9D . 50 push eax
0040CA9E . 64:8925 00000>mov fs:[0], esp
0040CAA5 . 83EC 20 sub esp, 20
0040CAA8 . A1 70545100 mov eax, ds:[515470]
0040CAAD . 53 push ebx
0040CAAE . 55 push ebp
0040CAAF . 56 push esi
0040CAB0 . 57 push edi
0040CAB1 . 8BF1 mov esi, ecx
0040CAB3 . 894424 10 mov ss:[esp+10], eax
0040CAB7 . 8B7C24 40 mov edi, ss:[esp+40]
0040CABB . C74424 38 000>mov dword ptr ss:[esp+38], 0
0040CAC3 . 833F 00 cmp dword ptr ds:[edi], 0
0040CAC6 . 0F84 89030000 je flashget.0040CE55
0040CACC . 894424 18 mov ss:[esp+18], eax
0040CAD0 . 8B86 90000000 mov eax, ds:[esi+90]
0040CAD6 . C64424 38 01 mov byte ptr ss:[esp+38], 1
0040CADB . 85C0 test eax, eax
0040CADD . 75 6B jnz short flashget.0040CB4A
0040CADF . 8D4424 10 lea eax, ss:[esp+10]
0040CAE3 . 50 push eax ; /Arg3
0040CAE4 . 68 E9030000 push 3E9 ; |Arg2 = 000003E9
0040CAE9 . 57 push edi ; |Arg1
0040CAEA . E8 106E0B00 call flashget.004C38FF ; \flashget.004C38FF
0040CAEF . 8B4C24 10 mov ecx, ss:[esp+10]
0040CAF3 . 8B41 F8 mov eax, ds:[ecx-8]
0040CAF6 . 85C0 test eax, eax
0040CAF8 . 74 20 je short flashget.0040CB1A
0040CAFA . 51 push ecx
0040CAFB . 8D5424 14 lea edx, ss:[esp+14]
0040CAFF . 8BCC mov ecx, esp
0040CB01 . 896424 44 mov ss:[esp+44], esp
0040CB05 . 52 push edx
0040CB06 . E8 E1BC0A00 call flashget.004B87EC
0040CB0B . 8B8E 8C000000 mov ecx, ds:[esi+8C] ; |
0040CB11 . E8 3A170300 call flashget.0043E250 ; \flashget.0043E250
0040CB16 . 85C0 test eax, eax
0040CB18 . 75 22 jnz short flashget.0040CB3C
0040CB1A > 8B4424 10 mov eax, ss:[esp+10]
0040CB1E . 8B48 F8 mov ecx, ds:[eax-8]
0040CB21 . 85C9 test ecx, ecx
0040CB23 . 0F85 98000000 jnz flashget.0040CBC1
0040CB29 . 8B8E 8C000000 mov ecx, ds:[esi+8C]
0040CB2F . E8 2C5F0300 call flashget.00442A60
0040CB34 . 85C0 test eax, eax
0040CB36 . 0F84 85000000 je flashget.0040CBC1
0040CB3C > 8D4C24 10 lea ecx, ss:[esp+10]
0040CB40 . 51 push ecx
0040CB41 . 8D4C24 1C lea ecx, ss:[esp+1C]
0040CB45 . E8 66C00A00 call flashget.004B8BB0
0040CB4A > 8D5424 14 lea edx, ss:[esp+14]
0040CB4E . 52 push edx
0040CB4F . 68 E1040000 push 4E1
0040CB54 . 57 push edi
0040CB55 . E8 F76D0B00 call flashget.004C3951
0040CB5A . 8B6C24 14 mov ebp, ss:[esp+14]
0040CB5E . 8B8E 8C000000 mov ecx, ds:[esi+8C]
0040CB64 . 33C0 xor eax, eax
0040CB66 . 85ED test ebp, ebp
0040CB68 . 0F94C0 sete al
0040CB6B . 50 push eax
0040CB6C . E8 2FBB0300 call flashget.004486A0
0040CB71 . 8D4C24 10 lea ecx, ss:[esp+10]
0040CB75 . 51 push ecx ; /Arg3
0040CB76 . 68 ED030000 push 3ED ; |Arg2 = 000003ED
0040CB7B . 57 push edi ; |Arg1
0040CB7C . E8 7E6D0B00 call flashget.004C38FF ; \flashget.004C38FF
0040CB81 . 51 push ecx
0040CB82 . 8D5424 14 lea edx, ss:[esp+14]
0040CB86 . 8BCC mov ecx, esp
0040CB88 . 896424 44 mov ss:[esp+44], esp
0040CB8C . 52 push edx
0040CB8D . E8 5ABC0A00 call flashget.004B87EC
0040CB92 . 8B8E 8C000000 mov ecx, ds:[esi+8C]
0040CB98 . E8 E3AC0300 call flashget.00447880
0040CB9D . 83BE 90000000>cmp dword ptr ds:[esi+90], 2
0040CBA4 . 74 62 je short flashget.0040CC08
0040CBA6 . 8D4424 10 lea eax, ss:[esp+10]
0040CBAA . 50 push eax ; /Arg3
0040CBAB . 68 EA030000 push 3EA ; |Arg2 = 000003EA
0040CBB0 . 57 push edi ; |Arg1
0040CBB1 . E8 496D0B00 call flashget.004C38FF ; \flashget.004C38FF
0040CBB6 . 8B4C24 10 mov ecx, ss:[esp+10]
0040CBBA . 8B41 F8 mov eax, ds:[ecx-8]
0040CBBD . 85C0 test eax, eax
0040CBBF . 75 2B jnz short flashget.0040CBEC
0040CBC1 > 6A FF push -1
0040CBC3 . 6A 00 push 0
0040CBC5 . 68 21EF0000 push 0EF21
0040CBCA . E8 D1240100 call flashget.0041F0A0
0040CBCF . 83C4 0C add esp, 0C
0040CBD2 . 8BCF mov ecx, edi
0040CBD4 . E8 4F6B0B00 call flashget.004C3728
0040CBD9 > 8D4C24 18 lea ecx, ss:[esp+18]
0040CBDD . C64424 38 00 mov byte ptr ss:[esp+38], 0
0040CBE2 . E8 90BE0A00 call flashget.004B8A77
0040CBE7 . E9 4D060000 jmp flashget.0040D239
0040CBEC > 51 push ecx
0040CBED . 8D5424 14 lea edx, ss:[esp+14]
0040CBF1 . 8BCC mov ecx, esp
0040CBF3 . 896424 44 mov ss:[esp+44], esp
0040CBF7 . 52 push edx
0040CBF8 . E8 EFBB0A00 call flashget.004B87EC
0040CBFD . 8B8E 8C000000 mov ecx, ds:[esi+8C]
0040CC03 . E8 B80F0300 call flashget.0043DBC0
0040CC08 > 8D4424 14 lea eax, ss:[esp+14]
0040CC0C . 50 push eax ; /Arg3
0040CC0D . 68 F4030000 push 3F4 ; |Arg2 = 000003F4
0040CC12 . 57 push edi ; |Arg1
0040CC13 . E8 5A6C0B00 call flashget.004C3872 ; \flashget.004C3872
0040CC18 . 6A 02 push 2
0040CC1A . E8 11700000 call flashget.00413C30
0040CC1F . 8BC8 mov ecx, eax
0040CC21 . E8 FA730000 call flashget.00414020
0040CC26 . 8B4C24 14 mov ecx, ss:[esp+14]
0040CC2A . 50 push eax ; /Arg4
0040CC2B . 6A 01 push 1 ; |Arg3 = 00000001
0040CC2D . 51 push ecx ; |Arg2
0040CC2E . 57 push edi ; |Arg1
0040CC2F . E8 546F0B00 call flashget.004C3B88 ; \flashget.004C3B88

同时这里我们需要重新启动一遍FlashGet,把堆栈锁定,观察这个0A是什么时候被压入到堆栈的。观察发现40CC21处的调用使得eax的值改变,而后系统将eax的0A压入堆栈,F7进入这个call,来到这里:

00414020 /$ 8B4424 04 mov eax, ss:[esp+4]
00414024 |. 83F8 5F cmp eax, 5F ; Switch (cases 2..214)
00414027 |. 0F8F DF020000 jg flashget.0041430C
0041402D |. 0F84 CA020000 je flashget.004142FD
00414033 |. 83C0 FE add eax, -2
00414036 |. 83F8 5C cmp eax, 5C
00414039 |. 0F87 E2050000 ja flashget.00414621
0041403F |. 33D2 xor edx, edx
00414041 |. 8A90 0C474100 mov dl, ds:[eax+41470C]
00414047 |. FF2495 284641>jmp near ds:[edx*4+414628]
0041404E |> 8B81 48010000 mov eax, ds:[ecx+148] ; Case 3D of switch 00414024
00414054 |. C2 0400 retn 4
00414057 |> 8B81 C4010000 mov eax, ds:[ecx+1C4] ; Case 39 of switch 00414024
0041405D |. 25 00200000 and eax, 2000
00414062 |. C2 0400 retn 4
00414065 |> 8B81 2C010000 mov eax, ds:[ecx+12C] ; Case 2A of switch 00414024
0041406B |. C2 0400 retn 4
0041406E |> 8B81 30010000 mov eax, ds:[ecx+130] ; Case 2B of switch 00414024
00414074 |. C2 0400 retn 4
00414077 |> 8B81 34010000 mov eax, ds:[ecx+134] ; Case 2E of switch 00414024
0041407D |. C2 0400 retn 4
00414080 |> 8B81 38010000 mov eax, ds:[ecx+138] ; Case 2C of switch 00414024
00414086 |. C2 0400 retn 4
00414089 |> 8B81 3C010000 mov eax, ds:[ecx+13C] ; Case 2D of switch 00414024
0041408F |. C2 0400 retn 4
00414092 |> 8B81 CC010000 mov eax, ds:[ecx+1CC] ; Case 2 of switch 00414024
注意了,就是这里,程序把ds:[00519C8C]的值0A送给了eax,然后后面的程序又把eax的值压入了堆栈,下面就是要看一下ds: [00519C8C]处的值是什么时候被写入的,因为系统刚启动时这里仍然是00,对这里下硬件写入断点,重新启动FlashGet

00414098 |. C2 0400 retn 4
0041409B |> 8B81 D0010000 mov eax, ds:[ecx+1D0] ; Case 3 of switch 00414024

运行后断在这里:
0041738D |. 6A 0A push 0A ; 最大限制
0041738F |. 68 98FC5000 push flashget.0050FC98 ; ASCII “Max Parallel Num”
00417394 |. 68 FCE45000 push flashget.0050E4FC ; ASCII “General”
00417399 |. 8BCE mov ecx, esi
0041739B |. 8986 E8000000 mov ds:[esi+E8], eax
004173A1 |. E8 1A7D0B00 call flashget.004CF0C0
004173A6 |. 83F8 1E cmp eax, 1E ; 和30比较
004173A9 |. 8986 CC010000 mov ds:[esi+1CC], eax
004173AF |. 7E 0A jle short flashget.004173BB ; 如果限制大于30就默认写为30
004173B1 |. C786 CC010000>mov dword ptr ds:[esi+1CC], 1E
004173BB |> 6A 08 push 8
呵呵,这里提示很明显,就是最大下载线程数的限制,需要注意的是0041738D处的push 0A就是最大限制,可以把这里改的稍微大一些,比如push 32(就是50),但是需要注意的是004173A6处还要和1E做比较,如果你改的数超过30,程序会自动把最大限制改成30,因此如果改的最大限制数超过30,就必须把这个cmp eax, 1E处的判定也修改一下,不过一般来说下载线程数30对于教育网来说就足够了,改的太大其实根本不会使下载速度变快,可能还会拖垮自己的电脑,很没有必要,我建议修改成1E就可以了,这样后面也不用改。

总结一下,简单修改的办法,用UltraEdit或类似的能进行16进制编辑的编辑器打开Flashget.exe文件,搜索6A0A6898FC5000,把其中的0A修改为1E就可以使最大进程数变为30了,如果还想变的更大些,就不仅仅要把这里改一下,而且还要把紧接在后面不远处的83F81E的1E也改为你修改的数值即可,也就是把判定换掉。需要注意的是这里只能把限制改成FF (即255)以内的数,也就是只能修改0A那一位,当然,想改成最大线程数是10000也可以,把那段判断的程序整个不要,重新改写一下源程序也就行了,也不难的,不过改成那么BT的数完全没意义,对下载速度没有啥贡献。


分类: 逆向手札, 随心所记 由 ssfighter 于 2006年5月23日 发表

自己的软件写的不怎么样,却天天琢磨着写一点程序就要注册挣钱,真是不让人鄙视都对不起作者本人。以前就看人说过要想挣钱就先把自己的软件写好,今天终于见识了一个挣钱不要脸的人了。我实在是不能理解作者怎么就能那么缺钱……

从天空软件站上下载了一个定时关机的小软件,软件创意还是不错的,不过功能挺一般的,却要收一大笔票子,看了程序就忍不住想骂作者……而且没注册的话限制还超级多,首先是只能连续运行一个小时,而且设置的时间不能保存,还有恶性的nag窗口,真不知道不注册的话这个程序还能干什么,ft2death。越看越想骂作者sb。

AsPack加的壳,不难脱,发现是FoxPro编的程序,用FoxTools可以完整地反编译。这个程序问题实在不少,其注册文件是放在相同目录下的。经常是启动了程序之后,根本就不去就退出了。最大的问题还是对注册码的判定上,因为我根本就不关心其他的功能。 FoxTools反编译后可以看到完整清晰的源程序(不得不说FoxTools确实太强大了),找到ZC.PRG,程序如下:

parameters xlh,zch
try
if ALLTRIM(UPPER(VARTYPE(xlh))) == “C” and ALLTRIM(UPPER(VARTYPE(zch))) == “C”
if LEN(ALLTRIM(xlh)) = 10 and LEN(ALLTRIM(zch)) = 10 and ALLTRIM(zch) == LEFT(ALLTRIM(STR((SQRT(SQRT(VAL(ALLTRIM(xlh))))/3.1)*67237770,30,0)),10)
else
sbtsbl = .t.
endif
else
sbtsbl = .t.
endif
catch
do tcxt.prg
endtry

xlh 就是序列号,大概是先取硬盘序列号,然后经过一系列简单的运算得到的。zch就是输入的注册号,从上面可以看到,正确的注册号应该是序列号开四次方再除以 3.1再乘以67237770后取整,如果位数大于10位就取前10位。不过因为序列号就是10位的,所以正确的注册号不会大于10位。注册算法大概就是这样,但是程序有问题,他执行时候得到的序列号好像是2002啥的来着,按照上面计算得到的算法输进去不对,后来用FoxPro直接打开程序一点点执行,发现启动时候经常是无法正确读取数据库文件,而且用FoxPro运行取得的注册号和单独执行时显示的完全不一样,不知道为什么,这样执行后得到的序列号用上面的算法可以得到正确的注册号并注册通过,但是重新启动程序之后又发现序列号又变了,注册又变得失败了,再次ft2death,也不知道是我系统的问题还是他程序的问题,不过我感觉他的程序问题多多,真是受不了这种类似于测试版的破程序拿出来卖钱的人是出于一种怎样的心理。为了弄这个破程序我还特意装了一份FoxPro8.0,结果仅仅知道了注册算法,但是不知道为什么就不能注册……

其实我破解软件本身就是出于爱好,世界上写程序的人千千万万,程序写的好坏也不尽相同,但是我真的忍不住想骂这个破程序的作者,自己的程序写的bug百出还要拿出来卖钱,而且本身功能就不多未注册限制还不少,这根本就是逼着人家必须注册……中国的程序员现在普遍都有一种浮躁的心理,这也可能就是我们这个浮躁的社会的体现吧。中国的好多软件都是自己的功能没怎么完善,但是加密、防盗版的技术做得特好,让人忍不住怀疑这个作者到底是在写软件,还是在练习防破解的技术。作为热爱中国软件业的人来说,真的不希望这种现象继续下去,挣钱是要在把自己的软件尽可能完善的基础上的,再也不愿意看到这样的程序了,也希望中国不要再有这样的程序员。


分类: 逆向手札 由 ssfighter 于 2006年5月22日 发表

应该说题目出的还是挺不错的,可惜我已经考完三级了,不然实在是应该用这个做一下题的,题量也比较大,觉得用来复习还是很不错的。程序就有一个缺点,就是程序写的太大了,主程序40多兆,估计是把整个题库都放在主程序中了吧,狂汗一下……不知道为什么不再做一个单独的数据文件呢?

由于文件太大,OllyDbg读取速度太慢,索性正好直接用SmartCheck,由于程序没有加反Smartcheck的东西,所以破解起来很顺利,但是看了半天SmartCheck里面的API调用,没看明白序列号和注册号之间有什么联系,只是找到了一个注册号,估计用在别人电脑上因为序列号不对也没啥用吧,写在这里好了:

我的序列号:RIPESOFTSJ793280335,注册码:CwrskuwDrgI

不过这个软件做得还是很不错的,完全应该加上适当的加密措施,这么就被破解,sigh,有点替科惠尔公司感到遗憾了……


分类: 岁月流光 由 ssfighter 于 2006年5月19日 发表

很久以来都想写点有关我的高中的东西,毕竟高中生活是我生命中很精彩的一段时光,每当我一个人静静地回忆过去的时候,总能想起那个建在山顶的操场,那个载着很多回忆的教室,以及那个当年不知天高地厚的男孩。如今这一切已经离我越来越远,这两年每年回家经过我的高中门口,终究没有再进去,然而思念的狂潮总是如汹涌的潮水不断像我袭来,我终于忍不住想写一点有关怀念我的高中的东西了。
其实高中带给我的早已不是连续的回忆了,那逝去的点点滴滴如今已经成为记忆的碎片存留在大脑中,有的那么清晰可见,有的却如尘封了多年的相片,覆盖了一层薄薄的尘土,总让人忍不住轻轻拂去,将那美化的回忆再次细细品位。高中的生活留给我的只是一段段记忆的片断,我努力回忆着这些片断,试图将他们连为一体,但我无能为力,可能这就是逝去的岁月的必然结果吧。也好,过去了就过去了吧,高中时候那些亲密的伙伴,那些一起拼搏的“战友”,以及那曾经深爱的人,就让他们都化作片片飞花,静静地飘落吧。

我终于不试图写一段我的完整的高中生活,我只想记下高中时候那些值得珍藏的岁月的片断,记在这里,也永远尘封在记忆深处,供我一生细细回味。

1. 先从初中时候说起,我的初中离高中说远不远,说近也不近。站在初中走廊的窗台上就能远远望见我的高中,那是因为高中建在山顶上,往上看自然容易看见,但是如果走过去估计至少也要走上一个小时。初二时候物理老师就教育我们要好好学习,说初三的学长天天就趴在走廊的窗台上看育明高中,但是无奈之前没有用功,去不了啊,以此勉励我们努力学习。那些初三学长的感受在我即将中考的时候也袭上心来,我每天也都会在那个窗台遥望一会儿,想像着未来的我的位置。

2. 后来终于如愿以偿地上了育明高中,可惜我好像天生就是不珍惜环境的人,刚上高中时候不知道用功。那个时候尤其不喜欢学习英语,老师在课堂上补充了很多词汇,可惜自己都没有认真地去背一个词,结果弄得整个高中时候英语成绩及其惨不忍睹,而且后遗症就是现在要在英语上画那么多功夫去背单词,去补以前落下的东西,想起来真是有些后悔啊。

3. 提到我的高中不得不提到分班,也许这是我们那片重点高中的通病吧,校长总希望把最好的学生都聚到一起让他们比着学,但是却不曾想到每次分班都是一次心情的振荡。这尤其以高一第一学期末的分班为甚,记得那次放假之前就已经分好班了,我们十班聚在一起搞联欢,大家后来都挺难过的,挺好的一个班级,分开真的觉得很可惜,一直到现在我还觉得最初的那个十班同学之间的感情是最好的,那次分班实在是很伤感的一次分别。可惜到后来分班次数太多,弄得自己都麻木了, sigh。

4. 高一的时候,有个mm追我,被我拒了:( 后来高中时候她就一直没有理过我,一直到上了大学,我才又和她有联系,才知道原来她一直都还那么喜欢我,去年她去了法国,去法国之前她还对我说仍然很喜欢我。每每想到她,我总是会有一种内疚感,我真的不值得你为我付出那么多感情啊,不知道你在浪漫的异国他乡过的怎样,我知道你恐怕永远都看不到这篇文章,但是我真的一直都感觉相当愧疚,希望你未来一切都好,能有一个深爱你的男人,不要像我这样,白白浪费着你的感情,对不起:(

5. 也是高一的时候,第一次有了爱一个人的感觉,有了对一个人的思念和牵挂,只可惜这一切来的都太早。年少的我不懂珍惜,尽管她后来成了我短暂的女友,但是我终究还是没能把握住这份感情,即使现在想起来都会觉得相当遗憾,也正如她所说的,其实如果没有那些,我们现在会是很好的哥们。但是那些事情已经发生,而且感情已经过去,随着那份感情在我心中逐渐淡漠,我只希望现在的她能够拥有自己的幸福:)

6. 高中的时候,去食堂抢饭永远是一件让人乐此不疲的事情。由于食堂小,是分时间供应伙食的。就是中午或者晚上下课的时候,有一批同学享有第一批去吃饭的权利,另一批同学必须先等待二十分钟才能去吃,一个月后这两批同学的吃饭时间对换。因此,只要在一下课的,如果往窗外看,总能看到一批接一批的学生像冲向战场的勇士一样,拎着筷子和勺子,用比跑百米还要快的速度冲向食堂。很荣幸,我也当过这批勇士,只是那个时候跑了那么多百米,到现在跑百米还是很慢,觉得有点对不住食堂啊。

7. 高中的时候做操要做三套操,分别是两套广播体操和一套太极拳,那个时候上体育课天天学太极拳和广播体操,都没有时间自由活动,想起来就埋怨学校啊:) 不过最郁闷的还是我这毫无协调性的身体,打出来的太极拳看起来总是像打醉拳,弄得老师经常过来批评我为什么不认真打。我冤枉啊,其实我有很认真地在打,但是我打出来的就是像醉拳,任你怎么纠正都没用,我对不起老师对不起党啊……

今天太晚了,就先回忆到这里,过几天接着写
to be continued…..