Displaying the value of arguments and return value of a call

Reven v2.10.0
API preview
OS Windows 64-bit
OS Linux 64-bit

When the prototype is known

Automatically detecting the calling convention from the OS

Reven v2.12.0
from typing import Optional


def auto_calling_convention(
    server: reven2.RevenServer,
) -> Optional[reven2.preview.prototypes.callconv_helper.CallConvHelper]:
    prototypes = reven2.preview.prototypes.RevenPrototypes(server)
    if server.ossi.os().architecture != reven2.ossi.Architecture.X64:
        return None
    if server.ossi.os().family == reven2.ossi.OsFamily.Windows:
        return prototypes.calling_conventions.Ms64
    elif server.ossi.os().family == reven2.ossi.OsFamily.Linux:
        return prototypes.calling_conventions.Sysv64
    return None

Windows 64-bit example

call_tr = tr.step_out(is_forward=False)
import reven2.preview.prototypes
prototypes = reven2.preview.prototypes.RevenPrototypes(server)
call_conv = auto_calling_convention(server)
prototype = "char * __cdecl OaGetEnv(char const *);"
f = prototypes.parse_one_function(prototype, call_conv)
call = f.call_site_values(call_tr)
call.arg_n(0)
call.ret()

Sample output:

'OACACHEPARAMS'
0

Linux 64-bit example

Use the Sysv64 calling convention.

call_tr = tr.step_out(is_forward=False)
import reven2.preview.prototypes
prototypes = reven2.preview.prototypes.RevenPrototypes(server)
call_conv = auto_calling_convention(server)
prototype = "struct FILE; FILE* fopen64(const char *filename, const char *mode);"
f = prototypes.parse_one_function(prototype, call_conv)
call = f.call_site_values(call_tr)
call.args()
call.ret()

Sample output:

{'filename': '/proc/spl/kstat/zfs/arcstats', 'mode': 'r'}
0

Using a default prototype

Example with 5 parameters.

call_tr = tr.step_out(is_forward=False)
import reven2.preview.prototypes
prototypes = reven2.preview.prototypes.RevenPrototypes(server)
call_conv = prototypes.calling_conventions.Ms64
prototype = "void* f(void* p0, void* p1, void* p2, void* p3, void* p4);"
f = prototypes.parse_one_function(prototype, call_conv)
call = f.call_site_values(call_tr)
call.args()
call.ret()

Sample output:

{'p0': 18446735287469384880,
 'p1': 0,
 'p2': 18446735287473289024,
 'p3': 0,
 'p4': 0}
1364968393473
Limitations apply

Using a default prototype works as long as the replaced parameters behave as void*.

This is notably not the case for structs passed by value that are larger than a pointer (in some calling conventions) and for floating-point arguments (in Sysv64).