2012-11-26 36 views
0

我正在写一个使用PacketFu侦听数据包的红宝石后门程序。Ctrl-c不再杀死我的程序

应用程序工作正常,但由于某些原因,它不会在中断退出(CTRL + C)

这是代码,似乎不受中断的部分。如果我完全清空每个循环,并不重要,它会始终停止忽略中断。

任何想法?

编辑:当packet.stream.each循环执行时(强制某些TCP流量),我可以正确捕获中断。似乎无论PacketFu在等待新数据包时如何使它免于中断。我想现在我会忽略它,如果有人知道什么PacketFu代码可能会导致这种情况,我很想知道!

PS。我已经包含下面的整个服务器代码,以防任何人想要自己测试。

代码段:(参见下面的整个文件)

begin 
# Start listening for connection packets via TCP 
print "starting up\n" 
capturedTCP = PacketFu::Capture.new(:iface => $config[:iface], :start => true, :promisc => true, :filter => "tcp") 
print "about to capture\n" 
capturedTCP.stream.each { |packet| 
    puts "Got one!" 
    pkt = Packet.parse packet 
    # Check that it is a TCP packet? 
    if pkt.is_tcp? 
     # Is it one of our SYN packets? 
     if pkt.tcp_flags.syn == 1 && pkt.ip_id == $identKey 
      # TODO: Respond with SYN/ACK 
      flags = [1,0,0,0,1,0] 
      payload = "" 
      tcpResp = tcpConstruct($identKey,srcIP,80,dstIP,Random.rand(65535),flags, payload) 
      tcpResp.to_w # Sent 
      # TODO: Use thread instead. 
      dataListener($identKey,dstIP,dstPort) 

     end 
    end 
} 
rescue Interrupt => e 
puts "Interrupted by user" 
exit 0 
end 

整个文件:

require 'rubygems' 
require 'packetfu' 
require 'thread' 

include PacketFu 

#TODO: Move these functions to a diff file 
# Utility function for loading latest config 
def loadConfig(filePath) 
#TODO: Load up file and get config 
#For now just hard coded. 
$iName = "eth0" 
identKey = 12345 
listenPortMain = "80" # Port to listen for connection requests 
processName = "xyz" # Change process name to hide. 
filterTCP = "tcp and port #{listenPortMain}" 
userCmdField = "src-port" # Options: src-port, dst-port 
userCmdRun = "20" 
end 

# Function for handling client session 
def clientListen(ip,port) 
# Start listening for connection packets via UDP 
capturedUDP = PacketFu::Capture.new(:iface => config[:iface], :start => true, :promisc => true, :filter => "udp and port #{port} and src host #{ip}") 

capturedUDP.stream.each { |packet| 
    pkt = Packet.parse packet 
    # Check that it is a UDP packet 
    if pkt.is_udp? 
     # Is it one of our UDP packets? 
     if pkt.ip_id == identKey 
      # Get the data 
      data = pkt.payload() 
      # Look for the command type 
      if userCmdField == "src-port" 
       cmdFieldVal = pkt.udp_src 
      end 
      if userCmdField == "dst-port" 
       cmdFieldVal = pkt.udp_dst 
      end 
      # Command processing 
      if userCmdField == userCmdRun 
       cmdDataChrs = []; 
       # Check for sequence number 
       seqCurrent = pkt.payload[0].unpack("H*")[0].to_i 
       seqTotal = pkt.payload[1].unpack("H*")[0].to_i 
       dataLen = (pkt.payload[2].unpack("H*").chr + pkt.payload[2].unpack("H*").chr).to_i 
       while pos <= dataLen do 
        cmdDataChrs.push(pkt.payload[pos]) 
        pos = pos + 1 
       end 
       cmdData = cmdDataChrs.unpack("H*") 
       print "Got command: #{cmdData}" 
      end 
     end 
    end 
} 
end 

#Construct TCP Packet 
def tcpConstruct(identKey,srcIP,srcPort,dstIP,dstPort,flags, payload) 
#--> Build TCP/IP 

