Skip to content

Instantly share code, notes, and snippets.

@cetaSYN
Created August 21, 2022 03:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cetaSYN/57c2b0e4fd6b79a0914cf5d9c79ab6c6 to your computer and use it in GitHub Desktop.
Save cetaSYN/57c2b0e4fd6b79a0914cf5d9c79ab6c6 to your computer and use it in GitHub Desktop.
Simple Multi-threaded Port Scanner
#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;
}
@cetaSYN
Copy link
Author

cetaSYN commented Aug 21, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment