bitdefender / bddisasm

bddisasm is a fast, lightweight, x86/x64 instruction decoder. The project also features a fast, basic, x86/x64 instruction emulator, designed specifically to detect shellcode-like behavior.
Apache License 2.0
875 stars 112 forks source link

xor byte ptr [rsp],cl RegFlags SF , Possible problems #51

Closed icyfox168168 closed 3 years ago

icyfox168168 commented 3 years ago

Error engineering file bdshemu.c

Error function ShemuEmulate

I tested it again with my test program and found that there may be a problem with setting the flag bit of this instruction

//shellcode

__writeeflags(0x202);
_ShemuEmulateEx("sub rsp,8\r\n mov byte ptr [rsp],0x2A \r\n mov cl,0xDE \r\n xor byte ptr [rsp],cl \r\n add rsp,8\r\n ret\n\n");

OUT: -------------------------------

OUT: Instruction Flags XOR byte ptr [rsp], cl cf 0 pf 1 af 0 zf 1 sf 1 tf 0 if 0 df 0 of 0

OUT: fucking XOR byte ptr [rsp], cl Old RegFlags 00000202 rax 0000000000000000 cf 0 pf 0 af 0 zf 0 sf 0 tf 0 if 1 df 0 of 0

OUT: tureend XOR byte ptr [rsp], cl Old RegFlags 00000202 rax 0000000000000000 cf 0 pf 0 af 0 zf 0 sf 1 tf 0 if 1 df 0 of 0

OUT: fuckend XOR byte ptr [rsp], cl Old RegFlags 00000202 rax 0000000000000000 cf 0 pf 0 af 0 zf 0 sf 0 tf 0 if 1 df 0 of 0

OUT: -------------------------------

icyfox168168 commented 3 years ago

I checked the data. The SF flag bit of this instruction must be set

vlutas commented 3 years ago

Hello,

You are correct, XOR affects the SF. However, I emulated the code you used in your example, and the SF is set correctly in this case:

        RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x0000000000200000 RFLAGS = 0x0000000000000202   CF:0 PF:0 AF:0 ZF:0 SF:0 TF:0 IF:1 DF:0 OF:0
Emulating: 0x0000000000200000 XOR       eax, eax
        RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x0000000000200002 RFLAGS = 0x0000000000000246   CF:0 PF:1 AF:0 ZF:1 SF:0 TF:0 IF:1 DF:0 OF:0
Emulating: 0x0000000000200002 SUB       rsp, 0x0000000000000008
        RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000100ff8 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x0000000000200006 RFLAGS = 0x0000000000000202   CF:0 PF:0 AF:0 ZF:0 SF:0 TF:0 IF:1 DF:0 OF:0
Emulating: 0x0000000000200006 MOV       byte ptr [rsp], 0x2a
        RAX = 0x0000000000000000 RCX = 0x0000000000000000 RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000100ff8 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x000000000020000a RFLAGS = 0x0000000000000202   CF:0 PF:0 AF:0 ZF:0 SF:0 TF:0 IF:1 DF:0 OF:0
Emulating: 0x000000000020000a MOV       cl, 0xde
        RAX = 0x0000000000000000 RCX = 0x00000000000000de RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000100ff8 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x000000000020000c RFLAGS = 0x0000000000000202   CF:0 PF:0 AF:0 ZF:0 SF:0 TF:0 IF:1 DF:0 OF:0
Emulating: 0x000000000020000c XOR       byte ptr [rsp], cl
        RAX = 0x0000000000000000 RCX = 0x00000000000000de RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000100ff8 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x000000000020000f RFLAGS = 0x0000000000000282   CF:0 PF:0 AF:0 ZF:0 SF:1 TF:0 IF:1 DF:0 OF:0
Emulating: 0x000000000020000f ADD       rsp, 0x0000000000000008
        RAX = 0x0000000000000000 RCX = 0x00000000000000de RDX = 0x0000000000000000 RBX = 0x0000000000000000
        RSP = 0x0000000000101000 RBP = 0x0000000000000000 RSI = 0x0000000000000000 RDI = 0x0000000000000000
        R8  = 0x0000000000000000 R9  = 0x0000000000000000 R10 = 0x0000000000000000 R11 = 0x0000000000000000
        R12 = 0x0000000000000000 R13 = 0x0000000000000000 R14 = 0x0000000000000000 R15 = 0x0000000000000000
        RIP = 0x0000000000200013 RFLAGS = 0x0000000000000206   CF:0 PF:1 AF:0 ZF:0 SF:0 TF:0 IF:1 DF:0 OF:0

As you can see, after the XOR is emulated, the SF is set appropriately to 1, since the most significant bit in the (byte) result is 1.

What you have to be careful at is the fact that after the XOR, in your example, you also have the ADD rsp, which will alter the flags XOR just set, so this is most likely why you see SF 0 instead of 1.

icyfox168168 commented 3 years ago

I'll look at my test system again. There may be a bug

Shellcode is extracted and may have problems

The original test shellcode is MD5 algorithm

icyfox168168 commented 3 years ago

It was a bug in my test program. I didn't handle the writing to memory and destroyed the original data. I was surprised to find that there was no bug. Except for the of of such an instruction as ror, it is not necessary. There is no bug

Perfect without bugs

        if (Ctx->Instruction.Instruction == ND_INS_XOR || Ctx->Instruction.Instruction == ND_INS_ADD ||
            Ctx->Instruction.Instruction == ND_INS_SUB || Ctx->Instruction.Instruction == ND_INS_AND ||
            Ctx->Instruction.Instruction == ND_INS_INC || Ctx->Instruction.Instruction == ND_INS_DEC ||
            Ctx->Instruction.Instruction == ND_INS_NEG || Ctx->Instruction.Instruction == ND_INS_OR ||
            Ctx->Instruction.Instruction == ND_INS_TEST || Ctx->Instruction.Instruction == ND_INS_CMP ||
            Ctx->Instruction.Instruction == ND_INS_BTC || Ctx->Instruction.Instruction == ND_INS_ADC ||
            Ctx->Instruction.Instruction == ND_INS_CMPXCHG || Ctx->Instruction.Instruction == ND_INS_XADD ||
            Ctx->Instruction.Instruction == ND_INS_MUL || Ctx->Instruction.Instruction == ND_INS_IMUL ||
            Ctx->Instruction.Instruction == ND_INS_ANDN)

            if (Ctx->Instruction.Operands[0].Type == ND_OP_MEM && !IsBadReadPtr(*(void**)((char*)&Ctx->Registers + Ctx->Instruction.Operands[0].Info.Memory.Base * sizeof(void*)),sizeof(void*)))
            {
                char* _NewPoint = (char*)calloc(1, 1 * 1024 * 1024);

                memmove(_NewPoint, (char*)*(void**)((char*)&Ctx->Registers + Ctx->Instruction.Operands[0].Info.Memory.Base * sizeof(void*)) - 0x1000, 0x2000);

                *(void**)((char*)&RegistersEx_Fuck_Point + Ctx->Instruction.Operands[0].Info.Memory.Base * sizeof(void*)) = _NewPoint + 0x1000;

            }
vlutas commented 3 years ago

Awesome, thanks for the feedback!