version of hd in go

This commit is contained in:
Neale Pickett 2013-07-23 16:30:38 -06:00
parent 306f0c6264
commit c47e11c329
7 changed files with 282 additions and 42 deletions

View File

@ -1,13 +1,20 @@
CFLAGS = -Wall -Werror -Wno-unused-variable CFLAGS = -Wall -Werror
TARGETS = pmerge puniq p4split pcat TARGETS = pmerge puniq p4split pcat
TARGETS += hd pyesc printfesc xor unhex TARGETS += hd pyesc printfesc xor unhex
all: $(TARGETS) all: $(TARGETS)
%: %.go
go build $<
pmerge: pmerge.o pcap.o pmerge: pmerge.o pcap.o
puniq: puniq.o pcap.o puniq: puniq.o pcap.o
p4split: p4split.c pcap.o
pcat: pcat.c pcap.o stream.o p4split: p4split.o pcap.o
pcat: pcat.o pcap.o stream.o
pcat.o: CFLAGS += -Wno-unused-variable
clean: clean:
rm -f $(TARGETS) *.o rm -f $(TARGETS) *.o

97
README Normal file
View File

@ -0,0 +1,97 @@
The Fluffy Suite
============
Fluffy was begun in April 2011 in Tennessee,
as a replacement for the aging "dirtbags.ip" codebase.
It is comprised of multiple small standalone binaries,
which are meant to be chained together,
either on the command-line or from a shell script,
to create a more powerful (and specific) piece of software.
Usually, a program expects input on stdin,
and produces output on stdout.
Flags are sparse by design.
hd -- Hex Dump
--------------
Like the normal hd,
but with unicode characters to represent all 256 octets,
instead of using "." for unprintable characters.
p4split -- split a pcap file by IPv4 address CIDR
---------------------------
Splits a pcap file up ito 256 files, based on a CIDR. For example:
p4split 32 < foo.pcap
Will create [0-255].pcap
pcat -- print text representation of pcap file
------------------------------
Prints a (lossy) text representation of a pcap file to stdout.
This program is the keystone of the Fluffy Suite.
By representing everything as text,
programmers can use any number of standard Unix text processing tools,
such as sed, awk, cut, grep, or head.
pmerge -- merge pcap files
-------------------------------------------
Takes a list of pcap files, assuming they are sorted by time
(you would have to work hard to create any other kind),
and merges them into a single sorted output.
printfesc -- printf escape input
--------------------------------
Reads octets,
writes a string suitable for copy-paste into printf.
puniq -- omit repeated frames
--------------------------------
Removes duplicate frames from input,
writing to output.
pyesc -- python escape input
---------------------------------
Escapes input octets for pasting into a python "print" statement.
unhex -- unescape hex
---------------------------------
Reads ASCII hex codes on stdin,
writes those octets to stdout.
The following pipe is equivalent to "cat":
./hd | cut -b 11-58 | ./unhex
xor -- xor mask octets
--------------------------------
Applies the given mask as an xor to input.
The mask will be repeated,
so for a 1-value mask, every octet is xored against that value.
For a 16-value mask, the mask is applied to 16-octet chunks at a time.
The "-x" option treats values as hex.
The following pipe is equivalent to "cat":
./xor 42 | ./xor -x 2A

77
hd.go Normal file
View File

@ -0,0 +1,77 @@
package main
import (
"bytes"
"fmt"
"os"
"io"
)
const charset = "" +
"·☺☻♥♦♣♠•◘○◙♂♀♪♫☼" +
"►◄↕‼¶§▬↨↑↓→←∟↔▲▼" +
" !\"#$%&'()*+,-./" +
"0123456789:;<=>?" +
"@ABCDEFGHIJKLMNO" +
"PQRSTUVWXYZ[\\]^_" +
"`abcdefghijklmno" +
"pqrstuvwxyz{|}~⌂" +
"ÇüéâäàåçêëèïîìÄÅ" +
"ÉæÆôöòûùÿÖÜ¢£¥€ƒ" +
"áíóúñѪº½⅓¼⅕⅙⅛«»" +
"░▒▓│┤╡╢╖╕╣║╗╝╜╛┐" +
"└┴┬├─┼╞╟╚╔╩╦╠═╬╧" +
"╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀" +
"αßΓπΣσµτΦΘΩδ∞φε∩" +
"⁰¹²³⁴⁵⁶⁷⁸⁹ⁱⁿ⁽⁼⁾¤"
func main() {
offset := 0
b := make([]byte, 16)
lb := make([]byte, 16)
chars := []rune(charset)
skipping := false
for ;; {
n, err := os.Stdin.Read(b)
if err != nil {
if err != io.EOF {
fmt.Println("read failed:", err)
}
break
}
if (offset > 0) && (bytes.Equal(lb, b)) {
if ! skipping {
fmt.Println("*")
}
skipping = true
continue
}
copy(lb, b)
skipping = false
fmt.Printf("%08x ", offset)
offset += n
for i := 0; i < 16; i += 1 {
if i % 8 == 0 {
fmt.Printf(" ")
}
if i < n {
fmt.Printf("%02x ", b[i])
} else {
fmt.Printf(" ")
}
}
fmt.Printf("ǀ")
for i := 0; i < n; i += 1 {
fmt.Printf("%c", chars[b[i]])
}
fmt.Printf("ǀ\n")
}
fmt.Printf("%08x\n", offset)
}

