dbg_appcall

Call application function ea - address to call type - type of the function to call. can be specified as:

  • declaration string. example: "int func();"

  • typeinfo object. example: get_tinfo(ea)

  • zero: the type will be retrieved from the idb ... - arguments of the function to call Returns: the result of the function call If the call fails because of an access violation or other exception, a runtime error will be generated (it can be caught with try/catch) In fact there is rarely any need to call this function explicitly. IDC tries to resolve any unknown function name using the application labels and in the case of success, will call the function. For example: _printf("hello\n") will call the application function _printf provided that there is no IDC function with the same name.

anyvalue dbg_appcall(ea, type, ...);

// Set/get appcall options #define set_appcall_options(x) set_inf_attr(INF_APPCALL_OPTIONS, x) #define get_appcall_options() get_inf_attr(INF_APPCALL_OPTIONS)

#define APPCALL_MANUAL 0x0001 // Only set up the appcall, do not run it. // you should call cleanup_appcall() when finished #define APPCALL_DEBEV 0x0002 // Return debug event information // If this bit is set, exceptions during appcall // will generate idc exceptions with full // information about the exception #define APPCALL_TIMEOUT 0x0004 // dbg_appcall with timeout // The timeout value in milliseconds is specified // in the high 2 bytes of the 'options' argument: // If timed out, exception message will contain "timeout". #define SET_APPCALL_TIMEOUT(x) ((x<<16)|0x0004) // dbg_appcall with timeout

With dbg_appcall, it is possible to call an arbitrary function from the debugged application without any special measures like dll injection or modifying the process memory. The call can be simplified to func(args), if the function name is a valid identifier. For example, given this:

        verinfo = object();
        verinfo.dwOSVersionInfoSize = sizeof("OSVERSIONINFOA");

the following dbg_appcall:

        GetVersionExA(&verinfo);

will call create an instance of OSVERSIONINFOA in the application memory and call GetVersionExA with a pointer to it. After the call, it will convert the OSVERSIONINFO instance into an IDC object. The verinfo variable will contain:

object __at__: 18FEB0h dwBuildNumber: 7600. dwMajorVersion: 6. dwMinorVersion: 1. dwOSVersionInfoSize: dwPlatformId: 2. szCSDVersion: "\x00\x00\x00\x00..."

The _at_ attribute tells us the address of the structure. If this particular case it is not very useful since the object was temporary, but in other cases it could be useful.

dbg_appcall converts IDC objects to C objects and vice versa. The conversion is controlled by the type information. The following rules control the conversion:

 PLAIN SCALARS:

  - if the target type a plain scalar type (not a pointer),
    a simple conversion is done, with sign extension or truncation.
    For example, an IDC value of -1 is converted into an __int32(0xFFFFFFFF).
    For example, an IDC value of 0x555 is converted into an __int8(0x55).

 POINTERS:

  - if the target type a pointer and the corresponding idc value is a string,
    the string is accepted as the pointed object. It is simply copied to the
    process memory without any modifications. There will be a terminating zero
    after the string.

    If the corresponding idc value a number, its value is used as the pointer
    value. To create pointers to numbers, use the & operator.

    If the corresponding idc value is not a string, it is converted to C
    and a pointer to the converted object will be used to initialize the pointer.

 STRUCTURES:

  - if the target type is a structure, ida tries to initialize its fields one by
    one, by accessing the corresponding attributes. For example, in the above
    sample only the dwOSVersionInfoSize attribute exists, and its corresponding
    field will be initialized with its value. If a field does not exist,
    the corresponding field will be initialized with zeroes.

 ARRAYS:

  - each array element is initialized individually, expect if the corresponding
    idc value is a string. In this case, the string value is used as the value
    of the whole array. It is the user's responsibility to prepare a valid
    string that will represent an array in this case.

Some more examples. Calling printf is very easy:

  auto n = 5;
  auto s = "short";
  _printf("Hello world, number is %d, string is %s\n", n, s);

Calling sscanf will require using the & operator:

  auto x;
  auto nsuccess = _sscanf(s, "%d", &x);

Structures can be passed by ref without & because they are always passed by reference:

  verinfo = object();
  GetVersionExA(verinfo);

All calling conventions, including __usercall, are supported.

For calls that generate exceptions, single stepping is possible using the APPCALL_MANUAL bit.

Last updated