XX下载器分析过程

1. 脱壳

查看下载器的PE信息,发现其使用了UPX加壳,所以首先对下载器进行UPX 脱壳。

2. 抓包分析

通过Wireshark查看下载器发送的HTTP请求,发现如下信息:

2.1 下载器发送的第一个请求为:

http://down.72zx.com/xml/web1.xml?winver=6.1

其中如下信息与接下来的HTTP请求相关:

<web>
<id>1</id>
<name>XX软件园</name>
<tag>ONLINEDOWNE</tag>
<xmlurl>
<![CDATA[
http://www.onlinedown.net/api/index.php?action=pc.pconline.soft
]]>
</xmlurl>
<logourl>
<![CDATA[ http://www.onlinedown.net/icon.png ]]>
</logourl>
</web>

2.2 下载器发送的第二个请求为:

http://www.onlinedown.net/api/index.php?action=pc.pconline.soft&webid=1&softid=20355&token=9b89c16eeafa0faf120b0f9b78294677

其返回的内容为xml格式,其中的downsrc保存了下载的来源:

<downsrc><![CDATA[http://crcfj.onlinedown.net/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://fjmcc.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://nmas.onlinedown.net/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://sdmcc.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://jsmcc5.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://sdmcc2.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://jsmcc2.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://cttnb.onlinedown.net/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://nm.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://sccrc.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://nm.onlinedown.net/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://amcc.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://klrs.onlinedown.net/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://sqyd3.newhua.com:82/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://sqyd4.newhua.com:82/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://zjmcc4.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://hlbr.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://cttxj.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://zjmcc5.newhua.com/down/QQ7.4.zip]]></downsrc>
<downsrc><![CDATA[http://jsmcc4.newhua.com/down/QQ7.4.zip]]></downsrc>

尝试改变HTTP请求中的SoftID来下载其他软件,服务器返回错误结果,因此推断后面的token应该是个参数有效性验证的信息。

现在的问题归结为下载器如何生成softidtoken信息。

3. 静态分析

使用IDA对下载器代码进行静态分析。

目前已知信息:

softid为整数: 20355 / 0x00004F83

token是长度为32的十六进制字符串: 9b89c16eeafa0faf120b0f9b78294677

初步静态分析发现:

.text:00569ECC DownloadRealFile proc near ; DATA XREF: .text:00568F5Co

处为下载器启动后与服务器交互并获取下载参数的代码

push    offset aWebid_0 ; "webid="
mov     eax, off_57FA04
push    dword ptr [eax]
push    offset aSoftid_0 ; "&softid="
mov     eax, off_57F550
push    dword ptr [eax]
push    offset aToken_0 ; "&token="
mov     eax, off_57FA04
push    dword ptr [eax+8]

此段代码显示相关信息存放在:

Name Address
softid off_57F550
token off_57FA04

首先从softid入手:

跟踪地址off_57F550

.data:0057F550 off_57F550 dd offset unk_5A569C ; DATA XREF: sub_54C7F4:loc_54C839r

跟踪偏移unk_5A569C

.bss:005A569C unk_5A569C      db    ? ;               ; DATA XREF: sub_54B2D4+37o
.bss:005A569C                                         ; .data:off_57F550o
.bss:005A569D                 db    ? ;
.bss:005A569E                 db    ? ;
.bss:005A569F                 db    ? ;

在此处设置 read/write 硬件断点。

对token做同样的处理:

跟踪地址off_57FA04

.data:0057FA04 off_57FA04 dd offset unk_5A5684 ; DATA XREF: sub_54C7F4+4Br

跟踪偏移unk_5A5684 + 8 -> : .bss : 005A568C

.bss:005A5684 unk_5A5684      db    ? ;               ; DATA XREF: sub_54B2D4+27o
.bss:005A5684                                         ; .data:off_57FA04o
.bss:005A5685                 db    ? ;
.bss:005A5686                 db    ? ;
.bss:005A5687                 db    ? ;
.bss:005A5688                 db    ? ;
.bss:005A5689                 db    ? ;
.bss:005A568A                 db    ? ;
.bss:005A568B                 db    ? ;
-------Here------
.bss:005A568C                 db    ? ;
.bss:005A568D                 db    ? ;
.bss:005A568E                 db    ? ;
.bss:005A568F                 db    ? ;

设置好断点后使用IDA Pro调试。

在如下代码处设置断点:

.text:0056A185                 push    offset aWebid_0 ; "webid="
.text:0056A18A                 mov     eax, off_57FA04
.text:0056A18F                 push    dword ptr [eax]
.text:0056A191                 push    offset aSoftid_0 ; "&softid="
.text:0056A196                 mov     eax, off_57F550
.text:0056A19B                 push    dword ptr [eax]
.text:0056A19D                 push    offset aToken_0 ; "&token="
.text:0056A1A2                 mov     eax, off_57FA04
.text:0056A1A7                 push    dword ptr [eax+8]
----Set breakpoint on next line ----
.text:0056A1AA                 push    offset dword_56AE54
.text:0056A1AF                 mov     eax, off_57F550
.text:0056A1B4                 push    dword ptr [eax]
.text:0056A1B6                 lea     eax, [ebp+var_B8]
.text:0056A1BC                 mov     edx, 3
.text:0056A1C1                 call    sub_407A4C

中断后栈上的值如下所示:

043EFDD8  021794BC  debug031:021794BC
043EFDDC  0056AE38  .text:aToken_0
043EFDE0  0214DF1C  debug031:0214DF1C
043EFDE4  0056AE18  .text:aSoftid_0
043EFDE8  0212B1C4  debug031:0212B1C4
043EFDEC  0056ADFC  .text:aWebid_0

由此可见:

.text:aSoftid_0的值存储在:debug031:0214DF1C

.text:aToken_0的值存储在:debug031:021794BC

检查对应内存地址的值:

Var Address Value
Softid debug031:0214DF1C [0214DF1C] 32 00 30 00 33 00 35 00 35 00 00 00 00 00 00 00 —- 2.0.3.5.5…….
Token debug031:021794BC [021794BC] 4F 00 4E 00 4C 00 49 00 4E 00 45 00 44 00 4F 00 —- O.N.L.I.N.E.D.O.
[021794CC] 57 00 4E 00 45 00 00 00 C0 8C 17 02 B0 04 02 00 —- W.N.E………..

从此处看,Softid已经是最后的值20355,而Token还会进一步处理才会变成最后的值。

分析如下代码显示:

.text:0054BE98 ; =============== S U B R O U T I N E =======================================
.text:0054BE98
.text:0054BE98 ; Attributes: bp-based frame
.text:0054BE98
.text:0054BE98 _csis_Send_Http_Request proc near       ; CODE XREF: sub_5672F0+184p
.text:0054BE98                                         ; sub_569ECC+BDp ...
.text:0054BE98
.text:0054BE98 var_18          = dword ptr -18h
.text:0054BE98 var_14          = dword ptr -14h
.text:0054BE98 var_10          = dword ptr -10h
.text:0054BE98 var_C           = dword ptr -0Ch
.text:0054BE98 var_8           = dword ptr -8
.text:0054BE98 var_1           = byte ptr -1
.text:0054BE98 arg_0           = dword ptr  8

.text:0054BE98处的函数 _csis_Send_Http_Request(为分析方便已重命名) 应该是负责发送HTTP请求的。

且寄存器EAX中将存放需要访问的HTTP地址的指针。

在发送获取下载地址的请求前设置断点,验证在call _csis_Send_Http_Request前,EAX中是否包含正确的token。

.text:0056A284 loc_56A284:                             ; CODE XREF: sub_569ECC+3E0j
.text:0056A284                 lea     edx, [ebp+var_BC]
.text:0056A28A                 mov     eax, [ebp+var_1C]
.text:0056A28D                 call    sub_412C5C
.text:0056A292                 cmp     [ebp+var_BC], 0
.text:0056A299                 jnz     short loc_56A2AB
.text:0056A29B                 lea     eax, [ebp+var_1C]
.text:0056A29E                 push    eax
.text:0056A29F                 mov     cl, 1
.text:0056A2A1                 xor     edx, edx
.text:0056A2A3                 mov     eax, [ebp+var_20]
------Set Break Point at next line-------
.text:0056A2A6                 call    _csis_Send_Http_Request

结果验证了如上的结论

RAX 0000000001ECEA4C debug030:01ECEA4C

debug030:01ECEA4C位置的内容为:

01ECEA4C  68 00 74 00 74 00 70 00  3A 00 2F 00 2F 00 77 00  h.t.t.p.:././.w.
01ECEA5C  77 00 77 00 2E 00 6F 00  6E 00 6C 00 69 00 6E 00  w.w...o.n.l.i.n.
01ECEA6C  65 00 64 00 6F 00 77 00  6E 00 2E 00 6E 00 65 00  e.d.o.w.n...n.e.
01ECEA7C  74 00 2F 00 61 00 70 00  69 00 2F 00 69 00 6E 00  t./.a.p.i./.i.n.
01ECEA8C  64 00 65 00 78 00 2E 00  70 00 68 00 70 00 3F 00  d.e.x...p.h.p.?.
01ECEA9C  61 00 63 00 74 00 69 00  6F 00 6E 00 3D 00 70 00  a.c.t.i.o.n.=.p.
01ECEAAC  63 00 2E 00 70 00 63 00  6F 00 6E 00 6C 00 69 00  c...p.c.o.n.l.i.
01ECEABC  6E 00 65 00 2E 00 73 00  6F 00 66 00 74 00 26 00  n.e...s.o.f.t.&.
01ECEACC  77 00 65 00 62 00 69 00  64 00 3D 00 31 00 26 00  w.e.b.i.d.=.1.&.
01ECEADC  73 00 6F 00 66 00 74 00  69 00 64 00 3D 00 32 00  s.o.f.t.i.d.=.2.
01ECEAEC  30 00 33 00 35 00 35 00  26 00 74 00 6F 00 6B 00  0.3.5.5.&.t.o.k.
01ECEAFC  65 00 6E 00 3D 00 39 00  62 00 38 00 39 00 63 00  e.n.=.9.b.8.9.c.
01ECEB0C  31 00 36 00 65 00 65 00  61 00 66 00 61 00 30 00  1.6.e.e.a.f.a.0.
01ECEB1C  66 00 61 00 66 00 31 00  32 00 30 00 62 00 30 00  f.a.f.1.2.0.b.0.
01ECEB2C  66 00 39 00 62 00 37 00  38 00 32 00 39 00 34 00  f.9.b.7.8.2.9.4.
01ECEB3C  36 00 37 00 37 00 00 00  01 00 00 00 00 00 00 00  6.7.7...........

从调用前的赋值行为.text:0056A2A3 mov eax, [ebp+var_20]看,此结果存储在作为上一级函数的参数传入的地址中。

查找当前函数中所有的对[ebp+var_20]的引用,跟踪到如下位置

.text:0056A22B                 lea     ecx, [ebp+var_20]
------Here-----------------------------^^^^^^^^^^^^^^^^^------
.text:0056A22E                 mov     eax, off_57FA04
.text:0056A233                 mov     eax, [eax+0Ch]
.text:0056A236                 call    sub_54B434
.text:0056A23B                 lea     eax, [ebp+var_1C]
.text:0056A23E                 xor     edx, edx
.text:0056A240                 call    sub_4074D8
.text:0056A245                 mov     eax, [ebp+var_64]
.text:0056A248                 mov     dword ptr [eax+48h], 3
.text:0056A24F                 mov     eax, [ebp+var_64]
.text:0056A252                 add     eax, 40h
.text:0056A255                 mov     edx, [ebp+var_20]
.text:0056A258                 call    sub_407484

.text:0056A236                 call    sub_54B434

处设置断点,观察在call前后[ebp+var_20]指向位置的变化,可以发现,在call之后,[ebp+var_20]所指位置的指针发生改变,从指针指向的结果字符串可得如下结论:

  1. [ebp+var_20]所存为指向字符串的指针。
  2. .text:0056A236 call sub_54B434可能是调用了一个类似于字符串format的函数。

如果是format函数,那么用于format的参数应该在call之前通过寄存器或者栈设置好。

往前回溯:

.text:0056A21B                 mov     edx, 6
.text:0056A220                 call    sub_407A4C
--------------------------------------------------------
.text:0056A225                 mov     edx, [ebp+var_A4]
.text:0056A22B                 lea     ecx, [ebp+var_20]
.text:0056A22E                 mov     eax, off_57FA04
.text:0056A233                 mov     eax, [eax+0Ch]
.text:0056A236                 call    sub_54B434

.text:0056A236 call sub_54B434 处设置断点,查看在call之前各寄存器的值。

得到如下结果:

RDX 0000000001FC2B24 debug040:01FC2B24

01FC2B24  77 00 65 00 62 00 69 00  64 00 3D 00 31 00 26 00  w.e.b.i.d.=.1.&.
01FC2B34  73 00 6F 00 66 00 74 00  69 00 64 00 3D 00 32 00  s.o.f.t.i.d.=.2.
01FC2B44  30 00 33 00 35 00 35 00  26 00 74 00 6F 00 6B 00  0.3.5.5.&.t.o.k.
01FC2B54  65 00 6E 00 3D 00 39 00  62 00 38 00 39 00 63 00  e.n.=.9.b.8.9.c.
01FC2B64  31 00 36 00 65 00 65 00  61 00 66 00 61 00 30 00  1.6.e.e.a.f.a.0.
01FC2B74  66 00 61 00 66 00 31 00  32 00 30 00 62 00 30 00  f.a.f.1.2.0.b.0.
01FC2B84  66 00 39 00 62 00 37 00  38 00 32 00 39 00 34 00  f.9.b.7.8.2.9.4.
01FC2B94  36 00 37 00 37 00 00 00  00 00 00 00 00 00 00 00  6.7.7...........

也就是说,在.text:0056A236 call sub_54B434 之前,token已经生成好了,而且其存放的位置为:

[ebp+var_A4]

同上,查找所有对 [ebp+var_A4] 的引用,有如下发现:

.text:0056A215                 lea     eax, [ebp+var_A4]
-------Here---------------------------------^^^^^^^^^^^^
.text:0056A21B                 mov     edx, 6
.text:0056A220                 call    sub_407A4C
.text:0056A225                 mov     edx, [ebp+var_A4]

.text:0056A220 call sub_407A4C 设置断点,查看call前后 [ebp+var_A4] 指向的值时候已包含token。

跟踪进入.text:0056A220 call sub_407A4C的执行过程:

.text:00407AA0 loc_407AA0:                             ; CODE XREF: sub_407A4C+50j
.text:00407AA0                 mov     ecx, [ebp+edx*4+4]
--------------------------------------------^^^^^^^^^^^^^-------
.text:00407AA4                 test    ecx, ecx
.text:00407AA6                 jz      short loc_407AE7
.text:00407AA8                 cmp     word ptr [ecx-0Ah], 2
.text:00407AAD                 jz      short loc_407AD3
.text:00407AAF                 mov     esi, eax
.text:00407AB1                 mov     [ebp+var_4], edx
.text:00407AB4                 mov     eax, [ebp+edx*4+4]
.text:00407AB8                 call    sub_40746C

从指令的执行过程看,当指令执行到.text:00407AA0 mov ecx, [ebp+edx*4+4]时,程序将debug041:00000000015C86C4赋值给了ECX,而此位置存储的是Token的值。

那么问题来了,debug041:00000000015C86C4是否是程序的常值?

让我们验证一下,等待程序启动,然后在内存中搜索

39 00 62 00 38 00 39 00 63 00 31 00 36 00 65 00 65 00 61 00 66 00 61 00 30 00 66 00 61 00 66 00

各种结果显示,在如下call之后,Token在内存中被成功生成:

.text:0056A1DC                 mov     eax, [ebp+var_B4]
.text:0056A1E2                 lea     edx, [ebp+var_B0]
.text:0056A1E8                 call    _CSIS_Gen_Token
------^^^^^^^^-------------------------^^^^^^^^^^-------
.text:0056A1ED                 mov     edx, [ebp+var_B0]
.text:0056A1F3                 lea     eax, [ebp+var_AC]

.text:0056A1DC mov eax, [ebp+var_B4]处将一个内存地址复制给EAX,查看所指向的内容,发现其中内容为:

EAX 000000000208950C debug047:0208950C

0208950C  4F 4E 4C 49 4E 45 44 4F  57 4E 45 5F 32 30 33 35  ONLINEDOWNE_2035
0208951C  35 00 00 00 00 00 00 00  91 96 08 02 B0 04 02 00  5...............

回想Token字符串的组织形式,发觉其与MD5非常类似,因此猜测Token的生成算法可能是MD5,使用MD5对如上的字符串ONLINEDOWNE_20355做散列运算,得到字符串9b89c16eeafa0faf120b0f9b78294677,与获取下载地址的HTTP请求中的Token一致!猜测正确!Nice!

4. 结论:

Token生成算法为 MD5(“ONLINEDOWNE_” + SoftID),SoftID为对应的软件ID。

现在剩下的问题为查找SoftID的存储位置。

4.1 静态查找

在IDA字符串窗口中搜索”20355” 的Unicode字符串与Ascii字符串,无果。

使用 20355 的十六进制 0x4F83在二进制文件中搜索 83 4F和4F 83,有结果,但是结果排查发现,其基本与发送请求不相关。

4.2 动态查找

使用IDA调试运行程序,然后在内存中搜索32 00 30 00 33 00 35 00

有意外发现:下载的文件名中就包含有SoftID…譬如:腾讯[email protected]中的20355。

为了排除文件名对内存搜索的影响,复制一份二进制文件,并修改文件名,去除掉其中的20355,另开一个IDA,调试运行此二进制文件。

结果发现:无论怎么运行,该二进制文件都显示无法获取下载信息的错误,费解… 使用改名前的二进制文件运行,无任何问题… 此时开始怀疑猜测下载器是从文件名中获取参数信息的。

为验证此猜测,对文件名进行修改,并运行查看是否能获取下载信息,测试结果如下:

FileName Run Result
腾讯[email protected] Fail
腾讯[email protected] Succ
[email protected] Succ

从以上结果可见,仅当下载器的文件名构成为

描述信息 + “_” + webid + “@” + softid + “.exe”

且各参数有效时,下载器才能正常工作,这说明猜测是合理的:下载器从自己的文件名中获取下载参数信息

5. 总结:

现在重新梳理下问题与结论:

Question

XX下载器是如何获取下载连接地址的?

Answer

使用类似如下链接的HTTP请求获取:

http://www.onlinedown.net/api/index.php?action=pc.pconline.soft&webid=1&softid=20355&token=9b89c16eeafa0faf120b0f9b78294677

其中webidsoftid参数包含在下载器的文件名中,所处位置为:[email protected]。

token参数为字符串 "ONLINEDOWNE_"加上 softid 后进行MD5散列运算后的值。

.

Question

如何在不下载下载器的情况下获取一个软件的SoftID。

Answer

XX软件站每个软件下载页面的URL中已包含相应的SoftID。

附录

附录A

通过SoftID获取下载链接的Python代码:

# -*- coding: utf-8 -*- 

import urllib2
from cookielib import CookieJar
import md5
import re
import sys

softid = 20355

m = md5.new()
m.update("ONLINEDOWNE_%s" % softid)
token = m.hexdigest()

opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(CookieJar()))
URL = ‘http://www.onlinedown.net/api/index.php?action=pc.pconline.soft&webid=1&softid=%d&token=%s‘ % (softid , token)

try:
    response = opener.open(URL)
    content = response.read()
except Exception, e:
    print "[Error]: Error in reading url content..."
    print e
    sys.exit()

try:
    pattern = re.compile(r‘<downsrc><!\[CDATA\[(.*)\]\]></downsrc>‘)
    match = re.match(pattern, content)
    DownloadURLs = pattern.findall(content)
except Exception, e:
    print "[Error]: Error in match urls..."
    print e
    sys.exit()

for url in DownloadURLs:
    print url

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-07-31 16:51:19

XX下载器分析过程的相关文章

CTB-Locker敲诈者病毒下载器分析

一. 样本基本信息 样本名称:927354529512.scr 样本大小:110592 字节 病毒名称:Win32.Trojan.Ctb-locker.Auto 样本MD5值:3A6D7E551C132AC4C40D95394938F266 二. 样本脱壳 该样本的出现的时间是2015.5.14日,和今年4月底出现的敲诈者病毒是同一批次,因为下载病毒的网址是一样的,和前面提到的情况一样,病毒依然在程序的代码指令中加入了比较多的垃圾指令,有可能是敲诈者病毒的心态有点急了.4月份出现的敲诈者病毒没之

Python实现多线程HTTP下载器

本文将介绍使用Python编写多线程HTTP下载器,并生成.exe可执行文件. 环境:windows/Linux + Python2.7.x 单线程 在介绍多线程之前首先介绍单线程.编写单线程的思路为: 解析url: 连接web服务器: 构造http请求包: 下载文件. 接下来通过代码进行说明. 解析url 通过用户输入url进行解析.如果解析的路径为空,则赋值为'/':如果端口号为空,则赋值为"80":下载文件的文件名可根据用户的意愿进行更改(输入'y'表示更改,输入其它表示不需要更

Elasticsearch的分析过程,内置字符过滤器、分析器、分词器、分词过滤器(真是变态多啊!美滋滋)

分析过程 当数据被发送到elasticsearch后并加入倒排序索引之前,elasticsearch会对文档进行处理: 字符过滤:使用字符过滤器转变字符. 文本切分为分词:将文本(档)分为单个或多个分词. 分词过滤:使用分词过滤器转变每个分词. 分词索引:最终将分词存储在Lucene倒排索引中. 整体流程: 目的是达到人性化的分词 内置字符过滤器 HTML字符过滤器.映射字符过滤器.模式替换过滤器 HTML字符过滤器 POST _analyze { "tokenizer": "

自己动手写工具:百度图片批量下载器

开篇:在某些场景下,我们想要对百度图片搜出来的东东进行保存,但是一个一个得下载保存不仅耗时而且费劲,有木有一种方法能够简化我们的工作量呢,让我们在离线模式下也能爽爽地浏览大量的美图呢?于是,我们想到了使用网络抓取去帮我们去下载图片,并且保存到我们设定的文件夹中,现在我们就来看看如何来设计开发一个这样的图片批量下载器. 一.关于网络抓取与爬虫 网络蜘蛛的主要作用是从Internet上不停地下载网络资源.它的基本实现思想就是通过一个或多个入口网址来获取更多的URL,然后通过对这些URL所指向的网络资

.NET破解之太乐地图下载器【非暴破】

不知不觉,接触破解逆向已经三个月了,从当初的门外汉到现在的小白,这个过程只有经历过才知道其中的苦与乐: 有无知.困惑.痛苦.惊喜.彻悟.欣慰…… 有无助的软件脱壳,茫然的代码分析,有无趣的反复测试, 有人说破解不应该程序员干的事,我回复我不是程序员: 有人说.NET程序太没难度了,去破安卓,后来我真开始研究起安卓来: 有人说能不能把支付宝破了,我没回答. 虽然很忙,时间少,但每天晚上都要抽些时间来关注52论坛,关注破解:虽然并没有从破解中获取物质利益,但我愿意将自己的心得或作品分享给大家.不管怎

BT下载原理分析

版权声明:本文为博主原创文章,未经博主允许不得转载. BitTorrent协议. BT全名为BitTorrent,是一个p2p软件,你在下载download的同时,也在为其他用户提供上传upload,因为大家是“互相帮助”,所以不会随着用户数的增加而降低下载速度. 下面是一般用ftp,http等分享流程: 下面是用BitTorrent分享的流程: 其实跟ED也十分相似,ED跟BT不同的地方有: ED--要连上一个固定server BT--没有固定server,只要分享者制作出该分享档案的.tor

用python实现的百度音乐下载器-python-pyqt-改进版

之前写过一个用python实现的百度新歌榜.热歌榜下载器的博文,实现了百度新歌.热门歌曲的爬取与下载.但那个采用的是单线程,网络状况一般的情况下,扫描前100首歌的时间大概得到40来秒.而且用Pyqt做的界面,在下载的过程中进行窗口操作,会出现UI阻塞的现象. 前两天有时间调整了一下,做了几方面的改进: 1.修改了UI界面阻塞的问题,下载的过程中可以进行其它的UI操作; 2.爬虫程序采用一个主线程,8个子线程的方式快速爬取,网络状况一致的情况下,将扫描100首歌曲的时间提高到了8.9秒左右:(本

自己动手写美女图片下载器

前言:看到标题可能会有人觉得似曾相识,没错,这篇博文的来源正是根据杨中科老师的<百度美女图片下载器开发教程.Net版>.因为我也观看了该教程,觉得很好玩,于是乎想自己独立完成一次,作为对之前基础学习内容的回顾和运用.以博文的形式和大家分享整个开发过程主要是想借此机会来重新整理下思路.锻炼下自己的表达能力.您如果对下面要用到知识点很熟悉,可忽略此文. 一.主要技术 Winform常用控件的基本使用 HttpWebRequest请求其他网站内容 Newtonsoft.Json.dll组件解析JSO

python动态视频下载器

这里向大家分享一下python爬虫的一些应用,主要是用爬虫配合简单的GUI界面实现视频,音乐和小说的下载器.今天就先介绍如何实现一个动态视频下载器. 爬取电影天堂视频 首先介绍的是python爬取电影天堂网站的视频(包括电影,电视剧,综艺等),主要是用selenium动态网页技术加上简单的爬虫技术. (1)电影网站首页面地址:https://www.dytt8.net/ (2)用到的技术:selenium模拟浏览器运行. (3)首先要安装配置selenium库和不同浏览器和该库配合的插件.这里安