1
0

added portScanDetection

This commit is contained in:
Andrew Woodlee 2022-12-01 14:48:27 -06:00
parent 1ecb7b5c77
commit df06753e1a
23 changed files with 777 additions and 39 deletions

View File

@ -1,39 +0,0 @@
import pygeoip
import re as regex
ipAddrList = { }
ipAddrCountry = { }
geoip = pygeoip.GeoIP('GeoIP.dat')
loginFile = open("logins.txt")
loginList = loginFile.readlines()
ipAddrRegex = regex.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
uniqueIPs = 0
uniqueIPsByCountry = 0
for login in loginList:
ipAddr = regex.split(ipAddrRegex, login)
ip = ipAddr[1]
# use dictionary for number of IPs in a Country
country = geoip.country_code_by_addr(ip)
if country not in ipAddrCountry.values():
uniqueIPsByCountry += 1
ipAddrCountry[ip] = country
if ip in ipAddrList.keys():
ipAddrList[ip] += 1
else:
uniqueIPs+=1
ipAddrList[ip] = 1
print("\nIP Addresses by count:\n")
for ipCount in ipAddrList:
print(ipCount,":", ipAddrList.get(ipCount))
print("\nIP Addresses by country:\n")
for ipCountry in ipAddrCountry:
print(ipCountry, ":", ipAddrCountry.get(ipCountry))
print("\nNumber of unique IP addresses: ", uniqueIPs)
print("\nNumber of unique IP addresses by Country: ", uniqueIPsByCountry, "\n")

View File

@ -0,0 +1,55 @@
import pygeoip
import re as regex
ipAddrList = { }
ipAddrCountryCount = { }
ipAddrCountries = { }
geoip = pygeoip.GeoIP('GeoIP.dat')
loginFile = open("logins.txt")
loginList = loginFile.readlines()
ipAddrRegex = regex.compile(r'(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
uniqueIPs = 0
uniqueIPsByCountry = 0
for login in loginList:
ipAddr = regex.split(ipAddrRegex, login)
ip = ipAddr[1]
if ip in ipAddrList:
country = geoip.country_code_by_addr(ip)
if country not in ipAddrCountryCount.values():
uniqueIPsByCountry += 1
ipAddrList[ip] += 1
else:
country = geoip.country_code_by_addr(ip)
if country not in ipAddrCountryCount.values():
uniqueIPsByCountry += 1
ipAddrCountries[ip] = country
uniqueIPs+=1
ipAddrList[ip] = 1
for ip in ipAddrList.keys():
# use dictionary for number of IPs in a Country
country = geoip.country_code_by_addr(ip)
if country in ipAddrCountryCount:
ipAddrCountryCount[country] += 1
else:
ipAddrCountryCount[country] = 1
print("\nIP Addresses by occurrence:\n")
for ipCount in ipAddrList:
print(ipCount,":", ipAddrList.get(ipCount))
print("\nIP Addresses by country:\n")
for ipCountry in ipAddrCountries:
print(ipCountry, ":", ipAddrCountries.get(ipCountry))
print("\nIP Address count from countries:\n")
for ipCountry in ipAddrCountryCount:
print(ipCountry, ":", ipAddrCountryCount.get(ipCountry))
print("\nNumber of unique IP addresses: ", uniqueIPs)

2
CPE449/portScanDetection/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.exe
build

View File

@ -0,0 +1,17 @@
{
"configurations": [
{
"name": "linux-gcc-x64",
"includePath": [
"${workspaceFolder}/**"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
"cStandard": "${default}",
"intelliSenseMode": "linux-gcc-x64",
"configurationProvider": "ms-vscode.makefile-tools",
"cppStandard": "${default}"
}
],
"version": 4
}

View File

@ -0,0 +1,51 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/anw0044.exe",
"args": [
"-i",
"connect_scan.pcap"
],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
{
"name": "C/C++ Runner: Debug Session",
"type": "cppdbg",
"request": "launch",
"args": [],
"stopAtEntry": false,
"externalConsole": false,
"cwd": "/home/andrew/Repositories/UAHCode/CPE449/portScanDetection",
"program": "/home/andrew/Repositories/UAHCode/CPE449/portScanDetection/build/Debug/outDebug",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
}
]
}

View File

