4

I have implemented a Memory Read Access hardware breakpoint in C code. It works perfect and provides me the next instruction after a memory is read.

I am using BeaEngine to disassemble the instruction at EIP.

I need to find out the previous executed instruction which is effectively the one that accessed the memory in question (For example, like Cheat Engine does it).

How can I accomplish this?

5

This is a tricky question.

On x86 platform the maximum length of an instruction is 15 bytes.

You can read 15 bytes backwards from the current EIP and pass it to Disasm function of BeaEngine. This returns the length of the disassembled instruction. If this equals 15 you have found the previous instruction. If it is less than 15, then pass 1 byte less (i.e 14 bytes) and so on until the length of the buffer passed to BeaEngine equals the length of the disassembled instruction.

This can be represented in pseudo code

eip = 0xDEADCODE

length = 15
while(length > 0)
{
    buffer = ReadProcessMemory(start=eip-length, length)
    lenDisasm = Disasm(buffer)

    if (lenDisasm == length) 
    {
        prevIns = eip-length
        break;
    }
    else length--;
}

Note that the above algorithm is not generic in nature i.e. you cannot use it to find the previously executed instruction given the current eip. This only works when the execution sequence is linear without any jumps in between. In case of hardware breakpoints on access the execution sequence is guaranteed to be linear and the above algorithm is applicable.

EDIT:

Even in case of hardware breakpoints on access the execution sequence may not be linear as in the following case

format PE

entry start

section '.text' code readable executable

start:
    nop
    nop
    jmp dword [here]
    mov eax, 1
    push eax
    pop eax

address:
    xor eax, eax
    ret     

section '.data' readable writable

here:   ; <<<<<<<< HWBP on read
 dd address

A hardware breakpoint on read is set on here. In this case the hwbp would hit when EIP is at address. If you use the above algorithm, the previously executed instruction turns out to be pop eax which is incorrect. For such cases you can use instruction tracing or memory breakpoints (1, 2, 3).

  • Makes sense, thanks so much for the explanation! – fred26 Mar 26 '16 at 12:09
  • even if the execution sequence is linear, you might not find what you expect. Consider the 32-bit disassembly 8B 8B 05 78 56 34 12. Then consider 8B 05 78 56 34 12. Depending on register values, either of them might be the correct one. It isn't really possible to disambiguate it. – peter ferrie Mar 28 '16 at 16:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.