zyantific / zydis

Fast and lightweight x86/x86-64 disassembler and code generation library
https://zydis.re
MIT License
3.47k stars 438 forks source link

Encoder error #432

Closed toxicmouse7 closed 1 year ago

toxicmouse7 commented 1 year ago
ZydisEncoderRequest req;
memset(&req, 0, sizeof(req));
req.mnemonic = ZYDIS_MNEMONIC_MOV;
req.machine_mode = ZYDIS_MACHINE_MODE_LEGACY_32;
req.operand_count = 2;
req.operands[0].type = ZYDIS_OPERAND_TYPE_REGISTER;
req.operands[0].reg.value = ZYDIS_REGISTER_EAX;
req.operands[1].type = ZYDIS_OPERAND_TYPE_IMMEDIATE;
req.operands[1].imm.u = 0x8fffffff;

ZyanU8 f[ZYDIS_MAX_INSTRUCTION_LENGTH];
ZyanUSize s;
if (ZYAN_FAILED(ZydisEncoderEncodeInstruction(&req, f, &s)))
    return -1;

If the second operand has value more, than INT_MAX (0x7fffffff), the function fails.

mappzor commented 1 year ago

And this is expected behavior. Immediates are considered signed by default (https://github.com/zyantific/zydis-db/pull/13) because that's how ISA works. Immediate operand of mov gets sign-extended if particular variant requires extension.

In your case sign-extension behavior doesn't occurr because both operands have the same size (32-bit register and 32-bit immediate value) but you still need to treat immediate as signed (Zydis interface requires you to pass full 64-bit value). You need to specify it like this:

req.operands[1].imm.u = 0xFFFFFFFF8FFFFFFF;

or this:

req.operands[1].imm.s = -1879048193;