#- Build Ethernet header:--------------------------------------- 
pkt = PacketFu::TCPPacket.new(:config => $config , :flavor => "Linux") 
# pkt.eth_src = "00:11:22:33:44:55" # Ether header: Source MAC ; you can use: pkt.eth_header.eth_src 
# pkt.eth_dst = "FF:FF:FF:FF:FF:FF" # Ether header: Destination MAC ; you can use: pkt.eth_header.eth_dst 
pkt.eth_proto # Ether header: Protocol ; you can use: pkt.eth_header.eth_proto 
#- Build IP header:--------------------------------------- 
pkt.ip_v = 4 # IP header: IPv4 ; you can use: pkt.ip_header.ip_v 
pkt.ip_hl = 5 # IP header: IP header length ; you can use: pkt.ip_header.ip_hl 
pkt.ip_tos = 0 # IP header: Type of service ; you can use: pkt.ip_header.ip_tos 
pkt.ip_len = 20 # IP header: Total Length ; you can use: pkt.ip_header.ip_len 
pkt.ip_id = identKey # IP header: Identification ; you can use: pkt.ip_header.ip_id 
pkt.ip_frag = 0 # IP header: Don't Fragment ; you can use: pkt.ip_header.ip_frag 
pkt.ip_ttl = 115 # IP header: TTL(64) is the default ; you can use: pkt.ip_header.ip_ttl 
pkt.ip_proto = 6 # IP header: Protocol = tcp (6) ; you can use: pkt.ip_header.ip_proto 
pkt.ip_sum # IP header: Header Checksum ; you can use: pkt.ip_header.ip_sum 
pkt.ip_saddr = srcIP # IP header: Source IP. use $config[:ip_saddr] if you want your real IP ; you can use: pkt.ip_header.ip_saddr 
pkt.ip_daddr = dstIP # IP header: Destination IP ; you can use: pkt.ip_header.ip_daddr 
#- TCP header:--------------------------------------- 
pkt.payload = payload # TCP header: packet header(body) 
pkt.tcp_flags.ack = flags[0] # TCP header: Acknowledgment 
pkt.tcp_flags.fin = flags[1] # TCP header: Finish 
pkt.tcp_flags.psh = flags[2] # TCP header: Push 
pkt.tcp_flags.rst = flags[3] # TCP header: Reset 
pkt.tcp_flags.syn = flags[4] # TCP header: Synchronize sequence numbers 
pkt.tcp_flags.urg = flags[5] # TCP header: Urgent pointer 
pkt.tcp_ecn = 0 # TCP header: ECHO 
pkt.tcp_win = 8192 # TCP header: Window 
pkt.tcp_hlen = 5 # TCP header: header length 
pkt.tcp_src = srcPort # TCP header: Source Port (random is the default) 
pkt.tcp_dst = dstPort # TCP header: Destination Port (make it random/range for general scanning) 
pkt.recalc # Recalculate/re-build whole pkt (should be at the end) 
return pkt 
end 

def dataListener(identKey,dstIP,dstPort) 
# Listen for UDP data packets 
print "Listening for Data from #{dstIP}\n" 
capturedUDP = PacketFu::Capture.new(:iface => $config[:iface], :start => true, :promisc => true, :filter => "udp and port #{dstPort}") 

capturedTCP.stream.each { |packet| 
    pkt = Packet.parse packet 
    if pkt.ip_id == identKey 
     # Get Packet Type 
     if userCmdField == "src-port" 
      dataType = pkt.udp_src 
     elsif userCmdField == "dst-port" 
      dataType = pkt.udp_dst 
     end 

     if dataType == userCmdRun 
      cmdLen = pkt.payload[0].unpack("c*") 
      cmd = "" 
      while i <= cmdLen do 
       cmd += pkt.payload[i].unpack("h*") 
      end 
      print "Command: #{cmd}\n" 
     end 
    end 
} 
end 
# - - - - Begin Main 

# Get config from file 
loadConfig("/path/to/file.txt") 

#$config = PacketFu::Config.new(PacketFu::Utils.whoami?(:iface=> iName)).config # set interface 
$config = PacketFu::Config.new(:iface=> $iName).config # use this line instead of above if you face `whoami?': uninitialized constant PacketFu::Capture (NameError) 

#TODO: Mask process name from config 

# Create sessions array (Holds threads) 
sessions = [] 
Signal.trap('INT') { exit 0 } 
begin 
# Start listening for connection packets via TCP 
print "starting up\n" 
capturedTCP = PacketFu::Capture.new(:iface => $config[:iface], :start => true, :promisc => true, :filter => "tcp") 
print "about to capture\n" 
capturedTCP.stream.each { |packet| 
    puts "Got one!" 
    pkt = Packet.parse packet 
    # Check that it is a TCP packet? 
    if pkt.is_tcp? 
     # Is it one of our SYN packets? 
     if pkt.tcp_flags.syn == 1 && pkt.ip_id == $identKey 
      # TODO: Respond with SYN/ACK 
      flags = [1,0,0,0,1,0] 
      payload = "" 
      tcpResp = tcpConstruct($identKey,srcIP,80,dstIP,Random.rand(65535),flags, payload) 
      tcpResp.to_w # Sent 
      # TODO: Use thread instead. 
      dataListener($identKey,dstIP,dstPort) 
     end 
    end 
} 

end 

回答

0

如果你的程序在Unix上的一些味道上运行,你可以赶上INT信号(由发Ctrl-C)并明确呼叫exit

把这个你begin块之前或之后:

Signal.trap('INT') do 
    # some cleanup here 
    puts "Interrupted by user" 
    exit 0 
end 

More on signals in Ruby

Unix signals list

+0

感谢:

Signal.trap('INT') { exit 0 } 

此外,你可以退出程序前做一些清理帮助,但没有改变如果我在开始块之前或之后添加陷阱。 我可以按Ctrl-c所有我想要的和字符只出现在终端。如果我输入Ctrl-z,那么它将会注册中断,但是只能让它进入睡眠状态(我仍然必须通过PID来清除它)。 –

+0

尝试'Signal.trap('INT'){放置“强制退出...”; :: Process.exit! }'让我知道你是否在输出 – 2012-11-26 00:51:41

+0

中看到“强制退出”并在开始块之前和之后尝试了它,并且根本没有输出。 –