Skip to content
Idapython script to carve binary for internal RPC structures
Python
Branch: master
Clone or download
Latest commit e69004c Sep 13, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
decompile Fix heuristic when reading unbounded rpc structs from the binary itself Aug 22, 2019
screenshot Add third and final example Sep 1, 2019
README.md Fix url Sep 13, 2019
findrpc.py Add a warning if IDA's autoanalysis is not finished Sep 1, 2019

README.md

findrpc : Ida script to extract RPC interface from binaries

Usage

Just run the script findrpc.py.

NB : wait for the autoanalysis to finish before running the script.

The script rely on the same heuristic as James Forshaw's FindRpcServerInterfaces but is a bit more powerful since it can use IDA's xrefs system to uncover "non-obvious" relationships between RPC structures (e.g. in the case of a proxy definition).

Unlike RpcView or NtApiDotNet findrpc.py also return the RPC clients embbeded in the binary, which may or may not be of use when reversing.

Features

  • View in a glance which RPC clients and servers are embedded in the binary :

  • Locate dispatch tables for RPC servers:

  • Quicky rename every RPC proc handlers found:

  • (On Windows) Generate decompiled IDL from RPC declarations :

BB : if you want to regenerate the IDL, you need to have the decompile folder in the same directory as findrpc.py. DecompileInterface.exe is a custom loader for Forshaw's NdrParser.ReadFromRpcServerInterface which uses a json file exported from IDA instead of reading a remote process's memory.

Study Example #1 : SgrmBroker

Some RPC servers are not accessible via RpcView or NtObjectManager, although any clients can connect to it. One prime example is SgrmBroker which is a service running as PPL on Windows 10. Protected Processes Light (PPL) are famously protected against remote process memory reading, even if thoses processes are running as admin, thus why RpcView fail at localizing the interface.

findrpc can find it since it rely only on the binary :

Decompiled Interface :

// DllOffset: 0x2C9C0
// DllPath C:\Windows\System32\SgrmBroker.exe 
// Complex Types:
/* Memory Size: 132 */
struct Struct_0 {
    /* Offset: 0 */ sbyte[128] Member0;
    /* Offset: 128 */ int Member1;
};


[uuid("7a20fcec-dec4-4c59-be57-212e8f65d3de"), version(1.0)]
interface intf_7a20fcec_dec4_4c59_be57_212e8f65d3de {

    HRESULT SgrmCreateSession(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] wchar_t[1]* p1, 
    	/* Stack Offset: 16 */ [In] struct Struct_0* p2, 
    	/* Stack Offset: 24 */ [Out] /* FC_BIND_CONTEXT */ handle_t* p3, 
    	/* Stack Offset: 32 */ [Out] UIntPtr* p4
    );

    HRESULT SgrmEndSession(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In, Out] /* FC_BIND_CONTEXT */ handle_t* p1
    );

    HRESULT GetSessionReport(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] /* FC_BIND_CONTEXT */ handle_t* p1, 
    	/* Stack Offset: 16 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(24)(FC_DEREFERENCE)(FC_ULONG)(0) */ sbyte[]* p2, 
    	/* Stack Offset: 24 */ [Out] int* p3
    );

    HRESULT GetRuntimeReport(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] /* FC_BIND_CONTEXT */ handle_t* p1, 
    	/* Stack Offset: 16 */ [In] struct Struct_0* p2, 
    	/* Stack Offset: 24 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(32)(FC_DEREFERENCE)(FC_ULONG)(0) */ sbyte[]* p3, 
    	/* Stack Offset: 32 */ [Out] int* p4
    );

    HRESULT GetSessionCertificate(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] /* FC_BIND_CONTEXT */ handle_t* p1, 
    	/* Stack Offset: 16 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(24)(FC_DEREFERENCE)(FC_ULONG)(0) */ sbyte[]* p2, 
    	/* Stack Offset: 24 */ [Out] int* p3
    );
}

Study Example #2 : WarpJITSvc

Some Windows services are only running "on demand" and exit as soon as they are done processing the client calls. This is the case for WarpJITSvc : this is a Windows service which provide CPU-generated shaders when there is no graphic acceleration provided by system (e.g. on a server or in a VM).

