Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS #6

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.0)
project(libpacket C)
cmake_minimum_required(VERSION 3.20)
project(libpacket C CXX)
add_subdirectory(src)

# Install library headers
Expand Down
23 changes: 23 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Using www.github.com/wtfbbqhax/krakatoa
FROM amd64/krakatoa AS libpacket_dev_env

USER root
RUN apk update

VOLUME /volume/libpacket
WORKDIR /volume/libpacket

RUN apk add \
libdaq-dev@local \
libdaq-pcap-module@local \
libdaq-dump-module@local

RUN apk add \
build-base \
cmake \
ninja \
gtest-dev

RUN echo alias vi=nvim > /root/.profile

RUN apk add neovim tmux ctags
37 changes: 33 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,22 +1,51 @@
.PHONY: build clean install test uninstall
.DEFAULT_GOAL := build

# Makefile rules to build the libpacket source code
.PHONY: build
build:
cmake -B build -G Ninja . \
-D CMAKE_BUILD_TYPE:STRING=Debug \
-D CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE
cmake --build build

clean:
rm -rf build/

.PHONY: install
install: build
cmake --install build

.PHONY: clean
clean:
rm -rf build/

.PHONY: test
test: install
make -C tests/

.PHONY: uninstall
uninstall:
rm -f /usr/local/include/packet.h
rm -rf /usr/local/include/packet/
rm -f /usr/local/lib/libpacket.so.*
rm -f /usr/local/lib/libpacket.so

# Makefile rules to build the libpacket development environment.
#
# If you have a working Docker environment, you can use and contribute to this
# code base.
IMAGE_NAME=wtfbbqhax/libpacket

.PHONY: container
container:
docker build . -f Containerfile -t $(IMAGE_NAME)

.PHONY: start
start:
docker run --name libpacket --rm -td -v "$(PWD)":/volume/libpacket "$(IMAGE_NAME)"

.PHONY: kill
kill:
docker kill libpacket

.PHONY: attach
attach:
docker exec -ti libpacket sh

1 change: 1 addition & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
25 changes: 25 additions & 0 deletions bin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.20)
project(pig C CXX)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

add_executable(
dnshog
)

target_sources(
dnshog
PRIVATE
dns_hog.cc
daq_print.cc
daq_print.h
)

target_link_libraries(
dnshog
PRIVATE
daq
pcap
packet
)
23 changes: 23 additions & 0 deletions bin/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.DEFAULT_GOAL := build

# Makefile rules to build the libpacket source code
.PHONY: build
build:
cmake -B build -G Ninja . \
-D CMAKE_BUILD_TYPE:STRING=Debug \
-D CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE
cmake --build build

.PHONY: install
install: build
cmake --install build

.PHONY: clean
clean:
rm -rf build/

.PHONY: test
test: install
make -C tests/


229 changes: 229 additions & 0 deletions bin/daq_print.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
// print_packet, coppied from many of my tools using libpacket
// Victor Roemer, wtfbbqhax <viroemer@badsec.org>

#include <cstdio>
#include <cstdint>
#include <ctype.h>
#include <arpa/inet.h>
#include <netdb.h>

#include <daq.h>
#include <packet/packet.h>
#include <packet/stats.h>
#include <packet/dns.h>

#include "daq_print.h"

#define IS_SET(flags, bit) ((flags & bit) == bit)

// From https://github.com/the-tcpdump-group/tcpdump/blob/master/nameser.h#L312

/*
* Macros for subfields of flag fields.
*/
#define DNS_QR(flags) ((flags) & 0x8000) /* response flag */
#define DNS_OPCODE(flags) (((flags) >> 11) & 0xF) /* purpose of message */
#define DNS_AA(flags) (flags & 0x0400) /* authoritative answer */
#define DNS_TC(flags) (flags & 0x0200) /* truncated message */
#define DNS_RD(flags) (flags & 0x0100) /* recursion desired */
#define DNS_RA(flags) (flags & 0x0080) /* recursion available */
#define DNS_AD(flags) (flags & 0x0020) /* authentic data from named */
#define DNS_CD(flags) (flags & 0x0010) /* checking disabled by resolver */
#define DNS_RCODE(flags) (flags & 0x000F) /* response code */