@ -0,0 +1,35 @@
{
"files.associations": {
"pcap.h": "c",
"search.h": "c"
},
"C_Cpp_Runner.msvcBatchPath": "",
"C_Cpp_Runner.cCompilerPath": "gcc",
"C_Cpp_Runner.cppCompilerPath": "g++",
"C_Cpp_Runner.debuggerPath": "gdb",
"C_Cpp_Runner.cStandard": "",
"C_Cpp_Runner.cppStandard": "",
"C_Cpp_Runner.useMsvc": false,
"C_Cpp_Runner.warnings": [
"-Wall",
"-Wextra",
"-Wpedantic"
],
"C_Cpp_Runner.enableWarnings": true,
"C_Cpp_Runner.warningsAsError": false,
"C_Cpp_Runner.compilerArgs": [],
"C_Cpp_Runner.linkerArgs": [],
"C_Cpp_Runner.includePaths": [],
"C_Cpp_Runner.includeSearch": [
"*",
"**/*"
],
"C_Cpp_Runner.excludeSearch": [
"**/build",
"**/build/**",
"**/.*",
"**/.*/**",
"**/.vscode",
"**/.vscode/**"
]
}

View File

@ -0,0 +1,30 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: gcc build active file",
"command": "/usr/bin/gcc",
"args": [
"-fdiagnostics-color=always",
"-I/usr/lib",
"-g",
"${file}",
"-o",
"${fileDirname}/${fileBasenameNoExtension}",
"-libpcap"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

View File

@ -0,0 +1,5 @@
default:
gcc -I/usr/lib -o anw0044.exe anw0044.c -lpcap
test:
gcc -I/usr/lib -o test.exe test.c -lpcap

View File

@ -0,0 +1,446 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <pcap.h>
#include <netinet/if_ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <search.h>
// Global structures
struct scanTypes
{
u_int connect;
u_int null;
u_int halfOpen;
u_int udp;
u_int attemptedScans;
u_int xmas;
} scansInFile;
struct scanTypesBools
{
bool connect;
bool null;
bool halfOpen;
bool udp;
bool attemptedScans;
bool xmas;
};
struct tcpFlagsSet
{
bool ACK;
bool SYN;
bool SYN_ACK;
bool RST_ACK;
bool FIN;
bool RST;
bool PSH;
bool URG;
};
struct tcpDictionary
{
struct tcpFlagsSet tcpFlags;
int packetNumInGroup;
struct scanTypesBools scanTypes;
uint16_t srcPort;
uint16_t port;
uint16_t dstPort;
uint16_t srcIP;
uint16_t dstIP;
} currentTCPPacket;
struct udpPacket
{
uint16_t srcPort;
uint16_t port;
uint16_t dstPort;
uint16_t srcIP;
uint16_t dstIP;
} currentUDPPacket;
// Provided structures
struct pcap_pkthdr *pcapHeaderStruct;
struct ether_header *ethNetHeaderStruct;
struct ip *ipHeaderStruct;
struct tcphdr *tcpHeaderStruct;
struct udphdr *udpHeaderStruct;
struct icmphdr *icmpHeaderStruct;
// Functions
void myHandler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
ENTRY *seachTable(int key);
void addToTable(int key, void *data);
void printScans();
// Global variables and constants
int *seqNums;
int connectScans = 0;
const int TCP_DICTIONARY_SIZE = 100000;
const char *ErrorMSG = "Must provide input file.\n";
uint8_t *shost;
uint8_t *dhost;
ENTRY *search;
ENTRY entry;
int main(int argc, char **argv)
{
if (hcreate(TCP_DICTIONARY_SIZE) == 0)
{
printf("error");
hcreate(50000);
};
if (argc < 3)
{
printf("%s", ErrorMSG);
return 0;
}
seqNums = malloc(TCP_DICTIONARY_SIZE * TCP_DICTIONARY_SIZE * sizeof(int));
char errbuf[PCAP_ERRBUF_SIZE];
char *pcapFileName = argv[2];
pcap_t *pcapFile = pcap_open_offline(pcapFileName, errbuf);
pcap_loop(pcapFile, 0, myHandler, NULL);
/* And close the session */
pcap_close(pcapFile);
printScans();
}
void printScans()
{
printf("Null: %d\n", scansInFile.null);
printf("Xmas: %d\n", scansInFile.xmas);
printf("UDP: %d\n", scansInFile.udp);
printf("Half-open: %d\n", scansInFile.halfOpen);
printf("Connect: %d\n", scansInFile.connect);
printf("Attempted scans: %d\n", scansInFile.attemptedScans);
}
void myHandler(
u_char *args,
const struct pcap_pkthdr *header,
const u_char *packet)
{
/* First, lets make sure we have an IP packet */
struct ether_header *eth_header;
eth_header = (struct ether_header *)packet;
if (ntohs(eth_header->ether_type) != ETHERTYPE_IP)
{
return;
}
const u_char *ip_header;
const u_char *tcp_header;
const u_char *udp_header;
const u_char *icmp_header;
const u_char *payload;
// Packet lengths
int ethHeaderLength = 14;
int ipHeaderLength;
int tcpHeaderLength;
int payloadLength;
ip_header = packet + ethHeaderLength;
ipHeaderLength = ((*ip_header) & 0x0F);
ipHeaderLength = ipHeaderLength * 4;
ipHeaderStruct = (struct iphdr *)ip_header;
// printf("%d\n", ipHeaderStruct->ip_id);
u_char protocol = *(ip_header + 9);
if ( protocol == IPPROTO_ICMP)
{
search = seachTable(currentUDPPacket.port);
struct udpPacket *prevUDPPacket;
if (search != NULL) prevUDPPacket = search->data;
scansInFile.udp--;
icmp_header = packet + ethHeaderLength + ipHeaderLength;
icmpHeaderStruct = (struct icmphdr *)icmp_header;
if (icmpHeaderStruct->type == ICMP_DEST_UNREACH)
{
scansInFile.attemptedScans++;
}
}
if (protocol == IPPROTO_UDP)
{
udp_header = packet + ethHeaderLength + ipHeaderLength;
udpHeaderStruct = (struct udphdr *)udp_header;
currentUDPPacket.port= ntohs(udpHeaderStruct->source);
addToTable(currentUDPPacket.port, &currentUDPPacket);
if (udpHeaderStruct->uh_dport == 53)
{
return;
}
scansInFile.udp++;
return;
}
if (protocol != IPPROTO_TCP)
{
return;
}
tcp_header = packet + ethHeaderLength + ipHeaderLength;
tcpHeaderLength = ((*(tcp_header + 12)) & 0xF0) >> 4;
tcpHeaderLength = tcpHeaderLength * 4;
tcpHeaderStruct = (struct tcphdr *)tcp_header;
const bool ACKflag = (tcpHeaderStruct->ack == 1);
const bool RSTflag = (tcpHeaderStruct->rst == 1);
const bool SYNflag = (tcpHeaderStruct->syn == 1);
const bool FINflag = (tcpHeaderStruct->fin == 1);
const bool PSHflag = (tcpHeaderStruct->fin == 1);
const bool URGflag = (tcpHeaderStruct->urg == 1);
const uint32_t tcpSEQ = tcpHeaderStruct->seq;
const uint32_t tcpACKSeq = tcpHeaderStruct->ack_seq;
currentTCPPacket.tcpFlags.ACK = ACKflag;
currentTCPPacket.tcpFlags.RST = RSTflag;
currentTCPPacket.tcpFlags.SYN = SYNflag;
currentTCPPacket.tcpFlags.FIN = FINflag;
currentTCPPacket.tcpFlags.PSH = PSHflag;
currentTCPPacket.tcpFlags.URG = URGflag;
/*
TCP SYN flag is set when connection is made and when server sends back SYN/ACK
ACK flag set when server sends back SYN/ACK, and when client sends response to SYN/ACK
TCP Half-open:
SYN, SYN/ACK, RST
Connect scan:
Open state:
SYN is first
SYN, ACK is second
RST is last
*/
search = seachTable(currentTCPPacket.port);
// printf("Packet Num: %d\n", currentTCPPacket.packetNumInGroup);
/*
returns a value when
*/
// first packet
const uint16_t srcPort = ntohs(tcpHeaderStruct->th_sport);
const uint16_t dstPort = ntohs(tcpHeaderStruct->th_dport);
// struct in_addr_t srcIP = ipHeaderStruct->ip_src.s_addr;
struct tcpDictionary *prevPacket;
if (search!=NULL) prevPacket = search->data;
if (search == NULL || srcPort == prevPacket->port
|| dstPort == prevPacket->port)
{
search = seachTable(currentTCPPacket.srcPort);
currentTCPPacket.packetNumInGroup = 0;
if (ACKflag || RSTflag)
{
return;
}
// start of packet for Half-open and Connect
if (SYNflag && !ACKflag && !RSTflag && !FINflag && !PSHflag && !URGflag)
{
currentTCPPacket.port = dstPort;
currentTCPPacket.packetNumInGroup = 1;
// hdestroy();
// hcreate(TCP_DICTIONARY_SIZE);
addToTable(currentTCPPacket.dstPort, &currentTCPPacket);
return;
}
// else one of the other scans
else
{
if (FINflag)
{
// Xmas pattern
if (PSHflag && URGflag)
{
scansInFile.xmas++;
currentTCPPacket.port = dstPort;
currentTCPPacket.packetNumInGroup = 1;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
}
// NULL pattern
if (!SYNflag && !ACKflag &&
!RSTflag && !FINflag &&
!PSHflag && !URGflag)
{
currentTCPPacket.port = dstPort;
currentTCPPacket.packetNumInGroup = 1;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
}
}
else
{
// printf("found\n");
// found packet
prevPacket = search->data;
currentTCPPacket.packetNumInGroup++;
// does last packet match X-Mas pattern?
if (prevPacket->tcpFlags.PSH &&
prevPacket->tcpFlags.FIN &&
prevPacket->tcpFlags.URG)
{
// printf("Run\n");
if (FINflag)
{
// Xmas pattern
if (PSHflag && URGflag)
{
// scansInFile.xmas++;
currentTCPPacket.port = dstPort;
currentTCPPacket.packetNumInGroup = 1;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
}
scansInFile.xmas++;
if (ACKflag && RSTflag)
{
scansInFile.xmas--;
scansInFile.attemptedScans++;
// printf("XMas\n");
currentTCPPacket.packetNumInGroup = 0;
return;
}
return;
}
// ACK and SYN current
else if (SYNflag && ACKflag &&
!RSTflag && !FINflag &&
!PSHflag && !URGflag)
{
currentTCPPacket.packetNumInGroup++;
if (prevPacket->tcpFlags.SYN && prevPacket->tcpFlags.ACK)
{
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
// ACK and SYN prev
// Connect and half-open
else if (prevPacket->tcpFlags.ACK && prevPacket->tcpFlags.SYN &&
!prevPacket->tcpFlags.FIN && !prevPacket->tcpFlags.PSH &&
!prevPacket->tcpFlags.RST && !prevPacket->tcpFlags.URG)
{
if (RSTflag){
scansInFile.halfOpen++;
addToTable(currentTCPPacket.port, &currentTCPPacket);
currentTCPPacket.packetNumInGroup = 0;
return;
}
else if (ACKflag)
{
currentTCPPacket.packetNumInGroup++;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
}
// ACK prev
// Connect successful?
else if (prevPacket->tcpFlags.ACK && !prevPacket->tcpFlags.SYN &&
!prevPacket->tcpFlags.FIN && !prevPacket->tcpFlags.PSH &&
!prevPacket->tcpFlags.RST && !prevPacket->tcpFlags.URG)
{
// yes
if (RSTflag){
scansInFile.connect++;
currentTCPPacket.packetNumInGroup = 0;
return;
}
// no
else if (ACKflag)
{
currentTCPPacket.packetNumInGroup++;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
}
// ACK prev, SYN current
else if (SYNflag && !ACKflag && !RSTflag && !FINflag && !PSHflag && !URGflag && prevPacket->tcpFlags.ACK)
{
currentTCPPacket.packetNumInGroup++;
addToTable(currentTCPPacket.port, &currentTCPPacket);
return;
}
// Filtered for
else if (!SYNflag && !ACKflag &&
!RSTflag && !FINflag &&
!PSHflag && !URGflag &&
prevPacket->tcpFlags.SYN)
{
scansInFile.attemptedScans++;
}
// scans for
else if (prevPacket->tcpFlags.SYN &&
!SYNflag && !ACKflag &&
RSTflag && !FINflag &&
!PSHflag && !URGflag)
{
return;
}
}
}
void addToTable(int key, void *data)
{
ENTRY dictionaryEntry;
char index[50];
sprintf(index, "%u", key);
dictionaryEntry.key = index;
dictionaryEntry.data = data;
hsearch(dictionaryEntry, ENTER);
}
ENTRY *seachTable(int key)
{
ENTRY dictionaryEntry;
char index[50];
sprintf(index, "%u", key);
dictionaryEntry.key = index;
ENTRY *search = hsearch(dictionaryEntry, FIND);
return search;
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,6 @@
Null: 0
Xmas: 1668
UDP: 0
Half-open: 0
Connect: 0
Attempted scans: 0

View File

View File

@ -0,0 +1,130 @@
#include <stdio.h>
#include <pcap.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
/* Finds the payload of a TCP/IP packet */
void my_packet_handler(
u_char *args,
const struct pcap_pkthdr *header,
const u_char *packet
)
{
/* First, lets make sure we have an IP packet */
struct ether_header *eth_header;
eth_header = (struct ether_header *) packet;
if (ntohs(eth_header->ether_type) != ETHERTYPE_IP) {
printf("Not an IP packet. Skipping...\n\n");
return;
}
/* The total packet length, including all headers
and the data payload is stored in
header->len and header->caplen. Caplen is
the amount actually available, and len is the
total packet length even if it is larger
than what we currently have captured. If the snapshot
length set with pcap_open_live() is too small, you may
not have the whole packet. */
printf("Total packet available: %d bytes\n", header->caplen);
printf("Expected packet size: %d bytes\n", header->len);
/* Pointers to start point of various headers */
const u_char *ip_header;
const u_char *tcp_header;
const u_char *payload;
/* Header lengths in bytes */
int ethernet_header_length = 14; /* Doesn't change */
int ip_header_length;
int tcp_header_length;
int payload_length;
/* Find start of IP header */
ip_header = packet + ethernet_header_length;
/* The second-half of the first byte in ip_header
contains the IP header length (IHL). */
ip_header_length = ((*ip_header) & 0x0F);
/* The IHL is number of 32-bit segments. Multiply
by four to get a byte count for pointer arithmetic */
ip_header_length = ip_header_length * 4;
printf("IP header length (IHL) in bytes: %d\n", ip_header_length);
/* Now that we know where the IP header is, we can
inspect the IP header for a protocol number to
make sure it is TCP before going any further.
Protocol is always the 10th byte of the IP header */
u_char protocol = *(ip_header + 9);
if (protocol != IPPROTO_TCP) {
printf("Not a TCP packet. Skipping...\n\n");
return;
}
/* Add the ethernet and ip header length to the start of the packet
to find the beginning of the TCP header */
tcp_header = packet + ethernet_header_length + ip_header_length;
/* TCP header length is stored in the first half
of the 12th byte in the TCP header. Because we only want
the value of the top half of the byte, we have to shift it
down to the bottom half otherwise it is using the most
significant bits instead of the least significant bits */
tcp_header_length = ((*(tcp_header + 12)) & 0xF0) >> 4;
/* The TCP header length stored in those 4 bits represents
how many 32-bit words there are in the header, just like
the IP header length. We multiply by four again to get a
byte count. */
tcp_header_length = tcp_header_length * 4;
printf("TCP header length in bytes: %d\n", tcp_header_length);
/* Add up all the header sizes to find the payload offset */
int total_headers_size = ethernet_header_length+ip_header_length+tcp_header_length;
printf("Size of all headers combined: %d bytes\n", total_headers_size);
payload_length = header->caplen -
(ethernet_header_length + ip_header_length + tcp_header_length);
printf("Payload size: %d bytes\n", payload_length);
payload = packet + total_headers_size;
printf("Memory address where payload begins: %p\n\n", payload);
/* Print payload in ASCII */
/*
if (payload_length > 0) {
const u_char *temp_pointer = payload;
int byte_count = 0;
while (byte_count++ < payload_length) {
printf("%c", *temp_pointer);
temp_pointer++;
}
printf("\n");
}
*/
return;
}
int main(int argc, char **argv) {
if (argc < 2)
{
// printf("%s",);
return 0;
}
// printf("%s", "blah");
for (int i = 0; i < argc; i++)
{
printf("%s\n", argv[i]);
}
char* pcapFileName = argv[2];
char error_buffer[PCAP_ERRBUF_SIZE];
pcap_t *handle;
/* Snapshot length is how many bytes to capture from each packet. This includes*/
int snapshot_length = 1024;
/* End the loop after this many packets are captured */
int total_packet_count = 200;
u_char *my_arguments = NULL;
handle = pcap_open_offline(pcapFileName, error_buffer);
pcap_loop(handle, total_packet_count, my_packet_handler, my_arguments);
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Binary file not shown.