WarpJITSvc is "triggered" when a client attempt to access the RPC interface "5a0ce74d-f9cf-4dea-a4c1-2d5fe4c89d51". The rasterization RPC server is not present in its ServiceDLL Windows.WARP.JITService.dll but in one of its dependency, d3d10warp.dll

// DllOffset: 0x5D5B70
// DllPath C:\Windows\System32\d3d10warp.dll

[uuid("5a0ce74d-f9cf-4dea-a4c1-2d5fe4c89d51"), version(1.0)]
interface intf_5a0ce74d_f9cf_4dea_a4c1_2d5fe4c89d51 {

    HRESULT WARPJITOOPServerConnect(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] /* FC_SYSTEM_HANDLE Process(VmOperation, VmRead, VmWrite, QueryLimitedInformation, Synchronize) */ HANDLE p1, 
    	/* Stack Offset: 16 */ [In] int p2, 
    	/* Stack Offset: 24 */ [In] /* C:(FC_TOP_LEVEL_CONFORMANCE)(16)(FC_ZERO)(FC_ULONG)(Early) */ byte[]* p3, 
    	/* Stack Offset: 32 */ [In] /* range: 0,2147483647 */ int p4, 
    	/* Stack Offset: 40 */ [Out] int* p5, 
    	/* Stack Offset: 48 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(32)(FC_ZERO)(FC_ULONG)(17)V:(FC_TOP_LEVEL_CONFORMANCE)(40)(FC_DEREFERENCE)(FC_ULONG)(Early) */ byte[]* p6
    );

    HRESULT WARPJITOOPServerPassMessage(
    	/* Stack Offset: 0 */ handle_t p0, 
    	/* Stack Offset: 8 */ [In] int p1, 
    	/* Stack Offset: 16 */ [In] /* C:(FC_TOP_LEVEL_CONFORMANCE)(8)(FC_ZERO)(FC_ULONG)(Early) */ byte[]* p2, 
    	/* Stack Offset: 24 */ [In] /* range: 0,2147483647 */ int p3, 
    	/* Stack Offset: 32 */ [Out] int* p4, 
    	/* Stack Offset: 40 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(24)(FC_ZERO)(FC_ULONG)(17)V:(FC_TOP_LEVEL_CONFORMANCE)(32)(FC_DEREFERENCE)(FC_ULONG)(Early) */ byte[]* p5
    );

    HRESULT WARPJITOOPServerGetConnectionUUID(
    	/* Stack Offset: 8 */ handle_t p0, 
    	/* Stack Offset: 16 */ [In] /* range: 0,2147483647 */ int p1, 
    	/* Stack Offset: 24 */ [Out] int* p2, 
    	/* Stack Offset: 32 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(16)(FC_ZERO)(FC_ULONG)(17)V:(FC_TOP_LEVEL_CONFORMANCE)(24)(FC_DEREFERENCE)(FC_ULONG)(Early) */ byte[]* p3
    );

    HRESULT WARPJITOOPServerGetConnectionUUID2(
    	/* Stack Offset: 8 */ handle_t p0, 
    	/* Stack Offset: 16 */ [In] /* range: 0,2147483647 */ int p1, 
    	/* Stack Offset: 24 */ [Out] int* p2, 
    	/* Stack Offset: 32 */ [Out] /* C:(FC_TOP_LEVEL_CONFORMANCE)(16)(FC_ZERO)(FC_ULONG)(17)V:(FC_TOP_LEVEL_CONFORMANCE)(24)(FC_DEREFERENCE)(FC_ULONG)(Early) */ byte[]* p3
    );
}

Study Example #3 : notskrnl.exe

RPC code is fucking everywhere, even in kerneland. Apparentlty some parts of the \\Device\\DeviceApi device can deserialize NDR data using RPC interface's bd84cd86-9825-4376-813d334c543f89b1 type and string formats :

This is coherent with the fact that the "Device Association" service register bd84cd86-9825-4376-813d334c543f89b1 interface on the epr mapper :

References

You can’t perform that action at this time.