#include "attack_plan_generator.h"
#include "task_engine.h"
#include "planner.h"
#include "mape_k.h"
#include "arc_model.h"
#include "pentest_state.h"
#include "utility.h"
#include "timestamp.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//Forwarde declare callbacks
static void target_select(struct task *t);
static void scan_select(struct task *t);
static void attack_select(struct task *t);
static void attack_plan_gen_ctrl(struct task *t);
void attack_plan_gen(struct plan *p)
{
timestamp("[","] ");
printf("[Planning] [Initialized]\n");
struct task *t_target_sel = task_engine_create_task(target_select, NULL,
&p->pl->mape_k->k_b, p);
task_engine_add_task(t_target_sel,0);
}
bool target_exploited(struct arc_model *a_m, char *target)
{
bool res = false;
size_t nbytes = snprintf(NULL,0,"%s:EXPLOITATION_STATE",target);
char es_buff[nbytes+1];
snprintf(es_buff,nbytes+1,"%s:EXPLOITATION_STATE",target);
struct arc_value v = arc_model_get_property(a_m,es_buff);
if(v.type != V_STRING)
{
res = false;
}
else
{
if(strcmp(v.v_str, "Escalated") == 0 || strcmp(v.v_str, "Cnd") == 0)
{
res = true;
}
free(v.v_str);
}
return res;
}
void target_select(struct task *t)
{
struct knowledge_base *k_b = task_get_ctx(t);
struct plan *p = task_get_cb_ctx(t);
//fetch pentest state
struct pentest_state *p_s = knowledge_base_get_res(k_b,"PentestState");
//fetch utility scores
struct utility_decision *target_utility = knowledge_base_get_res(k_b,"TargetUtility");
struct arc_model *a_m = k_b->model;
printf("Pentest Num Active Targes:%d\n",pentest_state_num_targets(p_s));
size_t num_slots = pentest_state_max_targets(p_s) - pentest_state_num_targets(p_s);
size_t idx = 0;
while(num_slots > 0 && idx < target_utility->num_alternatives)
{
char *target = target_utility->options[idx].name;
printf("Target: %s:%d:%d\n",target, pentest_active_target(p_s,target), target_exploited(a_m,target));
if(!pentest_active_target(p_s,target) && !target_exploited(a_m,target))
{
printf("[Planning] adding %s to active targets\n",target);
pentest_state_add_target(p_s,target);
num_slots--;
}
idx++;
}
struct task *t_scan_sel = task_engine_create_task(scan_select, NULL,
&p->pl->mape_k->k_b, p);
task_engine_add_task(t_scan_sel,0);
}
void scan_select(struct task *t)
{
struct knowledge_base *k_b = task_get_ctx(t);
struct plan *p = task_get_cb_ctx(t);
struct arc_model *a_m = k_b->model;
struct pentest_state *p_s = knowledge_base_get_res(k_b,"PentestState");
struct scan_repertoire *s_r= knowledge_base_get_res(k_b, "ScanRepertoire");
//fetch utility scores
struct utility_decision *scan_utility = knowledge_base_get_res(k_b,"ScanUtility");
struct utility_decision *target_utility = knowledge_base_get_res(k_b,"TargetUtility");
size_t num_slots = pentest_state_max_scans(p_s) - pentest_state_num_scans(p_s);
printf("Pentest num active Scans:%d\n",pentest_state_num_scans(p_s));
//Try scans with no targets
for(size_t i = 0 ; i < scan_utility->num_alternatives;i++)
{
if(num_slots == 0)
{
break;
}
char *target = NULL;
char *scan = scan_utility->options[i].name;
struct scan *sc = scan_repertoire_get_scan(s_r,scan);
if(sc && sc->s_t == ST_Network)
{
bool active = pentest_scan_active(p_s,scan,target);
bool guard = sc->guard && sc->guard(a_m,target);
bool done = pentest_scan_done(p_s,scan,target);
pthread_t ptid = pthread_self();
uint32_t tid = task_get_id(t);
printf("%u:%u:%s:%s:%u:%u:%u:\n",tid,ptid,scan, target, active, guard, done);
if(!active && !done && guard && num_slots > 0 )
{
printf("[Planning] adding %s:%s to active scans\n",scan,target);
struct active_scan *a_s = malloc(sizeof(struct active_scan));;
active_scan_init(a_s,sc,target);
pentest_state_add_scan(p_s, a_s);
num_slots--;
}
}
}
for(size_t i = 0; i < target_utility->num_alternatives; i++)
{
if(num_slots > 0)
{
char *target = target_utility->options[i].name;
for(size_t j = 0 ; j < scan_utility->num_alternatives; j++)
{
char *scan = scan_utility->options[j].name;
struct scan *sc = scan_repertoire_get_scan(s_r,scan);
if(sc && num_slots > 0 && sc->s_t != ST_Network)
{
bool active = pentest_scan_active(p_s,scan,target);
bool guard = sc->guard && sc->guard(a_m,target);
bool done = pentest_scan_done(p_s,scan,target);
pthread_t ptid = pthread_self();
uint32_t tid = task_get_id(t);
printf("%u:%u:%s:%s:%u:%u:%u:\n",tid,ptid,scan, target, active, guard, done);
//Test guard last since it's calling into the plugin.
if(!active && !done && guard )
{
printf("[Planning] adding %s:%s to active scans\n",scan,target);
struct active_scan *a_s = malloc(sizeof(struct active_scan));;
active_scan_init(a_s,sc,target);
pentest_state_add_scan(p_s, a_s);
num_slots--;
}
}
if(num_slots == 0)
{
break;
}
}
}
if(num_slots == 0)
{
break;
}
}
/*
//While we still are below the concurrency threshold and have things we haven't tested:
while(num_slots > 0 && s_idx < scan_utility->num_alternatives && t_idx < target_utility->num_alternatives)
{
char *scan = scan_utility->options[s_idx].name;
char *target = target_utility->options[t_idx].name;
//struct attack_pattern *a_p = attack_repertoire_get_pattern(a_r, attack);
struct scan *sc = scan_repertoire_get_scan(s_r,scan);
if(sc)
{
bool active = pentest_scan_active(p_s,scan,target);
bool guard = sc->guard && sc->guard(a_m,target);
bool done = pentest_scan_done(p_s,scan,target);
printf("%s:%s:%u:%u:%u:\n",scan, target, active, guard, done);
//Test guard last since it's calling into the plugin.
if(!active && !done && guard )
{
printf("[Planning] adding %s:%s to active scans\n",scan,target);
struct active_scan *a_s = malloc(sizeof(struct active_scan));;
active_scan_init(a_s,sc,target);
pentest_state_add_scan(p_s, a_s);
num_slots--;
//What is the condition to move to the next target?
if(target_exploited(a_m,target))
{
s_idx++;
}
}
s_idx++;
}
}
*/
struct task *t_attack_sel = task_engine_create_task(attack_select, attack_plan_gen_ctrl,
&p->pl->mape_k->k_b, p);
task_engine_add_task(t_attack_sel,0);
}
void attack_select(struct task *t)
{
struct knowledge_base *k_b = task_get_ctx(t);
struct arc_model *a_m = k_b->model;
struct pentest_state *p_s = knowledge_base_get_res(k_b,"PentestState");
struct attack_repertoire *a_r= knowledge_base_get_res(k_b, "AttackRepertoire");
//fetch utility scores
struct utility_decision *attack_utility = knowledge_base_get_res(k_b,"AttackUtility");
struct utility_decision *target_utility = knowledge_base_get_res(k_b,"TargetUtility");
size_t num_slots = pentest_state_max_attacks(p_s) - pentest_state_num_attacks(p_s);
printf("Pentest num active Attacks:%d\n",pentest_state_num_attacks(p_s));
/*
//While we still are below the concurrency threshold and have things we haven't tested:
while(num_slots > 0 && a_idx <attack_utility->num_alternatives && t_idx < target_utility->num_alternatives)
{
char *attack = attack_utility->options[a_idx].name;
char *target = target_utility->options[t_idx].name;
struct attack_pattern *a_p = attack_repertoire_get_pattern(a_r, attack);
if(a_p)
{
struct attack_step *a_s = attack_repertoire_get_attack_step(a_r,a_p->a_steps[0]);
if(a_s)
{
bool active = pentest_attack_active(p_s,attack,target);
bool guard = a_s->guard && a_s->guard(a_m,target);
bool failed = pentest_attack_failed(p_s,attack,target);
bool worked = pentest_attack_worked(p_s,attack,target);
printf("%s:%s:%u:%u:%u:%u\n",attack, target, active, guard, failed, worked);
//Test guard last since it's calling into the plugin.
if(!active && !failed && !worked && guard )
{
printf("[Planning] adding %s:%s to active attacks\n",attack,target);
struct active_attack *a_a = malloc(sizeof(struct active_attack));
active_attack_init(a_a,a_p,target);
pentest_state_add_attack(p_s, a_a);
num_slots--;
//What is the condition to move to the next target?
if(target_exploited(a_m,target))
{
t_idx++;
}
}
}
}
a_idx++;
}
*/
for(size_t i = 0 ; i < target_utility->num_alternatives;i++)
{
if(num_slots == 0)
{
break;
}
char *target = target_utility->options[i].name;
for(size_t j = 0 ; j < attack_utility->num_alternatives;j++)
{
char *attack = attack_utility->options[j].name;
struct attack_pattern *a_p = attack_repertoire_get_pattern(a_r, attack);
if(a_p && num_slots > 0)
{
struct attack_step *a_s = attack_repertoire_get_attack_step(a_r,a_p->a_steps[0]);
if(a_s)
{
bool active = pentest_attack_active(p_s,attack,target);
bool guard = a_s->guard && a_s->guard(a_m,target);
bool failed = pentest_attack_failed(p_s,attack,target);
bool worked = pentest_attack_worked(p_s,attack,target);
pthread_t ptid = pthread_self();
uint32_t tid = task_get_id(t);
printf("%u:%u:%s:%s:%u:%u:%u:%u\n",tid,ptid,attack, target, active, guard, failed, worked);
//Test guard last since it's calling into the plugin.
if(!active && !failed && !worked && guard )
{
printf("[Planning] adding %s:%s to active attacks\n",attack,target);
struct active_attack *a_a = malloc(sizeof(struct active_attack));
active_attack_init(a_a,a_p,target);
pentest_state_add_attack(p_s, a_a);
num_slots--;
}
}
}
}
if(num_slots == 0)
{
break;
}
}
}
static void attack_plan_gen_ctrl(struct task *t)
{
struct plan *p = task_get_cb_ctx(t);
timestamp("[","] ");
printf("[Planning] [Complete]\n");
plan_set_status(p, PLAN_DONE);
p->done(p);
}
void target_select_z(struct task *t)
{
struct knowledge_base *k_b = task_get_ctx(t);
struct plan *p = task_get_cb_ctx(t);
//fetch pentest state
struct pentest_state *p_s = knowledge_base_get_res(k_b,"PentestState");
//fetch utility scores
struct utility_score *target_utility = knowledge_base_get_res(k_b,"TargetUtilityRanking");
size_t num_utility_entries = knowledge_base_num_res(k_b,"TargetUtilityRanking");
struct arc_model *a_m = k_b->model;
printf("Pentest Num Active Targes:%d\n",pentest_state_num_targets(p_s));
size_t num_slots = pentest_state_max_targets(p_s) - pentest_state_num_targets(p_s);
size_t idx = 0;
while(num_slots > 0 && idx < num_utility_entries)
{
char *target = target_utility[idx].option;
printf("Target: %s:%d:%d\n",target, pentest_active_target(p_s,target), target_exploited(a_m,target));
if(!pentest_active_target(p_s,target) && !target_exploited(a_m,target))
{
printf("[Planning] adding %s to active targets\n",target);
pentest_state_add_target(p_s,target);
num_slots--;
}
idx++;
}
struct task *t_attack_sel = task_engine_create_task(attack_select, attack_plan_gen_ctrl,
&p->pl->mape_k->k_b, p);
task_engine_add_task(t_attack_sel,0);
}
void attack_select_z(struct task *t)
{
struct knowledge_base *k_b = task_get_ctx(t);
struct arc_model *a_m = k_b->model;
struct pentest_state *p_s = knowledge_base_get_res(k_b,"PentestState");
struct attack_repertoire *a_r= knowledge_base_get_res(k_b, "AttackRepertoire");
//fetch utility scores
struct utility_score *attack_utility = knowledge_base_get_res(k_b,"AttackUtilityRanking");
size_t num_a_utility_entries = knowledge_base_num_res(k_b,"AttackUtilityRanking");
struct utility_score *target_utility = knowledge_base_get_res(k_b,"TargetUtilityRanking");
size_t num_t_utility_entries = knowledge_base_num_res(k_b,"TargetUtilityRanking");
size_t num_slots = pentest_state_max_attacks(p_s) - pentest_state_num_attacks(p_s);
//attack utility index
size_t a_idx = 0;
//target utility index
size_t t_idx = 0;
printf("Pentest num active Attacks:%d\n",pentest_state_num_attacks(p_s));
//While we still are below the concurrency threshold and have things we haven't tested:
while(num_slots > 0 && a_idx < num_a_utility_entries && t_idx < num_t_utility_entries)
{
char *attack = attack_utility[a_idx].option;
//FIX:Get this from the target utility instead
char *target = target_utility[t_idx].option;
struct attack_pattern *a_p = attack_repertoire_get_pattern(a_r, attack);
if(a_p)
{
struct attack_step *a_s = attack_repertoire_get_attack_step(a_r,a_p->a_steps[0]);
if(a_s)
{
bool active = pentest_attack_active(p_s,attack,target);
bool guard = a_s->guard && a_s->guard(a_m,target);
bool failed = pentest_attack_failed(p_s,attack,target);
bool worked = pentest_attack_worked(p_s,attack,target);
printf("%s:%s:%u:%u:%u:%u\n",attack, target, active, guard, failed, worked);
//Test guard last since it's calling into the plugin.
if(!active && !failed && !worked && guard )
{
printf("[Planning] adding %s:%s to active attacks\n",attack,target);
struct active_attack *a_a = malloc(sizeof(struct active_attack));;
active_attack_init(a_a,a_p,target);
pentest_state_add_attack(p_s, a_a);
num_slots--;
//What is the condition to move to the next target?
if(target_exploited(a_m,target))
{
t_idx++;
}
}
}
}
a_idx++;
}
}