Merge pull request #33 from AFLplusplus/self_hooks

New hooks
This commit is contained in:
Andrea Fioraldi 2023-11-23 21:34:54 +01:00 committed by GitHub
commit 34b0d11943
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1010 additions and 821 deletions

View File

@ -68,558 +68,7 @@
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
#include "tcg/tcg-op.h" #include "libafl_extras/hook.h"
#include "tcg/tcg-internal.h"
#include "exec/helper-head.h"
#include "tcg/tcg-temp-internal.h"
#ifndef TARGET_LONG_BITS
#error "TARGET_LONG_BITS not defined"
#endif
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
target_ulong libafl_gen_cur_pc;
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
target_ulong dst_block, int exit_n,
target_ulong cs_base, uint32_t flags,
int cflags);
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi);
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi);
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
void libafl_gen_backdoor(target_ulong pc);
static TCGHelperInfo libafl_exec_edge_hook_info = {
.func = NULL, .name = "libafl_exec_edge_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
};
struct libafl_edge_hook {
uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data);
void (*exec)(uint64_t id, uint64_t data);
uint64_t data;
uint64_t cur_id;
TCGHelperInfo helper_info;
struct libafl_edge_hook* next;
};
struct libafl_edge_hook* libafl_edge_hooks;
void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data),
void (*exec)(uint64_t id, uint64_t data),
uint64_t data);
void libafl_add_edge_hook(uint64_t (*gen)(target_ulong src, target_ulong dst, uint64_t data),
void (*exec)(uint64_t id, uint64_t data),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_edge_hook* hook = malloc(sizeof(struct libafl_edge_hook));
hook->gen = gen;
hook->exec = exec;
hook->data = data;
hook->next = libafl_edge_hooks;
libafl_edge_hooks = hook;
if (exec) {
memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
}
}
static TCGHelperInfo libafl_exec_block_hook_info = {
.func = NULL, .name = "libafl_exec_block_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
};
struct libafl_block_hook {
uint64_t (*gen)(target_ulong pc, uint64_t data);
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data);
void (*exec)(uint64_t id, uint64_t data);
uint64_t data;
TCGHelperInfo helper_info;
struct libafl_block_hook* next;
};
struct libafl_block_hook* libafl_block_hooks;
void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data),
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data),
void (*exec)(uint64_t id, uint64_t data), uint64_t data);
void libafl_add_block_hook(uint64_t (*gen)(target_ulong pc, uint64_t data),
void (*post_gen)(target_ulong pc, target_ulong block_length, uint64_t data),
void (*exec)(uint64_t id, uint64_t data), uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_block_hook* hook = malloc(sizeof(struct libafl_block_hook));
hook->gen = gen;
hook->post_gen = post_gen;
hook->exec = exec;
hook->data = data;
hook->next = libafl_block_hooks;
libafl_block_hooks = hook;
if (exec) {
memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
}
}
static TCGHelperInfo libafl_exec_read_hook1_info = {
.func = NULL, .name = "libafl_exec_read_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_read_hook2_info = {
.func = NULL, .name = "libafl_exec_read_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_read_hook4_info = {
.func = NULL, .name = "libafl_exec_read_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_read_hook8_info = {
.func = NULL, .name = "libafl_exec_read_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_read_hookN_info = {
.func = NULL, .name = "libafl_exec_read_hookN", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2)
| dh_typemask(i64, 3) | dh_typemask(i64, 4)
};
static TCGHelperInfo libafl_exec_write_hook1_info = {
.func = NULL, .name = "libafl_exec_write_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_write_hook2_info = {
.func = NULL, .name = "libafl_exec_write_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_write_hook4_info = {
.func = NULL, .name = "libafl_exec_write_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_write_hook8_info = {
.func = NULL, .name = "libafl_exec_write_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2) | dh_typemask(i64, 3)
};
static TCGHelperInfo libafl_exec_write_hookN_info = {
.func = NULL, .name = "libafl_exec_write_hookN", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2)
| dh_typemask(i64, 3) | dh_typemask(i64, 4)
};
struct libafl_rw_hook {
uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data);
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data);
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data);
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data);
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data);
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data);
uint64_t data;
TCGHelperInfo helper_info1;
TCGHelperInfo helper_info2;
TCGHelperInfo helper_info4;
TCGHelperInfo helper_info8;
TCGHelperInfo helper_infoN;
struct libafl_rw_hook* next;
};
struct libafl_rw_hook* libafl_read_hooks;
void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
uint64_t data);
void libafl_add_read_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook));
hook->gen = gen;
hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;
hook->execN = execN;
hook->data = data;
hook->next = libafl_read_hooks;
libafl_read_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
if (execN) {
memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo));
hook->helper_infoN.func = execN;
}
}
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi)
{
size_t size = memop_size(get_memop(oi));
struct libafl_rw_hook* hook = libafl_read_hooks;
while (hook) {
uint64_t cur_id = 0;
if (hook->gen)
cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data);
TCGHelperInfo* info = NULL;
if (size == 1 && hook->exec1) info = &hook->helper_info1;
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
if (cur_id != (uint64_t)-1) {
if (info) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
addr,
tcgv_i64_temp(tmp1) };
tcg_gen_callN(info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
} else if (hook->execN) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
TCGv tmp1 = tcg_constant_tl(size);
TCGv_i64 tmp2 = tcg_constant_i64(hook->data);
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
addr,
#if TARGET_LONG_BITS == 32
tcgv_i32_temp(tmp1),
#else
tcgv_i64_temp(tmp1),
#endif
tcgv_i64_temp(tmp2) };
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
tcg_temp_free_i64(tmp0);
#if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp1);
#else
tcg_temp_free_i64(tmp1);
#endif
tcg_temp_free_i64(tmp2);
}
}
hook = hook->next;
}
}
struct libafl_rw_hook* libafl_write_hooks;
void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
uint64_t data);
void libafl_add_write_hook(uint64_t (*gen)(target_ulong pc, MemOpIdx oi, uint64_t data),
void (*exec1)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec2)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec4)(uint64_t id, target_ulong addr, uint64_t data),
void (*exec8)(uint64_t id, target_ulong addr, uint64_t data),
void (*execN)(uint64_t id, target_ulong addr, size_t size, uint64_t data),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_rw_hook* hook = malloc(sizeof(struct libafl_rw_hook));
hook->gen = gen;
hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;
hook->execN = execN;
hook->data = data;
hook->next = libafl_write_hooks;
libafl_write_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
if (execN) {
memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo));
hook->helper_infoN.func = execN;
}
}
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi)
{
size_t size = memop_size(get_memop(oi));
struct libafl_rw_hook* hook = libafl_write_hooks;
while (hook) {
uint64_t cur_id = 0;
if (hook->gen)
cur_id = hook->gen(libafl_gen_cur_pc, oi, hook->data);
TCGHelperInfo* info = NULL;
if (size == 1 && hook->exec1) info = &hook->helper_info1;
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
if (cur_id != (uint64_t)-1) {
if (info) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
addr,
tcgv_i64_temp(tmp1) };
tcg_gen_callN(info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
} else if (hook->execN) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
TCGv tmp1 = tcg_constant_tl(size);
TCGv_i64 tmp2 = tcg_constant_i64(hook->data);
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
addr,
#if TARGET_LONG_BITS == 32
tcgv_i32_temp(tmp1),
#else
tcgv_i64_temp(tmp1),
#endif
tcgv_i64_temp(tmp2) };
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
tcg_temp_free_i64(tmp0);
#if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp1);
#else
tcg_temp_free_i64(tmp1);
#endif
tcg_temp_free_i64(tmp2);
}
}
hook = hook->next;
}
}
static TCGHelperInfo libafl_exec_cmp_hook1_info = {
.func = NULL, .name = "libafl_exec_cmp_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook2_info = {
.func = NULL, .name = "libafl_exec_cmp_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook4_info = {
.func = NULL, .name = "libafl_exec_cmp_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook8_info = {
.func = NULL, .name = "libafl_exec_cmp_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(tl, 2) | dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
struct libafl_cmp_hook {
uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data);
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data);
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data);
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data);
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data);
uint64_t data;
TCGHelperInfo helper_info1;
TCGHelperInfo helper_info2;
TCGHelperInfo helper_info4;
TCGHelperInfo helper_info8;
struct libafl_cmp_hook* next;
};
struct libafl_cmp_hook* libafl_cmp_hooks;
void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data),
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data),
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data),
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data),
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data),
uint64_t data);
void libafl_add_cmp_hook(uint64_t (*gen)(target_ulong pc, size_t size, uint64_t data),
void (*exec1)(uint64_t id, uint8_t v0, uint8_t v1, uint64_t data),
void (*exec2)(uint64_t id, uint16_t v0, uint16_t v1, uint64_t data),
void (*exec4)(uint64_t id, uint32_t v0, uint32_t v1, uint64_t data),
void (*exec8)(uint64_t id, uint64_t v0, uint64_t v1, uint64_t data),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_cmp_hook* hook = malloc(sizeof(struct libafl_cmp_hook));
hook->gen = gen;
hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;
hook->data = data;
hook->next = libafl_cmp_hooks;
libafl_cmp_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
}
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot)
{
size_t size = 0;
switch (ot & MO_SIZE) {
case MO_64:
size = 8;
break;
case MO_32:
size = 4;
break;
case MO_16:
size = 2;
break;
case MO_8:
size = 1;
break;
default:
return;
}
struct libafl_cmp_hook* hook = libafl_cmp_hooks;
while (hook) {
uint64_t cur_id = 0;
if (hook->gen)
cur_id = hook->gen(pc, size, hook->data);
TCGHelperInfo* info = NULL;
if (size == 1 && hook->exec1) info = &hook->helper_info1;
else if (size == 2 && hook->exec2) info = &hook->helper_info2;
else if (size == 4 && hook->exec4) info = &hook->helper_info4;
else if (size == 8 && hook->exec8) info = &hook->helper_info8;
if (cur_id != (uint64_t)-1 && info) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id);
TCGv_i64 tmp1 = tcg_constant_i64(hook->data);
TCGTemp *tmp2[4] = { tcgv_i64_temp(tmp0),
#if TARGET_LONG_BITS == 32
tcgv_i32_temp(op0), tcgv_i32_temp(op1),
#else
tcgv_i64_temp(op0), tcgv_i64_temp(op1),
#endif
tcgv_i64_temp(tmp1) };
tcg_gen_callN(info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
}
hook = hook->next;
}
}
static TCGHelperInfo libafl_exec_backdoor_hook_info = {
.func = NULL, .name = "libafl_exec_backdoor_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2)
};
struct libafl_backdoor_hook {
void (*exec)(target_ulong pc, uint64_t data);
uint64_t data;
TCGHelperInfo helper_info;
struct libafl_backdoor_hook* next;
};
struct libafl_backdoor_hook* libafl_backdoor_hooks;
void libafl_add_backdoor_hook(void (*exec)(target_ulong pc, uint64_t data),
uint64_t data);
void libafl_add_backdoor_hook(void (*exec)(target_ulong id, uint64_t data),
uint64_t data)
{
struct libafl_backdoor_hook* hook = malloc(sizeof(struct libafl_backdoor_hook));
hook->exec = exec;
hook->data = data;
hook->next = libafl_backdoor_hooks;
libafl_backdoor_hooks = hook;
memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
}
//// --- End LibAFL code --- //// --- End LibAFL code ---
@ -840,10 +289,10 @@ static int setjmp_gen_code(CPUArchState *env, TranslationBlock *tb,
while (hook) { while (hook) {
uint64_t cur_id = 0; uint64_t cur_id = 0;
if (hook->gen) if (hook->gen)
cur_id = hook->gen(pc, hook->data); cur_id = hook->gen(hook->data, pc);
if (cur_id != (uint64_t)-1 && hook->exec) { if (cur_id != (uint64_t)-1 && hook->helper_info.func) {
TCGv_i64 tmp0 = tcg_constant_i64(cur_id); TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(hook->data); TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
tcg_gen_callN(&hook->helper_info, NULL, tmp2); tcg_gen_callN(&hook->helper_info, NULL, tmp2);
tcg_temp_free_i64(tmp0); tcg_temp_free_i64(tmp0);
@ -912,8 +361,8 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
while (hook) { while (hook) {
hook->cur_id = 0; hook->cur_id = 0;
if (hook->gen) if (hook->gen)
hook->cur_id = hook->gen(src_block, dst_block, hook->data); hook->cur_id = hook->gen(hook->data, src_block, dst_block);
if (hook->cur_id != (uint64_t)-1 && hook->exec) if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func)
no_exec_hook = 0; no_exec_hook = 0;
hook = hook->next; hook = hook->next;
} }
@ -970,10 +419,10 @@ TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
hook = libafl_edge_hooks; hook = libafl_edge_hooks;
size_t hcount = 0; size_t hcount = 0;
while (hook) { while (hook) {
if (hook->cur_id != (uint64_t)-1 && hook->exec) { if (hook->cur_id != (uint64_t)-1 && hook->helper_info.func) {
hcount++; hcount++;
TCGv_i64 tmp0 = tcg_constant_i64(hook->cur_id); TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(hook->data); TCGv_i64 tmp1 = tcg_constant_i64(hook->cur_id);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
tcg_gen_callN(&hook->helper_info, NULL, tmp2); tcg_gen_callN(&hook->helper_info, NULL, tmp2);
tcg_temp_free_i64(tmp0); tcg_temp_free_i64(tmp0);
@ -1193,7 +642,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
while (hook) while (hook)
{ {
if (hook->post_gen) if (hook->post_gen)
hook->post_gen(pc, tb->size, hook->data); hook->post_gen(hook->data, pc, tb->size);
hook = hook->next; hook = hook->next;
} }

View File

@ -114,45 +114,13 @@ static void gen_tb_end(const TranslationBlock *tb, uint32_t cflags,
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
#include "tcg/tcg-internal.h" #include "libafl_extras/exit.h"
#include "tcg/tcg-temp-internal.h" #include "libafl_extras/hook.h"
#ifndef TARGET_LONG_BITS #ifndef TARGET_LONG_BITS
#error "TARGET_LONG_BITS not defined" #error "TARGET_LONG_BITS not defined"
#endif #endif
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
extern target_ulong libafl_gen_cur_pc;
struct libafl_breakpoint {
target_ulong addr;
struct libafl_breakpoint* next;
};
extern struct libafl_breakpoint* libafl_qemu_breakpoints;
struct libafl_hook {
target_ulong addr;
void (*callback)(uint64_t);
uint64_t data;
TCGHelperInfo helper_info;
struct libafl_hook* next;
};
extern struct libafl_hook* libafl_qemu_hooks;
struct libafl_hook* libafl_search_hook(target_ulong addr);
struct libafl_backdoor_hook {
void (*exec)(target_ulong pc, uint64_t data);
uint64_t data;
TCGHelperInfo helper_info;
struct libafl_backdoor_hook* next;
};
extern struct libafl_backdoor_hook* libafl_backdoor_hooks;
//// --- End LibAFL code --- //// --- End LibAFL code ---
bool translator_use_goto_tb(DisasContextBase *db, vaddr dest) bool translator_use_goto_tb(DisasContextBase *db, vaddr dest)
@ -210,22 +178,22 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
struct libafl_hook* hk = libafl_search_hook(db->pc_next); struct libafl_hook* hk = libafl_search_hook(db->pc_next);
if (hk) { if (hk) {
TCGv_i64 tmp1 = tcg_constant_i64(hk->data); TCGv_i64 tmp0 = tcg_constant_i64(hk->data);
#if TARGET_LONG_BITS == 32 #if TARGET_LONG_BITS == 32
TCGv_i32 tmp0 = tcg_constant_i32(db->pc_next); TCGv_i32 tmp1 = tcg_constant_i32(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i32_temp(tmp1) };
#else #else
TCGv_i64 tmp0 = tcg_constant_i64(db->pc_next); TCGv_i64 tmp1 = tcg_constant_i64(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
#endif #endif
// tcg_gen_callN(hk->callback, NULL, 2, tmp2); // tcg_gen_callN(hk->callback, NULL, 2, tmp2);
tcg_gen_callN(&hk->helper_info, NULL, tmp2); tcg_gen_callN(&hk->helper_info, NULL, tmp2);
#if TARGET_LONG_BITS == 32 #if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp0); tcg_temp_free_i32(tmp1);
#else #else
tcg_temp_free_i64(tmp0);
#endif
tcg_temp_free_i64(tmp1); tcg_temp_free_i64(tmp1);
#endif
tcg_temp_free_i64(tmp0);
} }
struct libafl_breakpoint* bp = libafl_qemu_breakpoints; struct libafl_breakpoint* bp = libafl_qemu_breakpoints;
@ -251,22 +219,22 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
if (backdoor == 0x44) { if (backdoor == 0x44) {
struct libafl_backdoor_hook* bhk = libafl_backdoor_hooks; struct libafl_backdoor_hook* bhk = libafl_backdoor_hooks;
while (bhk) { while (bhk) {
TCGv_i64 tmp1 = tcg_constant_i64(bhk->data); TCGv_i64 tmp0 = tcg_constant_i64(bhk->data);
#if TARGET_LONG_BITS == 32 #if TARGET_LONG_BITS == 32
TCGv_i32 tmp0 = tcg_constant_i32(db->pc_next); TCGv_i32 tmp1 = tcg_constant_i32(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i32_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i32_temp(tmp1) };
#else #else
TCGv_i64 tmp0 = tcg_constant_i64(db->pc_next); TCGv_i64 tmp1 = tcg_constant_i64(db->pc_next);
TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) }; TCGTemp *tmp2[2] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1) };
#endif #endif
// tcg_gen_callN(bhk->exec, NULL, 2, tmp2); // tcg_gen_callN(bhk->exec, NULL, 2, tmp2);
tcg_gen_callN(&bhk->helper_info, NULL, tmp2); tcg_gen_callN(&bhk->helper_info, NULL, tmp2);
#if TARGET_LONG_BITS == 32 #if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp0); tcg_temp_free_i32(tmp1);
#else #else
tcg_temp_free_i64(tmp0);
#endif
tcg_temp_free_i64(tmp1); tcg_temp_free_i64(tmp1);
#endif
tcg_temp_free_i64(tmp0);
bhk = bhk->next; bhk = bhk->next;
} }

View File

@ -45,32 +45,8 @@
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
#include "tcg/tcg-op.h"
#include "tcg/tcg-internal.h"
#include "exec/helper-head.h"
#include "libafl_extras/exit.h" #include "libafl_extras/exit.h"
#include "libafl_extras/hook.h"
#define LIBAFL_TABLES_SIZE 16384
#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE)
struct libafl_breakpoint {
target_ulong addr;
struct libafl_breakpoint* next;
};
struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
struct libafl_hook {
target_ulong addr;
void (*callback)(target_ulong, uint64_t);
uint64_t data;
TCGHelperInfo helper_info;
size_t num;
struct libafl_hook* next;
};
struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
size_t libafl_qemu_hooks_num = 0;
static __thread GByteArray *libafl_qemu_mem_buf = NULL; static __thread GByteArray *libafl_qemu_mem_buf = NULL;
@ -85,13 +61,6 @@ int libafl_qemu_write_reg(CPUState* cpu, int reg, uint8_t* val);
int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val); int libafl_qemu_read_reg(CPUState* cpu, int reg, uint8_t* val);
int libafl_qemu_num_regs(CPUState* cpu); int libafl_qemu_num_regs(CPUState* cpu);
int libafl_qemu_set_breakpoint(target_ulong addr);
int libafl_qemu_remove_breakpoint(target_ulong addr);
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t),
uint64_t data, int invalidate);
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate);
int libafl_qemu_remove_hook(size_t num, int invalidate);
struct libafl_hook* libafl_search_hook(target_ulong addr);
void libafl_flush_jit(void); void libafl_flush_jit(void);
extern int libafl_restoring_devices; extern int libafl_restoring_devices;
@ -184,139 +153,6 @@ int libafl_qemu_num_regs(CPUState* cpu)
return cc->gdb_num_core_regs; return cc->gdb_num_core_regs;
} }
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
int libafl_qemu_set_breakpoint(target_ulong pc)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1);
bp->addr = pc;
bp->next = libafl_qemu_breakpoints;
libafl_qemu_breakpoints = bp;
return 1;
}
int libafl_qemu_remove_breakpoint(target_ulong pc)
{
CPUState *cpu;
int r = 0;
struct libafl_breakpoint** bp = &libafl_qemu_breakpoints;
while (*bp) {
if ((*bp)->addr == pc) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
*bp = (*bp)->next;
r = 1;
} else {
bp = &(*bp)->next;
}
}
return r;
}
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(target_ulong, uint64_t),
uint64_t data, int invalidate)
{
CPUState *cpu;
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
}
size_t idx = LIBAFL_TABLES_HASH(pc);
struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1);
hk->addr = pc;
hk->callback = callback;
hk->data = data;
hk->helper_info.func = callback;
hk->helper_info.name = "libafl_hook";
hk->helper_info.flags = dh_callflag(void);
hk->helper_info.typemask = dh_typemask(void, 0) | dh_typemask(tl, 1) | dh_typemask(i64, 2);
hk->num = libafl_qemu_hooks_num++;
hk->next = libafl_qemu_hooks[idx];
libafl_qemu_hooks[idx] = hk;
return hk->num;
}
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate)
{
CPUState *cpu;
size_t r = 0;
size_t idx = LIBAFL_TABLES_HASH(addr);
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
while (*hk) {
if ((*hk)->addr == addr) {
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, addr);
}
}
void *tmp = *hk;
*hk = (*hk)->next;
free(tmp);
r++;
} else {
hk = &(*hk)->next;
}
}
return r;
}
int libafl_qemu_remove_hook(size_t num, int invalidate)
{
CPUState *cpu;
size_t idx;
for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) {
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
while (*hk) {
if ((*hk)->num == num) {
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, (*hk)->addr);
}
}
void *tmp = *hk;
*hk = (*hk)->next;
free(tmp);
return 1;
} else {
hk = &(*hk)->next;
}
}
}
return 0;
}
struct libafl_hook* libafl_search_hook(target_ulong addr)
{
size_t idx = LIBAFL_TABLES_HASH(addr);
struct libafl_hook* hk = libafl_qemu_hooks[idx];
while (hk) {
if (hk->addr == addr) {
return hk;
}
hk = hk->next;
}
return NULL;
}
void libafl_flush_jit(void) void libafl_flush_jit(void)
{ {
CPUState *cpu; CPUState *cpu;

View File

@ -1601,8 +1601,8 @@ static void handle_query_thread_extra(GArray *params, void *user_ctx)
struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds; struct libafl_custom_gdb_cmd* libafl_qemu_gdb_cmds;
void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data); void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data);
void libafl_qemu_add_gdb_cmd(int (*callback)(uint8_t*, size_t, void*), void* data) void libafl_qemu_add_gdb_cmd(int (*callback)(void*, uint8_t*, size_t), void* data)
{ {
struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd)); struct libafl_custom_gdb_cmd* c = malloc(sizeof(struct libafl_custom_gdb_cmd));
c->callback = callback; c->callback = callback;

