Appcall
IDA Pro - Appcall user guide
Copyright 2023 Hex-Rays SA
Introduction
Appcall is a mechanism to call functions under a debugger session in the context of the debugged program using IDA's CLI (Command Line Interpreter) or from a script. Such a mechanism can be used for seamless blackbox function calling and use, fuzzing, process instrumentation, DLL injection, testing or extending applications.
Appcall mechanism highly depends on the type information of the called function. For that reason, it is necessary to have a correct function prototype before doing an Appcall, otherwise different or incorrect results may be returned.
In a nutshell, Appcall works by first hijacking the current thread's stack (please do switch threads explicitly if you want to Appcall in a different context), then pushing the arguments, and then temporarily adjusting the instruction pointer to the beginning of the called function. After the function returns (or an exception occurs), the original stack, instruction pointer, and other registers are restored, and the result is returned to the caller.
Please note that while most of the examples in this document are illustrated using a Windows user mode application, Appcall is not limited to Windows and can be used with any platform supported by IDA debuggers.
Quick start
Let's start explaining the basic concepts of Appcall using the IDC CLI. Let's imagine we have the following printf()
in the disassembly somewhere:
It can be called by simply typing the following in the IDC CLI (press "." to jump to the CLI):
As you noticed, we invoked an Appcall by simply treating _printf
as if it was a built-in IDC function. If the application had a console window, then you should see the message printed in it.
If you have a function with a mangled name or with characters that cannot be used as an identifier name in the IDC language, such as "_my_func@8", then you can use the LocByName
function to get its address given its name, then using the address variable (which is callable) we issue the Appcall:
Or simply directly as:
Using AppCall with IDC
Apart from calling Appcall naturally as shown in the previous section, it is possible to call it explicitly using the dbg_appcall
function:
The Appcall IDC function requires you to pass a function address, function type information (various forms are accepted) and the parameters (if any):
We've seen so far how to call a function if it already has type information, now suppose we have a function that does not:
Before calling this function with dbg_appcall
we have two options:
Pass the prototype as a string
Or, parse the prototype separately and pass the returned type info object.
This is how we can do it using the first option:
As for the second option, we can use parse_decl()
first, then proceed as usual:
Note that we used parse_decl()
function to construct a typeinfo object that we can pass to dbg_appcall
.
It is possible to permanently set the prototype of a function programmatically using apply_type()
:
In the following sections, we are going to cover different scenarios such as calling by reference, working with buffers and complex structures, etc.
Passing arguments by reference
To pass function arguments by reference, it suffices to use the & symbol as in the C language.
For example to call this function:
We can use this code from IDC:
To call a C function that takes a string buffer and modifies it: