This repository has been archived on 2025-02-19. You can view files and clone it, but cannot push or open issues or pull requests.

142 lines
5.3 KiB
Python
Raw Normal View History

import hashlib
import time
import socket
from network.advanceddispatcher import AdvancedDispatcher
import network.asyncore_pollchoose as asyncore
from network.proxy import Proxy, ProxyError, GeneralProxyError
from network.socks5 import Socks5Connection, Socks5Resolver, Socks5AuthError, Socks5Error
from network.socks4a import Socks4aConnection, Socks4aResolver, Socks4aError
import addresses
import protocol
class BMProtoError(ProxyError): pass
class BMConnection(AdvancedDispatcher):
def __init__(self, address):
AdvancedDispatcher.__init__(self)
self.destination = address
self.payload = None
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
self.connect(self.destination)
print "connecting in background to %s:%i" % (self.destination[0], self.destination[1])
def bm_proto_len_sufficient(self):
if len(self.read_buf) < protocol.Header.size:
print "Length below header size"
return False
if not self.payload:
self.magic, self.command, self.payloadLength, self.checksum = protocol.Header.unpack(self.read_buf[:protocol.Header.size])
self.command = self.command.rstrip('\x00')
if self.payloadLength > 1600100: # ~1.6 MB which is the maximum possible size of an inv message.
return False
if len(self.read_buf) < self.payloadLength + protocol.Header.size:
print "Length below announced object length"
return False
self.payload = self.read_buf[protocol.Header.size:self.payloadLength + protocol.Header.size]
return True
def bm_check_command(self):
if self.magic != 0xE9BEB4D9:
self.set_state("crap", protocol.Header.size)
print "Bad magic"
self.payload = None
return False
if self.checksum != hashlib.sha512(self.payload).digest()[0:4]:
self.set_state("crap", protocol.Header.size)
self.payload = None
print "Bad checksum"
return False
print "received %s (%ib)" % (self.command, self.payloadLength)
return True
def state_init(self):
self.write_buf += protocol.assembleVersionMessage(self.destination[0], self.destination[1], (1,), False)
if True:
print "Sending version (%ib)" % len(self.write_buf)
self.set_state("bm_reccommand", 0)
return False
def state_bm_reccommand(self):
if not self.bm_proto_len_sufficient():
return False
if not self.bm_check_command():
return False
if self.command == "version":
self.bm_recversion()
elif self.command == "verack":
self.bm_recverack()
else:
print "unimplemented command %s" % (self.command)
self.set_state("bm_reccommand", protocol.Header.size + self.payloadLength)
self.payload = None
print "buffer length = %i" % (len(self.read_buf))
return False
def bm_recverack(self):
self.verackReceived = True
return False
def bm_recversion(self):
self.remoteProtocolVersion, self.services, timestamp, padding1, self.myExternalIP, padding2, self.remoteNodeIncomingPort = protocol.VersionPacket.unpack(self.payload[:82])
print "remoteProtocolVersion: %i" % (self.remoteProtocolVersion)
print "services: %08X" % (self.services)
print "time offset: %i" % (timestamp - int(time.time()))
print "my external IP: %s" % (socket.inet_ntoa(self.myExternalIP))
print "remote node incoming port: %i" % (self.remoteNodeIncomingPort)
useragentLength, lengthofUseragentVarint = addresses.decodeVarint(self.payload[80:84])
readPosition = 80 + lengthOfUseragentVarint
self.userAgent = self.payload[readPosition:readPosition + useragentLength]
readPosition += useragentLength
print "user agent: %s" % (self.userAgent)
return False
def state_http_request_sent(self):
if len(self.read_buf) > 0:
print self.read_buf
self.read_buf = b""
if not self.connected:
self.set_state("close", 0)
return False
class Socks5BMConnection(Socks5Connection, BMConnection):
def __init__(self, address):
Socks5Connection.__init__(self, address=address)
def state_socks_handshake_done(self):
BMConnection.state_init(self)
return False
class Socks4aBMConnection(Socks4aConnection, BMConnection):
def __init__(self, address):
Socks4aConnection.__init__(self, address=address)
def state_socks_handshake_done(self):
BMConnection.state_init(self)
return False
if __name__ == "__main__":
# initial fill
for host in (("127.0.0.1", 8448),):
direct = BMConnection(host)
while len(asyncore.socket_map) > 0:
print "loop, state = %s" % (direct.state)
asyncore.loop(timeout=1, count=1)
continue
proxy = Socks5BMConnection(host)
while len(asyncore.socket_map) > 0:
# print "loop, state = %s" % (proxy.state)
asyncore.loop(timeout=1, count=1)
proxy = Socks4aBMConnection(host)
while len(asyncore.socket_map) > 0:
# print "loop, state = %s" % (proxy.state)
asyncore.loop(timeout=1, count=1)