AFLplusplus / qemuafl

This fork of QEMU enables fuzzing userspace ELF binaries under AFL++.

Home Page:https://aflplus.plus

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Persistent mode is broken on aarch64, since AFL_QEMU_TARGET_ARM64_SNIPPET is inserted before updating pc

galli-leo opened this issue · comments

I investigated an issue I had with persistent mode on aarch64, where a bunch of weird stuff would happen.

I finally figured out what causes this, in translate-a64.c AFL_QEMU_TARGET_ARM64_SNIPPET is referenced before the pc is updated (s->pc_curr = s->base.pc_next;).
In all other architectures, the pc is first updated, then the snippet is referenced. This leads to the persistent loop starting one instruction too late, and hence fp, lr are not preserved (at least for my binary).

Since I don't know where exactly it should come afterwards, I didn't open a PR, but if it's just the line afterwards like on arm, I can do that.

A repro case is here: https://gist.github.com/galli-leo/c879a84e5512f3b90d63b1e28f11112a
hook.c is not really important, just that one is needed. repro_fuzz.c should be compiled for aarch64.

Here is also the qemu log for the (beginning) of the do_fuzz function:

IN: do_fuzz
0x00400614:  a9bd7bfd  stp      x29, x30, [sp, #-0x30]!
0x00400618:  910003fd  mov      x29, sp
0x0040061c:  f90017e0  str      x0, [sp, #0x28]
0x00400620:  f90013e1  str      x1, [sp, #0x20]
0x00400624:  f9000fe2  str      x2, [sp, #0x18]
0x00400628:  f9400fe3  ldr      x3, [sp, #0x18]
0x0040062c:  f94013e2  ldr      x2, [sp, #0x20]
0x00400630:  f94017e1  ldr      x1, [sp, #0x28]
0x00400634:  90000000  adrp     x0, #0x400000
0x00400638:  911d2000  add      x0, x0, #0x748
0x0040063c:  97ffffa9  bl       #0x4004e0

OP:
 mov_i64 tmp0,$0x1461
 call afl_maybe_log,$0x1,$0,tmp0
 ld_i32 tmp2,env,$0xfffffffffffffff0
 brcond_i32 tmp2,$0x0,lt,$L0

 ---- 0000000000400614 0000000000000000 0000000000000000
 mov_i64 tmp0,sp
 add_i64 tmp0,tmp0,$0xffffffffffffffd0
 shl_i64 tmp5,tmp0,$0x8
 sar_i64 tmp5,tmp5,$0x8
 and_i64 tmp5,tmp5,tmp0
 qemu_st_i64 x29,tmp5,leq,8
 add_i64 tmp5,tmp5,$0x8
 qemu_st_i64 lr,tmp5,leq,8
 mov_i64 sp,tmp0

 ---- 0000000000400618 0000000000000000 0000000000000000
 call afl_persistent_routine,$0x1,$0,env
 mov_i64 tmp0,sp
 mov_i64 x29,tmp0

Hi @galli-leo ,
yes the pc update is in the wrong place, probably something went wrong while updating the patches.
Can you try to just move AFL_QEMU_TARGET_ARM64_SNIPPET the line before if (dc_isar_feature(aa64_bti, s)) { and tell me if this fix the issue?

You can rebuild qemuafl from afl++ keeping your changes using NO_CHECKOUT=1 when calling the build shell script

Yep works correctly!

@galli-leo do you want to push a PR?

Nevermind, I did it