View File

@ -236,7 +236,7 @@ int gdb_target_memory_rw_debug(CPUState *cs, hwaddr addr,
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
struct libafl_custom_gdb_cmd { struct libafl_custom_gdb_cmd {
int (*callback)(uint8_t*, size_t, void*); int (*callback)(void*, uint8_t*, size_t);
void* data; void* data;
struct libafl_custom_gdb_cmd* next; struct libafl_custom_gdb_cmd* next;
}; };

View File

@ -534,7 +534,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx)
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds; struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
int recognized = 0; int recognized = 0;
while (*c) { while (*c) {
recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data); recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
c = &(*c)->next; c = &(*c)->next;
} }

View File

@ -311,7 +311,7 @@ void gdb_handle_query_rcmd(GArray *params, void *user_ctx)
struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds; struct libafl_custom_gdb_cmd** c = &libafl_qemu_gdb_cmds;
int recognized = 0; int recognized = 0;
while (*c) { while (*c) {
recognized |= (*c)->callback(gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len, (*c)->data); recognized |= (*c)->callback((*c)->data, gdbserver_state.mem_buf->data, gdbserver_state.mem_buf->len);
c = &(*c)->next; c = &(*c)->next;
} }

View File

@ -9,6 +9,44 @@
#define THREAD_MODIFIER #define THREAD_MODIFIER
#endif #endif
struct libafl_breakpoint* libafl_qemu_breakpoints = NULL;
int libafl_qemu_set_breakpoint(target_ulong pc)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
struct libafl_breakpoint* bp = calloc(sizeof(struct libafl_breakpoint), 1);
bp->addr = pc;
bp->next = libafl_qemu_breakpoints;
libafl_qemu_breakpoints = bp;
return 1;
}
int libafl_qemu_remove_breakpoint(target_ulong pc)
{
CPUState *cpu;
int r = 0;
struct libafl_breakpoint** bp = &libafl_qemu_breakpoints;
while (*bp) {
if ((*bp)->addr == pc) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
*bp = (*bp)->next;
r = 1;
} else {
bp = &(*bp)->next;
}
}
return r;
}
static THREAD_MODIFIER struct libafl_exit_reason last_exit_reason; static THREAD_MODIFIER struct libafl_exit_reason last_exit_reason;
static THREAD_MODIFIER bool expected_exit = false; static THREAD_MODIFIER bool expected_exit = false;

