hackedteam/poc-x

View on GitHub
socks.rb

Summary

Maintainability
C
1 day
Test Coverage
#!/usr/bin/env ruby

require 'socket'
require 'thread'

def log(text)
  File.open('data/socks.log', 'a') {|f| f.write text.chomp + "\n"}
  puts text
end

localport = 9166
server = TCPServer.open(localport)
log "Listening on port tcp/#{localport}..."

MY_IP = "10.0.0.1"

@reply_650_NOTICE = "650 NOTICE New control connection opened.\r\n"
@reply_250OK = "250 OK\r\n"

@reply_bootstrap_phase = "250-status/bootstrap-phase=NOTICE BOOTSTRAP PROGRESS=100 TAG=done SUMMARY=\"Done\"\r\n"
@reply_net_listeners_socks = "250-net/listeners/socks=\"#{MY_IP}:9150\"\r\n"
@reply_Socks4Proxy = "250 Socks4Proxy\r\n"
@reply_Socks5Proxy = "250 Socks5Proxy\r\n"
@reply_HTTPSProxy = "250 HTTPSProxy\r\n"
@reply_ReachableAddresses = "250 ReachableAddresses\r\n"
@reply_UseBridges = "250 UseBridges=0\r\n"
@reply_Bridge = "250 Bridge\r\n"


class Event
  def initialize
    @lock = Mutex.new
    @cond = ConditionVariable.new
  end

  def set
    log "----- signal set -----"
    @lock.synchronize do
      @cond.broadcast
   end
  end

  def wait
    log "----- signal wait -----"
    @lock.synchronize do
      @cond.wait(@lock)
    end
  end
end

@event = Event.new

def reply(client, string)
  log " -> #{string}"
  client.puts string
end

def process_getinfo(client, req)
  if req['status/bootstrap-phase']
    reply client, @reply_bootstrap_phase
    reply client, @reply_250OK
    @vent.set
  elsif req['net/listeners/socks']
    reply client, @reply_net_listeners_socks
    reply client, @reply_250OK
  elsif req['Socks4Proxy']
    reply client, @reply_Socks4Proxy
  elsif req['Socks5Proxy']
    reply client, @reply_Socks5Proxy
  elsif req['HTTPSProxy']
    reply client, @reply_HTTPSProxy
  elsif req['ReachableAddresses']
    reply client, @reply_ReachableAddresses
  elsif req['UseBridges']
    reply client, @reply_UseBridges
  elsif req['Bridge']
    reply client, @reply_Bridge
  else 
    log "UNKNOWN GETINFO request!!!"
  end
end

def process_getconf(client, req)
  if req['Socks4Proxy']
    reply client, @reply_Socks4Proxy
  elsif req['Socks5Proxy']
    reply client, @reply_Socks5Proxy
  elsif req['HTTPSProxy']
    reply client, @reply_HTTPSProxy
  elsif req['ReachableAddresses']
    reply client, @reply_ReachableAddresses
  elsif req['UseBridges']
    reply client, @reply_UseBridges
  elsif req['Bridge']
    reply client, @reply_Bridge
  else 
    log "UNKNOWN GETCONF request!!!"
  end
end

def bootstrap_events(client)
  log "SENDING BOOTSTRAP EVENTS..."

  reply client, "650 NOTICE Bootstrapped 5%: Connecting to directory server.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=5 TAG=conn_dir SUMMARY=\"Connecting to directory server\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 10%: Finishing handshake with directory server.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=10 TAG=handshake_dir SUMMARY=\"Finishing handshake with directory server\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 15%: Establishing an encrypted directory connection.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=15 TAG=onehop_create SUMMARY=\"Establishing an encrypted directory connection\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 20%: Asking for networkstatus consensus.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=20 TAG=requesting_status SUMMARY=\"Asking for networkstatus consensus\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 25%: Loading networkstatus consensus.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=25 TAG=loading_status SUMMARY=\"Loading networkstatus consensus\"\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE CONSENSUS_ARRIVED\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 45%: Asking for relay descriptors.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=45 TAG=requesting_descriptors SUMMARY=\"Asking for relay descriptors\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE We now have enough directory information to build circuits.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE ENOUGH_DIR_INFO\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 80%: Connecting to the Tor network.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=80 TAG=conn_or SUMMARY=\"Connecting to the Tor network\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 90%: Establishing a Tor circuit.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=90 TAG=circuit_create SUMMARY=\"Establishing a Tor circuit\"\r\n"
  sleep 0.1
  reply client, "650 NOTICE Tor has successfully opened a circuit. Looks like client functionality is working.\r\n"
  sleep 0.1
  reply client, "650 NOTICE Bootstrapped 100%: Done.\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE BOOTSTRAP PROGRESS=100 TAG=done SUMMARY=\"Done\"\r\n"
  sleep 0.1
  reply client, "650 STATUS_CLIENT NOTICE CIRCUIT_ESTABLISHED\r\n"
end

def process_request(client)
  loop do
    begin
      req = client.gets  
      next unless req

      log "(#{Thread.current}) #{req}"
      
      if req.start_with? 'GETINFO'
        process_getinfo(client, req)
      elsif req.start_with? 'SETEVENTS'
        reply client, @reply_250OK
        @event.wait
        bootstrap_events(client)
        while(true)
          @event.wait
          log "EVENT NOTICE..."
          reply client, @reply_650_NOTICE
        end
      elsif req.start_with? 'SIGNAL NEWNYM'
        reply client, @reply_250OK
        log "NEWNYM !!!"
        @event.set
        return
      elsif req.start_with? 'TAKEOWNERSHIP'
        reply client, @reply_250OK
      elsif req.start_with? 'AUTHENTICATE'
        reply client, @reply_250OK
      elsif req.start_with? 'RESETCONF'
        reply client, @reply_250OK
      elsif req.start_with? 'GETCONF'
        process_getconf(client, req)
      elsif req.start_with? 'SETCONF' or req.start_with? 'SAVECONF'
        reply client, @reply_250OK
      end
    rescue Exception => e
      log e.message
    end
  end
end

loop do
  Thread.start(server.accept) do |client|
    
    port, ip = Socket.unpack_sockaddr_in(client.getpeername)
    log "(#{Thread.current}) New connection from: #{ip}:#{port}"
    
    process_request(client)

  end
end