Created
August 21, 2022 03:42
-
-
Save cetaSYN/57c2b0e4fd6b79a0914cf5d9c79ab6c6 to your computer and use it in GitHub Desktop.
Simple Multi-threaded Port Scanner
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <pthread.h> | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
#define DEBUG 0 | |
// https://stackoverflow.com/a/1644898 | |
#define debug_print(fmt, ...) \ | |
do { if (DEBUG) fprintf(stderr, "%s:%d:%s(): " fmt, __FILE__, \ | |
__LINE__, __func__, __VA_ARGS__); } while (0) | |
#define PORT_OPEN 0 | |
#define PORT_CLOSED 1 | |
#define PORT_ERR 2 | |
typedef struct scan_thread_data { | |
struct scan_thread_data *next; | |
struct sockaddr_in sockaddr; | |
pthread_t thread_id; | |
uint8_t open; | |
} scan_thread_data; | |
void* do_scan(void *argp) { | |
scan_thread_data *thread_data = argp; | |
int socket_fd = socket(AF_INET, SOCK_STREAM, 6); | |
if (socket_fd < 0) { | |
fprintf(stderr, "Could not create socket\n"); | |
thread_data->open = PORT_ERR; | |
return (void*) -1; | |
} | |
// Attempt connection - standard SYN-ACK | |
int connect_fd = connect(socket_fd, (struct sockaddr*) &thread_data->sockaddr, sizeof(thread_data->sockaddr)); | |
switch (connect_fd) { | |
case 0: | |
thread_data->open = PORT_OPEN; | |
break; | |
default: | |
thread_data->open = PORT_CLOSED; | |
break; | |
} | |
close(socket_fd); | |
return (void*) 0; | |
} | |
char* get_scan_result_msg(uint8_t open) { | |
switch (open) { | |
case PORT_OPEN: | |
return "OPEN"; | |
case PORT_CLOSED: | |
return "CLOSED"; | |
case PORT_ERR: | |
return "ERROR"; | |
} | |
} | |
int main(int argc, char *argv[]) { | |
if (argc != 2) { | |
fprintf(stderr, "%s <target_addr>\n", argv[0]); | |
return -1; | |
} | |
debug_print("argv[1]: %s\n", argv[1]); | |
// Common TCP ports | |
const uint16_t PORTS[] = {21, 22, 23, 25, 53, 80, 443, 445, 3389, 8000, 8080, 8443}; | |
const uint8_t PORTS_COUNT = sizeof(PORTS) / sizeof(PORTS[0]); | |
scan_thread_data *HEAD = calloc(1, sizeof(scan_thread_data)); | |
scan_thread_data *cthread = HEAD; // Current thread in linked list | |
// Initiate scans | |
for (u_int16_t i=0; i<PORTS_COUNT; i++){ | |
debug_print("Scanning Port: %u\n", PORTS[i]); | |
// Initialize sockaddr struct data | |
cthread->sockaddr.sin_port = htons(PORTS[i]); | |
cthread->sockaddr.sin_family = AF_INET; | |
if (inet_pton(AF_INET, argv[1], &cthread->sockaddr.sin_addr) <= 0) { | |
fprintf(stderr, "Address invalid\n"); | |
return -1; | |
} | |
pthread_create(&cthread->thread_id, NULL, do_scan, (void*) cthread); | |
debug_print("Thread Started: %li\n", cthread->thread_id); | |
// Link and iterate | |
cthread->next = calloc(1, sizeof(scan_thread_data)); | |
cthread = cthread->next; | |
} | |
cthread = HEAD; // Reset to start | |
// Get scan results + free | |
for (u_int16_t i=0; i<PORTS_COUNT; i++){ | |
debug_print("Joining thread: %li\n", cthread->thread_id); | |
int retval = pthread_join(cthread->thread_id, NULL); | |
if (retval != 0) { | |
fprintf(stderr, "Error executing thread %li\n", cthread->thread_id); | |
} | |
uint16_t port = ntohs(cthread->sockaddr.sin_port); | |
printf("%u - %s\n", port, get_scan_result_msg(cthread->open)); | |
debug_print("%u %li %i\n", port, | |
cthread->thread_id, cthread->open); | |
// Iterate and destroy | |
scan_thread_data *dthread = cthread; | |
cthread = cthread->next; | |
free(dthread); | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Please don't use this.
It was just a programming exercise using sockets and threads.
It has a long non-configurable timeout period, hardcoded ports, and more questionable shortcuts.
This is for my own use and needs work before being useful in any real-world context.
Just use nmap.