2

I would like to alter the behavior of some executable (in my case, a videogame). One way of doing this is to hook function calls (e.g., a function like Player::ReceiveDamage) and adjust parameters/return values.

I know how to inject code and how to hook functions. The challenge currently is to find the address of the function of interest. The source code of the target is not available, neither are debug symbols.

An approach I successfully used before is the following:

  1. Find all function addresses in the target executable (e.g., with IDA, radare2, Pyew, ...)
  2. With the executable running, hook all functions
  3. Black-list (and un-hook) functions that are called during moments that are not of interest
  4. White-list functions that are called during moments of interest
  5. Repeat steps (4,5) until function list is narrowed down sufficiently

Unfortunately, I have misplaced the code I was using for this process. I can re-write it, but I noticed that there is already an enormous offering of tools and libraries that may do exactly what I need.

Performance is a challenge: logging all function calls in a videogame introduces significant overhead. I noticed previously that it would take some time for my old tool to black-list enough irrelevant functions for the target to become responsive. This likely makes Frida not a good choice, as it injects javascript.

Does anyone know of a performant tool/library, supporting Windows and x64, that I can use to find functions of interest in a target executable?

2 Answers 2

1

You can use a binary dynamic instrumentation framework, such as:

1
  • Aha, the term I was looking for is "dynamic binary instrumentation"! Thank you very much. I've googled around a bit and indeed there appear to be some useful frameworks out there. I will update your answer to list a few of these. For my use case probably these frameworks are overkill. I'll probably be quicker whipping up something myself compared to writing a plugin for one of those tools...
    – tcpie
    Commented Mar 30 at 19:41
0

What I would do is the following steps:

  1. use IDA Pro to get all functions names and addresses (hopefully names if you renamed any of them) in the binary and export it as a python dictionary. examples can be found here.
  2. Install PyKd as described here and here.
  3. Create a PyKd script to set conditional breakpoints to print something everytime they are hit and then continue execution, like:
import pykd
funcList = { 'funcA': 0xAAAAAAAA,
             'funcB': 0xBBBBBBBB, 
               ...
           }

for funcName, funcAddr in funcList.items():
   pykd.DbgCommand('bp ' + funcAddr + ' ".echo ' + funcName + ' executed; gc"')
  1. Execute in WinDbg:
.load pykd
!py <path to script>
g

this will trace each function during the execution with the function names from your IDA Pro database.

2
  • 1
    With this method, for a large number of functions.. you may encounter a limit on the number of conditional breakpoints you're allowed to use. You can actually bypass this by patching both the dbgeng.dll!AddBreakpoint and dbgeng.dll!InsertBreakpoints functions. For v10.0.14321.1024, I've ended up using: eb dbgeng+0005c055 ff; eb dbgeng+0005c7da ff Commented May 9 at 0:55
  • 1
    However, for large numbers of breakpoints you'll encounter performance issues...where it actually feels worse than logarithmic time (unsure if this is still a thing in WinDbg preview). If you're using PyKd, you can trap on the STATUS_BREAKPOINT event and look up the address of the condition you want to execute with something better algorithmically. Commented May 9 at 0:56

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