// Function to decode the DNS protocol
int print_dns(dns const& dns)
{
bool is_response = DNS_QR(dns.h.flags);

if (is_response)
{
printf("[dns response] [rcode:%d, id:%d, qdcount: %d, ancount: %d, nscount: %d, arcount:%d]\n",
DNS_RCODE(dns.h.flags),
dns.h.id,
dns.h.qdcount,
dns.h.ancount,
dns.h.nscount,
dns.h.arcount);
}
else
{
printf("[dns query] [id:%d, qdcount: %d]\n",
dns.h.id,
dns.h.qdcount);
}

// Parsing Question Section
for (int i = 0; i < dns.h.qdcount; i++)
{
struct dns_query const& q = dns.questions[i];
// FIXME: Formatting/printing the QNAME
//struct dns_query *q = &dns.questions[i];
// Display QNAME
// Display QTYPE and QCLASS (assuming a structure in Packet to store this information)
printf("[query] [label: %s, type: %d, class: %d]\n",
q.label.c_str(),
q.dns_qtype,
q.dns_qclass);
}

// Parsing Answers Section
for (int i = 0; i < dns.h.ancount; i++)
{
char addr[INET6_ADDRSTRLEN];
std::string human;

struct dns_answer const &a = dns.answers[i];
if (a.dns_atype == 1)
{
inet_ntop(AF_INET, a.data.data(), addr, sizeof(addr));
human.append(addr, strnlen(addr, INET6_ADDRSTRLEN));
}
else if (a.dns_atype == 28)
{
inet_ntop(AF_INET6, a.data.data(), addr, sizeof(addr));
human.append(addr, strnlen(addr, INET6_ADDRSTRLEN));
}
else
{
human = a.data;
}
printf("[answer] [data: %s, type: %d, class %d, ttl: %d]\n",
human.c_str(),
a.dns_atype,
a.dns_aclass,
a.dns_ttl);
// // Display QNAME
// // Display QTYPE and QCLASS (assuming a structure in Packet to store this information)
// (void)dns[0].questions[i].dns_qtype;
// (void)dns[0].questions[i].dns_qclass;
}

printf("\n");
return 0;
}

// Taken from Pcapstats BSD License
//
void print_data(uint8_t const * data, int64_t length)
{
int i, x, j, c;
int w = 0;

for( i=0; length>0; length -= 16 )
{
c = length >= 16 ? 16 : length;
printf("%06X ", w);
w+=16;

for( j=0; j<c; j++ )
printf("%2.02X ", data[i+j]);

for( x = length; x<16; x++ )
printf(" ");

for( j=0; j<c; j++ )
printf("%c", (isprint(data[i+j]) ? data[i+j] : '.'));

printf("\n");
i+=c;
}
}


void
print_packet(int const instance_id, DAQ_PktHdr_t const* hdr, uint8_t const * data, size_t const len)
{
Packet packet;

packet_clear(&packet);

int error = packet_decode(&packet, data, len);
(void)error;

struct ipaddr src = packet_srcaddr(&packet);
struct ipaddr dst = packet_dstaddr(&packet);
struct ipaddr *a = &src;
struct ipaddr *b = &dst;
uint32_t sport = packet_srcport(&packet);
uint32_t dport = packet_dstport(&packet);
uint32_t proto = packet_protocol(&packet);

#ifdef PRINT_PACKET_LAYERS
// Extra debug logging
unsigned it;
for (Protocol *_p = packet_proto_first(&packet, &it);
_p; _p = packet_proto_next(&packet, &it))
{
printf("%s:", packet_proto_name(_p));
}
printf("\n");
#endif

int version = packet_version(&packet);
int af = AF_INET;
if (version == 6) {
af = AF_INET6;
}

char addr[INET6_ADDRSTRLEN];
printf("[src: %s, ", inet_ntop(af, a, addr, sizeof(addr)));
printf("dst: %s, ", inet_ntop(af, b, addr, sizeof(addr)));
printf("proto: %d, id: %d, sp: %d, dp: %d, dlen: %u] [instance: %d]\n",
proto,
packet_id(&packet),
sport,
dport,
packet_paysize(&packet),
instance_id);

if (packet_is_fragment(&packet))
{
printf(" |ip off: %u %s\n",
packet_frag_offset(&packet),
packet_frag_mf(&packet) ? "mf" : "");
}

uint32_t max = packet_paysize(&packet);
const uint8_t *payload = packet_payload(&packet);
if (sport == 53 || dport == 53)
{
dns _dns;
decode_dns(payload, max, &_dns);
print_dns(_dns);
}

max = max > 128 ? 128 : max;
//print_data(payload, max);

#ifdef PRINT_PACKET_STATS
// Packet stats are useful for determining decoding errors
struct packet_stats const * stats;
packet_stats(&stats);

printf("ip4 headers: %u\n"
"ip4 badsum: %u\n"
"ip4 tooshort: %u\n"
"ip4 toosmall: %u\n"
"ip4 badhlen: %u\n"
"ip4 badlen: %u\n",
stats->ips_packets,
stats->ips_badsum,
stats->ips_tooshort,
stats->ips_toosmall,
stats->ips_badhlen,
stats->ips_badlen);
printf("tcp headers: %u\n"
"tcp badsum: %u\n"
"tcp badoff: %u\n"
"tcp tooshort %u\n",
stats->tcps_packets,
stats->tcps_badsum,
stats->tcps_badoff,
stats->tcps_tooshort);
#endif
}




24 changes: 24 additions & 0 deletions bin/daq_print.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef MINISNORT_PRINT_PACKET_H
#define MINISNORT_PRINT_PACKET_H

#include <cstdint>
#include <sys/types.h>

/*
* PRINT_PACKET_LAYERS
* @desc Print the protocol layer composition.
*/
#undef PRINT_PACKET_LAYERS

/*
* PRINT_PACKET_STATS
* @desc Print the packet decoding stats.
* Useful for debugging decoding errors.
*/
#undef PRINT_PACKET_STATS

typedef struct _daq_pkt_hdr DAQ_PktHdr_t;
void print_packet(int const instance_id, DAQ_PktHdr_t const * hdr, uint8_t const * data, size_t const len);

#endif // MINISNORT_PRINT_PACKET_H

Loading