Repository: airbus-cyber/afl_ghidra_emu
Branch: master
Commit: 751c0df730b1
Files: 13
Total size: 42.3 KB
Directory structure:
gitextract_9yizunl3/
├── .gitignore
├── README.md
├── afl_bridge_external/
│ ├── Makefile
│ ├── afl_bridge_external.c
│ └── types.h
├── examples/
│ ├── ppc/
│ │ ├── bin/
│ │ │ └── keygenme_ppc.elf
│ │ └── fuzz_ppc_check_serial.py
│ └── xtensa/
│ ├── bin/
│ │ └── keygenme_xtensa.elf
│ └── fuzz_xtensa_check_serial.py
├── libAFL/
│ ├── __init__.py
│ └── libAFL.py
└── libUtils/
├── __init__.py
└── libUtils.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.pyc
.class
.log
================================================
FILE: README.md
================================================
# afl_ghidra_emu
[](https://opensource.org/licenses/Apache-2.0)
afl_ghidra_emu is no longer maintained and replaced by **[Ghidralligator](https://github.com/airbus-cyber/ghidralligator). Try it!**
afl_ghidra_emu allows to fuzz exotic architecture using AFL++ and Ghidra emulation with code coverage functionality.
For more information, read this [article](https://github.com/airbus-cyber/blogpost/tree/main/fuzzing-exotic-arch-with-afl-using-ghidra-emulator).
<p align="center">
<img src="https://github.com/airbus-cyber/blogpost/blob/main/fuzzing-exotic-arch-with-afl-using-ghidra-emulator/image/202104_Blog_Graphic_Fuzzing-1536x536.png">
</p>
## How it works?
AFL++ runs a trampoline program (afl_bridge_external) which is in charge of forwarding samples to Ghidra emulation
via a TCP socket (Ex: 127.0.0.1:6674/tcp).
A python script in Ghidra (fuzz_xtensa_check_serial.py) is responsible for emulating code execution. It listens
on a TCP socket (127.0.0.1:6674/tcp) and waits for input data coming from trampoline script.
As soon as the script receives input data, the emulation will be started. During the execution, the executed path addresses,
and the execution status are sent to afl_bridge_external using established TCP socket.
afl_bridge_external reports the execution status and execution path to AFL++ using pipes and shared memory.
## Installation
Install [AFL++](https://github.com/AFLplusplus/AFLplusplus)
Clone afl_ghidra_emu directory
```bash
git clone https://github.com/airbus-cyber/afl_ghidra_emu.git
```
Compile afl_bridge_external
```
cd afl_ghidra_emu/afl_bridge_external
make
```
Copy afl_ghidra_emu files to your ghidra script directory
```bash
cd ../..
cp –r afl_ghidra_emu/* $USER_HOME/ghidra_scripts/
```
## Example: Fuzzing Xtensa binary code keygenme_xtensa.elf
./examples/xtensa/bin/keygenme_xtensa.elf is a *keygenMe* compiled for Xtensa (ex: esp32) architecture.
Xtensa is not officially supported in Ghidra yet. So, you need first to install it by following these [instruction](https://github.com/Ebiroll/ghidra-xtensa)
#### Load in Ghidra
- Create a new project in Ghidra;
- Import file ./bin/keygenme_xtensa.elf (arch: Xtensa:LE:32);
- Open it in CodeBrowser and execute auto-analyze;
- Open Script Manager in "Window" submenu;
- Run script fuzz_xtensa_check_serial.py;
#### Start Fuzz
Make AFL workspace directories
```bash
mkdir input output
```
Add first sample
```bash
echo -n "BBBBBBBB" > input/sample1.bin
```
Start AFL++ with trampoline program.
```bash
afl-fuzz -D -i input -o output afl_bridge_external 127.0.0.1 6674 20
```
#### Stop Ghidra emulation
Stop AFL++ using CTRL+C. If Ghidra emulation still running, we can send "STOP" command:
```bash
echo -e "\xff" | nc 127.0.0.1 6674
```
Do no use Ghidra Cancel button, because it does not properly close the socket.
## Example: Fuzzing PPC binary code keygenme_ppc.elf
./examples/ppc/bin/keygenme_ppc.elf is also a *keygenMe* compiled for PowerPC architecture.
Follow the same steps above with PowerPC:BE:32:default architecture in Ghidra and run the script fuzz_ppc_check_serial.py.
================================================
FILE: afl_bridge_external/Makefile
================================================
all: afl_bridge_external
afl_bridge_external: afl_bridge_external.c
$(CC) -I../../include -o afl_bridge_external afl_bridge_external.c
clean:
rm -f afl_bridge_external *~ core
================================================
FILE: afl_bridge_external/afl_bridge_external.c
================================================
/*
american fuzzy lop++ - afl_brifge_external
---------------------------------------------------
Written by Flavian Dola
Copyright 2021 by Airbus CyberSecurity. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Adapted from afl_proxy (https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/afl_proxy/afl-proxy.c)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
*/
#include "types.h"
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <fcntl.h>
#define FORKSRV_FD 198
#define MAP_SIZE_POW2 16
#define MAP_SIZE (1U << MAP_SIZE_POW2)
#define SHM_ENV_VAR "__AFL_SHM_ID"
u8 *__afl_area_ptr;
u32 __afl_map_size = MAP_SIZE;
unsigned long afl_prev_loc = 0;
int isSocketServerRunning = 0;
int sockfd = -1;
int connfd = -1;
FILE* logfd;
u32 id_sample = 0;
#define CONFIG 0x2
#define TRACE 0x3
#define STOP 0xff
#define CRASH 0xfe
#define END 0xfd
#define ERR 0xfc
#define EXEC_END_OK 1
#define EXEC_CRASH 2
#define EXEC_ERR -1
#define EXEC_UNK -2
#define CLOSE_SOCKET(sock)({if (sock != -1) {close(sock); sock = -1;} })
#define MAX_SZ_SAMPLE 0x7fff
#define SA struct sockaddr
/* Error reporting to forkserver controller */
void send_forkserver_error(int error) {
u32 status;
if (!error || error > 0xffff) return;
status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return;
}
/* SHM setup. */
static void __afl_map_shm(void) {
char *id_str = getenv(SHM_ENV_VAR);
char *ptr;
/* NOTE TODO BUG FIXME: if you want to supply a variable sized map then
uncomment the following: */
/*
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) {
u32 val = atoi(ptr);
if (val > 0) __afl_map_size = val;
}
*/
if (__afl_map_size > MAP_SIZE) {
if (__afl_map_size > FS_OPT_MAX_MAPSIZE) {
fprintf(stderr,
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to "
"be able to run this instrumented program!\n",
__afl_map_size);
if (id_str) {
send_forkserver_error(FS_ERROR_MAP_SIZE);
exit(-1);
}
} else {
fprintf(stderr,
"Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to "
"be able to run this instrumented program!\n",
__afl_map_size);
}
}
if (id_str) {
#ifdef USEMMAP
const char * shm_file_path = id_str;
int shm_fd = -1;
unsigned char *shm_base = NULL;
/* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
if (shm_fd == -1) {
fprintf(stderr, "shm_open() failed\n");
send_forkserver_error(FS_ERROR_SHM_OPEN);
exit(1);
}
/* map the shared memory segment to the address space of the process */
shm_base =
mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_base == MAP_FAILED) {
close(shm_fd);
shm_fd = -1;
fprintf(stderr, "mmap() failed\n");
send_forkserver_error(FS_ERROR_MMAP);
exit(2);
}
__afl_area_ptr = shm_base;
#else
u32 shm_id = atoi(id_str);
__afl_area_ptr = shmat(shm_id, 0, 0);
#endif
if (__afl_area_ptr == (void *)-1) {
send_forkserver_error(FS_ERROR_SHMAT);
exit(1);
}
/* Write something into the bitmap so that the parent doesn't give up */
__afl_area_ptr[0] = 1;
}
}
/* Fork server logic. */
static void __afl_start_forkserver(void) {
u8 tmp[4] = {0, 0, 0, 0};
u32 status = 0;
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
if (status) status |= (FS_OPT_ENABLED);
memcpy(tmp, &status, 4);
/* Phone home and tell the parent that we're OK. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
}
static u32 __afl_next_testcase(u8 *buf, u32 max_len) {
s32 status, res = 0xffffff;
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (read(FORKSRV_FD, &status, 4) != 4) return 0;
/* we have a testcase - read it */
memset(buf, 0, max_len);
status = read(0, buf, max_len);
/* report that we are starting the target */
if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0;
return status;
}
static void __afl_end_testcase(int status) {
//int status = 0xffffff;
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);
}
void clear_afl_trace()
{
afl_prev_loc = 0;
}
void afl_maybe_log(unsigned long cur_loc) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
unsigned long afl_idx = cur_loc ^ afl_prev_loc;
afl_idx &= __afl_map_size - 1;
__afl_area_ptr[afl_idx]++;
afl_prev_loc = cur_loc >> 1;
}
int flush_socket() {
char c;
int r = 1;
while (r == 1) {
r = recv(sockfd, &c, 1, SO_RCVTIMEO);
}
}
int get_exec_info() {
int r = 0;
unsigned char buff[4];
u32 rcv_id = 0;
clear_afl_trace();
for (;;) {
r = recv(sockfd, buff, 1, 0);
if (r != 1){
fprintf(logfd, "get_exec_info: Error on recv\n");
fflush(logfd);
return(EXEC_ERR);
}
switch (buff[0]) {
case END:
r = recv(sockfd, &rcv_id, 4, 0);
if (r != 4) {
fprintf(logfd, "get_exec_info: (END) Error on rcv_id\n");
fflush(logfd);
return(EXEC_ERR);
}
if (rcv_id != id_sample) {
fprintf(logfd, "get_exec_info: (END) rcv_id (%d) not match id_sample (%d)\n", rcv_id, id_sample);
fflush(logfd);
return(EXEC_ERR);
}
// Remote execution ended without a crash
return(EXEC_END_OK);
case CRASH:
r = recv(sockfd, &rcv_id, 4, 0);
if (r != 4) {
fprintf(logfd, "get_exec_info: (CRASH) Error on rcv_id\n");
fflush(logfd);
return(EXEC_ERR);
}
if (rcv_id != id_sample) {
fprintf(logfd, "get_exec_info: (CRASH) rcv_id (%d) not match id_sample (%d)\n", rcv_id, id_sample);
fflush(logfd);
return(EXEC_ERR);
}
// Remote execution ended with a crash
return(EXEC_CRASH);
case TRACE:
r = recv(sockfd, &rcv_id, 4, 0);
if (r != 4) {
fprintf(logfd, "get_exec_info: (TRACE) Error on rcv_id\n");
fflush(logfd);
return(EXEC_ERR);
}
if (rcv_id != id_sample) {
fprintf(logfd, "get_exec_info: (TRACE) rcv_id (%d) not match id_sample (%d)\n", rcv_id, id_sample);
fflush(logfd);
return(EXEC_ERR);
}
r = recv(sockfd, buff, 4, 0);
if (r != 4) {
fprintf(logfd, "get_exec_info: Error on get exec trace\n");
fflush(logfd);
return(EXEC_ERR);
}
afl_maybe_log(*(unsigned long*) buff);
break;
case ERR:
if (rcv_id != id_sample) {
fprintf(logfd, "get_exec_info: (ERR) error received\n");
fflush(logfd);
return(EXEC_ERR);
}
default:
fprintf(logfd, "get_exec_info: Error unknown receive code: 0x%X\nn", buff[0]);
fflush(logfd);
return(EXEC_UNK);
}
}
}
int connect_to_ext(char* pIpAddress, u32 port, u32 timeout_ms) {
struct sockaddr_in servaddr;
int res = 0;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
fprintf(logfd, "socket creation failed...\n");
fflush(logfd);
return(res);
}
// set timeout
struct timeval tv;
tv.tv_sec = timeout_ms/1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv) != 0) {
fprintf(logfd, "setsockopt creation failed...\n");
fflush(logfd);
return(res);
}
bzero(&servaddr, sizeof(servaddr));
// assign IP, PORT
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr(pIpAddress);
servaddr.sin_port = htons(port);
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
fprintf(logfd, "connection with the server failed...\n");
fflush(logfd);
CLOSE_SOCKET(sockfd);
return(res);
}
res = 1;
return res;
}
int send_all(void *data2send, size_t length) {
int res = 0;
char *ptr = (char*) data2send;
while (length > 0)
{
int i = send(sockfd, ptr, length, 0);
if (i < 1) {
return(res);
}
ptr += i;
length -= i;
}
res = 1;
return(res);
}
int send_input_data(char* pInputData, u16 sz) {
int res = 0;
int offset = 0;
char buf[1+4+sz+MAX_SZ_SAMPLE];
memset(buf, 0, sizeof(buf));
if (pInputData == 0)
{
return(res);
}
if (sz > MAX_SZ_SAMPLE) {
sz = MAX_SZ_SAMPLE;
}
buf[offset] = CONFIG;
offset++;
*(u32*)(buf+offset) = id_sample;
offset = offset + sizeof(u32);
*(u16*)(buf+offset) = sz;
offset = offset + sizeof(u16);
memcpy(buf+offset, pInputData, sz);
if (1 != send_all(buf, offset+sz))
{
fprintf(logfd, "send_input_data: Send failed\n");
fflush(logfd);
return(res);
}
/* Write something into the bitmap so that the parent doesn't give up */
__afl_area_ptr[0] = 1;
res = 1;
return(res);
}
void exit_with_segfault() {
kill(getpid(), SIGSEGV);
sleep(5);
}
void print_usage() {
fprintf(stderr, "USAGE:\n afl_bridge_external IP PORT timeout_ms\n");
fprintf(logfd, "USAGE:\n afl_bridge_external IP PORT timeout_ms\n");
fflush(logfd);
return;
}
int main(int argc, char *argv[]) {
/* This is were the testcase data is written into */
u8 buf[MAX_SZ_SAMPLE];
s32 len;
int res_exec = 0;
// log to log
logfd = fopen("./afl_bridge_external.log", "a");
if (logfd == 0) {
fprintf(stderr, "Error open log file\n");
goto END_MAIN;
}
if (argc != 4)
{
fprintf(stderr, "Error: bad args\n");
fprintf(logfd, "Error: bad args\n");
print_usage();
goto END_MAIN;
}
if (1 != connect_to_ext(argv[1], atoi(argv[2]), atoi(argv[3])) ) {
fprintf(stderr, "Error: Failed to connect %s:%s\n", argv[1], argv[2]);
fprintf(logfd, "Error: Failed to connect %s:%s\n", argv[1], argv[2]);
fflush(logfd);
goto END_MAIN;
}
/* here you specify the map size you need that you are reporting to
afl-fuzz. Any value is fine as long as it can be divided by 32. */
__afl_map_size = MAP_SIZE; // default is 65536
/* then we initialize the shared memory map and start the forkserver */
__afl_map_shm();
__afl_start_forkserver();
while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) {
id_sample++;
if (1 != send_input_data(buf, (u16)len)){
fprintf(logfd, "Error on send input data\n");
goto END_MAIN;
}
res_exec = get_exec_info();
switch (res_exec)
{
case EXEC_ERR:
fprintf(logfd, "EXEC_ERR: Error on collect execution info\n");
fflush(logfd);
//goto END_MAIN;
// TODO: to improve....
flush_socket();
__afl_end_testcase(0x0);
break;
case EXEC_END_OK:
// remote execution ended
// no crash detect
__afl_end_testcase(0x0);
break;
case EXEC_CRASH:
// remote execution crashed
// report to AFL
//exit_with_segfault();
__afl_end_testcase(0x0005);
break;
default:
fprintf(logfd, "Unknown execution code %d\n", res_exec);
fflush(logfd);
goto END_MAIN;
}
}
END_MAIN:
fclose(logfd);
CLOSE_SOCKET(sockfd);
return 0;
}
================================================
FILE: afl_bridge_external/types.h
================================================
/*
american fuzzy lop++ - type definitions and minor macros
--------------------------------------------------------
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
*/
#ifndef _HAVE_TYPES_H
#define _HAVE_TYPES_H
#include <stdint.h>
#include <stdlib.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
#ifdef WORD_SIZE_64
typedef unsigned __int128 uint128_t;
typedef uint128_t u128;
#endif
/* Extended forkserver option values */
/* Reporting errors */
#define FS_OPT_ERROR 0xf800008f
#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8)
#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8)
#define FS_ERROR_MAP_SIZE 1
#define FS_ERROR_MAP_ADDR 2
#define FS_ERROR_SHM_OPEN 4
#define FS_ERROR_SHMAT 8
#define FS_ERROR_MMAP 16
/* Reporting options */
#define FS_OPT_ENABLED 0x80000001
#define FS_OPT_MAPSIZE 0x40000000
#define FS_OPT_SNAPSHOT 0x20000000
#define FS_OPT_AUTODICT 0x10000000
#define FS_OPT_SHDMEM_FUZZ 0x01000000
#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000
// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22
#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)
#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)
#define FS_OPT_SET_MAPSIZE(x) \
(x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1))
typedef unsigned long long u64;
typedef int8_t s8;
typedef int16_t s16;
typedef int32_t s32;
typedef int64_t s64;
#ifdef WORD_SIZE_64
typedef __int128 int128_t;
typedef int128_t s128;
#endif
#ifndef MIN
#define MIN(a, b) \
({ \
\
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; \
\
})
#define MAX(a, b) \
({ \
\
__typeof__(a) _a = (a); \
__typeof__(b) _b = (b); \
_a > _b ? _a : _b; \
\
})
#endif /* !MIN */
#define SWAP16(_x) \
({ \
\
u16 _ret = (_x); \
(u16)((_ret << 8) | (_ret >> 8)); \
\
})
#define SWAP32(_x) \
({ \
\
u32 _ret = (_x); \
(u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | \
((_ret >> 8) & 0x0000FF00)); \
\
})
#define SWAP64(_x) \
({ \
\
u64 _ret = (_x); \
_ret = \
(_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \
_ret = \
(_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \
_ret = \
(_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8; \
_ret; \
\
})
// It is impossible to define 128 bit constants, so ...
#ifdef WORD_SIZE_64
#define SWAPN(_x, _l) \
({ \
\
u128 _res = (_x), _ret; \
char *d = (char *)&_ret, *s = (char *)&_res; \
int i; \
for (i = 0; i < 16; i++) \
d[15 - i] = s[i]; \
u32 sr = 128U - ((_l) << 3U); \
(_ret >>= sr); \
(u128) _ret; \
\
})
#endif
#define SWAPNN(_x, _y, _l) \
({ \
\
char *d = (char *)(_x), *s = (char *)(_y); \
u32 i, l = (_l)-1; \
for (i = 0; i <= l; i++) \
d[l - i] = s[i]; \
\
})
#ifdef AFL_LLVM_PASS
#if defined(__linux__) || !defined(__ANDROID__)
#define AFL_SR(s) (srandom(s))
#define AFL_R(x) (random() % (x))
#else
#define AFL_SR(s) ((void)s)
#define AFL_R(x) (arc4random_uniform(x))
#endif
#else
#if defined(__linux__) || !defined(__ANDROID__)
#define SR(s) (srandom(s))
#define R(x) (random() % (x))
#else
#define SR(s) ((void)s)
#define R(x) (arc4random_uniform(x))
#endif
#endif /* ^AFL_LLVM_PASS */
#define STRINGIFY_INTERNAL(x) #x
#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
#define MEM_BARRIER() __asm__ volatile("" ::: "memory")
#if __GNUC__ < 6
#ifndef likely
#define likely(_x) (_x)
#endif
#ifndef unlikely
#define unlikely(_x) (_x)
#endif
#else
#ifndef likely
#define likely(_x) __builtin_expect(!!(_x), 1)
#endif
#ifndef unlikely
#define unlikely(_x) __builtin_expect(!!(_x), 0)
#endif
#endif
#endif /* ! _HAVE_TYPES_H */
================================================
FILE: examples/ppc/fuzz_ppc_check_serial.py
================================================
"""
Copyright 2021 by Airbus CyberSecurity - Flavian Dola
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import struct
import time
from ghidra.app.emulator import EmulatorHelper
from ghidra.program.model.address import GenericAddress
from ghidra.util.task import ConsoleTaskMonitor
from ghidra.program.model.block import BasicBlockModel
from libAFL import libAFL
from libUtils import libUtils
# TCP listen PORT
PORT = 6674
DEBUG = False
REG_FILTER = [
"r1", "r2", "r3", "r4",
"r9", "r31"
]
D_REG = {
"r1": "r1",
"r2": "r2",
"r3": "r3",
"r4": "r4",
"r9": "r9",
"r31": "r31",
}
def write_memory(addr, data, sz = None):
if type(addr) == GenericAddress:
addr = libAFL.addr2int(addr)
data_str = data
if sz:
if data < 0:
raise ValueError("data must be positive")
data_str = ""
while data != 0:
b = data & 0xff
data_str += struct.pack("B", b)
data = data >> 8
i = 0
while i < len(data_str):
c = struct.unpack("B", data_str[i])[0]
ghidra_addr = toAddr(addr+i)
emuHelper.writeMemoryValue(ghidra_addr, 1, c)
i += 1
return
def apply_hooks(emuHelper, addr, debug=False):
"""
Apply hook if needed
"""
# n_addr = get_next_execution_addr(addr)
bRes = None
addr_int = libUtils.addr2int(addr)
if addr_int in D_HOOKS.keys():
if debug:
print(" * * * apply_hook: %s - %s" % (str(addr), D_HOOKS[addr_int]["name"]))
bRes = D_HOOKS[addr_int]["callback"](emuHelper, addr)
return bRes
def hook_good_serial(emuHelper, addr):
ret = emuHelper.readRegister("r3")
if ret == 2:
# force crash
# => pc = 0
emuHelper.writeRegister(emuHelper.getPCRegister(), 0x0)
return True
return False
D_HOOKS = {
0x1000071c:{
"name": "good_serial",
"callback": hook_good_serial,
},
}
if __name__ == '__main__':
emuHelper = EmulatorHelper(currentProgram)
monitor = ConsoleTaskMonitor()
bbm = BasicBlockModel(currentProgram)
ctx = {}
ctx = libAFL.init_ctx(ctx, monitor, bbm)
res, ctx = libAFL.run_bridge_server_api(ctx, port=PORT)
if not res:
print("Error on listen on %d tcp port", PORT)
exit(1)
start_addr = 0x1000063c
stop_addr = toAddr(0x1000071c)
# Add new memory section to store emulate values
addr_section_emu = 0x20000000
sz_emu = 0x100000
pInput = addr_section_emu
count = 0
bFirstRun = True
isRunning = True
while isRunning:
# reset previous block reached
ctx = libAFL.init_ctx(ctx, monitor, bbm)
res, ctx = libAFL.rcv_input(ctx, debug=DEBUG)
if not res:
if DEBUG:
print("Error get config")
res, ctx = libAFL.notify_err(ctx)
continue
if DEBUG:
print("CONFIG: %s" % str(ctx))
if libAFL.isStopOrder(ctx):
isRunning = False
break
# Do some stats
if count % 1000 == 0:
count = 0
if not bFirstRun:
stat = 1000.0 / (time.time() - ref_time)
print("Exec %d/s" % int(stat))
bFirstRun = False
ref_time = time.time()
count += 1
write_memory(pInput, libAFL.get_data_input(ctx))
szInput = len(libAFL.get_data_input(ctx))
# set register
emuHelper.writeRegister("r3", pInput)
emuHelper.writeRegister("r4", szInput)
emuHelper.writeRegister(emuHelper.getPCRegister(), start_addr)
# Emulation
bCrash = False
while True:
if monitor.isCancelled():
break
executionAddress = emuHelper.getExecutionAddress()
if apply_hooks(emuHelper, executionAddress):
continue
if (executionAddress in [stop_addr]):
if DEBUG:
print("Emulation complete.")
break
# Print current instruction and the registers we care about
if DEBUG:
print("\n%s: %s" % (str(executionAddress).upper(), getInstructionAt(executionAddress)))
res, ctx = libAFL.notify_code_coverage(ctx, executionAddress, debug=DEBUG)
if not res:
print("Error on notify_code_coverage")
isRunning = False
break
if DEBUG:
for reg in REG_FILTER:
reg_value = emuHelper.readRegister(reg)
print("\t{} ({}) =\t{:08X}".format(reg, D_REG[reg], reg_value))
# single step emulation
success = emuHelper.step(monitor)
if success == False:
bCrash = True
lastError = emuHelper.getLastError()
print("Emulation Error: '{}'".format(lastError))
break
# End of Emulation
if bCrash:
res, ctx = libAFL.notify_crash(ctx)
else:
res, ctx = libAFL.notify_end_exec(ctx)
if not res:
# Error on notify
break
# End of prog
ctx = libAFL.free_ctx(ctx)
================================================
FILE: examples/xtensa/fuzz_xtensa_check_serial.py
================================================
"""
Copyright 2021 by Airbus CyberSecurity - Flavian Dola
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import struct
from ghidra.app.emulator import EmulatorHelper
from ghidra.program.model.address import GenericAddress
from ghidra.util.task import ConsoleTaskMonitor
from ghidra.program.model.block import BasicBlockModel
import time
from libAFL import libAFL
# TCP listen PORT
PORT = 6674
DEBUG = False
REG_FILTER = [
"a1", "a2", "a3", "a4",
"a5", "a6", "a7", "a8",
"a9"
]
D_REG = {
"a0": "a0",
"a1": "a1",
"a2": "a2",
"a3": "a3",
"a4": "a4",
"a5": "a5",
"a6": "a6",
"a7": "a7",
"a8": "a8",
"a9": "a9",
}
def write_memory(addr, data, sz = None):
if type(addr) == GenericAddress:
addr = libAFL.addr2int(addr)
data_str = data
if sz:
if data < 0:
raise ValueError("data must be positive")
data_str = ""
while data != 0:
b = data & 0xff
data_str += struct.pack("B", b)
data = data >> 8
i = 0
while i < len(data_str):
c = struct.unpack("B", data_str[i])[0]
ghidra_addr = toAddr(addr+i)
emuHelper.writeMemoryValue(ghidra_addr, 1, c)
i += 1
return
def apply_hooks(emuHelper, addr, debug=False):
"""
Apply hook if needed
"""
# n_addr = get_next_execution_addr(addr)
bRes = None
addr_int = libAFL.addr2int(addr)
if addr_int in D_HOOKS.keys():
if debug:
print(" * * * apply_hook: %s - %s" % (str(addr), D_HOOKS[addr_int]["name"]))
bRes = D_HOOKS[addr_int]["callback"](emuHelper, addr)
return bRes
def hook_good_serial(emuHelper, addr):
ret = emuHelper.readRegister("a2")
if ret == 2:
# force crash
# => pc = 0
emuHelper.writeRegister(emuHelper.getPCRegister(), 0x0)
return True
return False
D_HOOKS = {
0x400e3120:{
"name": "good_serial",
"callback": hook_good_serial,
},
}
if __name__ == '__main__':
emuHelper = EmulatorHelper(currentProgram)
monitor = ConsoleTaskMonitor()
bbm = BasicBlockModel(currentProgram)
ctx = {}
ctx = libAFL.init_ctx(ctx, monitor, bbm)
res, ctx = libAFL.run_bridge_server_api(ctx, port=PORT)
if not res:
print("Error on listen on %d tcp port", PORT)
exit(1)
start_addr = 0x400e30ab
stop_addr = toAddr(0x400e3120)
# Add new memory section to store emulate values
addr_section_emu = 0x20000000
sz_emu = 0x100000
pInput = addr_section_emu
count = 0
bFirstRun = True
isRunning = True
while isRunning:
# reset previous block reached
ctx = libAFL.init_ctx(ctx, monitor, bbm)
res, ctx = libAFL.rcv_input(ctx, debug=DEBUG)
if not res:
if DEBUG:
print("Error get config")
res, ctx = libAFL.notify_err(ctx)
continue
if DEBUG:
print("CONFIG: %s" % str(ctx))
if libAFL.isStopOrder(ctx):
isRunning = False
break
# Do some stats
if count % 1000 == 0:
count = 0
if not bFirstRun:
stat = 1000.0 / (time.time() - ref_time)
print("Exec %d/s" % int(stat))
bFirstRun = False
ref_time = time.time()
count += 1
write_memory(pInput, libAFL.get_data_input(ctx))
szInput = len(libAFL.get_data_input(ctx))
# set register
emuHelper.writeRegister("a2", pInput)
emuHelper.writeRegister("a3", szInput)
emuHelper.writeRegister(emuHelper.getPCRegister(), start_addr)
# Emulation
bCrash = False
while True:
if monitor.isCancelled():
break
executionAddress = emuHelper.getExecutionAddress()
if apply_hooks(emuHelper, executionAddress):
continue
if (executionAddress in [stop_addr]):
if DEBUG:
print("Emulation complete.")
break
# Print current instruction and the registers we care about
if DEBUG:
print("\n%s: %s" % (str(executionAddress).upper(), getInstructionAt(executionAddress)))
res, ctx = libAFL.notify_code_coverage(ctx, executionAddress, debug=DEBUG)
if not res:
print("Error on notify_code_coverage")
isRunning = False
break
if DEBUG:
for reg in REG_FILTER:
reg_value = emuHelper.readRegister(reg)
print("\t{} ({}) =\t{:08X}".format(reg, D_REG[reg], reg_value))
# single step emulation
success = emuHelper.step(monitor)
if success == False:
bCrash = True
lastError = emuHelper.getLastError()
print("Emulation Error: '{}'".format(lastError))
break
# End of Emulation
if bCrash:
res, ctx = libAFL.notify_crash(ctx)
else:
res, ctx = libAFL.notify_end_exec(ctx)
# End of prog
ctx = libAFL.free_ctx(ctx)
================================================
FILE: libAFL/__init__.py
================================================
================================================
FILE: libAFL/libAFL.py
================================================
#!/usr/bin/python2
"""
Copyright 2021 by Airbus CyberSecurity - Flavian Dola
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import struct
import socket
from libUtils import libUtils
CONFIG = "\x02"
TRACE = "\x03"
STOP = "\xff"
CRASH = "\xfe"
END = "\xfd"
ERR = "\xfc"
def run_bridge_server_api(ctx, host="127.0.0.1", port=6666):
res = False
s_bridge = None
try:
s_bridge = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s_bridge.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s_bridge.bind((host, port))
s_bridge.listen(1)
ctx.update({"sock_bridge": s_bridge})
res = True
except Exception as e:
print("run_bridge_server_api failed: %s" % str(e))
if s_bridge is not None:
s_bridge.close()
return res, ctx
def parse_cmd(ctx, data, debug=False):
res = False
if len(data) < 1:
# too short
if debug:
print("parse_cmd: Data too short: %d\n" % len(data))
return res, ctx
offset = 0
if data[0] == CONFIG:
offset += 1
if len(data[offset:]) < 6:
if debug:
print("parse_cmd: data invalid length: %d\n" % len(data[offset:]))
return res, ctx
id_sample = struct.unpack("<I", data[offset:offset+4])[0]
offset += 4
size_input_data = struct.unpack("<H", data[offset:offset+2])[0]
offset += 2
input_data = data[offset:]
if len(input_data) != size_input_data:
if debug:
print("parse_cmd: input_data_length not match: 0x%X - 0x%X\n" % (len(input_data), size_input_data))
return res, ctx
ctx.update(
{
"id_sample" : id_sample,
"DATA_INPUT": input_data,
}
)
res = True
elif data[0] == STOP:
ctx.update({"STOP": True})
res = True
return res, ctx
def get_data_input(ctx):
return ctx["DATA_INPUT"]
def isStopOrder(ctx):
if ctx.has_key("STOP"):
if ctx["STOP"]:
return True
return False
def rcv_large(sock, sz):
chunk_size = 0x40
data = ""
while len(data) < sz:
sz2rcv = chunk_size
sz_left = sz - len(data)
if sz_left < chunk_size:
sz2rcv = sz_left
data += sock.recv(sz2rcv)
return data
def rcv_cmd(ctx, debug):
res = False
frame_raw = ""
if not ctx.has_key("sock_bridge"):
return res, ctx, frame_raw
if not ctx.has_key("conn_bridge"):
conn, addr = ctx["sock_bridge"].accept()
if debug:
print('rcv_cmd: Connected by', addr)
ctx.update({"conn_bridge": conn})
c = ctx["conn_bridge"].recv(1)
if c is None:
print("rcv_cmd: rcv type failed")
return res, ctx, frame_raw
if c not in [CONFIG, STOP]:
print("rcv_cmd: invalid type frame:"+c.encode("hex"))
return res, ctx, frame_raw
frame_raw += c
if c == STOP:
res = True
return res, ctx, frame_raw
# get CONFIG frame
id_sample = ctx["conn_bridge"].recv(4)
if len(id_sample) != 4:
print("rcv_cmd: rcv id_sample failed")
return res, ctx, frame_raw
frame_raw += id_sample
sz_sample = ctx["conn_bridge"].recv(2)
if len(sz_sample) != 2:
print("rcv_cmd: rcv sz_sample failed")
return res, ctx, frame_raw
frame_raw += sz_sample
frame_raw += rcv_large(ctx["conn_bridge"], struct.unpack("<H", sz_sample)[0])
res = True
return res, ctx, frame_raw
def rcv_input(ctx, debug):
res = False
# GET input frame
res, ctx, config_raw = rcv_cmd(ctx, debug)
if not res:
#if debug:
print("rcv_input: error on get config frame\n")
return res, ctx
ctx.update({"CONFIG_RAW": config_raw})
res, ctx = parse_cmd(ctx, config_raw, debug)
if not res:
#if debug:
print("rcv_input: error on parse config frame: %s\n" % config_raw.encode("hex"))
return res, ctx
res = True
return res, ctx
def notify_crash(ctx):
res = False
try:
ctx["conn_bridge"].sendall(CRASH+struct.pack("<I", ctx["id_sample"]))
res = True
except Exception as e:
print("notify_crash: error: %s\n" % str(e))
if ctx.has_key("conn_bridge"):
ctx["conn_bridge"].close()
del ctx["conn_bridge"]
return res, ctx
def notify_end_exec(ctx):
res = False
try:
ctx["conn_bridge"].sendall(END+struct.pack("<I", ctx["id_sample"]))
res = True
except Exception as e:
print("notify_end_exec: error: %s\n" % str(e))
if ctx.has_key("conn_bridge"):
ctx["conn_bridge"].close()
del ctx["conn_bridge"]
return res, ctx
def notify_err(ctx):
res = False
try:
ctx["conn_bridge"].sendall(ERR)
res = True
except Exception as e:
print("notify_err: error: %s\n" % str(e))
if ctx.has_key("conn_bridge"):
ctx["conn_bridge"].close()
del ctx["conn_bridge"]
return res, ctx
def init_ctx(ctx, monitor, bbm):
ctx.update({
"monitor": monitor,
"bbm": bbm,
"last_block_addr": 0
})
return ctx
def free_ctx(ctx):
if ctx.has_key("conn_bridge"):
try:
ctx["conn_bridge"].shutdown(socket.SHUT_RDWR)
except:
pass
ctx["conn_bridge"].close()
del ctx["conn_bridge"]
if ctx.has_key("sock_bridge"):
try:
ctx["sock_bridge"].shutdown(socket.SHUT_RDWR)
except:
pass
ctx["sock_bridge"].close()
del ctx["sock_bridge"]
return ctx
def notify_code_coverage(ctx, executionAddress, debug=False):
res = False
b = ctx["bbm"].getFirstCodeBlockContaining(executionAddress, ctx["monitor"])
if b is None:
print("notify_code_coverage: Warning cannot get block for addr 0x%08X" % libUtils.addr2int(executionAddress))
return True, ctx
b_addr = libUtils.addr2int(b.minAddress)
if b_addr == ctx["last_block_addr"]:
res = True
return res, ctx
else:
# New block
if debug:
print("notify_code_coverage: New block: 0x%08X\n" % b_addr)
if not ctx.has_key("conn_bridge"):
print("notify_code_coverage: Error socket")
return res, ctx
try:
ctx["conn_bridge"].sendall(TRACE + struct.pack("<I", ctx["id_sample"]) + struct.pack("<I", b_addr))
ctx["last_block_addr"] = b_addr
res = True
except Exception as e:
print("notify_code_coverage: Failed to send address: %s" % str(e))
ctx["conn_bridge"].close()
del ctx["conn_bridge"]
return res, ctx
================================================
FILE: libUtils/__init__.py
================================================
================================================
FILE: libUtils/libUtils.py
================================================
#!/usr/bin/python2
import struct
from ghidra.program.model.address import GenericAddress
from ghidra.program.flatapi import FlatProgramAPI
def addr2int(addr):
return addr.offset
def write_memory(emuHelper, addr, data, sz = None):
api = None
if type(addr) == GenericAddress:
addr = addr2int(addr)
data_str = data
if sz:
if data < 0:
raise ValueError("data must be positive")
data_str = ""
while data != 0:
b = data & 0xff
data_str += struct.pack("B", b)
data = data >> 8
api = FlatProgramAPI(emuHelper.getProgram())
i = 0
while i < len(data_str):
c = struct.unpack("B", data_str[i])[0]
ghidra_addr = api.toAddr(addr+i)
emuHelper.writeMemoryValue(ghidra_addr, 1, c)
i += 1
del api
return
def get_string(emuHelper, addr):
my_str = ""
api = None
if type(addr) != GenericAddress:
api = FlatProgramAPI(emuHelper.getProgram())
addr = api.toAddr(addr)
while True:
b = emuHelper.readMemoryByte(addr)
if b == 0:
break
my_str += struct.pack("B", b)
addr = addr.add(1)
del api
return my_str
def apply_hooks(emuHelper, d_hooks, addr, debug=False):
"""
Apply hook if needed
"""
# n_addr = get_next_execution_addr(addr)
bRes = None
addr_int = addr2int(addr)
if addr_int in d_hooks.keys():
if debug:
print(" * * * apply_hook: %s - %s" % (str(addr), d_hooks[addr_int]["name"]))
bRes = d_hooks[addr_int]["callback"](emuHelper, addr)
return bRes
def get_next_execution_addr(addr):
if type(addr) in [int, long]:
addr = toAddr(addr)
return getInstructionAfter(addr).address
gitextract_9yizunl3/
├── .gitignore
├── README.md
├── afl_bridge_external/
│ ├── Makefile
│ ├── afl_bridge_external.c
│ └── types.h
├── examples/
│ ├── ppc/
│ │ ├── bin/
│ │ │ └── keygenme_ppc.elf
│ │ └── fuzz_ppc_check_serial.py
│ └── xtensa/
│ ├── bin/
│ │ └── keygenme_xtensa.elf
│ └── fuzz_xtensa_check_serial.py
├── libAFL/
│ ├── __init__.py
│ └── libAFL.py
└── libUtils/
├── __init__.py
└── libUtils.py
SYMBOL INDEX (51 symbols across 6 files)
FILE: afl_bridge_external/afl_bridge_external.c
function send_forkserver_error (line 84) | void send_forkserver_error(int error) {
function __afl_map_shm (line 97) | static void __afl_map_shm(void) {
function __afl_start_forkserver (line 198) | static void __afl_start_forkserver(void) {
function u32 (line 214) | static u32 __afl_next_testcase(u8 *buf, u32 max_len) {
function __afl_end_testcase (line 232) | static void __afl_end_testcase(int status) {
function clear_afl_trace (line 248) | void clear_afl_trace()
function afl_maybe_log (line 255) | void afl_maybe_log(unsigned long cur_loc) {
function flush_socket (line 266) | int flush_socket() {
function get_exec_info (line 276) | int get_exec_info() {
function connect_to_ext (line 380) | int connect_to_ext(char* pIpAddress, u32 port, u32 timeout_ms) {
function send_all (line 423) | int send_all(void *data2send, size_t length) {
function send_input_data (line 442) | int send_input_data(char* pInputData, u16 sz) {
function exit_with_segfault (line 485) | void exit_with_segfault() {
function print_usage (line 493) | void print_usage() {
function main (line 502) | int main(int argc, char *argv[]) {
FILE: afl_bridge_external/types.h
type u8 (line 29) | typedef uint8_t u8;
type u16 (line 30) | typedef uint16_t u16;
type u32 (line 31) | typedef uint32_t u32;
type uint128_t (line 33) | typedef unsigned __int128 uint128_t;
type uint128_t (line 34) | typedef uint128_t u128;
type u64 (line 62) | typedef unsigned long long u64;
type s8 (line 64) | typedef int8_t s8;
type s16 (line 65) | typedef int16_t s16;
type s32 (line 66) | typedef int32_t s32;
type s64 (line 67) | typedef int64_t s64;
type __int128 (line 69) | typedef __int128 int128_t;
type int128_t (line 70) | typedef int128_t s128;
FILE: examples/ppc/fuzz_ppc_check_serial.py
function write_memory (line 54) | def write_memory(addr, data, sz = None):
function apply_hooks (line 76) | def apply_hooks(emuHelper, addr, debug=False):
function hook_good_serial (line 93) | def hook_good_serial(emuHelper, addr):
FILE: examples/xtensa/fuzz_xtensa_check_serial.py
function write_memory (line 60) | def write_memory(addr, data, sz = None):
function apply_hooks (line 82) | def apply_hooks(emuHelper, addr, debug=False):
function hook_good_serial (line 99) | def hook_good_serial(emuHelper, addr):
FILE: libAFL/libAFL.py
function run_bridge_server_api (line 39) | def run_bridge_server_api(ctx, host="127.0.0.1", port=6666):
function parse_cmd (line 58) | def parse_cmd(ctx, data, debug=False):
function get_data_input (line 103) | def get_data_input(ctx):
function isStopOrder (line 108) | def isStopOrder(ctx):
function rcv_large (line 117) | def rcv_large(sock, sz):
function rcv_cmd (line 130) | def rcv_cmd(ctx, debug):
function rcv_input (line 178) | def rcv_input(ctx, debug):
function notify_crash (line 203) | def notify_crash(ctx):
function notify_end_exec (line 218) | def notify_end_exec(ctx):
function notify_err (line 232) | def notify_err(ctx):
function init_ctx (line 248) | def init_ctx(ctx, monitor, bbm):
function free_ctx (line 258) | def free_ctx(ctx):
function notify_code_coverage (line 281) | def notify_code_coverage(ctx, executionAddress, debug=False):
FILE: libUtils/libUtils.py
function addr2int (line 12) | def addr2int(addr):
function write_memory (line 16) | def write_memory(emuHelper, addr, data, sz = None):
function get_string (line 42) | def get_string(emuHelper, addr):
function apply_hooks (line 62) | def apply_hooks(emuHelper, d_hooks, addr, debug=False):
function get_next_execution_addr (line 78) | def get_next_execution_addr(addr):
Condensed preview — 13 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (46K chars).
[
{
"path": ".gitignore",
"chars": 17,
"preview": ".pyc\n.class\n.log\n"
},
{
"path": "README.md",
"chars": 3187,
"preview": "# afl_ghidra_emu\n[](https://opensource.org/license"
},
{
"path": "afl_bridge_external/Makefile",
"chars": 180,
"preview": "all:\tafl_bridge_external\n\nafl_bridge_external:\tafl_bridge_external.c\n\t$(CC) -I../../include -o afl_bridge_external afl_b"
},
{
"path": "afl_bridge_external/afl_bridge_external.c",
"chars": 12800,
"preview": "/*\n american fuzzy lop++ - afl_brifge_external\n ---------------------------------------------------\n\n Written by F"
},
{
"path": "afl_bridge_external/types.h",
"chars": 6487,
"preview": "/*\n american fuzzy lop++ - type definitions and minor macros\n ------------------------------------------------------"
},
{
"path": "examples/ppc/fuzz_ppc_check_serial.py",
"chars": 5748,
"preview": "\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Version 2.0 (the \"Licens"
},
{
"path": "examples/xtensa/fuzz_xtensa_check_serial.py",
"chars": 5737,
"preview": "\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Version 2.0 (the \"Licens"
},
{
"path": "libAFL/__init__.py",
"chars": 1,
"preview": "\n"
},
{
"path": "libAFL/libAFL.py",
"chars": 7356,
"preview": "#!/usr/bin/python2\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Versio"
},
{
"path": "libUtils/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "libUtils/libUtils.py",
"chars": 1787,
"preview": "#!/usr/bin/python2\n\n\n\nimport struct\nfrom ghidra.program.model.address import GenericAddress\nfrom ghidra.program.flatapi "
}
]
// ... and 2 more files (download for full content)
About this extraction
This page contains the full source code of the airbus-cyber/afl_ghidra_emu GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 13 files (42.3 KB), approximately 11.8k tokens, and a symbol index with 51 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.