mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-08 08:11:34 +00:00
c example now uses persistent mode
This commit is contained in:
parent
a0e6b98ce8
commit
8b92a40e19
Binary file not shown.
@ -29,13 +29,13 @@
|
|||||||
#include <unicorn/unicorn.h>
|
#include <unicorn/unicorn.h>
|
||||||
|
|
||||||
// Path to the file containing the binary to emulate
|
// Path to the file containing the binary to emulate
|
||||||
#define BINARY_FILE ("simple_target_x86_64")
|
#define BINARY_FILE ("persistent_target_x86_64")
|
||||||
|
|
||||||
// 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
|
||||||
static const int64_t BASE_ADDRESS = 0x100000;
|
static const int64_t BASE_ADDRESS = 0x100000;
|
||||||
static const int64_t CODE_ADDRESS = 0x101119;
|
static const int64_t CODE_ADDRESS = 0x101139;
|
||||||
static const int64_t END_ADDRESS = 0x1011d7;
|
static const int64_t END_ADDRESS = 0x10120d;
|
||||||
// Address of the stack (Some random address again)
|
// Address of the stack (Some random address again)
|
||||||
static const int64_t 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)
|
||||||
@ -52,15 +52,33 @@ static const int64_t ALIGNMENT = 0x1000;
|
|||||||
// In our special case, we emulate main(), so argc is needed.
|
// In our special case, we emulate main(), so argc is needed.
|
||||||
static const uint64_t EMULATED_ARGC = 2;
|
static const uint64_t EMULATED_ARGC = 2;
|
||||||
|
|
||||||
|
// The return from our fake strlen
|
||||||
|
static size_t current_input_len = 0;
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data)
|
static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||||
{
|
|
||||||
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
printf(">>> Tracing instruction at 0x%"PRIx64 ", instruction size = 0x%x\n", address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The sample uses strlen, since we don't have a loader or libc, we'll fake it.
|
||||||
|
We know the strlen will return the lenght of argv[1] that we just planted.
|
||||||
|
It will be a lot faster than an actual strlen for this specific purpose.
|
||||||
|
*/
|
||||||
|
static void hook_strlen(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||||
|
//Hook
|
||||||
|
//116b: e8 c0 fe ff ff call 1030 <strlen@plt>
|
||||||
|
// We place the return at RAX
|
||||||
|
//printf("Strlen hook at addr 0x%lx (size: 0x%x), result: %ld\n", address, size, current_input_len);
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RAX, ¤t_input_len);
|
||||||
|
// We skip the actual call by updating RIP
|
||||||
|
uint64_t next_addr = address + size;
|
||||||
|
uc_reg_write(uc, UC_X86_REG_RIP, &next_addr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Unicorn page needs to be 0x1000 aligned, apparently */
|
/* Unicorn page needs to be 0x1000 aligned, apparently */
|
||||||
static uint64_t pad(uint64_t size) {
|
static uint64_t pad(uint64_t size) {
|
||||||
if (size % ALIGNMENT == 0) return size;
|
if (size % ALIGNMENT == 0) return size;
|
||||||
@ -107,8 +125,6 @@ static bool place_input_callback(
|
|||||||
// Test input too short or 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.
|
// 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
|
uc_reg_write(uc, UC_X86_REG_RIP, &CODE_ADDRESS); // Set the instruction pointer back
|
||||||
@ -116,10 +132,14 @@ static bool place_input_callback(
|
|||||||
uc_reg_write(uc, UC_X86_REG_RSI, &INPUT_LOCATION); // argv
|
uc_reg_write(uc, UC_X86_REG_RSI, &INPUT_LOCATION); // argv
|
||||||
uc_reg_write(uc, UC_X86_REG_RDI, &EMULATED_ARGC); // argc == 2
|
uc_reg_write(uc, UC_X86_REG_RDI, &EMULATED_ARGC); // argc == 2
|
||||||
|
|
||||||
// Make sure the input is 0 terminated.
|
// We need a valid c string, make sure it never goes out of bounds.
|
||||||
//input[input_len-1] = '\0';
|
input[input_len-1] = '\0';
|
||||||
// Write the testcase to unicorn.
|
// 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);
|
||||||
|
|
||||||
|
// store input_len for the faux strlen hook
|
||||||
|
current_input_len = input_len;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,6 +231,11 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
uc_hook_add(uc, &hooks[1], UC_HOOK_CODE, hook_code, NULL, BASE_ADDRESS, BASE_ADDRESS + len - 1);
|
uc_hook_add(uc, &hooks[1], UC_HOOK_CODE, hook_code, NULL, BASE_ADDRESS, BASE_ADDRESS + len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add our strlen hook (for this specific testcase only)
|
||||||
|
int strlen_hook_pos = BASE_ADDRESS + 0x116b;
|
||||||
|
uc_hook strlen_hook;
|
||||||
|
uc_hook_add(uc, &strlen_hook, UC_HOOK_CODE, hook_strlen, NULL, strlen_hook_pos, strlen_hook_pos);
|
||||||
|
|
||||||
printf("Starting to fuzz :)\n");
|
printf("Starting to fuzz :)\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
|
@ -10,25 +10,30 @@
|
|||||||
* Written by Nathan Voss <njvoss99@gmail.com>
|
* Written by Nathan Voss <njvoss99@gmail.com>
|
||||||
* Adapted by Lukas Seidel <seidel.1@campus.tu-berlin.de>
|
* Adapted by Lukas Seidel <seidel.1@campus.tu-berlin.de>
|
||||||
*/
|
*/
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if(argc < 2){
|
if (argc < 2) return -1;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *data_buf = argv[1];
|
char *data_buf = argv[1];
|
||||||
|
uint64_t data_len = strlen(data_buf);
|
||||||
|
if (data_len < 20) return -2;
|
||||||
|
|
||||||
if (data_buf[20] != 0) {
|
for (; data_len --> 0 ;) {
|
||||||
// Cause an 'invalid read' crash if data[0..3] == '\x01\x02\x03\x04'
|
if (data_len >= 18) continue;
|
||||||
unsigned char invalid_read = *(unsigned char *) 0x00000000;
|
if (data_len > 2 && data_len < 18) {
|
||||||
} else if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
|
((char *)data_len)[(uint64_t)data_buf] = data_buf[data_len + 1];
|
||||||
|
} else if (data_buf[9] == 0x90 && data_buf[10] != 0x00 && data_buf[11] == 0x90) {
|
||||||
|
// Cause a crash if data[10] is not zero, but [9] and [11] are zero
|
||||||
|
unsigned char invalid_read = *(unsigned char *) 0x00000000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
|
||||||
// Cause an 'invalid read' crash if (0x10 < data[0] < 0x20) and data[1] > data[2]
|
// Cause an 'invalid read' crash if (0x10 < data[0] < 0x20) and data[1] > data[2]
|
||||||
unsigned char invalid_read = *(unsigned char *) 0x00000000;
|
unsigned char invalid_read = *(unsigned char *) 0x00000000;
|
||||||
} else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
|
}
|
||||||
// Cause a crash if data[10] is not zero, but [9] and [11] are zero
|
|
||||||
unsigned char invalid_read = *(unsigned char *) 0x00000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
BIN
unicorn_mode/samples/c/persistent_target_x86_64
Normal file
BIN
unicorn_mode/samples/c/persistent_target_x86_64
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user