View File

@ -5,6 +5,19 @@
#define EXCP_LIBAFL_EXIT 0xf4775747 #define EXCP_LIBAFL_EXIT 0xf4775747
struct libafl_breakpoint {
target_ulong addr;
struct libafl_breakpoint* next;
};
extern struct libafl_breakpoint* libafl_qemu_breakpoints;
// in cpu-target.c
void libafl_breakpoint_invalidate(CPUState *cpu, target_ulong pc);
int libafl_qemu_set_breakpoint(target_ulong pc);
int libafl_qemu_remove_breakpoint(target_ulong pc);
enum libafl_exit_reason_kind { enum libafl_exit_reason_kind {
BREAKPOINT = 0, BREAKPOINT = 0,
SYNC_BACKDOOR = 1 SYNC_BACKDOOR = 1

661
libafl_extras/hook.c Normal file
View File

@ -0,0 +1,661 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "exec/exec-all.h"
#include "exec/tb-flush.h"
#include "hook.h"
#include "exit.h"
#ifndef TARGET_LONG_BITS
#error "TARGET_LONG_BITS not defined"
#endif
target_ulong libafl_gen_cur_pc;
struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
size_t libafl_qemu_hooks_num = 0;
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t data, target_ulong pc),
uint64_t data, int invalidate)
{
CPUState *cpu;
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, pc);
}
}
size_t idx = LIBAFL_TABLES_HASH(pc);
struct libafl_hook* hk = calloc(sizeof(struct libafl_hook), 1);
hk->addr = pc;
// hk->callback = callback;
hk->data = data;
hk->helper_info.func = callback;
hk->helper_info.name = "libafl_hook";
hk->helper_info.flags = dh_callflag(void);
hk->helper_info.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2);
// TODO check for overflow
hk->num = libafl_qemu_hooks_num++;
hk->next = libafl_qemu_hooks[idx];
libafl_qemu_hooks[idx] = hk;
return hk->num;
}
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate)
{
CPUState *cpu;
size_t r = 0;
size_t idx = LIBAFL_TABLES_HASH(addr);
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
while (*hk) {
if ((*hk)->addr == addr) {
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, addr);
}
}
void *tmp = *hk;
*hk = (*hk)->next;
free(tmp);
r++;
} else {
hk = &(*hk)->next;
}
}
return r;
}
int libafl_qemu_remove_hook(size_t num, int invalidate)
{
CPUState *cpu;
size_t idx;
for (idx = 0; idx < LIBAFL_TABLES_SIZE; ++idx) {
struct libafl_hook** hk = &libafl_qemu_hooks[idx];
while (*hk) {
if ((*hk)->num == num) {
if (invalidate) {
CPU_FOREACH(cpu) {
libafl_breakpoint_invalidate(cpu, (*hk)->addr);
}
}
void *tmp = *hk;
*hk = (*hk)->next;
free(tmp);
return 1;
} else {
hk = &(*hk)->next;
}
}
}
return 0;
}
struct libafl_hook* libafl_search_hook(target_ulong addr)
{
size_t idx = LIBAFL_TABLES_HASH(addr);
struct libafl_hook* hk = libafl_qemu_hooks[idx];
while (hk) {
if (hk->addr == addr) {
return hk;
}
hk = hk->next;
}
return NULL;
}
#define GEN_REMOVE_HOOK(name) \
int libafl_qemu_remove_##name##_hook(size_t num, int invalidate) \
{ \
CPUState *cpu; \
struct libafl_##name##_hook** hk = &libafl_##name##_hooks; \
\
while (*hk) { \
if ((*hk)->num == num) { \
if (invalidate) { \
CPU_FOREACH(cpu) { \
tb_flush(cpu); \
} \
} \
\
void *tmp = *hk; \
*hk = (*hk)->next; \
free(tmp); \
return 1; \
} else { \
hk = &(*hk)->next; \
} \
} \
\
return 0; \
}
#define GEN_REMOVE_HOOK1(name) \
int libafl_qemu_remove_##name##_hook(size_t num) \
{ \
struct libafl_##name##_hook** hk = &libafl_##name##_hooks; \
\
while (*hk) { \
if ((*hk)->num == num) { \
void *tmp = *hk; \
*hk = (*hk)->next; \
free(tmp); \
return 1; \
} else { \
hk = &(*hk)->next; \
} \
} \
\
return 0; \
}
static TCGHelperInfo libafl_exec_backdoor_hook_info = {
.func = NULL, .name = "libafl_exec_backdoor_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(tl, 2)
};
struct libafl_backdoor_hook* libafl_backdoor_hooks;
size_t libafl_backdoor_hooks_num = 0;
size_t libafl_add_backdoor_hook(void (*exec)(uint64_t data, target_ulong pc),
uint64_t data)
{
struct libafl_backdoor_hook* hook = calloc(sizeof(struct libafl_backdoor_hook), 1);
// hook->exec = exec;
hook->data = data;
hook->num = libafl_backdoor_hooks_num++;
hook->next = libafl_backdoor_hooks;
libafl_backdoor_hooks = hook;
memcpy(&hook->helper_info, &libafl_exec_backdoor_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
return hook->num;
}
GEN_REMOVE_HOOK(backdoor)
static TCGHelperInfo libafl_exec_edge_hook_info = {
.func = NULL, .name = "libafl_exec_edge_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
};
struct libafl_edge_hook* libafl_edge_hooks;
size_t libafl_edge_hooks_num = 0;
size_t libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst),
void (*exec)(uint64_t data, uint64_t id),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_edge_hook* hook = calloc(sizeof(struct libafl_edge_hook), 1);
hook->gen = gen;
// hook->exec = exec;
hook->data = data;
hook->num = libafl_edge_hooks_num++;
hook->next = libafl_edge_hooks;
libafl_edge_hooks = hook;
if (exec) {
memcpy(&hook->helper_info, &libafl_exec_edge_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
}
return hook->num;
}
GEN_REMOVE_HOOK(edge)
static TCGHelperInfo libafl_exec_block_hook_info = {
.func = NULL, .name = "libafl_exec_block_hook", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
};
struct libafl_block_hook* libafl_block_hooks;
size_t libafl_block_hooks_num = 0;
size_t libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc),
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length),
void (*exec)(uint64_t data, uint64_t id), uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_block_hook* hook = calloc(sizeof(struct libafl_block_hook), 1);
hook->gen = gen;
hook->post_gen = post_gen;
// hook->exec = exec;
hook->data = data;
hook->num = libafl_block_hooks_num++;
hook->next = libafl_block_hooks;
libafl_block_hooks = hook;
if (exec) {
memcpy(&hook->helper_info, &libafl_exec_block_hook_info, sizeof(TCGHelperInfo));
hook->helper_info.func = exec;
}
return hook->num;
}
GEN_REMOVE_HOOK(block)
static TCGHelperInfo libafl_exec_read_hook1_info = {
.func = NULL, .name = "libafl_exec_read_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_read_hook2_info = {
.func = NULL, .name = "libafl_exec_read_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_read_hook4_info = {
.func = NULL, .name = "libafl_exec_read_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_read_hook8_info = {
.func = NULL, .name = "libafl_exec_read_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_read_hookN_info = {
.func = NULL, .name = "libafl_exec_read_hookN", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
| dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
static TCGHelperInfo libafl_exec_write_hook1_info = {
.func = NULL, .name = "libafl_exec_write_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_write_hook2_info = {
.func = NULL, .name = "libafl_exec_write_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_write_hook4_info = {
.func = NULL, .name = "libafl_exec_write_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_write_hook8_info = {
.func = NULL, .name = "libafl_exec_write_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2) | dh_typemask(tl, 3)
};
static TCGHelperInfo libafl_exec_write_hookN_info = {
.func = NULL, .name = "libafl_exec_write_hookN", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1) | dh_typemask(i64, 2)
| dh_typemask(tl, 3) | dh_typemask(i64, 4)
};
struct libafl_rw_hook* libafl_read_hooks;
size_t libafl_read_hooks_num = 0;
size_t libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1);
hook->gen = gen;
/*hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;
hook->execN = execN;*/
hook->data = data;
hook->num = libafl_read_hooks_num++;
hook->next = libafl_read_hooks;
libafl_read_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_read_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_read_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_read_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_read_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
if (execN) {
memcpy(&hook->helper_infoN, &libafl_exec_read_hookN_info, sizeof(TCGHelperInfo));
hook->helper_infoN.func = execN;
}
return hook->num;
}
GEN_REMOVE_HOOK(read)
struct libafl_rw_hook* libafl_write_hooks;
size_t libafl_write_hooks_num = 0;
size_t libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_rw_hook* hook = calloc(sizeof(struct libafl_rw_hook), 1);
hook->gen = gen;
/*hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;
hook->execN = execN;*/
hook->data = data;
hook->num = libafl_write_hooks_num++;
hook->next = libafl_write_hooks;
libafl_write_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_write_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_write_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_write_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_write_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
if (execN) {
memcpy(&hook->helper_infoN, &libafl_exec_write_hookN_info, sizeof(TCGHelperInfo));
hook->helper_infoN.func = execN;
}
return hook->num;
}
GEN_REMOVE_HOOK(write)
static void libafl_gen_rw(TCGTemp *addr, MemOpIdx oi, struct libafl_rw_hook* hook)
{
size_t size = memop_size(get_memop(oi));
while (hook) {
uint64_t cur_id = 0;
if (hook->gen)
cur_id = hook->gen(hook->data, libafl_gen_cur_pc, oi);
TCGHelperInfo* info = NULL;
if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1;
else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2;
else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4;
else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8;
if (cur_id != (uint64_t)-1) {
if (info) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
TCGTemp *tmp2[3] = { tcgv_i64_temp(tmp0),
tcgv_i64_temp(tmp1),
addr };
tcg_gen_callN(info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
} else if (hook->helper_infoN.func) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
TCGv tmp2 = tcg_constant_tl(size);
TCGTemp *tmp3[4] = { tcgv_i64_temp(tmp0),
tcgv_i64_temp(tmp1),
addr,
#if TARGET_LONG_BITS == 32
tcgv_i32_temp(tmp2) };
#else
tcgv_i64_temp(tmp2) };
#endif
tcg_gen_callN(&hook->helper_infoN, NULL, tmp3);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
#if TARGET_LONG_BITS == 32
tcg_temp_free_i32(tmp2);
#else
tcg_temp_free_i64(tmp2);
#endif
}
}
hook = hook->next;
}
}
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi)
{
libafl_gen_rw(addr, oi, libafl_read_hooks);
}
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi)
{
libafl_gen_rw(addr, oi, libafl_write_hooks);
}
static TCGHelperInfo libafl_exec_cmp_hook1_info = {
.func = NULL, .name = "libafl_exec_cmp_hook1", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook2_info = {
.func = NULL, .name = "libafl_exec_cmp_hook2", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook4_info = {
.func = NULL, .name = "libafl_exec_cmp_hook4", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(i64, 2) | dh_typemask(tl, 3) | dh_typemask(tl, 4)
};
static TCGHelperInfo libafl_exec_cmp_hook8_info = {
.func = NULL, .name = "libafl_exec_cmp_hook8", \
.flags = dh_callflag(void), \
.typemask = dh_typemask(void, 0) | dh_typemask(i64, 1)
| dh_typemask(i64, 2) | dh_typemask(i64, 3) | dh_typemask(i64, 4)
};
struct libafl_cmp_hook* libafl_cmp_hooks;
size_t libafl_cmp_hooks_num = 0;
size_t libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size),
void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1),
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1),
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1),
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1),
uint64_t data)
{
CPUState *cpu;
CPU_FOREACH(cpu) {
tb_flush(cpu);
}
struct libafl_cmp_hook* hook = calloc(sizeof(struct libafl_cmp_hook), 1);
hook->gen = gen;
/*hook->exec1 = exec1;
hook->exec2 = exec2;
hook->exec4 = exec4;
hook->exec8 = exec8;*/
hook->data = data;
hook->num = libafl_cmp_hooks_num++;
hook->next = libafl_cmp_hooks;
libafl_cmp_hooks = hook;
if (exec1) {
memcpy(&hook->helper_info1, &libafl_exec_cmp_hook1_info, sizeof(TCGHelperInfo));
hook->helper_info1.func = exec1;
}
if (exec2) {
memcpy(&hook->helper_info2, &libafl_exec_cmp_hook2_info, sizeof(TCGHelperInfo));
hook->helper_info2.func = exec2;
}
if (exec4) {
memcpy(&hook->helper_info4, &libafl_exec_cmp_hook4_info, sizeof(TCGHelperInfo));
hook->helper_info4.func = exec4;
}
if (exec8) {
memcpy(&hook->helper_info8, &libafl_exec_cmp_hook8_info, sizeof(TCGHelperInfo));
hook->helper_info8.func = exec8;
}
return hook->num;
}
GEN_REMOVE_HOOK(cmp)
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot)
{
size_t size = 0;
switch (ot & MO_SIZE) {
case MO_64:
size = 8;
break;
case MO_32:
size = 4;
break;
case MO_16:
size = 2;
break;
case MO_8:
size = 1;
break;
default:
return;
}
struct libafl_cmp_hook* hook = libafl_cmp_hooks;
while (hook) {
uint64_t cur_id = 0;
if (hook->gen)
cur_id = hook->gen(hook->data, pc, size);
TCGHelperInfo* info = NULL;
if (size == 1 && hook->helper_info1.func) info = &hook->helper_info1;
else if (size == 2 && hook->helper_info2.func) info = &hook->helper_info2;
else if (size == 4 && hook->helper_info4.func) info = &hook->helper_info4;
else if (size == 8 && hook->helper_info8.func) info = &hook->helper_info8;
if (cur_id != (uint64_t)-1 && info) {
TCGv_i64 tmp0 = tcg_constant_i64(hook->data);
TCGv_i64 tmp1 = tcg_constant_i64(cur_id);
TCGTemp *tmp2[4] = { tcgv_i64_temp(tmp0), tcgv_i64_temp(tmp1),
#if TARGET_LONG_BITS == 32
tcgv_i32_temp(op0), tcgv_i32_temp(op1) };
#else
tcgv_i64_temp(op0), tcgv_i64_temp(op1) };
#endif
tcg_gen_callN(info, NULL, tmp2);
tcg_temp_free_i64(tmp0);
tcg_temp_free_i64(tmp1);
}
hook = hook->next;
}
}
struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks;
struct libafl_post_syscall_hook* libafl_post_syscall_hooks;
size_t libafl_pre_syscall_hooks_num = 0;
size_t libafl_post_syscall_hooks_num = 0;
size_t libafl_add_pre_syscall_hook(struct syshook_ret (*callback)(
uint64_t data, int sys_num, target_ulong arg0,
target_ulong arg1, target_ulong arg2,
target_ulong arg3, target_ulong arg4,
target_ulong arg5, target_ulong arg6,
target_ulong arg7),
uint64_t data)
{
struct libafl_pre_syscall_hook* hook = calloc(sizeof(struct libafl_pre_syscall_hook), 1);
hook->callback = callback;
hook->data = data;
hook->num = libafl_pre_syscall_hooks_num++;
hook->next = libafl_pre_syscall_hooks;
libafl_pre_syscall_hooks = hook;
return hook->num;
}
size_t libafl_add_post_syscall_hook(target_ulong (*callback)(
uint64_t data, target_ulong ret, int sys_num,
target_ulong arg0, target_ulong arg1,
target_ulong arg2, target_ulong arg3,
target_ulong arg4, target_ulong arg5,
target_ulong arg6, target_ulong arg7),
uint64_t data)
{
struct libafl_post_syscall_hook* hook = calloc(sizeof(struct libafl_post_syscall_hook), 1);
hook->callback = callback;
hook->data = data;
hook->num = libafl_post_syscall_hooks_num++;
hook->next = libafl_post_syscall_hooks;
libafl_post_syscall_hooks = hook;
return hook->num;
}
GEN_REMOVE_HOOK1(pre_syscall)
GEN_REMOVE_HOOK1(post_syscall)
struct libafl_new_thread_hook* libafl_new_thread_hooks;
size_t libafl_new_thread_hooks_num = 0;
size_t libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid),
uint64_t data) {
struct libafl_new_thread_hook* hook = calloc(sizeof(struct libafl_new_thread_hook), 1);
hook->callback = callback;
hook->data = data;
hook->num = libafl_new_thread_hooks_num++;
hook->next = libafl_new_thread_hooks;
libafl_new_thread_hooks = hook;
return hook->num;
}
GEN_REMOVE_HOOK1(new_thread)

