[
  {
    "path": ".gitignore",
    "content": ".pyc\n.class\n.log\n"
  },
  {
    "path": "README.md",
    "content": "# afl_ghidra_emu\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nafl_ghidra_emu is no longer maintained and replaced by **[Ghidralligator](https://github.com/airbus-cyber/ghidralligator). Try it!**\n\nafl_ghidra_emu allows to fuzz exotic architecture using AFL++ and Ghidra emulation with code coverage functionality.\n\nFor more information, read this [article](https://github.com/airbus-cyber/blogpost/tree/main/fuzzing-exotic-arch-with-afl-using-ghidra-emulator).\n\n<p align=\"center\">\n<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\">\n</p>\n\n\n## How it works?\n\nAFL++ runs a trampoline program (afl_bridge_external) which is in charge of forwarding samples to Ghidra emulation \nvia a TCP socket (Ex: 127.0.0.1:6674/tcp). \n\nA python script in Ghidra (fuzz_xtensa_check_serial.py) is responsible for emulating code execution. It listens \non a TCP socket (127.0.0.1:6674/tcp) and waits for input data coming from trampoline script.\nAs soon as the script receives input data, the emulation will be started. During the execution, the executed path addresses, \nand the execution status are sent to afl_bridge_external using established TCP socket. \n\nafl_bridge_external reports the execution status and execution path to AFL++ using pipes and shared memory. \n\n\n## Installation\nInstall [AFL++](https://github.com/AFLplusplus/AFLplusplus)  \n\nClone afl_ghidra_emu directory\n```bash\ngit clone https://github.com/airbus-cyber/afl_ghidra_emu.git\n```\n\nCompile afl_bridge_external\n```\ncd afl_ghidra_emu/afl_bridge_external\nmake\n```\n\nCopy afl_ghidra_emu files to your ghidra script directory\n```bash\ncd ../..\ncp –r afl_ghidra_emu/* $USER_HOME/ghidra_scripts/\n```\n\n## Example: Fuzzing Xtensa binary code keygenme_xtensa.elf\n./examples/xtensa/bin/keygenme_xtensa.elf is a *keygenMe* compiled for Xtensa (ex: esp32) architecture.\nXtensa is not officially supported in Ghidra yet. So, you need first to install it by following these [instruction](https://github.com/Ebiroll/ghidra-xtensa)\n\n\n#### Load in Ghidra\n- Create a new project in Ghidra;\n- Import file ./bin/keygenme_xtensa.elf (arch: Xtensa:LE:32);\n- Open it in CodeBrowser and execute auto-analyze;\n- Open Script Manager in \"Window\" submenu;\n- Run script fuzz_xtensa_check_serial.py;\n\n\n\n#### Start Fuzz\nMake AFL workspace directories\n```bash\nmkdir input output\n```\n\nAdd first sample\n```bash\necho -n \"BBBBBBBB\" > input/sample1.bin\n```\n\nStart AFL++ with trampoline program.\n```bash\nafl-fuzz -D -i input -o output afl_bridge_external 127.0.0.1 6674 20\n```\n\n#### Stop Ghidra emulation\nStop AFL++ using CTRL+C. If Ghidra emulation still running, we can send \"STOP\" command:\n```bash\necho -e \"\\xff\" | nc 127.0.0.1 6674\n```\nDo no use Ghidra Cancel button, because it does not properly close the socket.\n\n## Example: Fuzzing PPC binary code keygenme_ppc.elf\n./examples/ppc/bin/keygenme_ppc.elf is also a *keygenMe* compiled for PowerPC architecture.\n\nFollow the same steps above with PowerPC:BE:32:default architecture in Ghidra and run the script fuzz_ppc_check_serial.py.\n  \n\n\n"
  },
  {
    "path": "afl_bridge_external/Makefile",
    "content": "all:\tafl_bridge_external\n\nafl_bridge_external:\tafl_bridge_external.c\n\t$(CC) -I../../include -o afl_bridge_external afl_bridge_external.c\n\nclean:\n\trm -f afl_bridge_external *~ core\n"
  },
  {
    "path": "afl_bridge_external/afl_bridge_external.c",
    "content": "/*\n   american fuzzy lop++ - afl_brifge_external\n   ---------------------------------------------------\n\n   Written by Flavian Dola\n\n   Copyright 2021 by Airbus CyberSecurity. All rights reserved.\n   Copyright 2019-2020 AFLplusplus Project. All rights reserved.\n\n   Adapted from afl_proxy (https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/afl_proxy/afl-proxy.c)\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at:\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\n\n*/\n\n#include \"types.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <signal.h>\n#include <unistd.h>\n#include <string.h>\n#include <assert.h>\n#include <stdint.h>\n#include <errno.h>\n\n#include <sys/mman.h>\n#include <sys/shm.h>\n#include <sys/wait.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <arpa/inet.h>\n#include <fcntl.h>\n\n\n#define FORKSRV_FD 198\n#define MAP_SIZE_POW2 16\n#define MAP_SIZE (1U << MAP_SIZE_POW2)\n#define SHM_ENV_VAR \"__AFL_SHM_ID\"\n\nu8 *__afl_area_ptr;\nu32 __afl_map_size = MAP_SIZE;\n\nunsigned long afl_prev_loc = 0;\nint isSocketServerRunning = 0;\nint sockfd = -1;\nint connfd = -1;\nFILE* logfd;\nu32 id_sample = 0;\n\n\n#define CONFIG 0x2\n\n#define TRACE  0x3\n#define STOP   0xff\n#define CRASH  0xfe\n#define END    0xfd\n#define ERR    0xfc\n\n\n#define EXEC_END_OK 1\n#define EXEC_CRASH 2\n#define EXEC_ERR -1\n#define EXEC_UNK -2\n\n\n\n#define CLOSE_SOCKET(sock)({if (sock != -1) {close(sock); sock = -1;} })\n#define MAX_SZ_SAMPLE 0x7fff\n#define SA struct sockaddr\n\n\n\n\n\n\n/* Error reporting to forkserver controller */\n\nvoid send_forkserver_error(int error) {\n\n  u32 status;\n  if (!error || error > 0xffff) return;\n  status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));\n  if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return;\n\n}\n\n/* SHM setup. */\n\n\n\nstatic void __afl_map_shm(void) {\n\n  char *id_str = getenv(SHM_ENV_VAR);\n  char *ptr;\n\n  /* NOTE TODO BUG FIXME: if you want to supply a variable sized map then\n     uncomment the following: */\n\n  /*\n  if ((ptr = getenv(\"AFL_MAP_SIZE\")) != NULL) {\n\n    u32 val = atoi(ptr);\n    if (val > 0) __afl_map_size = val;\n\n  }\n\n  */\n\n  if (__afl_map_size > MAP_SIZE) {\n\n    if (__afl_map_size > FS_OPT_MAX_MAPSIZE) {\n\n      fprintf(stderr,\n              \"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to \"\n              \"be able to run this instrumented program!\\n\",\n              __afl_map_size);\n      if (id_str) {\n\n        send_forkserver_error(FS_ERROR_MAP_SIZE);\n        exit(-1);\n\n      }\n\n    } else {\n\n      fprintf(stderr,\n              \"Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to \"\n              \"be able to run this instrumented program!\\n\",\n              __afl_map_size);\n\n    }\n\n  }\n\n  if (id_str) {\n\n#ifdef USEMMAP\n    const char *   shm_file_path = id_str;\n    int            shm_fd = -1;\n    unsigned char *shm_base = NULL;\n\n    /* create the shared memory segment as if it was a file */\n    shm_fd = shm_open(shm_file_path, O_RDWR, 0600);\n    if (shm_fd == -1) {\n\n      fprintf(stderr, \"shm_open() failed\\n\");\n      send_forkserver_error(FS_ERROR_SHM_OPEN);\n      exit(1);\n\n    }\n\n    /* map the shared memory segment to the address space of the process */\n    shm_base =\n        mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);\n\n    if (shm_base == MAP_FAILED) {\n\n      close(shm_fd);\n      shm_fd = -1;\n\n      fprintf(stderr, \"mmap() failed\\n\");\n      send_forkserver_error(FS_ERROR_MMAP);\n      exit(2);\n\n    }\n\n    __afl_area_ptr = shm_base;\n#else\n    u32 shm_id = atoi(id_str);\n\n    __afl_area_ptr = shmat(shm_id, 0, 0);\n\n#endif\n\n    if (__afl_area_ptr == (void *)-1) {\n\n      send_forkserver_error(FS_ERROR_SHMAT);\n      exit(1);\n\n    }\n\n    /* Write something into the bitmap so that the parent doesn't give up */\n\n    __afl_area_ptr[0] = 1;\n\n  }\n\n}\n\n/* Fork server logic. */\n\nstatic void __afl_start_forkserver(void) {\n\n  u8  tmp[4] = {0, 0, 0, 0};\n  u32 status = 0;\n\n  if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)\n    status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);\n  if (status) status |= (FS_OPT_ENABLED);\n  memcpy(tmp, &status, 4);\n\n  /* Phone home and tell the parent that we're OK. */\n\n  if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;\n\n}\n\nstatic u32 __afl_next_testcase(u8 *buf, u32 max_len) {\n\n  s32 status, res = 0xffffff;\n\n  /* Wait for parent by reading from the pipe. Abort if read fails. */\n  if (read(FORKSRV_FD, &status, 4) != 4) return 0;\n\n  /* we have a testcase - read it */\n  memset(buf, 0, max_len);\n  status = read(0, buf, max_len);\n\n  /* report that we are starting the target */\n  if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0;\n\n  return status;\n\n}\n\nstatic void __afl_end_testcase(int status) {\n\n  //int status = 0xffffff;\n\n  if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);\n\n}\n\n\n\n\n\n\n\n\n\nvoid clear_afl_trace()\n{\n    afl_prev_loc = 0;\n}\n\n\n\nvoid afl_maybe_log(unsigned long cur_loc) {\n\n  cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);\n  unsigned long afl_idx = cur_loc ^ afl_prev_loc;\n  afl_idx &= __afl_map_size - 1;\n  __afl_area_ptr[afl_idx]++;\n\n  afl_prev_loc = cur_loc >> 1;\n}\n\n\nint flush_socket() {\n    char c;\n    int r = 1;\n\n    while (r == 1) {\n        r = recv(sockfd, &c, 1, SO_RCVTIMEO);\n    }\n}\n\n\nint get_exec_info() {\n\n    int r = 0;\n    unsigned char buff[4];\n    u32 rcv_id = 0;\n\n\n    clear_afl_trace();\n\n\n    for (;;) {\n\n        r = recv(sockfd, buff, 1, 0);\n        if (r != 1){\n            fprintf(logfd, \"get_exec_info: Error on recv\\n\");\n            fflush(logfd);\n            return(EXEC_ERR);\n        }\n\n        switch (buff[0]) {\n            case END:\n                r = recv(sockfd, &rcv_id, 4, 0);\n                if (r != 4) {\n                    fprintf(logfd, \"get_exec_info: (END) Error on rcv_id\\n\");\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n                if (rcv_id != id_sample) {\n                    fprintf(logfd, \"get_exec_info: (END) rcv_id (%d) not match id_sample (%d)\\n\", rcv_id, id_sample);\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n\n                // Remote execution ended without a crash\n                return(EXEC_END_OK);\n\n\n            case CRASH:\n                r = recv(sockfd, &rcv_id, 4, 0);\n                if (r != 4) {\n                    fprintf(logfd, \"get_exec_info: (CRASH) Error on rcv_id\\n\");\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n                if (rcv_id != id_sample) {\n                    fprintf(logfd, \"get_exec_info: (CRASH) rcv_id (%d) not match id_sample (%d)\\n\", rcv_id, id_sample);\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n\n                // Remote execution ended with a crash\n                return(EXEC_CRASH);\n\n\n            case TRACE:\n                r = recv(sockfd, &rcv_id, 4, 0);\n                if (r != 4) {\n                    fprintf(logfd, \"get_exec_info: (TRACE) Error on rcv_id\\n\");\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n                if (rcv_id != id_sample) {\n                    fprintf(logfd, \"get_exec_info: (TRACE) rcv_id (%d) not match id_sample (%d)\\n\", rcv_id, id_sample);\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n\n\n                r = recv(sockfd, buff, 4, 0);\n                if (r != 4) {\n                    fprintf(logfd, \"get_exec_info: Error on get exec trace\\n\");\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n                afl_maybe_log(*(unsigned long*) buff);\n                break;\n\n            case ERR:\n                if (rcv_id != id_sample) {\n                    fprintf(logfd, \"get_exec_info: (ERR) error received\\n\");\n                    fflush(logfd);\n                    return(EXEC_ERR);\n                }\n\n            default:\n                fprintf(logfd, \"get_exec_info: Error unknown receive code: 0x%X\\nn\", buff[0]);\n                fflush(logfd);\n                return(EXEC_UNK);\n\n        }\n    }\n}\n\n\n\n\n\n\n\n\n\n\n\n\nint connect_to_ext(char* pIpAddress, u32 port, u32 timeout_ms) {\n\n    struct sockaddr_in servaddr;\n    int res = 0;\n\n\n    sockfd = socket(AF_INET, SOCK_STREAM, 0);\n    if (sockfd == -1) {\n            fprintf(logfd, \"socket creation failed...\\n\");\n            fflush(logfd);\n            return(res);\n        }\n\n    // set timeout\n    struct timeval tv;\n    tv.tv_sec = timeout_ms/1000;\n    tv.tv_usec = (timeout_ms % 1000) * 1000;\n    if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv) != 0) {\n        fprintf(logfd, \"setsockopt creation failed...\\n\");\n        fflush(logfd);\n        return(res);\n    }\n\n    bzero(&servaddr, sizeof(servaddr));\n    // assign IP, PORT\n    servaddr.sin_family = AF_INET;\n    servaddr.sin_addr.s_addr = inet_addr(pIpAddress);\n    servaddr.sin_port = htons(port);\n\n    if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {\n            fprintf(logfd, \"connection with the server failed...\\n\");\n            fflush(logfd);\n            CLOSE_SOCKET(sockfd);\n            return(res);\n    }\n\n    res = 1;\n\n    return res;\n\n}\n\n\nint send_all(void *data2send, size_t length) {\n    int res = 0;\n    char *ptr = (char*) data2send;\n    while (length > 0)\n    {\n        int i = send(sockfd, ptr, length, 0);\n        if (i < 1) {\n            return(res);\n        }\n        ptr += i;\n        length -= i;\n    }\n    res = 1;\n    return(res);\n\n}\n\n\n\nint send_input_data(char* pInputData, u16 sz) {\n    int res = 0;\n    int offset = 0;\n    char buf[1+4+sz+MAX_SZ_SAMPLE];\n\n    memset(buf, 0, sizeof(buf));\n\n\n    if (pInputData == 0)\n    {\n        return(res);\n    }\n\n    if (sz > MAX_SZ_SAMPLE) {\n        sz = MAX_SZ_SAMPLE;\n    }\n\n    buf[offset] = CONFIG;\n    offset++;\n\n    *(u32*)(buf+offset) = id_sample;\n    offset = offset + sizeof(u32);\n\n    *(u16*)(buf+offset) = sz;\n    offset = offset + sizeof(u16);\n    memcpy(buf+offset, pInputData, sz);\n\n    if (1 != send_all(buf, offset+sz))\n    {\n        fprintf(logfd, \"send_input_data: Send failed\\n\");\n        fflush(logfd);\n        return(res);\n    }\n\n\n    /* Write something into the bitmap so that the parent doesn't give up */\n    __afl_area_ptr[0] = 1;\n\n    res = 1;\n    return(res);\n}\n\n\nvoid exit_with_segfault() {\n    kill(getpid(), SIGSEGV);\n    sleep(5);\n}\n\n\n\n\nvoid print_usage() {\n    fprintf(stderr, \"USAGE:\\n afl_bridge_external IP PORT timeout_ms\\n\");\n    fprintf(logfd, \"USAGE:\\n afl_bridge_external IP PORT timeout_ms\\n\");\n    fflush(logfd);\n    return;\n}\n\n\n\nint main(int argc, char *argv[]) {\n\n  /* This is were the testcase data is written into */\n  u8  buf[MAX_SZ_SAMPLE];\n  s32 len;\n  int res_exec = 0;\n\n  // log to log\n  logfd = fopen(\"./afl_bridge_external.log\", \"a\");\n  if (logfd == 0) {\n      fprintf(stderr, \"Error open log file\\n\");\n      goto END_MAIN;\n  }\n\n  if (argc != 4)\n  {\n      fprintf(stderr, \"Error: bad args\\n\");\n      fprintf(logfd, \"Error: bad args\\n\");\n      print_usage();\n      goto END_MAIN;\n  }\n\n  if (1 != connect_to_ext(argv[1], atoi(argv[2]), atoi(argv[3])) ) {\n      fprintf(stderr, \"Error: Failed to connect %s:%s\\n\", argv[1], argv[2]);\n      fprintf(logfd, \"Error: Failed to connect %s:%s\\n\", argv[1], argv[2]);\n      fflush(logfd);\n      goto END_MAIN;\n  }\n\n\n  /* here you specify the map size you need that you are reporting to\n     afl-fuzz.  Any value is fine as long as it can be divided by 32. */\n  __afl_map_size = MAP_SIZE;  // default is 65536\n\n  /* then we initialize the shared memory map and start the forkserver */\n  __afl_map_shm();\n  __afl_start_forkserver();\n\n  while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) {\n    id_sample++;\n\n    if (1 != send_input_data(buf, (u16)len)){\n        fprintf(logfd, \"Error on send input data\\n\");\n        goto END_MAIN;\n    }\n\n\n    res_exec = get_exec_info();\n    switch (res_exec)\n    {\n        case EXEC_ERR:\n            fprintf(logfd, \"EXEC_ERR: Error on collect execution info\\n\");\n            fflush(logfd);\n            //goto END_MAIN;\n            // TODO: to improve....\n            flush_socket();\n            __afl_end_testcase(0x0);\n            break;\n        case EXEC_END_OK:\n            // remote execution ended\n            // no crash detect\n            __afl_end_testcase(0x0);\n            break;\n        case EXEC_CRASH:\n            // remote execution crashed\n            // report to AFL\n            //exit_with_segfault();\n            __afl_end_testcase(0x0005);\n            break;\n        default:\n            fprintf(logfd, \"Unknown execution code %d\\n\", res_exec);\n            fflush(logfd);\n            goto END_MAIN;\n    }\n\n  }\n\nEND_MAIN:\n  fclose(logfd);\n  CLOSE_SOCKET(sockfd);\n\n  return 0;\n\n}\n\n"
  },
  {
    "path": "afl_bridge_external/types.h",
    "content": "/*\n   american fuzzy lop++ - type definitions and minor macros\n   --------------------------------------------------------\n\n   Originally written by Michal Zalewski\n\n   Now maintained by Marc Heuse <mh@mh-sec.de>,\n                     Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,\n                     Andrea Fioraldi <andreafioraldi@gmail.com>,\n                     Dominik Maier <mail@dmnk.co>\n\n   Copyright 2016, 2017 Google Inc. All rights reserved.\n   Copyright 2019-2020 AFLplusplus Project. All rights reserved.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at:\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n */\n\n#ifndef _HAVE_TYPES_H\n#define _HAVE_TYPES_H\n\n#include <stdint.h>\n#include <stdlib.h>\n\ntypedef uint8_t  u8;\ntypedef uint16_t u16;\ntypedef uint32_t u32;\n#ifdef WORD_SIZE_64\ntypedef unsigned __int128 uint128_t;\ntypedef uint128_t         u128;\n#endif\n\n/* Extended forkserver option values */\n\n/* Reporting errors */\n#define FS_OPT_ERROR 0xf800008f\n#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8)\n#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8)\n#define FS_ERROR_MAP_SIZE 1\n#define FS_ERROR_MAP_ADDR 2\n#define FS_ERROR_SHM_OPEN 4\n#define FS_ERROR_SHMAT 8\n#define FS_ERROR_MMAP 16\n\n/* Reporting options */\n#define FS_OPT_ENABLED 0x80000001\n#define FS_OPT_MAPSIZE 0x40000000\n#define FS_OPT_SNAPSHOT 0x20000000\n#define FS_OPT_AUTODICT 0x10000000\n#define FS_OPT_SHDMEM_FUZZ 0x01000000\n#define FS_OPT_OLD_AFLPP_WORKAROUND 0x0f000000\n// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22\n#define FS_OPT_MAX_MAPSIZE ((0x00fffffeU >> 1) + 1)\n#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1)\n#define FS_OPT_SET_MAPSIZE(x) \\\n  (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1))\n\ntypedef unsigned long long u64;\n\ntypedef int8_t  s8;\ntypedef int16_t s16;\ntypedef int32_t s32;\ntypedef int64_t s64;\n#ifdef WORD_SIZE_64\ntypedef __int128 int128_t;\ntypedef int128_t s128;\n#endif\n\n#ifndef MIN\n  #define MIN(a, b)           \\\n    ({                        \\\n                              \\\n      __typeof__(a) _a = (a); \\\n      __typeof__(b) _b = (b); \\\n      _a < _b ? _a : _b;      \\\n                              \\\n    })\n\n  #define MAX(a, b)           \\\n    ({                        \\\n                              \\\n      __typeof__(a) _a = (a); \\\n      __typeof__(b) _b = (b); \\\n      _a > _b ? _a : _b;      \\\n                              \\\n    })\n\n#endif                                                              /* !MIN */\n\n#define SWAP16(_x)                    \\\n  ({                                  \\\n                                      \\\n    u16 _ret = (_x);                  \\\n    (u16)((_ret << 8) | (_ret >> 8)); \\\n                                      \\\n  })\n\n#define SWAP32(_x)                                                   \\\n  ({                                                                 \\\n                                                                     \\\n    u32 _ret = (_x);                                                 \\\n    (u32)((_ret << 24) | (_ret >> 24) | ((_ret << 8) & 0x00FF0000) | \\\n          ((_ret >> 8) & 0x0000FF00));                               \\\n                                                                     \\\n  })\n\n#define SWAP64(_x)                                                             \\\n  ({                                                                           \\\n                                                                               \\\n    u64 _ret = (_x);                                                           \\\n    _ret =                                                                     \\\n        (_ret & 0x00000000FFFFFFFF) << 32 | (_ret & 0xFFFFFFFF00000000) >> 32; \\\n    _ret =                                                                     \\\n        (_ret & 0x0000FFFF0000FFFF) << 16 | (_ret & 0xFFFF0000FFFF0000) >> 16; \\\n    _ret =                                                                     \\\n        (_ret & 0x00FF00FF00FF00FF) << 8 | (_ret & 0xFF00FF00FF00FF00) >> 8;   \\\n    _ret;                                                                      \\\n                                                                               \\\n  })\n\n// It is impossible to define 128 bit constants, so ...\n#ifdef WORD_SIZE_64\n  #define SWAPN(_x, _l)                            \\\n    ({                                             \\\n                                                   \\\n      u128  _res = (_x), _ret;                     \\\n      char *d = (char *)&_ret, *s = (char *)&_res; \\\n      int   i;                                     \\\n      for (i = 0; i < 16; i++)                     \\\n        d[15 - i] = s[i];                          \\\n      u32 sr = 128U - ((_l) << 3U);                \\\n      (_ret >>= sr);                               \\\n      (u128) _ret;                                 \\\n                                                   \\\n    })\n#endif\n\n#define SWAPNN(_x, _y, _l)                     \\\n  ({                                           \\\n                                               \\\n    char *d = (char *)(_x), *s = (char *)(_y); \\\n    u32   i, l = (_l)-1;                       \\\n    for (i = 0; i <= l; i++)                   \\\n      d[l - i] = s[i];                         \\\n                                               \\\n  })\n\n#ifdef AFL_LLVM_PASS\n  #if defined(__linux__) || !defined(__ANDROID__)\n    #define AFL_SR(s) (srandom(s))\n    #define AFL_R(x) (random() % (x))\n  #else\n    #define AFL_SR(s) ((void)s)\n    #define AFL_R(x) (arc4random_uniform(x))\n  #endif\n#else\n  #if defined(__linux__) || !defined(__ANDROID__)\n    #define SR(s) (srandom(s))\n    #define R(x) (random() % (x))\n  #else\n    #define SR(s) ((void)s)\n    #define R(x) (arc4random_uniform(x))\n  #endif\n#endif                                                    /* ^AFL_LLVM_PASS */\n\n#define STRINGIFY_INTERNAL(x) #x\n#define STRINGIFY(x) STRINGIFY_INTERNAL(x)\n\n#define MEM_BARRIER() __asm__ volatile(\"\" ::: \"memory\")\n\n#if __GNUC__ < 6\n  #ifndef likely\n    #define likely(_x) (_x)\n  #endif\n  #ifndef unlikely\n    #define unlikely(_x) (_x)\n  #endif\n#else\n  #ifndef likely\n    #define likely(_x) __builtin_expect(!!(_x), 1)\n  #endif\n  #ifndef unlikely\n    #define unlikely(_x) __builtin_expect(!!(_x), 0)\n  #endif\n#endif\n\n#endif                                                   /* ! _HAVE_TYPES_H */\n\n"
  },
  {
    "path": "examples/ppc/fuzz_ppc_check_serial.py",
    "content": "\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\"\"\"\n\n\nimport struct\nimport time\n\nfrom ghidra.app.emulator import EmulatorHelper\nfrom ghidra.program.model.address import GenericAddress\nfrom ghidra.util.task import ConsoleTaskMonitor\nfrom ghidra.program.model.block import BasicBlockModel\n\nfrom libAFL import libAFL\nfrom libUtils import libUtils\n\n\n# TCP listen PORT\nPORT = 6674\n\nDEBUG = False\n\nREG_FILTER = [\n        \"r1\", \"r2\", \"r3\", \"r4\",\n        \"r9\", \"r31\"\n]\n\nD_REG = {\n    \"r1\": \"r1\",\n    \"r2\": \"r2\",\n    \"r3\": \"r3\",\n    \"r4\": \"r4\",\n    \"r9\": \"r9\",\n    \"r31\": \"r31\",\n}\n\n\n\n\ndef write_memory(addr, data, sz = None):\n    if type(addr) == GenericAddress:\n        addr = libAFL.addr2int(addr)\n    data_str = data\n    if sz:\n        if data < 0:\n            raise ValueError(\"data must be positive\")\n        data_str = \"\"\n        while data != 0:\n            b = data & 0xff\n            data_str += struct.pack(\"B\", b)\n            data = data >> 8\n    i = 0\n    while i < len(data_str):\n        c = struct.unpack(\"B\", data_str[i])[0]\n        ghidra_addr = toAddr(addr+i)\n        emuHelper.writeMemoryValue(ghidra_addr, 1, c)\n        i += 1\n    return\n\n\n\ndef apply_hooks(emuHelper, addr, debug=False):\n    \"\"\"\n    Apply hook if needed\n    \"\"\"\n    # n_addr = get_next_execution_addr(addr)\n\n    bRes = None\n    addr_int = libUtils.addr2int(addr)\n    if addr_int in D_HOOKS.keys():\n        if debug:\n            print(\" * * * apply_hook: %s - %s\" % (str(addr), D_HOOKS[addr_int][\"name\"]))\n        bRes = D_HOOKS[addr_int][\"callback\"](emuHelper, addr)\n\n    return bRes\n\n\n\ndef hook_good_serial(emuHelper, addr):\n    ret = emuHelper.readRegister(\"r3\")\n    if ret == 2:\n        # force crash\n        # => pc = 0\n        emuHelper.writeRegister(emuHelper.getPCRegister(), 0x0)\n        return True\n    return False\n\n\nD_HOOKS = {\n    0x1000071c:{\n        \"name\": \"good_serial\",\n        \"callback\": hook_good_serial,\n        },\n}\n\n\nif __name__ == '__main__':\n\n    emuHelper = EmulatorHelper(currentProgram)\n\n    monitor = ConsoleTaskMonitor()\n    bbm = BasicBlockModel(currentProgram)\n\n    ctx = {}\n    ctx = libAFL.init_ctx(ctx, monitor, bbm)\n\n    res, ctx = libAFL.run_bridge_server_api(ctx, port=PORT)\n    if not res:\n        print(\"Error on listen on %d tcp port\", PORT)\n        exit(1)\n\n    start_addr = 0x1000063c\n    stop_addr = toAddr(0x1000071c)\n\n    # Add new memory section to store emulate values\n    addr_section_emu = 0x20000000\n    sz_emu = 0x100000\n\n    pInput = addr_section_emu\n\n    count = 0\n    bFirstRun = True\n\n    isRunning = True\n    while isRunning:\n\n        # reset previous block reached\n        ctx = libAFL.init_ctx(ctx, monitor, bbm)\n\n        res, ctx = libAFL.rcv_input(ctx, debug=DEBUG)\n        if not res:\n            if DEBUG:\n                print(\"Error get config\")\n            res, ctx = libAFL.notify_err(ctx)\n            continue\n\n        if DEBUG:\n            print(\"CONFIG: %s\" % str(ctx))\n\n        if libAFL.isStopOrder(ctx):\n            isRunning = False\n            break\n\n        # Do some stats\n        if count % 1000 == 0:\n            count = 0\n            if not bFirstRun:\n                stat = 1000.0 / (time.time() - ref_time)\n                print(\"Exec %d/s\" % int(stat))\n            bFirstRun = False\n            ref_time = time.time()\n        count += 1\n\n        write_memory(pInput, libAFL.get_data_input(ctx))\n        szInput = len(libAFL.get_data_input(ctx))\n\n        # set register\n        emuHelper.writeRegister(\"r3\", pInput)\n        emuHelper.writeRegister(\"r4\", szInput)\n        emuHelper.writeRegister(emuHelper.getPCRegister(), start_addr)\n\n\n        # Emulation\n        bCrash = False\n        while True:\n            if monitor.isCancelled():\n                break\n\n            executionAddress = emuHelper.getExecutionAddress()\n\n\n            if apply_hooks(emuHelper, executionAddress):\n                continue\n\n\n            if (executionAddress in [stop_addr]):\n                if DEBUG:\n                    print(\"Emulation complete.\")\n                break\n\n\n           # Print current instruction and the registers we care about\n\n            if DEBUG:\n                print(\"\\n%s: %s\" % (str(executionAddress).upper(), getInstructionAt(executionAddress)))\n\n            res, ctx = libAFL.notify_code_coverage(ctx, executionAddress, debug=DEBUG)\n            if not res:\n                print(\"Error on notify_code_coverage\")\n                isRunning = False\n                break\n\n            if DEBUG:\n                for reg in REG_FILTER:\n                    reg_value = emuHelper.readRegister(reg)\n                    print(\"\\t{} ({}) =\\t{:08X}\".format(reg, D_REG[reg], reg_value))\n\n            # single step emulation\n            success = emuHelper.step(monitor)\n            if success == False:\n                bCrash = True\n                lastError = emuHelper.getLastError()\n                print(\"Emulation Error: '{}'\".format(lastError))\n                break\n\n        # End of Emulation\n        if bCrash:\n            res, ctx = libAFL.notify_crash(ctx)\n        else:\n            res, ctx = libAFL.notify_end_exec(ctx)\n\n        if not res:\n            # Error on notify\n            break\n\n    # End of prog\n\n    ctx = libAFL.free_ctx(ctx)\n\n\n"
  },
  {
    "path": "examples/xtensa/fuzz_xtensa_check_serial.py",
    "content": "\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\"\"\"\n\n\nimport struct\n\nfrom ghidra.app.emulator import EmulatorHelper\nfrom ghidra.program.model.address import GenericAddress\nfrom ghidra.util.task import ConsoleTaskMonitor\nfrom ghidra.program.model.block import BasicBlockModel\n\nimport time\n\nfrom libAFL import libAFL\n\n# TCP listen PORT\nPORT = 6674\n\nDEBUG = False\n\nREG_FILTER = [\n        \"a1\", \"a2\", \"a3\", \"a4\",\n        \"a5\", \"a6\", \"a7\", \"a8\",\n        \"a9\"\n]\n\nD_REG = {\n    \"a0\": \"a0\",\n    \"a1\": \"a1\",\n    \"a2\": \"a2\",\n    \"a3\": \"a3\",\n    \"a4\": \"a4\",\n    \"a5\": \"a5\",\n    \"a6\": \"a6\",\n    \"a7\": \"a7\",\n    \"a8\": \"a8\",\n    \"a9\": \"a9\",\n}\n\n\n\n\n\n\ndef write_memory(addr, data, sz = None):\n    if type(addr) == GenericAddress:\n        addr = libAFL.addr2int(addr)\n    data_str = data\n    if sz:\n        if data < 0:\n            raise ValueError(\"data must be positive\")\n        data_str = \"\"\n        while data != 0:\n            b = data & 0xff\n            data_str += struct.pack(\"B\", b)\n            data = data >> 8\n    i = 0\n    while i < len(data_str):\n        c = struct.unpack(\"B\", data_str[i])[0]\n        ghidra_addr = toAddr(addr+i)\n        emuHelper.writeMemoryValue(ghidra_addr, 1, c)\n        i += 1\n    return\n\n\n\ndef apply_hooks(emuHelper, addr, debug=False):\n    \"\"\"\n    Apply hook if needed\n    \"\"\"\n    # n_addr = get_next_execution_addr(addr)\n\n    bRes = None\n    addr_int = libAFL.addr2int(addr)\n    if addr_int in D_HOOKS.keys():\n        if debug:\n            print(\" * * * apply_hook: %s - %s\" % (str(addr), D_HOOKS[addr_int][\"name\"]))\n        bRes = D_HOOKS[addr_int][\"callback\"](emuHelper, addr)\n\n    return bRes\n\n\n\ndef hook_good_serial(emuHelper, addr):\n    ret = emuHelper.readRegister(\"a2\")\n    if ret == 2:\n        # force crash\n        # => pc = 0\n        emuHelper.writeRegister(emuHelper.getPCRegister(), 0x0)\n        return True\n    return False\n\n\nD_HOOKS = {\n    0x400e3120:{\n        \"name\": \"good_serial\",\n        \"callback\": hook_good_serial,\n        },\n}\n\n\nif __name__ == '__main__':\n    emuHelper = EmulatorHelper(currentProgram)\n\n    monitor = ConsoleTaskMonitor()\n    bbm = BasicBlockModel(currentProgram)\n\n    ctx = {}\n    ctx = libAFL.init_ctx(ctx, monitor, bbm)\n\n    res, ctx = libAFL.run_bridge_server_api(ctx, port=PORT)\n    if not res:\n        print(\"Error on listen on %d tcp port\", PORT)\n        exit(1)\n\n    start_addr = 0x400e30ab\n    stop_addr = toAddr(0x400e3120)\n\n    # Add new memory section to store emulate values\n    addr_section_emu = 0x20000000\n    sz_emu = 0x100000\n\n    pInput = addr_section_emu\n\n    count = 0\n    bFirstRun = True\n\n    isRunning = True\n    while isRunning:\n\n        # reset previous block reached\n        ctx = libAFL.init_ctx(ctx, monitor, bbm)\n\n        res, ctx = libAFL.rcv_input(ctx, debug=DEBUG)\n        if not res:\n            if DEBUG:\n                print(\"Error get config\")\n            res, ctx = libAFL.notify_err(ctx)\n            continue\n\n        if DEBUG:\n            print(\"CONFIG: %s\" % str(ctx))\n\n        if libAFL.isStopOrder(ctx):\n            isRunning = False\n            break\n\n        # Do some stats\n        if count % 1000 == 0:\n            count = 0\n            if not bFirstRun:\n                stat = 1000.0 / (time.time() - ref_time)\n                print(\"Exec %d/s\" % int(stat))\n            bFirstRun = False\n            ref_time = time.time()\n        count += 1\n\n\n        write_memory(pInput, libAFL.get_data_input(ctx))\n        szInput = len(libAFL.get_data_input(ctx))\n\n        # set register\n        emuHelper.writeRegister(\"a2\", pInput)\n        emuHelper.writeRegister(\"a3\", szInput)\n        emuHelper.writeRegister(emuHelper.getPCRegister(), start_addr)\n\n\n        # Emulation\n        bCrash = False\n        while True:\n            if monitor.isCancelled():\n                break\n\n            executionAddress = emuHelper.getExecutionAddress()\n\n\n            if apply_hooks(emuHelper, executionAddress):\n                continue\n\n\n            if (executionAddress in [stop_addr]):\n                if DEBUG:\n                    print(\"Emulation complete.\")\n                break\n\n\n           # Print current instruction and the registers we care about\n\n            if DEBUG:\n                print(\"\\n%s: %s\" % (str(executionAddress).upper(), getInstructionAt(executionAddress)))\n\n            res, ctx = libAFL.notify_code_coverage(ctx, executionAddress, debug=DEBUG)\n            if not res:\n                print(\"Error on notify_code_coverage\")\n                isRunning = False\n                break\n\n            if DEBUG:\n                for reg in REG_FILTER:\n                    reg_value = emuHelper.readRegister(reg)\n                    print(\"\\t{} ({}) =\\t{:08X}\".format(reg, D_REG[reg], reg_value))\n\n            # single step emulation\n            success = emuHelper.step(monitor)\n            if success == False:\n                bCrash = True\n                lastError = emuHelper.getLastError()\n                print(\"Emulation Error: '{}'\".format(lastError))\n                break\n\n        # End of Emulation\n        if bCrash:\n            res, ctx = libAFL.notify_crash(ctx)\n        else:\n            res, ctx = libAFL.notify_end_exec(ctx)\n\n\n    # End of prog\n\n    ctx = libAFL.free_ctx(ctx)\n\n\n"
  },
  {
    "path": "libAFL/__init__.py",
    "content": "\n"
  },
  {
    "path": "libAFL/libAFL.py",
    "content": "#!/usr/bin/python2\n\n\"\"\"\nCopyright 2021 by Airbus CyberSecurity - Flavian Dola\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\"\"\"\n\n\nimport struct\nimport socket\nfrom libUtils import libUtils\n\n\n\nCONFIG  = \"\\x02\"\n\nTRACE   = \"\\x03\"\nSTOP    = \"\\xff\"\nCRASH   = \"\\xfe\"\nEND     = \"\\xfd\"\nERR     = \"\\xfc\"\n\n\n\n\n\n\ndef run_bridge_server_api(ctx, host=\"127.0.0.1\", port=6666):\n    res = False\n    s_bridge = None\n    try:\n        s_bridge = socket.socket(socket.AF_INET, socket.SOCK_STREAM)\n        s_bridge.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)\n        s_bridge.bind((host, port))\n        s_bridge.listen(1)\n        ctx.update({\"sock_bridge\": s_bridge})\n        res = True\n    except Exception as e:\n        print(\"run_bridge_server_api failed: %s\" % str(e))\n        if s_bridge is not None:\n            s_bridge.close()\n\n    return res, ctx\n\n\n\ndef parse_cmd(ctx, data, debug=False):\n    res = False\n\n\n    if len(data) < 1:\n        # too short\n        if debug:\n            print(\"parse_cmd: Data too short: %d\\n\" % len(data))\n        return res, ctx\n\n    offset = 0\n    if data[0] == CONFIG:\n        offset += 1\n        if len(data[offset:]) < 6:\n            if debug:\n                print(\"parse_cmd: data invalid length: %d\\n\" % len(data[offset:]))\n            return res, ctx\n\n        id_sample = struct.unpack(\"<I\", data[offset:offset+4])[0]\n        offset += 4\n\n        size_input_data = struct.unpack(\"<H\", data[offset:offset+2])[0]\n        offset += 2\n        input_data = data[offset:]\n        if len(input_data) != size_input_data:\n            if debug:\n                print(\"parse_cmd: input_data_length not match: 0x%X - 0x%X\\n\" % (len(input_data), size_input_data))\n            return res, ctx\n\n        ctx.update(\n            {\n                \"id_sample\" : id_sample,\n                \"DATA_INPUT\": input_data,\n            }\n        )\n        res = True\n\n    elif data[0] == STOP:\n        ctx.update({\"STOP\": True})\n        res = True\n\n    return res, ctx\n\n\n\ndef get_data_input(ctx):\n    return ctx[\"DATA_INPUT\"]\n\n\n\ndef isStopOrder(ctx):\n    if ctx.has_key(\"STOP\"):\n        if ctx[\"STOP\"]:\n            return True\n    return False\n\n\n\n\ndef rcv_large(sock, sz):\n    chunk_size = 0x40\n    data = \"\"\n    while len(data) < sz:\n        sz2rcv = chunk_size\n        sz_left = sz - len(data)\n        if sz_left < chunk_size:\n            sz2rcv = sz_left\n        data += sock.recv(sz2rcv)\n    return data\n\n\n\ndef rcv_cmd(ctx, debug):\n    res = False\n    frame_raw = \"\"\n    if not ctx.has_key(\"sock_bridge\"):\n        return res, ctx, frame_raw\n\n\n    if not ctx.has_key(\"conn_bridge\"):\n        conn, addr = ctx[\"sock_bridge\"].accept()\n        if debug:\n            print('rcv_cmd: Connected by', addr)\n\n        ctx.update({\"conn_bridge\": conn})\n\n    c = ctx[\"conn_bridge\"].recv(1)\n    if c is None:\n        print(\"rcv_cmd: rcv type failed\")\n        return res, ctx, frame_raw\n\n    if c not in [CONFIG, STOP]:\n        print(\"rcv_cmd: invalid type frame:\"+c.encode(\"hex\"))\n        return res, ctx, frame_raw\n\n    frame_raw += c\n    if c == STOP:\n        res = True\n        return res, ctx, frame_raw\n\n    # get CONFIG frame\n    id_sample = ctx[\"conn_bridge\"].recv(4)\n    if len(id_sample) != 4:\n        print(\"rcv_cmd: rcv id_sample failed\")\n        return res, ctx, frame_raw\n    frame_raw += id_sample\n\n    sz_sample = ctx[\"conn_bridge\"].recv(2)\n    if len(sz_sample) != 2:\n        print(\"rcv_cmd: rcv sz_sample failed\")\n        return res, ctx, frame_raw\n    frame_raw += sz_sample\n\n    frame_raw += rcv_large(ctx[\"conn_bridge\"], struct.unpack(\"<H\", sz_sample)[0])\n\n    res = True\n    return res, ctx, frame_raw\n\n\n\ndef rcv_input(ctx, debug):\n    res = False\n\n    # GET input frame\n    res, ctx, config_raw = rcv_cmd(ctx, debug)\n    if not res:\n        #if debug:\n        print(\"rcv_input: error on get config frame\\n\")\n        return res, ctx\n\n\n    ctx.update({\"CONFIG_RAW\": config_raw})\n    res, ctx = parse_cmd(ctx, config_raw, debug)\n    if not res:\n        #if debug:\n        print(\"rcv_input: error on parse config frame: %s\\n\" % config_raw.encode(\"hex\"))\n        return res, ctx\n\n\n    res = True\n\n    return res, ctx\n\n\n\ndef notify_crash(ctx):\n    res = False\n    try:\n        ctx[\"conn_bridge\"].sendall(CRASH+struct.pack(\"<I\", ctx[\"id_sample\"]))\n        res = True\n    except Exception as e:\n        print(\"notify_crash: error: %s\\n\" % str(e))\n        if ctx.has_key(\"conn_bridge\"):\n            ctx[\"conn_bridge\"].close()\n            del ctx[\"conn_bridge\"]\n\n    return res, ctx\n\n\n\ndef notify_end_exec(ctx):\n    res = False\n    try:\n        ctx[\"conn_bridge\"].sendall(END+struct.pack(\"<I\", ctx[\"id_sample\"]))\n        res = True\n    except Exception as e:\n        print(\"notify_end_exec: error: %s\\n\" % str(e))\n        if ctx.has_key(\"conn_bridge\"):\n            ctx[\"conn_bridge\"].close()\n            del ctx[\"conn_bridge\"]\n\n    return res, ctx\n\n\ndef notify_err(ctx):\n    res = False\n    try:\n        ctx[\"conn_bridge\"].sendall(ERR)\n        res = True\n    except Exception as e:\n        print(\"notify_err: error: %s\\n\" % str(e))\n        if ctx.has_key(\"conn_bridge\"):\n            ctx[\"conn_bridge\"].close()\n            del ctx[\"conn_bridge\"]\n\n    return res, ctx\n\n\n\n\ndef init_ctx(ctx, monitor, bbm):\n    ctx.update({\n        \"monitor\": monitor,\n        \"bbm\": bbm,\n        \"last_block_addr\": 0\n    })\n    return ctx\n\n\n\ndef free_ctx(ctx):\n\n    if ctx.has_key(\"conn_bridge\"):\n        try:\n            ctx[\"conn_bridge\"].shutdown(socket.SHUT_RDWR)\n        except:\n            pass\n        ctx[\"conn_bridge\"].close()\n        del ctx[\"conn_bridge\"]\n\n    if ctx.has_key(\"sock_bridge\"):\n        try:\n            ctx[\"sock_bridge\"].shutdown(socket.SHUT_RDWR)\n        except:\n            pass\n        ctx[\"sock_bridge\"].close()\n        del ctx[\"sock_bridge\"]\n\n    return ctx\n\n\n\n\ndef notify_code_coverage(ctx, executionAddress, debug=False):\n    res = False\n    b = ctx[\"bbm\"].getFirstCodeBlockContaining(executionAddress, ctx[\"monitor\"])\n    if b is None:\n        print(\"notify_code_coverage: Warning cannot get block for addr 0x%08X\" % libUtils.addr2int(executionAddress))\n        return True, ctx\n\n    b_addr = libUtils.addr2int(b.minAddress)\n\n\n    if b_addr == ctx[\"last_block_addr\"]:\n        res = True\n        return res, ctx\n    else:\n        # New block\n        if debug:\n            print(\"notify_code_coverage: New block: 0x%08X\\n\" % b_addr)\n\n        if not ctx.has_key(\"conn_bridge\"):\n            print(\"notify_code_coverage: Error socket\")\n            return res, ctx\n\n        try:\n            ctx[\"conn_bridge\"].sendall(TRACE + struct.pack(\"<I\", ctx[\"id_sample\"]) + struct.pack(\"<I\", b_addr))\n            ctx[\"last_block_addr\"] = b_addr\n            res = True\n        except Exception as e:\n            print(\"notify_code_coverage: Failed to send address: %s\" % str(e))\n            ctx[\"conn_bridge\"].close()\n            del ctx[\"conn_bridge\"]\n\n    return res, ctx\n\n"
  },
  {
    "path": "libUtils/__init__.py",
    "content": ""
  },
  {
    "path": "libUtils/libUtils.py",
    "content": "#!/usr/bin/python2\n\n\n\nimport struct\nfrom ghidra.program.model.address import GenericAddress\nfrom ghidra.program.flatapi import FlatProgramAPI\n\n\n\n\ndef addr2int(addr):\n    return addr.offset\n\n\ndef write_memory(emuHelper, addr, data, sz = None):\n    api = None\n    if type(addr) == GenericAddress:\n        addr = addr2int(addr)\n    data_str = data\n    if sz:\n        if data < 0:\n            raise ValueError(\"data must be positive\")\n        data_str = \"\"\n        while data != 0:\n            b = data & 0xff\n            data_str += struct.pack(\"B\", b)\n            data = data >> 8\n\n    api = FlatProgramAPI(emuHelper.getProgram())\n    i = 0\n    while i < len(data_str):\n        c = struct.unpack(\"B\", data_str[i])[0]\n        ghidra_addr = api.toAddr(addr+i)\n        emuHelper.writeMemoryValue(ghidra_addr, 1, c)\n        i += 1\n    del api\n    return\n\n\n\ndef get_string(emuHelper, addr):\n    my_str = \"\"\n    api = None\n    if type(addr) != GenericAddress:\n        api = FlatProgramAPI(emuHelper.getProgram())\n        addr = api.toAddr(addr)\n\n\n    while True:\n        b = emuHelper.readMemoryByte(addr)\n        if b == 0:\n            break\n        my_str += struct.pack(\"B\", b)\n        addr = addr.add(1)\n\n    del api\n    return my_str\n\n\n\ndef apply_hooks(emuHelper, d_hooks, addr, debug=False):\n    \"\"\"\n    Apply hook if needed\n    \"\"\"\n    # n_addr = get_next_execution_addr(addr)\n\n    bRes = None\n    addr_int = addr2int(addr)\n    if addr_int in d_hooks.keys():\n        if debug:\n            print(\" * * * apply_hook: %s - %s\" % (str(addr), d_hooks[addr_int][\"name\"]))\n        bRes = d_hooks[addr_int][\"callback\"](emuHelper, addr)\n\n    return bRes\n\n\ndef get_next_execution_addr(addr):\n    if type(addr) in [int, long]:\n        addr = toAddr(addr)\n    return getInstructionAfter(addr).address"
  }
]