nyx-fuzz/libxdc

ERR: TNT ...

tklengyel opened this issue · 8 comments

A new issue I've encountered. The PT buffer is getting processed AFAICT but still no calls to the bb or page-cache callback functions.

This is my init code:

    uint64_t filter[4][2] = {0};
    void* bitmap = malloc(0x10000);
    libxdc_t* decoder = libxdc_init(filter, &page_cache_fetch, NULL, bitmap, 0x10000);
    libxdc_register_bb_callback(decoder, &trace_log, NULL);
    ret = libxdc_decode(decoder, buf, pt_buf_size);
    libxdc_free(decoder);
    free(bitmap);

The processing stops with an error message after a bit. With DEBUG_TRACES enabled I see this at the end.

disasm(ffffffff816f3b07,0)      TNT: 30270
TNT 5a
TIP     ffffffff8114160c (TNT: 30275)


disasm(ffffffff810e4403,0)      TNT: 30275
TNT 4
TIP     ffffffff811415be (TNT: 30276)


disasm(ffffffff8114160c,0)      TNT: 30276
TNT e
TIP     ffffffff811415e5 (TNT: 30278)


disasm(ffffffff811415be,0)      TNT: 30278

ERR:    TNT 30278

It seems to have gotten quite far into the trace. Any recommendation on how to further debug this?

eqv commented

The filter isn't set. you need to set the filter the same way that you configured it in intel pt (in your case presumably 0,ffffffffffffff) or something like that

Hm, we don't do any filtering on the PT, at least AFAICT. When I set the filter for libxdc as such:

    uint64_t filter[4][2] = { 0 };
    filter[0][1] = ~0;

I get:

xdc-vmi: src/disassembler.c:364: init_disassembler: Assertion `!in_range_specific(self->min_addr_1, self->min_addr_0, self->max_addr_0)' failed.
Aborted
eqv commented

try setting filter[0][0] = 0x1000; not an ideal solution I admit, but intel-pt breaks/becomes undecodable if code is mapped to 0 anyway.

Alright, finally got a callback to my page cache fetch function! 🥳

Page cache fetch 0xffffffff81141ebd

Alright, now I'm getting bb callbacks as well, but for some reason the src is always 2:

TRACE: 2->ffffffff811427c7
TRACE: 2->ffffffff811427a0
TRACE: 2->ffffffff81142808
TRACE: 2->ffffffff81b81619
TRACE: 2->ffffffff81b81ea7
TRACE: 2->ffffffff81b81eb4
TRACE: 2->ffffffff81b81ec2
TRACE: 2->ffffffff81b819f7
TRACE: 2->ffffffff81b81967
TRACE: 2->ffffffff81b81985
TRACE: 2->ffffffff81b81997
TRACE: 2->ffffffff81b8199d

OK I guess that's what the edge coverage callback is for. Interestingly some destinations found in the bb callback are missing in the edge coverage and vice-verse:

TRACE: ffffffff81141ec4->ffffffff81b8fee3
TRACE: ffffffff81141ec4->ffffffff81b8fee3
TRACE: ffffffff811427fb->ffffffff811427a0
TRACE: ffffffff811427ad->ffffffff81142808
TRACE: ffffffff81142808->ffffffff81b81619
TRACE: ffffffff81b81622->ffffffff81b81ea7
TRACE: ffffffff81b81eb2->ffffffff81b81eb4
TRACE: ffffffff81b81eb7->ffffffff81b81ec2
TRACE: ffffffff81b81ec2->ffffffff81b819f7
TRACE: ffffffff81b819fb->ffffffff81b81967
TRACE: ffffffff81b81983->ffffffff81b81985
TRACE: ffffffff81b81995->ffffffff81b81997
TRACE: ffffffff81b8199b->ffffffff81b8199d
TRACE: ffffffff81b819ae->ffffffff810201a0
eqv commented

The basic block callback can be called with basic blocks not encountered (for example if a conditional branch is disassembled in both directions). All targets of the edge callback should be also disassembled (and hence trigger a bb callback) unless they are outside of the trace region. If that's the case a transition to fffffffffffffffffff should always be the very next transition. However the bb callback is only called when the basic block is first disassembled, not every time it's encountered, while the edge callback is called every time an edge is taken. (you shouldn't be using the edge callback for fuzzing purposes, as it is somewhat slow).

For fuzzing it looks like I just have to plug in the shared memory buffer AFL passes me as the bitmap. So that seems pretty straight forward :) With that I think I got everything set. Thanks!