220
libafl_extras/hook.h Normal file
View File

@ -0,0 +1,220 @@
#pragma once
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "tcg/tcg-op.h"
#include "tcg/tcg-internal.h"
#include "tcg/tcg-temp-internal.h"
#define LIBAFL_TABLES_SIZE 16384
#define LIBAFL_TABLES_HASH(p) (((13*((size_t)(p))) ^ (((size_t)(p)) >> 15)) % LIBAFL_TABLES_SIZE)
void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args);
TranslationBlock *libafl_gen_edge(CPUState *cpu, target_ulong src_block,
target_ulong dst_block, int exit_n,
target_ulong cs_base, uint32_t flags,
int cflags);
void libafl_gen_cmp(target_ulong pc, TCGv op0, TCGv op1, MemOp ot);
void libafl_gen_backdoor(target_ulong pc);
extern target_ulong libafl_gen_cur_pc;
struct libafl_hook {
target_ulong addr;
// void (*callback)(uint64_t, target_ulong);
uint64_t data;
size_t num;
TCGHelperInfo helper_info;
struct libafl_hook* next;
};
extern struct libafl_hook* libafl_qemu_hooks[LIBAFL_TABLES_SIZE];
extern size_t libafl_qemu_hooks_num;
size_t libafl_qemu_set_hook(target_ulong pc, void (*callback)(uint64_t data, target_ulong pc),
uint64_t data, int invalidate);
size_t libafl_qemu_remove_hooks_at(target_ulong addr, int invalidate);
int libafl_qemu_remove_hook(size_t num, int invalidate);
struct libafl_hook* libafl_search_hook(target_ulong addr);
struct libafl_backdoor_hook {
void (*exec)(uint64_t data, target_ulong pc);
uint64_t data;
size_t num;
TCGHelperInfo helper_info;
struct libafl_backdoor_hook* next;
};
extern struct libafl_backdoor_hook* libafl_backdoor_hooks;
size_t libafl_add_backdoor_hook(void (*exec)(uint64_t data, target_ulong pc),
uint64_t data);
int libafl_qemu_remove_backdoor_hook(size_t num, int invalidate);
struct libafl_edge_hook {
uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst);
// void (*exec)(uint64_t data, uint64_t id);
uint64_t data;
size_t num;
uint64_t cur_id;
TCGHelperInfo helper_info;
struct libafl_edge_hook* next;
};
extern struct libafl_edge_hook* libafl_edge_hooks;
size_t libafl_add_edge_hook(uint64_t (*gen)(uint64_t data, target_ulong src, target_ulong dst),
void (*exec)(uint64_t data, uint64_t id),
uint64_t data);
int libafl_qemu_remove_edge_hook(size_t num, int invalidate);
struct libafl_block_hook {
uint64_t (*gen)(uint64_t data, target_ulong pc);
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length);
// void (*exec)(uint64_t data, uint64_t id);
uint64_t data;
size_t num;
TCGHelperInfo helper_info;
struct libafl_block_hook* next;
};
extern struct libafl_block_hook* libafl_block_hooks;
size_t libafl_add_block_hook(uint64_t (*gen)(uint64_t data, target_ulong pc),
void (*post_gen)(uint64_t data, target_ulong pc, target_ulong block_length),
void (*exec)(uint64_t data, uint64_t id), uint64_t data);
int libafl_qemu_remove_block_hook(size_t num, int invalidate);
struct libafl_rw_hook {
uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi);
/*void (*exec1)(uint64_t data, uint64_t id, target_ulong addr);
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr);
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr);
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr);
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size);*/
uint64_t data;
size_t num;
TCGHelperInfo helper_info1;
TCGHelperInfo helper_info2;
TCGHelperInfo helper_info4;
TCGHelperInfo helper_info8;
TCGHelperInfo helper_infoN;
struct libafl_rw_hook* next;
};
// alias
#define libafl_read_hook libafl_rw_hook
#define libafl_write_hook libafl_rw_hook
extern struct libafl_rw_hook* libafl_read_hooks;
extern struct libafl_rw_hook* libafl_write_hooks;
size_t libafl_add_read_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
uint64_t data);
size_t libafl_add_write_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, MemOpIdx oi),
void (*exec1)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec2)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec4)(uint64_t data, uint64_t id, target_ulong addr),
void (*exec8)(uint64_t data, uint64_t id, target_ulong addr),
void (*execN)(uint64_t data, uint64_t id, target_ulong addr, size_t size),
uint64_t data);
int libafl_qemu_remove_read_hook(size_t num, int invalidate);
int libafl_qemu_remove_write_hook(size_t num, int invalidate);
void libafl_gen_read(TCGTemp *addr, MemOpIdx oi);
void libafl_gen_write(TCGTemp *addr, MemOpIdx oi);
struct libafl_cmp_hook {
uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size);
/*void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1);
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1);
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1);
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1);*/
uint64_t data;
size_t num;
TCGHelperInfo helper_info1;
TCGHelperInfo helper_info2;
TCGHelperInfo helper_info4;
TCGHelperInfo helper_info8;
struct libafl_cmp_hook* next;
};
extern struct libafl_cmp_hook* libafl_cmp_hooks;
size_t libafl_add_cmp_hook(uint64_t (*gen)(uint64_t data, target_ulong pc, size_t size),
void (*exec1)(uint64_t data, uint64_t id, uint8_t v0, uint8_t v1),
void (*exec2)(uint64_t data, uint64_t id, uint16_t v0, uint16_t v1),
void (*exec4)(uint64_t data, uint64_t id, uint32_t v0, uint32_t v1),
void (*exec8)(uint64_t data, uint64_t id, uint64_t v0, uint64_t v1),
uint64_t data);
int libafl_qemu_remove_cmp_hook(size_t num, int invalidate);
struct syshook_ret {
target_ulong retval;
bool skip_syscall;
};
struct libafl_pre_syscall_hook {
struct syshook_ret (*callback)(uint64_t data, int sys_num, target_ulong arg0,
target_ulong arg1, target_ulong arg2,
target_ulong arg3, target_ulong arg4,
target_ulong arg5, target_ulong arg6,
target_ulong arg7);
uint64_t data;
size_t num;
struct libafl_pre_syscall_hook* next;
};
struct libafl_post_syscall_hook {
target_ulong (*callback)(uint64_t data, target_ulong ret, int sys_num,
target_ulong arg0, target_ulong arg1,
target_ulong arg2, target_ulong arg3,
target_ulong arg4, target_ulong arg5,
target_ulong arg6, target_ulong arg7);
uint64_t data;
size_t num;
struct libafl_post_syscall_hook* next;
};
extern struct libafl_pre_syscall_hook* libafl_pre_syscall_hooks;
extern struct libafl_post_syscall_hook* libafl_post_syscall_hooks;
size_t libafl_add_pre_syscall_hook(struct syshook_ret (*callback)(
uint64_t data, int sys_num, target_ulong arg0,
target_ulong arg1, target_ulong arg2,
target_ulong arg3, target_ulong arg4,
target_ulong arg5, target_ulong arg6,
target_ulong arg7),
uint64_t data);
size_t libafl_add_post_syscall_hook(target_ulong (*callback)(
uint64_t data, target_ulong ret, int sys_num,
target_ulong arg0, target_ulong arg1,
target_ulong arg2, target_ulong arg3,
target_ulong arg4, target_ulong arg5,
target_ulong arg6, target_ulong arg7),
uint64_t data);
int libafl_qemu_remove_pre_syscall_hook(size_t num);
int libafl_qemu_remove_post_syscall_hook(size_t num);
struct libafl_new_thread_hook {
bool (*callback)(uint64_t data, uint32_t tid);
uint64_t data;
size_t num;
struct libafl_new_thread_hook* next;
};
extern struct libafl_new_thread_hook* libafl_new_thread_hooks;
size_t libafl_add_new_thread_hook(bool (*callback)(uint64_t data, uint32_t tid),
uint64_t data);
int libafl_qemu_remove_new_thread_hook(size_t num);

