justinstenning / SharpDisasm

SharpDisasm - x86 / x86-64 disassembler for .NET
https://www.nuget.org/packages/SharpDisasm
Other
212 stars 39 forks source link

Previous instruction / Backward disassemble #16

Closed Symbai closed 6 years ago

Symbai commented 6 years ago

Would be useful to retreive the previous instruction by a given byte array. Example:

00CD038E - 8B 45 08              - mov eax,[ebp+08]
00CD0391 - 56                    - push esi
00CD0392 - 8B 48 3C              - mov ecx,[eax+3C]
00CD0395 - 03 C8                 - add ecx,eax
00CD0397 - 0FB7 41 14            - movzx eax,word ptr [ecx+14] <------------------ Assume this is our current location. Not important for disassembler though but to understand the following

call:
PreviousInstruction(new [] {0x56 0x8B 0x48 0x3C 0x03 0xC8}...)
PreviousInstruction(new [] {0x8B 0x48 0x3C 0x03 0xC8}...)
PreviousInstruction(new [] {0x48 0x3C 0x03 0xC8}...)
PreviousInstruction(new [] {0x3C 0x03 0xC8}...)

return should in ALL cases be:
00CD0395 - 03 C8                 - add ecx,eax

Forward disassemble will always start with first byte in array but on backward disassemble the instruction lengths are unknown so a forward disassemble with shifted bytes lead to wrong results. That means with shifted bytes the last instruction can be different. This is why backward disassemble is required.

Fonger commented 6 years ago

This is impossible to implement. You can only decode in a forward manner because that's how CPU works. The first byte determine what the instruction is and the following bytes are operands.

You should at least specify the start address of the last instruction.

for example {0x3C, 0x03, 0xC8}

The 0x3C prefix means cmp with al 0x3C 0x03 = cmp al, 03

It happened to be meaningful. How can I know the exact execution instruction start at index 1?

Symbai commented 6 years ago

But other disassembler supports this:

https://wiki.cheatengine.org/index.php?title=Lua:getPreviousOpcode https://stormsecurity.wordpress.com/2010/09/17/backward-disassembler-for-rop-exploitation/

justinstenning commented 6 years ago

@symbai you could do this by working backwards from the memory address 1-byte at a time until you get a valid instruction, however as Fonger said, it will not always be correct, ie there will be multiple possibilities as instruction lengths differ.

Even what you linked says the same thing.