62
pcat.c
View File

@ -1,3 +1,17 @@
/*
* pcat.c -- pcap to text
*
* Reads pcap on stdin, dumps text representation to stdout.
* This discards or ignores some parts of packets. If fidelity is a concern,
* deal directly with the original pcap.
*
* Output lines are of the form:
*
* PROTO SRC DST OPTS PAYLOAD
*
*/
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "pcap.h" #include "pcap.h"
@ -31,33 +45,33 @@ print_payload(struct stream *s)
void void
process_tcp(struct stream *s, char *saddr_s, char *daddr_s) process_tcp(struct stream *s, char *saddr_s, char *daddr_s)
{ {
uint16_t sport = read_uint16be(s); uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16be(s); uint16_t dport = read_uint16(s);
uint32_t seq = read_uint32be(s); uint32_t seq = read_uint32(s);
uint32_t ack = read_uint32be(s); uint32_t ack = read_uint32(s);
uint8_t off = read_uint8(s); uint8_t off = read_uint8(s);
uint8_t hlen = (off >> 4) * 4; uint8_t hlen = (off >> 4) * 4;
uint8_t flags = read_uint8(s); uint8_t flags = read_uint8(s);
uint16_t window = read_uint16be(s); uint16_t window = read_uint16(s);
uint16_t chksum = read_uint16be(s); uint16_t chksum = read_uint16(s);
uint16_t urgent = read_uint16be(s); uint16_t urgent = read_uint16(s);
if (hlen < 20) { if (hlen < 20) {
printf("!"); printf("!");
} }
printf("TCP %s,%u,%u %s,%u,%u ", saddr_s, sport, seq, daddr_s, dport, ack); printf("TCP %s,%u %s,%u %u,%u,%d ", saddr_s, sport, daddr_s, dport, seq, ack, flags);
} }
void void
process_udp(struct stream *s, char *saddr_s, char *daddr_s) process_udp(struct stream *s, char *saddr_s, char *daddr_s)
{ {
uint16_t sport = read_uint16be(s); uint16_t sport = read_uint16(s);
uint16_t dport = read_uint16be(s); uint16_t dport = read_uint16(s);
uint16_t len = read_uint16be(s); uint16_t len = read_uint16(s);
uint16_t chksum = read_uint16be(s); uint16_t chksum = read_uint16(s);
printf("UDP %s,%u %s,%u ", saddr_s, sport, daddr_s, dport); printf("UDP %s,%u %s,%u 0 ", saddr_s, sport, daddr_s, dport);
} }
void void
@ -65,7 +79,7 @@ process_icmp(struct stream *s, char *saddr_s, char *daddr_s)
{ {
uint8_t type = read_uint8(s); uint8_t type = read_uint8(s);
uint8_t code = read_uint8(s); uint8_t code = read_uint8(s);
uint16_t checksum = read_uint16be(s); uint16_t checksum = read_uint16(s);
printf("ICMP %s %s %d ", saddr_s, daddr_s, code); printf("ICMP %s %s %d ", saddr_s, daddr_s, code);
} }
@ -76,14 +90,14 @@ process_ip4(struct stream *s)
uint8_t vhl = read_uint8(s); uint8_t vhl = read_uint8(s);
uint8_t ihl = (vhl & 0x0f) * 4; uint8_t ihl = (vhl & 0x0f) * 4;
uint8_t tos = read_uint8(s); uint8_t tos = read_uint8(s);
uint16_t length = read_uint16be(s); uint16_t length = read_uint16(s);
uint16_t id = read_uint16be(s); uint16_t id = read_uint16(s);
uint16_t off = read_uint16be(s); uint16_t off = read_uint16(s);
uint8_t ttl = read_uint8(s); uint8_t ttl = read_uint8(s);
uint8_t proto = read_uint8(s); uint8_t proto = read_uint8(s);
uint16_t chksum = read_uint16be(s); uint16_t chksum = read_uint16(s);
uint32_t saddr = read_uint32be(s); uint32_t saddr = read_uint32(s);
uint32_t daddr = read_uint32be(s); uint32_t daddr = read_uint32(s);
char saddr_s[20]; char saddr_s[20];
char daddr_s[20]; char daddr_s[20];
@ -125,12 +139,12 @@ print_ethernet(struct stream *s)
sread(s, &saddr, sizeof(saddr)); sread(s, &saddr, sizeof(saddr));
sread(s, &daddr, sizeof(daddr)); sread(s, &daddr, sizeof(daddr));
ethertype = read_uint16be(s); ethertype = read_uint16(s);
if (ethertype == 0x8100) { if (ethertype == 0x8100) {
// VLAN // VLAN
read_uint16be(s); read_uint16(s);
ethertype = read_uint16be(s); ethertype = read_uint16(s);
} }
switch (ethertype) { switch (ethertype) {
@ -146,7 +160,7 @@ print_frame(struct pcap_file *p, struct pcap_pkthdr *hdr, char const *frame)
struct stream streambuf; struct stream streambuf;
struct stream *s = &streambuf; struct stream *s = &streambuf;
sinit(s, frame, hdr->caplen); sinit(s, frame, hdr->caplen, ENDIAN_BIG);
printf("%u.%u ", hdr->ts.tv_sec, hdr->ts.tv_usec); printf("%u.%u ", hdr->ts.tv_sec, hdr->ts.tv_usec);
switch (p->linktype) { switch (p->linktype) {
case LINKTYPE_ETHERNET: case LINKTYPE_ETHERNET:

View File

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <ctype.h>
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
@ -11,13 +12,24 @@ main(int argc, char *argv[])
switch (c) { switch (c) {
case EOF: case EOF:
break; break;
case '0' ... '9': case '\n':
case 'A' ... 'Z': printf("\\n");
case 'a' ... 'z': break;
putchar(c); case '\r':
printf("\\r");
break;
case '\t':
printf("\\t");
break;
case '"':
printf("\\\"");
break; break;
default: default:
printf("\\\\%03o", c); if (isprint(c)) {
putchar(c);
} else {
printf("\\%03o", c);
}
break; break;
} }
} }

View File

@ -5,10 +5,11 @@
#include "stream.h" #include "stream.h"
void void
sinit(struct stream *s, char const *buf, size_t buflen) sinit(struct stream *s, char const *buf, size_t buflen, enum endianness endian)
{ {
s->buf = buf; s->buf = buf;
s->len = buflen; s->len = buflen;
s->endian = endian;
} }
bool bool
@ -37,6 +38,8 @@ sread(struct stream * s, void *buf, size_t count)
return true; return true;
} }
uint8_t uint8_t
read_uint8(struct stream *s) read_uint8(struct stream *s)
{ {
@ -48,6 +51,8 @@ read_uint8(struct stream * s)
return d[0]; return d[0];
} }
uint16_t uint16_t
read_uint16be(struct stream *s) read_uint16be(struct stream *s)
{ {
@ -59,6 +64,7 @@ read_uint16be(struct stream * s)
return ((d[0] << 8) | (d[1] << 0)); return ((d[0] << 8) | (d[1] << 0));
} }
uint16_t uint16_t
read_uint16le(struct stream *s) read_uint16le(struct stream *s)
{ {
@ -70,11 +76,21 @@ read_uint16le(struct stream * s)
return ((d[0] << 0) | (d[1] << 8)); return ((d[0] << 0) | (d[1] << 8));
} }
uint16_t
read_uint16(struct stream *s)
{
if (s->endian == ENDIAN_BIG) {
return read_uint16be(s);
} else {
return read_uint16le(s);
}
}
uint32_t uint32_t
read_uint32be(struct stream *s) read_uint32be(struct stream *s)
{ {
uint8_t *d = (uint8_t *) s->buf; uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 4)) { if (!sskip(s, 4)) {
return 0; return 0;
} }
@ -85,9 +101,18 @@ uint32_t
read_uint32le(struct stream *s) read_uint32le(struct stream *s)
{ {
uint8_t *d = (uint8_t *) s->buf; uint8_t *d = (uint8_t *) s->buf;
if (!sskip(s, 4)) { if (!sskip(s, 4)) {
return 0; return 0;
} }
return ((d[0] << 0) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24)); return ((d[0] << 0) | (d[1] << 8) | (d[2] << 16) | (d[3] << 24));
} }
uint32_t
read_uint32(struct stream *s)
{
if (s->endian == ENDIAN_BIG) {
return read_uint32be(s);
} else {
return read_uint32le(s);
}
}

View File

@ -5,18 +5,26 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
enum endianness {
ENDIAN_BIG,
ENDIAN_LITTLE
};
struct stream { struct stream {
char const *buf; char const *buf;
size_t len; size_t len;
enum endianness endian;
}; };
void sinit(struct stream *s, char const *buf, size_t len); void sinit(struct stream *s, char const *buf, size_t len, enum endianness endian);
bool sskip(struct stream *s, size_t count); bool sskip(struct stream *s, size_t count);
bool sread(struct stream *s, void *buf, size_t count); bool sread(struct stream *s, void *buf, size_t count);
uint8_t read_uint8(struct stream *s); uint8_t read_uint8(struct stream *s);
uint16_t read_uint16be(struct stream *s); uint16_t read_uint16be(struct stream *s);
uint16_t read_uint16le(struct stream *s); uint16_t read_uint16le(struct stream *s);
uint16_t read_uint16(struct stream *s);
uint32_t read_uint32be(struct stream *s); uint32_t read_uint32be(struct stream *s);
uint32_t read_uint32le(struct stream *s); uint32_t read_uint32le(struct stream *s);
uint32_t read_uint32(struct stream *s);
#endif #endif