#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
/*
COMPILE and RUN
rm pscn_proof_of_bug;
gcc -ggdb pscn_proof_of_bug.c -o pscn_proof_of_bug -std=gnu99 -Wl,-Bstatic -lm -lrt -lz -Wl,-Bdynamic -ldl -pthread;
valgrind --track-origins=yes --leak-check=full ./pscn_proof_of_bug;
*/
char* scan_software = "masscan";
char* protocol = "http";
int current_port;
pthread_mutex_t mutexQueue;
pthread_cond_t condQueue;
int thread_max = 20; // how many checking threads to spawn [suggesting number between 4 and 8]
#define thread_submit 20 // how many thread submits, usually has to be lower or equal tu thread_max
// fake task setup
int number_of_fake_line_generator = 351;
int task_max_timeout = 5; // in seconds
int continue_read_results = 0;
#define SMALLEST_STACK PTHREAD_STACK_MIN
#define SMALL_STACK (24*1024)
typedef struct Task {
int id;
char* ip;
int port;
} Task;
// PROBLEM1 : i need this to be dynamically modified at the run time, right bow it only accept lvalue
Task taskQueue[thread_submit];
int taskCount = 0;
int rand_range(int min, int max)
{
return (int) (((double)(max-min+1)/RAND_MAX) * rand() + min);
}
void *run_fake_scan()
{
puts("run_fake_scan.start");
continue_read_results = 1;
FILE *fp_filetest;
fp_filetest = fopen("testfile.txt","w");
srand(time(NULL));
for(int i = 1; i <= number_of_fake_line_generator; i++)
{
if((strcmp(scan_software,"zmap") == 0))
{
// simulate ZMAP
fprintf(fp_filetest,"%d.%d.%d.%d\n",
rand_range(1,255),rand_range(1,255),rand_range(1,255),rand_range(1,255));
}
else if((strcmp(scan_software,"masscan") == 0))
{
// simulate MASSCAN
fprintf(fp_filetest,"open tcp %d %d.%d.%d.%d 1390380064 \n",
rand_range(80,8080),
rand_range(1,255),rand_range(1,255),rand_range(1,255),rand_range(1,255));
}
else
{
printf("No known scan available.\n");
continue_read_results = 0;
break;
}
//usleep(rand_range(5000,10000)); // fast
usleep(rand_range(5000,100000)); // slower
}
fclose(fp_filetest);
puts("run_fake_scan.finish");
continue_read_results = 0;
return NULL;
}
void executeTask(Task *task)
{
printf("executeTask -> checking #%d [%s][%d]\n",task->id, task->ip,task->port);
float sleep_time_microseconds = (float) rand_range(1000000*1,1000000*task_max_timeout)/1000000; // task wil take between 1 to 10 seconds
char cmd[500] = {0};
cmd[499] = '\0';
sprintf(cmd,"sleep %.6f",sleep_time_microseconds);
system(cmd);
printf("executeTask -> checked #%d [%s][%d]\n",task->id, task->ip,task->port);
free(task->ip);
}
void submitTask(Task task)
{
pthread_mutex_lock(&mutexQueue);
taskQueue[taskCount] = task; // segmentation fault happening sometimes
taskCount++;
pthread_mutex_unlock(&mutexQueue);
pthread_cond_signal(&condQueue);
}
void* startThread()
{
while(1)
{
Task task;
printf("startThread -> i am here 1\n");
pthread_mutex_lock(&mutexQueue);
while(taskCount == 0)
{
printf("startThread -> i am here 2\n");
pthread_cond_wait(&condQueue,&mutexQueue);
printf("startThread -> i am here 3\n");
}
// move the task
task = taskQueue[0];
for(int i = 0; i < taskCount - 1; i++)
{
taskQueue[i] = taskQueue[i + 1];
}
taskCount--;
printf("startThread -> i am here 4, and taskCount=%d\n",taskCount);
pthread_mutex_unlock(&mutexQueue);
executeTask(&task);
printf("startThread -> i am here 5\n");
}
}
void *read_results()
{
puts("read_results -> start");
// 1. create threads
printf("read_results -> Creating threads ...\n");
pthread_t threads[thread_max];
//pthread_attr_t threads_attr[thread_max];
pthread_mutex_init(&mutexQueue,NULL);
pthread_cond_init(&condQueue,NULL);
for(int iThreads = 0; iThreads < thread_max; iThreads++)
{
//pthread_attr_init(&threads_attr[iThreads]);
//pthread_attr_setdetachstate(&threads_attr[iThreads], 1);
if(pthread_create(&threads[iThreads],NULL,&startThread,NULL) == 0) // <== this line memory leaks according to valgrind
{
printf("read_results -> Thread created no. %d\n",iThreads);
}
else
{
printf("read_results -> Thread creating error no. %d\n",iThreads);
}
}
sleep(1);
char ch;
FILE *fp;
long int nbytes_read = 0;
char str[128];
int j = 0;
int first_time = 1;
int thread_num = 1;
memset(str, '\0', 128);
fp = fopen("testfile.txt", "r");
while (continue_read_results) {
if (first_time != 1) {
fp = fopen("testfile.txt", "r");
fseek(fp, nbytes_read, SEEK_SET);
sleep(1);
}
if (fp != NULL) {
while ((ch = fgetc(fp)) != EOF) {
if (ch == '\n') {
Task task;
task.id = thread_num++;
str[j++] = ch;
if((strcmp(scan_software,"zmap") == 0))
{
char this_ip[128] = {0};
this_ip[127] = '\0';
strncpy(this_ip,str,strlen(str)-1);
task.ip = (char*) strdup(this_ip);
task.port = current_port;
}
else if((strcmp(scan_software,"masscan") == 0))
{
char *pch = strtok(str," ");
int pch_num = 1;
while(pch != NULL)
{
if(pch_num == 3)
{
task.port = atoi(pch);
}
if(pch_num == 4)
{
char this_ip[128] = {0};
this_ip[127] = '\0';
strncpy(this_ip,pch,strlen(pch));
task.ip = (char*) strdup(this_ip);
}
pch = strtok(NULL," ");
pch_num++;
}
}
printf("read_results -> Reading thread_id=%d\tip=%s\tport=%d\tcontinue_read_results=%d\ttaskCount=%d\n",task.id,task.ip,task.port,continue_read_results,taskCount);
while(1)
{
if(taskCount >= thread_max)
{
//printf("read_results -> Queue is busy [%d]\n",taskCount);
usleep(5000);
}
else
{
//printf("read_results -> Submit thread_id=%d\tip=%s\tport=%d\n",task.id,task.ip,task.port);
submitTask(task); // <== seg fault is happening here
break;
}
}
memset(str, '\0', 128);
j = 0;
}
else
{
str[j++] = ch;
}
nbytes_read++;
}
first_time = 0;
}
fclose(fp);
}
/*
// no need to join them anymore
printf("read_results -> Join last threads ...\n");
for(int iThreads = 0; iThreads < thread_max; iThreads++)
{
//pthread_attr_init(&threads_attr[iThreads]);
//pthread_attr_setdetachstate(&threads_attr[iThreads], 1);
if(pthread_join(threads[iThreads],NULL) == 0)
{
printf("read_results -> Thread join no. %d\n",iThreads);
}
else
{
printf("read_results -> Thread join error no. %d\n",iThreads);
}
}
*/
printf("read_results -> Wait for all threads to finish ...\n");
usleep(1000000*10);
// 5. Cancel all threads
printf("Cancel threads ...\n");
for(int iThreads = 0; iThreads < thread_max; iThreads++)
{
if(pthread_cancel(threads[iThreads]) == 0)
{
printf("read_results -> Thread cancel no. %d\n",iThreads);
}
else
{
printf("read_results -> Thread cancel error no. %d\n",iThreads);
}
//pthread_attr_destroy(&threads_attr[iThreads]);
}
pthread_mutex_destroy(&mutexQueue);
pthread_cond_destroy(&condQueue);
puts("read_results -> finish");
return NULL;
}
int main()
{
printf("Script begining\n");
// PROBLEM2 : after first for, is stopping
for(int this_port = 80; this_port <= 88; this_port++)
{
current_port = this_port;
printf("Checking port [%d]\n",current_port);
continue_read_results = 0;
// using this for memory leak prevention
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, SMALL_STACK);
pthread_t thread_scan;
pthread_t thread_read;
pthread_create(&thread_scan, &attr, &run_fake_scan, NULL);
pthread_create(&thread_read, &attr, &read_results, NULL);
pthread_join(thread_scan, NULL);
pthread_join(thread_read, NULL);
pthread_attr_destroy(&attr);
}
printf("Script finished!\n");
return 0;
}