Add some Linux T1040 packet capture tests using raw sockets

This commit is contained in:
Alex M
2022-10-30 19:01:59 -05:00
parent 6f0df94b1d
commit 56a896d90b
2 changed files with 290 additions and 1 deletions
+119 -1
View File
@@ -153,4 +153,122 @@ atomic_tests:
cleanup_command: |-
pktmon filter remove
name: command_prompt
elevation_required: true
elevation_required: true
- name: Packet Capture Linux socket AF_PACKET,SOCK_RAW with sudo
description: |
Captures packets with domain=AF_PACKET, type=SOCK_RAW for a few seconds.
supported_platforms:
- linux
input_arguments:
csource_path:
description: Path to C program source
type: String
default: PathToAtomicsFolder/T1040/src/linux_pcapdemo.c
program_path:
description: Path to compiled C program
type: String
default: /tmp/t1040_linux_pcapdemo
dependency_executor_name: bash
dependencies:
- description: |
compile C program
prereq_command: |
exit 1
get_prereq_command: |
cc #{csource_path} -o #{program_path}
executor:
command: |
sudo #{program_path} -a -t 3
cleanup_command: |
rm -f #{program_path}
name: bash
elevation_required: true
- name: Packet Capture Linux socket AF_INET,SOCK_RAW,TCP with sudo
description: |
Captures packets with domain=AF_INET,type=SOCK_RAW,protocol=TCP for a few seconds.
supported_platforms:
- linux
input_arguments:
csource_path:
description: Path to C program source
type: String
default: PathToAtomicsFolder/T1040/src/linux_pcapdemo.c
program_path:
description: Path to compiled C program
type: String
default: /tmp/t1040_linux_pcapdemo
dependency_executor_name: bash
dependencies:
- description: |
compile C program
prereq_command: |
exit 1
get_prereq_command: |
cc #{csource_path} -o #{program_path}
executor:
command: |
sudo #{program_path} -4 -p 6 -t 3
cleanup_command: |
rm -f #{program_path}
name: bash
elevation_required: true
- name: Packet Capture Linux socket AF_INET,SOCK_PACKET,UDP with sudo
description: |
Captures packets with domain=AF_INET,type=SOCK_PACKET,protocol=UDP for a few seconds.
SOCK_PACKET is "obsolete" according to the man page, but still works on Ubuntu 20.04
supported_platforms:
- linux
input_arguments:
csource_path:
description: Path to C program source
type: String
default: PathToAtomicsFolder/T1040/src/linux_pcapdemo.c
program_path:
description: Path to compiled C program
type: String
default: /tmp/t1040_linux_pcapdemo
dependency_executor_name: bash
dependencies:
- description: |
compile C program
prereq_command: |
exit 1
get_prereq_command: |
cc #{csource_path} -o #{program_path}
executor:
command: |
sudo #{program_path} -4 -P -p 17 -t 3
cleanup_command: |
rm -f #{program_path}
name: bash
elevation_required: true
- name: Packet Capture Linux socket AF_PACKET,SOCK_RAW with BPF filter for UDP with sudo
description: |
Captures packets with domain=AF_PACKET,type=SOCK_RAW for a few seconds.
Sets a BPF filter on the socket to filter for UDP traffic.
supported_platforms:
- linux
input_arguments:
csource_path:
description: Path to C program source
type: String
default: PathToAtomicsFolder/T1040/src/linux_pcapdemo.c
program_path:
description: Path to compiled C program
type: String
default: /tmp/t1040_linux_pcapdemo
dependency_executor_name: bash
dependencies:
- description: |
compile C program
prereq_command: |
exit 1
get_prereq_command: |
cc #{csource_path} -o #{program_path}
executor:
command: |
sudo #{program_path} -a -f -t 3
cleanup_command: |
rm -f #{program_path}
name: bash
elevation_required: true
+171
View File
@@ -0,0 +1,171 @@
#include <errno.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <netinet/ip_icmp.h> //Provides declarations for icmp header
#include <netinet/udp.h> //Provides declarations for udp header
#include <netinet/tcp.h> //Provides declarations for tcp header
#include <netinet/ip.h> //Provides declarations for ip header
#include <sys/socket.h>
#include <arpa/inet.h>
static const struct option longopts[] = {
{ "afpacket", no_argument, NULL, 'a'},
{ "afinet4", no_argument, NULL, '4'},
{ "afinet6", no_argument, NULL, '6'},
{ "protocol", required_argument, NULL, 'p'},
{ "sockpacket", no_argument, NULL, 'P'},
{ "sockraw", no_argument, NULL, 'R'},
{ "time", required_argument, NULL, 't'},
{ 0, 0, 0, 0 }
};
static void usage(const char *progname)
{
printf("usage: %s <options>\n", progname);
printf(" -a --afpacket Set domain to AF_PACKET.\n");
printf(" -4 --afinet Set domain to AF_INET (default).\n");
printf(" -6 --afinet6 Set domain to AF_PACKET.\n");
printf(" -p --protocol <int value> Integer value to set as protocol argument. For AF_INET default is IPPROTO_TCP=6. Others:IPPROTO_UDP=17 IPPROTO_ICMP=1\n");
printf(" -P --sockpacket Set sock_type to SOCK_PACKET.\n");
printf(" -R --sockraw Set sock_type to SOCK_RAW (default)\n");
printf(" -t --time <num seconds> Exit after number of seconds. Default is to run until killed.\n");
}
void ProcessPacket(unsigned char* buf, int size, int af);
int sock_raw;
int tcp=0,udp=0,icmp=0,others=0,igmp=0,total=0,i,j;
struct sockaddr_in source,dest;
int main(int argc, char *argv[])
{
int af = AF_INET;
int sock_type = SOCK_RAW;
int sock_protocol_inet = IPPROTO_TCP;
int sock_protocol = sock_protocol_inet;
int timeout = 0;
int sock_protocol_packet = htons(3); // AF_PACKET
int saddr_size , data_size;
struct sockaddr saddr;
struct in_addr in;
unsigned char *buffer = (unsigned char *)malloc(65536);
int c;
while(1)
{
int option_index = 0;
c = getopt_long(argc, argv, "a46p:PRt:", longopts, &option_index);
if (c == -1)
break;
switch (c) {
case 'a':
af = AF_PACKET;
sock_protocol = sock_protocol_packet;
break;
case '4':
af = AF_INET;
break;
case '6':
af = AF_INET6;
break;
case 'P':
sock_type = SOCK_PACKET;
break;
case 'R':
sock_type = SOCK_RAW;
break;
case 'p':
sock_protocol = atoi(optarg);
printf("using protocol=%d (0x%x)\n", sock_protocol, sock_protocol);
break;
case 't':
timeout = atoi(optarg);
printf("will exit after %d seconds\n", timeout);
break;
default:
printf("invalid argument: '%c'\n", c);
usage(argv[0]);
return -1;
}
}
printf("Starting...\n");
// create RAW socket to capture packets
sock_raw = socket(af , sock_type , sock_protocol);
if(sock_raw < 0)
{
printf("Socket Error\n");
return 1;
}
time_t tstop = time(NULL) + timeout;
while(1)
{
int flags = MSG_DONTWAIT;
saddr_size = sizeof saddr;
//Receive a packet
data_size = recvfrom(sock_raw , buffer , 65536 , flags , &saddr , &saddr_size);
if(data_size <0 )
{
if (EAGAIN == errno || EWOULDBLOCK == errno) {
usleep(15000);
if (timeout > 0 && time(NULL) >= tstop) {
break;
}
continue;
}
printf("Recvfrom error , failed to get packets\n");
return 1;
}
ProcessPacket(buffer , data_size, af);
}
close(sock_raw);
printf("Finished\n");
return 0;
}
void ProcessPacket(unsigned char* buffer, int size, int af)
{
++total;
if (AF_PACKET == af)
{
return; // TODO: parse ether
}
//Get the IP Header part of this packet
struct iphdr *iph = (struct iphdr*)buffer;
switch (iph->protocol) //Check the Protocol and do accordingly...
{
case IPPROTO_ICMP:
++icmp;
break;
case IPPROTO_TCP:
++tcp;
break;
case IPPROTO_UDP:
++udp;
break;
default:
++others;
break;
}
printf("TCP : %d UDP : %d ICMP : %d Others : %d Total : %d\n",tcp,udp,icmp,others,total);
}