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).