root/dump/ftpexe.py

Revision 1939, 3.8 KB (checked in by common, 7 months ago)

dump

  • add ftpexe.py, simple ftp client for downloading files from malware ftp servers from nat, excluding known bad ports
  • Property svn:keywords set to id rev
Line 
1from ftplib import FTP
2
3import os
4import sys
5import socket
6import random
7
8class dFTP(FTP):
9    def __init__(self):
10        FTP.__init__(self)
11        self.nat_host = None
12        self.nat_port_range = None
13
14    def makeport(self):
15        '''Create a new socket and send a PORT command for it.'''
16        msg = "getaddrinfo returns an empty list"
17        sock = None
18        for res in socket.getaddrinfo(None, 0, self.af, socket.SOCK_STREAM, 0, socket.AI_PASSIVE):
19            af, socktype, proto, canonname, sa = res
20            ports = list(filter(lambda port: ((port >> 4) & 0xf) != 0, range(self.nat_port_range[0], self.nat_port_range[1])))
21            random.shuffle(ports)
22            for port in ports:
23                try:
24                    sock = socket.socket(af, socktype, proto)
25                    sa = tuple([sa[0], port])
26                    sock.bind(sa)
27                except socket.error as msg:
28                    if sock:
29                        sock.close()
30                    sock = None
31                    continue
32                break
33        if not sock:
34            raise socket.error(msg)
35        sock.listen(1)
36        port = sock.getsockname()[1] # Get proper port
37        host = socket.gethostbyname(self.nat_host)
38        if self.af == socket.AF_INET:
39            resp = self.sendport(host, port)
40        else:
41            resp = self.sendeprt(host, port)
42        return sock
43
44    def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
45        conn = self.transfercmd(cmd, rest)
46        while 1:
47            data = conn.recv(blocksize)
48            if not data:
49                break
50            callback(data)
51        conn.close()
52        return self.voidresp()
53               
54def download():
55    '''ftp via nat program.
56    Usage: ftpexe [options]
57    -v verbose
58    -H nat host
59    -R nat port-range
60    -s host:port
61    -u user
62    -p password
63    -f file
64    -b send TYPE I
65    '''
66
67    verbose = 0
68    nat_host = None
69    nat_port_range = None
70    host = None
71    port = None
72    user = None
73    password = None
74    rfile = None
75    binary = False
76
77    i = 1
78    while i < len(sys.argv):
79        print("ARG %s" % (sys.argv[i]))
80        if sys.argv[i] == '-v':
81            verbose = verbose+1
82        elif sys.argv[i] == '-H':
83            i=i+1
84            nat_host = sys.argv[i]
85        elif sys.argv[i] == '-R':
86            i=i+1
87            nat_port_range = sys.argv[i]
88        elif sys.argv[i] == '-s':
89            i=i+1
90            host = sys.argv[i]
91        elif sys.argv[i] == '-u':
92            i=i+1
93            user = sys.argv[i]
94        elif sys.argv[i] == '-f':
95            i=i+1
96            rfile = sys.argv[i]
97        elif sys.argv[i] == '-b':
98            binary=True
99        elif sys.argv[i] == '-h':
100            print(download.__doc__)
101            sys.exit(0)
102        i=i+1
103
104    if not host or not nat_port_range or not nat_host or not rfile:
105        print(download.__doc__)
106        sys.exit(0)
107       
108    off = host.find(':')
109    if off != -1:
110        port = int(host[off+1:])
111        host = host[:off]
112    else:
113        port = 21
114    print("host %s %i" % (host, port))
115
116    if nat_port_range:
117        x = nat_port_range.find('-')
118        min_port = int(nat_port_range[:x])
119        max_port = int(nat_port_range[x+1:])
120    print("nat host %s port range %s to %s" % (nat_host, min_port, max_port))   
121
122    if not user:
123        user = 'anonymous'
124        password = 'guest'
125    print("user %s pass %s" % (user, password))
126
127    ftp = dFTP()
128    ftp.set_debuglevel(verbose)
129    ftp.connect(host=host, port=port)
130    ftp.nat_host = nat_host
131    ftp.nat_port_range = [min_port, max_port]
132
133    ftp.login(user, password)
134    lfile=open(rfile, 'wb')
135    ftp.set_pasv(not ftp.passiveserver)
136    if binary:
137        ftp.voidcmd('TYPE I')
138    ftp.retrbinary('RETR ' + rfile, \
139                           lfile.write, 1024)
140    ftp.quit()
141
142
143if __name__ == '__main__':
144    download()
Note: See TracBrowser for help on using the browser.