airbus-seclab / bincat

Binary code static analyser, with IDA integration. Performs value and taint analysis, type reconstruction, use-after-free and double-free detection
1.66k stars 159 forks source link

Inappropriate translation of x86-64 registers computation #98

Closed p-state closed 5 years ago

p-state commented 5 years ago

I have the following test case:

#include <stdio.h>

void test(__int64 num)
{
    if (num == 0)
        puts("num is zero");
    else
        puts("num is not zero");
}

int main()
{
    test(-1);
    test(0);

    return 0;
}

Without optimizations main function will be compiled to this assembly:

main            proc near
                sub     rsp, 28h
                mov     rcx, 0FFFFFFFFFFFFFFFFh
                call    sub_140001000
                xor     ecx, ecx
                call    sub_140001000
                xor     eax, eax
                add     rsp, 28h
                retn
main            endp

Output of started application:

num is not zero
num is zero

Problems you may encounter when trying to analysis this binary with bincat:

  1. Analysis failed within function puts:
    INFO:bincat.plugin:[ABORT] core_x86: at 0x140002d8f: Immediate size (32) bigger than target size (8)
    INFO:bincat.plugin:Raised by primitive operation at file "utils/log.ml", line 157, characters 41-69
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml" (inlined), line 808, characters 19-53
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml", line 2074, characters 40-66
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml", line 3021, characters 19-28
    INFO:bincat.plugin:Called from file "fixpoint/interpreter.ml", line 723, characters 30-103
    INFO:bincat.plugin:Called from file "main.ml", line 152, characters 25-60
    INFO:bincat.plugin:Called from file "bincat.ml", line 42, characters 7-49
    INFO:bincat.plugin:[EXCEPTION] interpreter: Unexpected exception
    INFO:bincat.plugin:Exceptions.Error("at 0x140002d8f: Immediate size (32) bigger than target size (8)")
    INFO:bincat.plugin:Raised at file "utils/log.ml", line 160, characters 4-32
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml" (inlined), line 808, characters 19-53
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml", line 2074, characters 40-66
    INFO:bincat.plugin:Called from file "disassembly/core_x86.ml", line 3021, characters 19-28
    INFO:bincat.plugin:Re-raised at file "disassembly/core_x86.ml", line 3024, characters 33-40
    INFO:bincat.plugin:Called from file "fixpoint/interpreter.ml", line 723, characters 30-103
    INFO:bincat.plugin:[EXCEPTION] main: Exception caught in main loop
    INFO:bincat.plugin:Exceptions.Error("at 0x140002d8f: Immediate size (32) bigger than target size (8)")
    INFO:bincat.plugin:Raised at file "fixpoint/interpreter.ml", line 778, characters 82-89
    INFO:bincat.plugin:Called from file "main.ml", line 152, characters 25-60
    INFO:bincat.plugin:[STOP] stopped on 0x140002d8f

The problem place is:

test    cl, 1

I think that if register size is 1 byte, then size of immediate value should be treated as 1 byte.

  1. If we nop out calls to puts function (sub_140002D50), then it might seem that there are no problems. But if we look at test function (sub_140001000), we can see that path "num is zero" was not taken. image

The problem is that bincat translates xor ecx, ecx in main function to rcx[0, 31] <- (rcx[0, 31] xor rcx[0, 31]); statement. This is totally wrong, because xor ecx, ecx will zero out the whole rcx register, not just 32 bits of it. You can read more about it here: https://stackoverflow.com/questions/11177137/why-do-x86-64-instructions-on-32-bit-registers-zero-the-upper-part-of-the-full-6

szennou commented 5 years ago

Thanks for the investigation of the two bugs. They should be fixed now. If not please, provide us with the corresponding binary

trou commented 5 years ago

The fix introduced another bug, which is fixed now.