【破文作者】xu_wh (在别的论坛,我的注册名是xu_wh,只有在这里是yuyu)
【所属组织】PCG
【作者主页】
【 E-mail 】xu_wh@163.com
【 作者QQ 】
【文章题目】利用OD,增加FlashGet同时下载的线程
【软件名称】FlashGet 1.7
【使用工具】OD,UltraEdit
【软件限制】
【破解平台】WinXP
=======================================================================================================
【文章简介】
FlashGet默认的一个任务下载的最大线程是10个。往往10个线程是不够用的。网上有关于这个问题的补丁,但是没有文字说明。本文的目的是做这个方面的研究。
=======================================================================================================
【反向过程】
今天没有上班,就在家里看看书,补补内功。
突然想到,我的FlashGet虽然已经注册过了,但是,单个任务下载还是限制在10个线程内。今天就扩展一下吧,
以前在找FlashGet 1.65注册算法的时候用OD跟过。现在又要对你动手了,呵呵~~~~。
先运行软件,右键点击一个在下载的任务,选择属性。在我用的版本是文件分成2份同时下载,那么我们输入20,点击确定,出现一个对话框:说明我们输入的数字只能在0-10之间。好了,这个对话框就成了我们下手的入口点了:
1,OD载入程序,bp MessageBoxA,F9,我们来到这里:
004C1E60 /$ 55 push ebp
004C1E61 |. 8BEC mov ebp,esp
004C1E63 |. 81EC 14010000 sub esp,114
004C1E69 |. 53 push ebx
```````` (略)
004C1EF6 |. 68 04010000 push 104 ; /BufSize = 104 (260.)
004C1EFB |. 50 push eax ; |PathBuffer
004C1EFC |. 6A 00 push 0 ; |hModule = NULL
004C1EFE |. 8DBD ECFEFFFF lea edi,dword ptr ss:[ebp-114] ; |
004C1F04 |. FF15 A8234E00 call near dword ptr ds:[<&KERNEL32>; \GetModuleFileNameA
004C1F0A |> 53 push ebx ; /Style
004C1F0B |. 57 push edi ; |Title
004C1F0C |. FF75 08 push dword ptr ss:[ebp+8] ; |Text
004C1F0F |. FF75 F4 push dword ptr ss:[ebp-C] ; |hOwner
004C1F12 |. FF15 84254E00 call near dword ptr ds:[<&USER32.M>; \MessageBoxA
004C1F18 |. 85F6 test esi,esi ; flashget.00513A2C
=============================================================================
从004C1F12向上,我们没有找到能跳过这个对话框的语句,所以,执行到这里是由调用004C1E60的部分决定的,所以,我们要找到是谁调用了这段子程序。我们来到这里:
=============================================================================
004C1F47 /$ 55 push ebp
004C1F48 |. 8BEC mov ebp,esp
004C1F4A |. E8 BEA10000 call flashget.004CC10D
004C1F4F |. 8B40 04 mov eax,dword ptr ds:[eax+4]
004C1F52 |. 85C0 test eax,eax
004C1F54 |. 74 15 je short flashget.004C1F6B
004C1F56 |. FF75 10 push dword ptr ss:[ebp+10]
004C1F59 |. 8B10 mov edx,dword ptr ds:[eax]
004C1F5B |. 8BC8 mov ecx,eax
004C1F5D |. FF75 0C push dword ptr ss:[ebp+C]
004C1F60 |. FF75 08 push dword ptr ss:[ebp+8]
004C1F63 |. FF92 8C000000 call near dword ptr ds:[edx+8C]
004C1F69 |. EB 10 jmp short flashget.004C1F7B
004C1F6B |> FF75 10 push dword ptr ss:[ebp+10] ; /Arg3
004C1F6E |. 33C9 xor ecx,ecx ; |
004C1F70 |. FF75 0C push dword ptr ss:[ebp+C] ; |Arg2
004C1F73 |. FF75 08 push dword ptr ss:[ebp+8] ; |Arg1
004C1F76 |. E8 E5FEFFFF call flashget.004C1E60 ; \flashget.004C1E60
004C1F7B |> 5D pop ebp
004C1F7C \. C2 0C00 retn 0C
=============================================================================
是程序在通常情况下04C1F63处调用上面的过程的。要想对后面的语句进行控制,必须控制JE的跳转。在004C1F4F上下断,CTRL+F2重来,断在004C1F4A处,发现EAX=00513990,这显然是一个变量的地址,所以对EAX的判断是不能修改的确。我们再往前找。看看是谁调用004C1F47的。我们找到这里:
=============================================================================
004C0D76 /$ B8 B4F94D00 mov eax,flashget.004DF9B4
004C0D7B |. E8 5824FEFF call flashget.004A31D8
004C0D80 |. 83EC 40 sub esp,40
004C0D83 |. 57 push edi
004C0D84 |. 8B7D 08 mov edi,dword ptr ss:[ebp+8]
004C0D87 |. 833F 00 cmp dword ptr ds:[edi],0
004C0D8A |. 74 6B je short flashget.004C0DF7
004C0D8C |. 56 push esi
004C0D8D |. 8B35 D4254E00 mov esi,dword ptr ds:[<&USER32.wsp>; USER32.wsprintfA
004C0D93 |. FF75 0C push dword ptr ss:[ebp+C]
004C0D96 |. 8D45 B4 lea eax,dword ptr ss:[ebp-4C]
004C0D99 |. FF75 14 push dword ptr ss:[ebp+14] ; |Format
004C0D9C |. 50 push eax ; |s
004C0D9D |. FFD6 call near esi ; \wsprintfA
004C0D9F |. FF75 10 push dword ptr ss:[ebp+10]
004C0DA2 |. 8D45 D4 lea eax,dword ptr ss:[ebp-2C]
004C0DA5 |. FF75 14 push dword ptr ss:[ebp+14] ; |Format
004C0DA8 |. 50 push eax ; |s
004C0DA9 |. FFD6 call near esi ; \wsprintfA
004C0DAB |. A1 58135100 mov eax,dword ptr ds:[511358]
004C0DB0 |. 83C4 18 add esp,18
004C0DB3 |. 8945 08 mov dword ptr ss:[ebp+8],eax
004C0DB6 |. 8D45 D4 lea eax,dword ptr ss:[ebp-2C]
004C0DB9 |. 8365 FC 00 and dword ptr ss:[ebp-4],0
004C0DBD |. 50 push eax
004C0DBE |. 8D45 B4 lea eax,dword ptr ss:[ebp-4C]
004C0DC1 |. 50 push eax
004C0DC2 |. 8D45 08 lea eax,dword ptr ss:[ebp+8]
004C0DC5 |. FF75 18 push dword ptr ss:[ebp+18]
004C0DC8 |. 50 push eax
004C0DC9 |. E8 36200000 call flashget.004C2E04
004C0DCE |. FF75 18 push dword ptr ss:[ebp+18] ; /Arg3
004C0DD1 |. 6A 30 push 30 ; |Arg2 = 00000030
004C0DD3 |. FF75 08 push dword ptr ss:[ebp+8] ; |Arg1
004C0DD6 |. E8 6C110000 call flashget.004C1F47 ; \flashget.004C1F47
004C0DDB |. 8D4D 08 lea ecx,dword ptr ss:[ebp+8]
004C0DDE |. E8 F34EFFFF call flashget.004B5CD6
004C0DE3 |. 8BCF mov ecx,edi
004C0DE5 |. E8 BFFBFFFF call flashget.004C09A9
=============================================================================
在上面这段程序中,只有一个跳转语句,而比较的条件是一个变量和 0 进行比较,我们大家需要的和 A (因为最大是10)进行比较,所以还要向上找,(不要怕麻烦呀,主席教导我们:坚持就是胜利!),是下面这部分程序调用上面的:
=============================================================================
004C0E06 /$ 55 push ebp
004C0E07 |. 8BEC mov ebp,esp
004C0E09 |. 8B45 0C mov eax,dword ptr ss:[ebp+C] ; eax是同时下载的线程数
004C0E0C |. 3B45 10 cmp eax,dword ptr ss:[ebp+10] ; ss:[ebp+10] = 1, 是最小值
004C0E0F |. 7C 05 jl short flashget.004C0E16
004C0E11 |. 3B45 14 cmp eax,dword ptr ss:[ebp+14] ; ss:[ebp+14] =A, 是最大值
004C0E14 |. 7E 18 jle short flashget.004C0E2E
004C0E16 |> 68 12F10000 push 0F112
004C0E1B |. 68 B4A45000 push flashget.0050A4B4 ; ASCII "%ld"
004C0E20 |. FF75 14 push dword ptr ss:[ebp+14]
004C0E23 |. FF75 10 push dword ptr ss:[ebp+10]
004C0E26 |. FF75 08 push dword ptr ss:[ebp+8]
004C0E29 |. E8 48FFFFFF call flashget.004C0D76
004C0E2E |> 5D pop ebp
004C0E2F \. C2 1000 retn 10
=============================================================================
eax是我们输入的同时可以下载的线程数,如果这个值比预定的值大,就会出现我们看到的那个信息提示框。所以,我们要追踪eax的来源,它来自ss:[ebp+14],既然是用堆栈的方式,前面一定有一条语句是进栈的:
=============================================================================
调用上面这个子程序的是:
0040CA8F . 8BC8 mov ecx,eax
0040CA91 . E8 5A750000 call flashget.00413FF0 ; F7
0040CA96 . 8B4C24 14 mov ecx,dword ptr ss:[esp+14]
0040CA9A . 50 push eax ; /Arg4
0040CA9B . 6A 01 push 1 ; |Arg3 = 00000001
0040CA9D . 51 push ecx ; |Arg2
0040CA9E . 57 push edi ; |Arg1
0040CA9F . E8 62430B00 call flashget.004C0E06 ; \flashget.004C0E06
0040CAA4 . 8B5424 14 mov edx,dword ptr ss:[esp+14]
0040CAA8 . 8B8E 8C000000 mov ecx,dword ptr ds:[esi+8C]
=============================================================================
执行到这里,eax的值是0000000A,它是在CALL 004C0E06之前就进栈的。我们需要在0040CA91的地方下断,看看eax值的来源,CTRL + F2,在004CA91处断下,我们F7跟进:
00414062 |> \8B81 CC010000 mov eax,dword ptr ds:[ecx+1CC] ; Case 2 of switch 00413FF4
00414068 |. C2 0400 retn 4
=============================================================================
是在这里给eax赋值的,但是ds:[ecx+1CC],这个值是程序用到的一个变量。它的地址在ECX + 1CC = 00513990 + 1CC = 00513B5C。
这个值一定是程序在初始化的时候赋的值,所以,在00513B5C处下断,类型当然要写入断点了,我习惯下硬件断点。好了,CTRL+F2,重新开始:
=============================================================================
004172E3 |. E8 B2500B00 call flashget.004CC39A
004172E8 |. 68 6CDC0200 push 2DC6C
004172ED |. 68 88BA5000 push flashget.0050BA88 ; ASCII "BandWidth"
004172F2 |. 68 C0BA5000 push flashget.0050BAC0 ; ASCII "Connection"
004172F7 |. 8BCE mov ecx,esi
004172F9 |. 8986 E0000000 mov dword ptr ds:[esi+E0],eax
004172FF |. E8 96500B00 call flashget.004CC39A
00417304 |. 6A 08 push 8
00417306 |. 68 7CBA5000 push flashget.0050BA7C ; ASCII "ConnType"
0041730B |. 68 C0BA5000 push flashget.0050BAC0 ; ASCII "Connection"
00417310 |. 8BCE mov ecx,esi
00417312 |. 8986 E4000000 mov dword ptr ds:[esi+E4],eax
00417318 |. E8 7D500B00 call flashget.004CC39A
0041731D |. 6A 0A push 0A
0041731F |. 68 B8BC5000 push flashget.0050BCB8 ; ASCII "Max Parallel Num"
00417324 |. 68 FCA45000 push flashget.0050A4FC ; ASCII "General"
00417329 |. 8BCE mov ecx,esi
0041732B |. 8986 E8000000 mov dword ptr ds:[esi+E8],eax
00417331 |. E8 64500B00 call flashget.004CC39A
00417336 |. 83F8 1E cmp eax,1E
00417339 |. 8986 CC010000 mov dword ptr ds:[esi+1CC],eax ; eax=单个任务可同时下载的线程数
0041733F |. 7E 0A jle short flashget.0041734B
00417341 |. C786 CC010000 1E000000 mov dword ptr ds:[esi+1CC],1E
0041734B |> 6A 08 push 8
0041734D |. 68 ACBC5000 push flashget.0050BCAC ; ASCII "MaxSimJobs"
00417352 |. 68 FCA45000 push flashget.0050A4FC ; ASCII "General"
00417357 |. 8BCE mov ecx,esi
00417359 |. E8 3C500B00 call flashget.004CC39A
=============================================================================
大概一看上面的程序就知道,是对注册表进行访问的:)。不过我可是找了,我的注册表里没有这一项。没有的话 EAX 就是10了。注意EAX要和'1E'(30)进行比较的,也就是说,如果你添加注册表,最大不能超过30!,既然我们都要改了,还受这30的限制干什么? ??
动手吧!我机器上的程序我做主!
=============================================================================
我们将:
00417336 |. 83F8 1E cmp eax,1E
00417339 |. 8986 CC010000 mov dword ptr ds:[esi+1CC],eax
0041733F |. 7E 0A jle short flashget.0041734B
改为:
00417336 C1E0 0A shl eax,0A
00417339 |. 8986 CC010000 mov dword ptr ds:[esi+1CC],eax ; eax=单个任务可同时下载的线程数
0041733F EB 0A jmp short flashget.0041734B
好了,用UltraEdit按照左边的偏移,找到机器码,就自己动手改吧!
不过,你不要太狠心,一下子改得很大。可能你的网络也提供不了那么大的带宽,同时,你的线程过多的话,会影响别人的速度。
=======================================================================================================
【我的心得】
在反向的过程中,要坚持,坚持就是胜利!
=======================================================================================================
【声 明】我是一个小小菜虫子,文章如有错误,请高手指正!
【版权声明】本文纯属技术交流, 转载请注明作者并保持文章的完整, 谢谢!
=======================================================================================================
文章完成于2005-12-9 上午 3:51:24 xu_wh[PCG]
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!