View File

@ -3,4 +3,4 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
'syx-snapshot/syx-snapshot.c', 'syx-snapshot/syx-snapshot.c',
'syx-snapshot/channel-buffer-writeback.c', 'syx-snapshot/channel-buffer-writeback.c',
)]) )])
specific_ss.add(files('exit.c')) specific_ss.add(files('exit.c', 'hook.c'))

View File

@ -6522,8 +6522,9 @@ typedef struct {
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
#include "libafl_extras/hook.h"
extern __thread CPUArchState *libafl_qemu_env; extern __thread CPUArchState *libafl_qemu_env;
void (*libafl_on_thread_hook)(uint32_t);
//// --- End LibAFL code --- //// --- End LibAFL code ---
@ -6560,8 +6561,14 @@ static void *clone_func(void *arg)
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
libafl_qemu_env = env; libafl_qemu_env = env;
if (libafl_on_thread_hook) { if (libafl_new_thread_hooks) {
libafl_on_thread_hook(info->tid); bool continue_execution = true;
struct libafl_new_thread_hook* h = libafl_new_thread_hooks;
while (h) {
continue_execution = h->callback(h->data, info->tid) && continue_execution;
h = h->next;
}
if (continue_execution) cpu_loop(env);
} else { } else {
cpu_loop(env); cpu_loop(env);
} }
@ -13706,17 +13713,6 @@ IntervalTreeNode * libafl_maps_next(IntervalTreeNode *node, struct libafl_mapinf
} }
} }
struct syshook_ret {
uint64_t retval;
bool skip_syscall;
};
struct syshook_ret (*libafl_pre_syscall_hook)(int, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t);
uint64_t (*libafl_post_syscall_hook)(uint64_t, int, uint64_t, uint64_t,
uint64_t, uint64_t, uint64_t, uint64_t,
uint64_t, uint64_t);
//// --- End LibAFL code --- //// --- End LibAFL code ---
abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1, abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
@ -13750,21 +13746,26 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
if (libafl_pre_syscall_hook) { bool skip_syscall = false;
struct syshook_ret hook_ret = libafl_pre_syscall_hook(num, struct libafl_pre_syscall_hook* h = libafl_pre_syscall_hooks;
(uint64_t)arg1, while (h) {
(uint64_t)arg2, // no null check
(uint64_t)arg3, struct syshook_ret hook_ret = h->callback(h->data, num,
(uint64_t)arg4, (target_ulong)arg1,
(uint64_t)arg5, (target_ulong)arg2,
(uint64_t)arg6, (target_ulong)arg3,
(uint64_t)arg7, (target_ulong)arg4,
(uint64_t)arg8); (target_ulong)arg5,
if (hook_ret.skip_syscall) { (target_ulong)arg6,
ret = (abi_ulong)hook_ret.retval; (target_ulong)arg7,
goto after_syscall; (target_ulong)arg8);
} if (hook_ret.skip_syscall) {
skip_syscall = true;
ret = (abi_ulong)hook_ret.retval;
}
h = h->next;
} }
if (skip_syscall) goto after_syscall;
//// --- End LibAFL code --- //// --- End LibAFL code ---
@ -13773,19 +13774,22 @@ abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
//// --- Begin LibAFL code --- //// --- Begin LibAFL code ---
after_syscall: after_syscall:;
if (libafl_post_syscall_hook) { struct libafl_post_syscall_hook* p = libafl_post_syscall_hooks;
ret = (abi_ulong)libafl_post_syscall_hook((uint64_t)ret, num, while (p) {
(uint64_t)arg1, // no null check
(uint64_t)arg2, ret = (abi_ulong)p->callback(p->data, (target_ulong)ret, num,
(uint64_t)arg3, (target_ulong)arg1,
(uint64_t)arg4, (target_ulong)arg2,
(uint64_t)arg5, (target_ulong)arg3,
(uint64_t)arg6, (target_ulong)arg4,
(uint64_t)arg7, (target_ulong)arg5,
(uint64_t)arg8); (target_ulong)arg6,
(target_ulong)arg7,
(target_ulong)arg8);
p = p->next;
} }
//// --- End LibAFL code --- //// --- End LibAFL code ---
if (unlikely(qemu_loglevel_mask(LOG_STRACE))) { if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {