[AFL++] No coverage guidance generated by instrumented target

122 views
Skip to first unread message

Tarun Kumar

unread,
Oct 19, 2022, 8:54:12 PM10/19/22
to afl-users

Hi all,

I am new to fuzzing using AFL++. 

 

My objective is to fuzz my firmware which runs on a separate HW. It can receive/send command from/to a host. My intention is to add instrumentation to my firmware and trigger the test from the host. Since there is no shared memory between HW and the host, therefore I will be using a host interface to send guidance data from HW to host. On the host side, I assume LibAFL can be used to get the guidance information and use that for doing the next iteration of fuzzing. Following are the steps I am doing:

1.      I am compiling https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/afl-gcc-pass.so.cc to generate a afl-gcc-pass plugin which can be used for adding instrumentation to my FW. The command used for generating the plugin is as below:

 g++ -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2 -Wall -std=c++11 -fPIC -fno-rtti \

    -I$PATH_TO_GCC_PLUGIN_DIR/include -I$PATH_TO_GCC_PLUGIN_DIR -shared \

    -o "$PATH_TO_GCC_PLUGIN_DIR/afl-gcc-pass.so" "PATH_TO_afl-gcc-pass.so.cc"

  • While I was creating the plugin I configured the map size to 16KB.

 2.      Added -fplugin=afl-gcc-pass -Wno-maybe-uninitialized in my makefile to use the afl-gcc-pass plugin for adding instrumentation to my FW binary.

  • As a result, I see that the generated binary has got some assembly code added to it.
  • I see that it has _emutls_get_address and some other code.

 3.      Added the definition of _afl_area_ptr and __afl_prev_loc as below:

  • uint8_t __afl_area_ptr[16384] ={0};
  • __thread uint32_t __afl_prev_loc;

 

4.      Added the instrumentation to a set of files only by setting

        export AFL_GCC_ALLOWLIST=afl_allow_list.txt

 

5.      Printing the content of__afl_area_ptr on the trigger of a command.
    for (uint32_t ti = 0; ti < 16384; ti++)
        printf("%x ",__afl_area_ptr[ti]);

 

6.      Loaded the binary on the device and sent a test command. This test command is for the instrumented code

 The printed output is showing all 0. Ideally it should show the guidance data. Can someone please help me to understand what the missing/incorrect things are.

 Additionally, I observed a crash due to an out of range address returned by _emutls_get_address.

 Note: My FW is multi-threaded system.

 I have doubt on the autogenerated function __emutls_get_address. Function __gthread_active_p() which invoked by __emutls_get_address is also one of the autogenerated function always returns 0.

 

Kindly help.

Marc

unread,
Oct 20, 2022, 2:14:02 AM10/20/22
to afl-...@googlegroups.com, Tarun Kumar
Hi,

> * While I was creating the plugin I configured the map size to 16KB.

please don't. first I don't know if the plugin supports different map
sizes than 64kb (which might be the reason you saw the crash), second
16kb is a map size you would use for a target with just 500 edges.

> 4. Added the instrumentation to a set of files only by setting
>
> /        export AFL_GCC_ALLOWLIST=afl_allow_list.txt///

you should also remove this during testing to ensure you are generating
coverage

Regards,
Marc

--
Marc Heuse
www.mh-sec.de

PGP: AF3D 1D4C D810 F0BB 977D 3807 C7EE D0A0 6BE9 F573

Tarun Kumar

unread,
Oct 21, 2022, 4:27:58 AM10/21/22
to Marc, afl-...@googlegroups.com
Thanks  Marc for your quick response.

There is a limitation of RAM in my system and I cannot allocate more than 16KB of RAM for coverage. Is there any workaround for this?

Can you/someone please share any inputs on  __emutls_get_address() and __gthread_active_p() functions which are added by the compiler as part of instrumentation. I see that __gthread_active_p() function always returns 0 even though my FW is multithreaded.


Thanks and regards
Tarun 

--

Tarun kumar

Marc

unread,
Oct 21, 2022, 4:52:42 AM10/21/22
to afl-...@googlegroups.com, Tarun Kumar
Hi,

On 10/21/22 10:27, Tarun Kumar wrote:
> There is a limitation of RAM in my system and I cannot allocate more
> than 16KB of RAM for coverage. Is there any workaround for this?

you could check if a 16kb map works with afl-gcc-fast or not (just use
it on a normal linux target).
If not you would need to fix instrumentation/afl-gcc-pass.so.cc - but
gimple coding (the gcc instrumentation functions) are very obscure.

> Can you/someone please share any inputs on / __emutls_get_address() /and
> /__gthread_active_p() /functions which are added by the compiler as part
> of instrumentation. I see that /__gthread_active_p() /function always
> returns 0 even though my FW is multithreaded.

I have never used it beside simple testing if it works. it was submitted
to us by adacore.

btw have you thought about rehosting your target? running it in qemu
(user or system mode)?
Or harnessing the functions you want to fuzz and fuzz them directly on a
normal Linux system?

Tarun Kumar

unread,
Nov 3, 2022, 6:11:03 AM11/3/22
to afl-users
Thankyou Marc for your inputs.

I had to fix  __emutls_get_address() to get coverage working.

Thanks and regards,
Tarun

Tarun Kumar

unread,
Nov 3, 2022, 6:34:48 AM11/3/22
to afl-users
Hi Marc,

I have added instrumentation to my FW (which runs on a separate HW device) and coverage guidance is generated. I used -fplugin=afl-gcc-pass -Wno-maybe-uninitialized for adding the instrumentation. On the host side I want to use afl-proxy.c to fuzzing. I am planning to make the guidance available from my FW (separate HW to host) and afl-proxy.c can use that guidance.

I am surprised how can afl-proxy.c use this coverage guidance to perform mutation of the input corpus while it does not have any information about the target binary or its ELF/map file etc. Could you please share some pointers how does it make use of this guidance ?

Thanks and regards,
Tarun

Reply all
Reply to author
Forward
0 new messages