mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
persistent mode harness
This commit is contained in:
@ -1940,17 +1940,17 @@ void check_binary(u8* fname) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((qemu_mode || unicorn_mode) &&
|
if ((qemu_mode) &&
|
||||||
memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
|
memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
|
||||||
|
|
||||||
SAYF("\n" cLRD "[-] " cRST
|
SAYF("\n" cLRD "[-] " cRST
|
||||||
"This program appears to be instrumented with afl-gcc, but is being "
|
"This program appears to be instrumented with afl-gcc, but is being "
|
||||||
"run in\n"
|
"run in\n"
|
||||||
" QEMU or Unicorn mode (-Q or -U). This is probably not what you "
|
" QEMU mode (-Q). This is probably not what you "
|
||||||
"want -\n"
|
"want -\n"
|
||||||
" this setup will be slow and offer no practical benefits.\n");
|
" this setup will be slow and offer no practical benefits.\n");
|
||||||
|
|
||||||
FATAL("Instrumentation found in -Q or -U mode");
|
FATAL("Instrumentation found in -Q mode");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,21 +33,24 @@
|
|||||||
|
|
||||||
// Memory map for the code to be tested
|
// Memory map for the code to be tested
|
||||||
// Arbitrary address where code to test will be loaded
|
// Arbitrary address where code to test will be loaded
|
||||||
#define BASE_ADDRESS (0x100000)
|
static const int64_t BASE_ADDRESS = 0x100000;
|
||||||
#define CODE_ADDRESS (0x101119)
|
static const int64_t CODE_ADDRESS = 0x101119;
|
||||||
#define END_ADDRESS (0x1011d7)
|
static const int64_t END_ADDRESS = 0x1011d7;
|
||||||
// Address of the stack (Some random address again)
|
// Address of the stack (Some random address again)
|
||||||
#define STACK_ADDRESS (((int64_t) 0x01) << 58)
|
static const int64_t STACK_ADDRESS = (((int64_t) 0x01) << 58);
|
||||||
// Size of the stack (arbitrarily chosen, just make it big enough)
|
// Size of the stack (arbitrarily chosen, just make it big enough)
|
||||||
#define STACK_SIZE (0x10000)
|
static const int64_t STACK_SIZE = 0x10000;
|
||||||
// Location where the input will be placed (make sure the emulated program knows this somehow, too ;) )
|
// Location where the input will be placed (make sure the emulated program knows this somehow, too ;) )
|
||||||
#define INPUT_LOCATION (0x10000)
|
static const int64_t INPUT_LOCATION = 0x10000;
|
||||||
// Inside the location, we have an ofset in our special case
|
// Inside the location, we have an ofset in our special case
|
||||||
#define INPUT_OFFSET (0x16)
|
static const int64_t INPUT_OFFSET = 0x16;
|
||||||
// Maximum allowable size of mutated data from AFL
|
// Maximum allowable size of mutated data from AFL
|
||||||
#define INPUT_SIZE_MAX (0x10000)
|
static const int64_t INPUT_SIZE_MAX = 0x10000;
|
||||||
// Alignment for unicorn mappings (seems to be needed)
|
// Alignment for unicorn mappings (seems to be needed)
|
||||||
#define ALIGNMENT ((uint64_t) 0x1000)
|
static const int64_t ALIGNMENT = 0x1000;
|
||||||
|
|
||||||
|
// In our special case, we emulate main(), so argc is needed.
|
||||||
|
static const uint64_t EMULATED_ARGC = 2;
|
||||||
|
|
||||||
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
static void hook_block(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||||
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
printf(">>> Tracing basic block at 0x%"PRIx64 ", block size = 0x%x\n", address, size);
|
||||||
@ -100,10 +103,22 @@ static bool place_input_callback(
|
|||||||
void *data
|
void *data
|
||||||
){
|
){
|
||||||
// printf("Placing input with len %ld to %x\n", input_len, DATA_ADDRESS);
|
// printf("Placing input with len %ld to %x\n", input_len, DATA_ADDRESS);
|
||||||
if (input_len >= INPUT_SIZE_MAX - INPUT_OFFSET) {
|
if (input_len < 1 || input_len >= INPUT_SIZE_MAX - INPUT_OFFSET) {
|
||||||
// Test input too long, ignore this testcase
|
// Test input too short or too long, ignore this testcase
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
// We need a valid c string, make sure it never goes out of bounds.
|
||||||
|
input[input_len-1] = '\0';
|
||||||
|
|
||||||
|
// For persistent mode, we have to set up stack and memory each time.
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RIP, &CODE_ADDRESS); // Set the instruction pointer back
|
||||||
|
// Set up the function parameters accordingly RSI, RDI (see calling convention/disassembly)
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RSI, &INPUT_LOCATION); // argv
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RDI, &EMULATED_ARGC); // argc == 2
|
||||||
|
|
||||||
|
// Make sure the input is 0 terminated.
|
||||||
|
//input[input_len-1] = '\0';
|
||||||
|
// Write the testcase to unicorn.
|
||||||
uc_mem_write(uc, INPUT_LOCATION + INPUT_OFFSET, input, input_len);
|
uc_mem_write(uc, INPUT_LOCATION + INPUT_OFFSET, input, input_len);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -188,12 +203,7 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
|
|
||||||
uc_mem_write(uc, 0x10008, "\x16\x00\x01", 3); // little endian of 0x10016, see above
|
uc_mem_write(uc, 0x10008, "\x16\x00\x01", 3); // little endian of 0x10016, see above
|
||||||
|
|
||||||
// Set up the function parameters accordingly RSI, RDI (see calling convention/disassembly)
|
|
||||||
uint64_t input_location = INPUT_LOCATION;
|
|
||||||
uc_reg_write(uc, UC_X86_REG_RSI, &input_location); // argv
|
|
||||||
uint64_t emulated_argc = 2;
|
|
||||||
uc_reg_write(uc, UC_X86_REG_RDI, &emulated_argc); // argc == 2
|
|
||||||
|
|
||||||
// If we want tracing output, set the callbacks here
|
// If we want tracing output, set the callbacks here
|
||||||
if (tracing) {
|
if (tracing) {
|
||||||
// tracing all basic blocks with customized callback
|
// tracing all basic blocks with customized callback
|
||||||
@ -212,9 +222,9 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
&end_address, // Where to exit (this is an array)
|
&end_address, // Where to exit (this is an array)
|
||||||
1, // Count of end addresses
|
1, // Count of end addresses
|
||||||
NULL, // Optional calback to run after each exec
|
NULL, // Optional calback to run after each exec
|
||||||
false,
|
false, // true, if the optional callback should be run also for non-crashes
|
||||||
1, // For persistent mode: How many rounds to run
|
100, // For persistent mode: How many rounds to run
|
||||||
NULL
|
NULL // additional data pointer
|
||||||
);
|
);
|
||||||
switch(afl_ret) {
|
switch(afl_ret) {
|
||||||
case UC_AFL_RET_ERROR:
|
case UC_AFL_RET_ERROR:
|
||||||
|
Reference in New Issue
Block a user