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
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.
Even in case of hardware breakpoints on access the execution sequence may not be linear as in the following case
section '.text' code readable executable
jmp dword [here]
mov eax, 1
xor eax, eax
section '.data' readable writable
here: ; <<<<<<<< HWBP on read
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).