From 92fe528f27d7bdded8622a1cedf6ef424384a331 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Wed, 28 Feb 2018 13:03:19 +0100 Subject: [PATCH 01/11] Simplify QtWinExtras find library --- RpcView/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/RpcView/CMakeLists.txt b/RpcView/CMakeLists.txt index 0d8855f..4755384 100644 --- a/RpcView/CMakeLists.txt +++ b/RpcView/CMakeLists.txt @@ -12,6 +12,7 @@ set(CMAKE_AUTOMOC ON) # Find the QtWidgets library # set CMAKE_PREFIX_PATH=C:\Qt\Qt5.9.1\5.9.1\msvc2015 or c:\Qt\Qt5.9.1\5.9.1\msvc2015_64 find_package(Qt5Widgets) +find_package(Qt5WinExtras) add_executable( RpcView @@ -47,4 +48,4 @@ add_executable( # C4091 in ShlObj.h and Dbghelp.h # C4127 (conditional expression is constant) in qt headers set_target_properties(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "/wd4091 /wd4127") -target_link_libraries(RpcView Qt5::Widgets $ENV{CMAKE_PREFIX_PATH}/lib/Qt5WinExtras.lib) \ No newline at end of file +target_link_libraries(RpcView Qt5::Widgets Qt5::WinExtras) \ No newline at end of file From 80ca2914c03c52109230efb316c1e64f195dec79 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 16:49:57 +0100 Subject: [PATCH 02/11] Force /0d optimization on Debug builds --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 929228d..11ec27a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,8 +24,8 @@ include_directories("${PROJECT_BINARY_DIR}") set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) -set(CMAKE_CXX_FLAGS_DEBUG "/W4 /WX /MDd /EHsc /Zi") -set(CMAKE_C_FLAGS_DEBUG "/W4 /WX /MDd /EHsc /Zi") +set(CMAKE_CXX_FLAGS_DEBUG "/W4 /WX /Od /MDd /EHsc /Zi") +set(CMAKE_C_FLAGS_DEBUG "/W4 /WX /Od /MDd /EHsc /Zi") set(CMAKE_CXX_FLAGS_RELEASE "/W4 /WX /O2 /Oi /Ot /Gy /MD /EHsc /MP") set(CMAKE_C_FLAGS_RELEASE "/W4 /WX /O2 /Oi /Ot /Gy /MD /EHsc /MP") From e69e76981f12339f30b1cdf097fd3d31c3ef2feb Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 16:50:41 +0100 Subject: [PATCH 03/11] Add a static build of RpcDecompiler --- RpcDecompiler/CMakeLists.txt | 67 +++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/RpcDecompiler/CMakeLists.txt b/RpcDecompiler/CMakeLists.txt index b10c0cd..a1f99f6 100644 --- a/RpcDecompiler/CMakeLists.txt +++ b/RpcDecompiler/CMakeLists.txt @@ -2,36 +2,41 @@ cmake_minimum_required (VERSION 3.0.2) message("[RpcDecompiler]") -add_library(RpcDecompiler SHARED - internalComplexTypesArrays.cpp - internalComplexTypesArrays.h - InternalComplexTypesMisc.cpp - InternalComplexTypesMisc.h - internalComplexTypesPointers.cpp - internalComplexTypesPointers.h - internalComplexTypesStrings.cpp - internalComplexTypesStrings.h - internalComplexTypesStructs.cpp - internalComplexTypesStructs.h - internalComplexTypesUnions.cpp - internalComplexTypesUnions.h - internalRpcDecompiler.cpp - internalRpcDecompiler.h - InternalRpcDecompTypeDefs.cpp - internalRpcDecompTypeDefs.h - internalRpcDecompTypeDefsNew.h - internalRpcUtils.h - InternalsRpcUtils.cpp - internalTypeTools.cpp - internalTypeTools.h - RpcDecompiler.cpp - RpcDecompiler.h - IdlFunction.h - IdlFunction.cpp - IdlType.h - IdlType.cpp - IdlInterface.h - IdlInterface.cpp - RpcDecompilerResource.rc) + +set(RpcDecompilerFiles + internalComplexTypesArrays.cpp + internalComplexTypesArrays.h + InternalComplexTypesMisc.cpp + InternalComplexTypesMisc.h + internalComplexTypesPointers.cpp + internalComplexTypesPointers.h + internalComplexTypesStrings.cpp + internalComplexTypesStrings.h + internalComplexTypesStructs.cpp + internalComplexTypesStructs.h + internalComplexTypesUnions.cpp + internalComplexTypesUnions.h + internalRpcDecompiler.cpp + internalRpcDecompiler.h + InternalRpcDecompTypeDefs.cpp + internalRpcDecompTypeDefs.h + internalRpcDecompTypeDefsNew.h + internalRpcUtils.h + InternalsRpcUtils.cpp + internalTypeTools.cpp + internalTypeTools.h + RpcDecompiler.cpp + RpcDecompiler.h + IdlFunction.h + IdlFunction.cpp + IdlType.h + IdlType.cpp + IdlInterface.h + IdlInterface.cpp + RpcDecompilerResource.rc +) + +add_library(RpcDecompiler SHARED ${RpcDecompilerFiles}) +add_library(RpcDecompilerStatic ${RpcDecompilerFiles}) From ee970014f457cb8c6d138a4fa3f177af247eeab7 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 16:51:40 +0100 Subject: [PATCH 04/11] Add prototype version of RpcDecompileIt --- CMakeLists.txt | 3 +- RpcDecompileIt/CMakeLists.txt | 19 + RpcDecompileIt/DecompileItRpcStub.cpp | 137 +++++ RpcDecompileIt/RpcDecompileIt.cpp | 709 ++++++++++++++++++++++++++ RpcDecompileIt/RpcDecompileIt.h | 271 ++++++++++ RpcDecompiler/RpcDecompiler.h | 2 +- 6 files changed, 1139 insertions(+), 2 deletions(-) create mode 100644 RpcDecompileIt/CMakeLists.txt create mode 100644 RpcDecompileIt/DecompileItRpcStub.cpp create mode 100644 RpcDecompileIt/RpcDecompileIt.cpp create mode 100644 RpcDecompileIt/RpcDecompileIt.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 11ec27a..0b67c4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,4 +36,5 @@ add_definitions(-D_MBCS) add_subdirectory(RpcView) add_subdirectory(RpcDecompiler) -add_subdirectory(RpcCore) \ No newline at end of file +add_subdirectory(RpcCore) +add_subdirectory(RpcDecompileIt) \ No newline at end of file diff --git a/RpcDecompileIt/CMakeLists.txt b/RpcDecompileIt/CMakeLists.txt new file mode 100644 index 0000000..870a958 --- /dev/null +++ b/RpcDecompileIt/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required (VERSION 3.0.2) + +message("[RpcDecompileIt]") + +add_executable(RpcDecompileIt + RpcDecompileIt.cpp + DecompileItRpcStub.cpp + ../RpcCommon/Misc.c + ../RpcView/Pdb.c +) + + +target_link_libraries(RpcDecompileIt + RpcDecompilerStatic + Rpcrt4.lib + ntdll.lib + Dbghelp.lib +) + diff --git a/RpcDecompileIt/DecompileItRpcStub.cpp b/RpcDecompileIt/DecompileItRpcStub.cpp new file mode 100644 index 0000000..23c7b32 --- /dev/null +++ b/RpcDecompileIt/DecompileItRpcStub.cpp @@ -0,0 +1,137 @@ +#include "RpcDecompileIt.h" +#include + +PVOID +DecompileItRpcAlloc( + _In_ size_t Size +) +{ + return malloc(Size); +} + +void +DecompileItRpcFree( + _In_ PVOID pMem +) +{ + free(pMem); +} + +void +DecompileItRpcPrint( + _In_ PVOID Context, + _In_ const char *pText +) +{ + UNREFERENCED_PARAMETER(Context); + + printf(pText); +} + +void +DecompileItRpcDebug( + _In_ const char *pFunction, + _In_ ULONG Line, + _In_ const char *pFormat, + ... +) +{ + va_list Arg; + UNREFERENCED_PARAMETER(pFunction); + UNREFERENCED_PARAMETER(Line); + va_start(Arg, pFormat); + _vcprintf(pFormat, Arg); +} + +bool +DecompileItRpcGetInterfaceName( + _In_ GUID *pIfId, + _Out_ UCHAR *pName, + _Out_ ULONG NameLength +) +{ + HKEY hKey = NULL; + ULONG DataLength; + UCHAR SubKeyName[MAX_PATH]; + RPC_CSTR pUuidString = NULL; + BOOL bResult = FALSE; + + if (UuidToStringA(pIfId, &pUuidString) != RPC_S_OK) goto End; + sprintf_s((char*) SubKeyName, sizeof(SubKeyName), "Interface\\{%s}", pUuidString); + + if (RegOpenKeyExA(HKEY_CLASSES_ROOT, (LPCSTR)SubKeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) goto End; + DataLength = NameLength; + if (RegQueryValueExA(hKey, NULL, NULL, NULL, pName, &DataLength) != ERROR_SUCCESS) goto End; + + bResult = TRUE; +End: + if (hKey != NULL) RegCloseKey(hKey); + if (pUuidString != NULL) RpcStringFreeA(&pUuidString); + return (bResult); +} + + +bool __fastcall +DecompileItRpcGetProcessData( + _In_ RpcModuleInfo_T *Context, + _In_ RVA_T Rva, + _Out_ VOID* pBuffer, + _Out_ UINT BufferLength +) +{ + HANDLE hTargetProcess = INVALID_HANDLE_VALUE; + BOOL bResult = FALSE; + VOID* pAddress = NULL; + + RpcModuleInfo_T *DecompileContext = (RpcModuleInfo_T *)Context; + + if ((Context == NULL) || (DecompileContext->Pid == 0)) + { + goto End; + } + + hTargetProcess = OpenProcess( + PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, + FALSE, + DecompileContext->Pid + ); + + if (hTargetProcess == INVALID_HANDLE_VALUE) + { + goto End; + } + + pAddress = (VOID*)(DecompileContext->pModuleBase + Rva); + bResult = ReadProcessMemory( + hTargetProcess, + pAddress, + pBuffer, + BufferLength, + NULL + ); + +End: + if (hTargetProcess != INVALID_HANDLE_VALUE) + { + CloseHandle(hTargetProcess); + } + + return (bResult); +} + + +void +DecompileItInitRpcViewStub +( + _Inout_ RpcViewHelper_T *RpcViewStub, + _In_ PVOID Context +) +{ + RpcViewStub->pContext = &Context; + RpcViewStub->RpcAlloc = (RpcAllocFn_T) &DecompileItRpcAlloc; + RpcViewStub->RpcFree = (RpcFreeFn_T) &DecompileItRpcFree; + RpcViewStub->RpcGetProcessData = (RpcGetProcessDataFn_T)&DecompileItRpcGetProcessData; + RpcViewStub->RpcPrint = &DecompileItRpcPrint; + RpcViewStub->RpcDebug = &DecompileItRpcDebug; + RpcViewStub->RpcGetInterfaceName = (RpcGetInterfaceNameFn_T)&DecompileItRpcGetInterfaceName; +} \ No newline at end of file diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp new file mode 100644 index 0000000..d8dca6a --- /dev/null +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -0,0 +1,709 @@ +#include "RpcDecompileIt.h" + +#include +#include +#include "../RpcDecompiler/IdlInterface.h" + +#if _WIN64 + #define RPC_CORE_IS_WOW64 false +#else + #define RPC_CORE_IS_WOW64 true +#endif + +#pragma region TO_DELETE + +#include "..\RpcCommon\Misc.h" +#include "..\RpcView\Pdb.h" + + +#if (RPC_CORE_IS_WOW64==TRUE) +#define REG_PREFIX L"Wow6432Node\\" +#else +#define REG_PREFIX L"" +#endif + +//BOOL WINAPI GetRegValueData(HKEY hRootKey, WCHAR* pSubkeyName, WCHAR* pValueName, VOID* pData, UINT DataLength) +//{ +// DWORD Size; +// HKEY hKey = NULL; +// BOOL bResult = FALSE; +// +// if (RegOpenKeyExW(hRootKey, pSubkeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) goto End; +// Size = DataLength; +// if (RegQueryValueExW(hKey, pValueName, NULL, NULL, (LPBYTE)pData, &Size) != ERROR_SUCCESS) goto End; +// bResult = TRUE; +//End: +// if (hKey != NULL) RegCloseKey(hKey); +// return (bResult); +//} + +//------------------------------------------------------------------------------ +BOOL NTAPI GetComInterfaceName(const RPC_IF_ID* pInterfaceId, WCHAR* pName, UINT NameLength) +{ + WCHAR SubKeyName[MAX_PATH]; + RPC_WSTR pUuidString = NULL; + BOOL bResult = FALSE; + + if (UuidToStringW(&pInterfaceId->Uuid, &pUuidString) != RPC_S_OK) goto End; + swprintf_s(SubKeyName, sizeof(SubKeyName), REG_PREFIX L"Interface\\{%ws}", (wchar_t*) pUuidString); + if (GetRegValueData(HKEY_CLASSES_ROOT, SubKeyName, NULL, pName, NameLength) == FALSE) goto End; + + bResult = TRUE; +End: + if (pUuidString != NULL) RpcStringFreeW(&pUuidString); + return (bResult); +} + +IfType_T WINAPI GetInterfaceType(const RPC_INTERFACE_T* pRpcInterface) +{ + WCHAR TmpPath[MAX_PATH]; + + if (pRpcInterface->Flags & RPC_IF_OLE) + { + return (IfType_OLE); + } + + if (GetComInterfaceName(&pRpcInterface->RpcServerInterface.InterfaceId, TmpPath, sizeof(TmpPath)) == FALSE) + { + return (IfType_RPC); + } + return (IfType_DCOM); +} + +BOOL __fastcall GetInterfaceName(RPC_IF_ID* pInterfaceId, WCHAR* pName, UINT NameLength) +{ + //WCHAR FullPath[MAX_PATH]; + RPC_WSTR pUuidString = NULL; + BOOL bResult = FALSE; + + if (pInterfaceId == NULL) goto End; + + pName[0] = 0; + bResult = GetComInterfaceName(pInterfaceId, pName, NameLength); + /*if (bResult == FALSE) + { + UuidToStringW(&pInterfaceId->Uuid, &pUuidString); + GetFullPathNameW(gInterfaceFile, _countof(FullPath), FullPath, NULL); + GetPrivateProfileStringW((LPCWSTR)pUuidString, L"Name", NULL, pName, NameLength / sizeof(WCHAR), FullPath); + }*/ +End: + if (pUuidString != NULL) RpcStringFreeW(&pUuidString); + return (bResult); +} + +void NTAPI InitDecompilerInfo(_In_ RpcInterfaceInfo_T* pRpcInterfaceInfo, _Out_ RpcDecompilerInfo_T* pRpcDecompilerInfo) +{ + UINT i; + UINT SymboleLength; + HANDLE hProcess = NULL; + void* hPdb = NULL; + WCHAR SymboleName[RPC_MAX_LENGTH]; + + if (pRpcDecompilerInfo == NULL) goto End; + if (pRpcInterfaceInfo == NULL) goto End; + + pRpcDecompilerInfo->pModuleBase = (UINT64)pRpcInterfaceInfo->pLocationBase; + pRpcDecompilerInfo->pIfId = &pRpcInterfaceInfo->If; + pRpcDecompilerInfo->Pid = pRpcInterfaceInfo->Pid; + swprintf_s(pRpcDecompilerInfo->InterfaceName, sizeof(pRpcDecompilerInfo->InterfaceName), L"%ws", pRpcInterfaceInfo->Name); + pRpcDecompilerInfo->pSyntaxId = &pRpcInterfaceInfo->TransfertSyntax; + + pRpcDecompilerInfo->MIDLVersion = pRpcInterfaceInfo->NdrInfo.MIDLVersion; + pRpcDecompilerInfo->NDRFags = (UINT) pRpcInterfaceInfo->NdrInfo.mFlags; + pRpcDecompilerInfo->NDRVersion = pRpcInterfaceInfo->NdrInfo.Version; + + pRpcDecompilerInfo->NumberOfProcedures = pRpcInterfaceInfo->NumberOfProcedures; + pRpcDecompilerInfo->ppProcAddressTable = pRpcInterfaceInfo->ppProcAddressTable; + pRpcDecompilerInfo->pTypeFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pTypeFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + + pRpcDecompilerInfo->pFormatStringOffsetTable = pRpcInterfaceInfo->pFormatStringOffsetTable; + pRpcDecompilerInfo->pProcFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pProcFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + + pRpcDecompilerInfo->apfnExprEval = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->apfnExprEval - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + pRpcDecompilerInfo->bIsInlined = FALSE; + + pRpcDecompilerInfo->pExprOffset = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprOffset - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + pRpcDecompilerInfo->pExprFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); + // + // Cannot decompile if we cannot get the ppProcAddressTable value!!! + // + if (pRpcDecompilerInfo->ppProcAddressTable == NULL) + { + printf("*** No procedure: %u\n", pRpcDecompilerInfo->NumberOfProcedures); + // ExitProcess(0); + // goto End; + } + + pRpcDecompilerInfo->ppProcNameTable = (WCHAR**)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(UCHAR*)); + if (pRpcDecompilerInfo->ppProcNameTable == NULL) goto End; + + hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pRpcInterfaceInfo->Pid); + if (hProcess == NULL) goto End; +#ifdef _WIN64 + pRpcDecompilerInfo->bIs64Bits = !pRpcInterfaceInfo->bWow64Process; +#else + pRpcDecompilerInfo->bIs64Bits = FALSE; +#endif + // + // Creates and initialiaze the pbFunctionInterpreted bool table + // TODO : should be really initialized + // + pRpcDecompilerInfo->pbFunctionInterpreted = (BOOL*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(BOOL)); + if (pRpcDecompilerInfo->pbFunctionInterpreted == NULL) goto End; + // + // Creates and initialiaze the ppProcFormatInlined RVA_T table + // TODO : should be really initialized + // + pRpcDecompilerInfo->ppProcFormatInlined = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(RVA_T)); + if (pRpcDecompilerInfo->ppProcFormatInlined == NULL) goto End; + // + // Creates and initialiaze the ppDispatchProcAddressTable RVA_T table + // TODO : should be really initialized + // + pRpcDecompilerInfo->ppDispatchProcAddressTable = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(RVA_T)); + if (pRpcDecompilerInfo->ppDispatchProcAddressTable == NULL) goto End; + + hPdb = PdbInit(hProcess, pRpcInterfaceInfo->pLocationBase, (UINT) pRpcInterfaceInfo->LocationSize); + if (hPdb == NULL) goto End; + for (i = 0; iNumberOfProcedures; i++) + { + SymboleName[0] = 0; + if (PdbGetSymbolName(hPdb, (UCHAR*)pRpcInterfaceInfo->pLocationBase + pRpcDecompilerInfo->ppProcAddressTable[i], SymboleName, sizeof(SymboleName))) + { + SymboleLength = ((UINT)wcslen(SymboleName) + 1) * sizeof(WCHAR); + pRpcDecompilerInfo->ppProcNameTable[i] = (WCHAR*)OS_ALLOC(SymboleLength); + memcpy(pRpcDecompilerInfo->ppProcNameTable[i], SymboleName, SymboleLength); + } + } + PdbUninit(hPdb); +End: + if (hProcess != NULL) CloseHandle(hProcess); + return; +} +#pragma endregion TO_DELETE + +// copied from ../RpcCore/RpcCore.c +RpcInterfaceInfo_T* WINAPI InternalGetInterfaceInfo(PVOID Context, HANDLE hProcess, VOID* pRpcInterface, DWORD Pid, ULONG InterfaceInfoMask) +{ + MIDL_SERVER_INFO_T MidlServerInfo; + MIDL_STUB_DESC_T MidlStubDesc; + RPC_DISPATCH_TABLE_T RpcDispatchTbl; + RPC_INTERFACE_T RpcInterface; + MODULEENTRY32W ModuleEntry; + UINT i; + NDR_EXPR_DESC_T NdrExprDesc; + VOID PTR_T pProc = NULL; + WCHAR* pModuleName = NULL; + HANDLE hModulesSnapshot = NULL; + RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; + LocationInfo_T LocationInfo = {0}; + + UNREFERENCED_PARAMETER(Context); + // + // Get the RPC_INTERFACE + // + if (!ReadProcessMemory(hProcess, pRpcInterface, &RpcInterface, sizeof(RpcInterface), NULL)) + { + //printf("ReadProcessMemory failed RpcInterface\n"); + goto End; + } + + pRpcInterfaceInfo=(RpcInterfaceInfo_T*)OS_ALLOC(sizeof(RpcInterfaceInfo_T)); + if (pRpcInterfaceInfo == NULL) { DEBUG_BREAK(); goto End; } + // + // Get Default interface information + // - Pid + // - Flags + // - Type + // - UUID + // - Transfert Syntax GUID + // - Name + // +#ifdef _WIN64 + pRpcInterfaceInfo->bWow64Process = (sizeof(PVOID) != sizeof(uint64_t)) /*RPC_CORE_IS_WOW64*/; +#endif + pRpcInterfaceInfo->Pid = Pid; + pRpcInterfaceInfo->Flags = RpcInterface.Flags; + pRpcInterfaceInfo->IfType = GetInterfaceType(&RpcInterface); + // + memcpy(&pRpcInterfaceInfo->If,&RpcInterface.RpcServerInterface.InterfaceId,sizeof(pRpcInterfaceInfo->If)); + memcpy(&pRpcInterfaceInfo->TransfertSyntax,&RpcInterface.RpcServerInterface.TransferSyntax,sizeof(pRpcInterfaceInfo->TransfertSyntax)); + // + GetInterfaceName(&RpcInterface.RpcServerInterface.InterfaceId,pRpcInterfaceInfo->Name,sizeof(pRpcInterfaceInfo->Name)); + + //!!!!!!to change!!!!!! + if (InterfaceInfoMask == 0) goto End; + + switch(pRpcInterfaceInfo->IfType) + { + case IfType_DCOM: + case IfType_OLE: + goto End; //NO DCOM now!! + break; + // + case IfType_RPC: + { + if (GetLocationInfo(hProcess, (void*)RpcInterface.RpcServerInterface.DispatchTable, &LocationInfo)) + { + memcpy(pRpcInterfaceInfo->Location, LocationInfo.Location, sizeof(pRpcInterfaceInfo->Location)); + } + pRpcInterfaceInfo->pLocationBase = LocationInfo.pBaseAddress; + pRpcInterfaceInfo->LocationState = LocationInfo.State; + pRpcInterfaceInfo->LocationType = LocationInfo.Type; + pRpcInterfaceInfo->LocationSize = LocationInfo.Size; + } + break; + // + default: + break; + } + // + // If we have a module path then we can get its real base and size + // + if (LocationInfo.Location[0] != 0) + { + pModuleName = wcsrchr(pRpcInterfaceInfo->Location, '\\'); + if (pModuleName == NULL) pModuleName = pRpcInterfaceInfo->Location; + else pModuleName++; + // + // Get module base and size + // + hModulesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, Pid); + if (hModulesSnapshot != INVALID_HANDLE_VALUE) + { + ModuleEntry.dwSize = sizeof(ModuleEntry); + if (Module32FirstW(hModulesSnapshot, &ModuleEntry)) + do + { + if (_wcsicmp(pModuleName, ModuleEntry.szModule) == 0) + { + pRpcInterfaceInfo->pLocationBase = ModuleEntry.modBaseAddr; + pRpcInterfaceInfo->LocationSize = ModuleEntry.modBaseSize; + break; + } + } while (Module32NextW(hModulesSnapshot, &ModuleEntry)); + CloseHandle(hModulesSnapshot); + } + else + { + ULONG_PTR Base = 0; + WORD Magic = 0; + IMAGE_DOS_HEADER ImageDosHeader; + IMAGE_NT_HEADERS ImageNtHeaders; + // + // Last chance approach + // + Base = ((ULONG_PTR)pRpcInterfaceInfo->pLocationBase) & (~0xFFFF); + while (Magic != IMAGE_DOS_SIGNATURE) + { + ReadProcessMemory(hProcess, (PVOID)Base, &Magic, sizeof(Magic), NULL); + Base -= 0x1000; + } + pRpcInterfaceInfo->pLocationBase = (PVOID)(Base + 0x1000); + ReadProcessMemory(hProcess, pRpcInterfaceInfo->pLocationBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL); + ReadProcessMemory(hProcess, (PVOID)((ULONG_PTR)pRpcInterfaceInfo->pLocationBase + ImageDosHeader.e_lfanew), &ImageNtHeaders, sizeof(ImageNtHeaders), NULL); + } + } + // + // Get module display name + // + GetModuleDescription(pRpcInterfaceInfo->Location,pRpcInterfaceInfo->Description,sizeof(pRpcInterfaceInfo->Description)); + // + // Get the interface procedures count ony for RPC interfaces + // + if (pRpcInterfaceInfo->IfType == IfType_RPC) + { + if (ReadProcessMemory(hProcess,RpcInterface.RpcServerInterface.DispatchTable,&RpcDispatchTbl,sizeof(RpcDispatchTbl),NULL)) + { + pRpcInterfaceInfo->NumberOfProcedures=RpcDispatchTbl.DispatchTableCount; + } + else + { + ZeroMemory(pRpcInterfaceInfo, sizeof(*pRpcInterfaceInfo)); + goto End; + } + } + // + // Interpreted stub + // + if (RpcInterface.RpcServerInterface.InterpreterInfo!=NULL) + { + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pRpcInterfaceInfo->TypeOfStub=TypeOfStub_Interpreted; + } + // + // Get NDR info + // + ZeroMemory(&MidlServerInfo,sizeof(MidlServerInfo)); + ZeroMemory(&MidlStubDesc,sizeof(MidlStubDesc)); + if (!ReadProcessMemory(hProcess, RpcInterface.RpcServerInterface.InterpreterInfo, &MidlServerInfo, sizeof(MidlServerInfo), NULL)) + { + goto End; + } + if (!ReadProcessMemory(hProcess, MidlServerInfo.pStubDesc, &MidlStubDesc, sizeof(MidlStubDesc), NULL)) + { + goto End; + } + // + pRpcInterfaceInfo->NdrInfo.Version = MidlStubDesc.Version; + pRpcInterfaceInfo->NdrInfo.MIDLVersion = MidlStubDesc.MIDLVersion; + pRpcInterfaceInfo->NdrInfo.mFlags = MidlStubDesc.mFlags; + pRpcInterfaceInfo->pTypeFormatString = (UCHAR*)MidlStubDesc.pFormatTypes; + pRpcInterfaceInfo->apfnExprEval = (void*)MidlStubDesc.apfnExprEval; + + if (MidlStubDesc.pExprInfo != NULL) + { + if (ReadProcessMemory(hProcess, MidlStubDesc.pExprInfo, &NdrExprDesc, sizeof(NdrExprDesc), NULL)) + { + pRpcInterfaceInfo->pExprOffset = (USHORT*)NdrExprDesc.pOffset; + pRpcInterfaceInfo->pExprFormatString = (UCHAR*)NdrExprDesc.pFormatExpr; + } + else + { + //printf("Unable to read the pExprInfo at address %p in process %u\n", MidlStubDesc.pExprInfo, pRpcInterfaceInfo->Pid); + } + } + + pRpcInterfaceInfo->pProcFormatString = (UCHAR*)MidlServerInfo.ProcString; + // + // Get the interface procedure addresses table + // + pRpcInterfaceInfo->ppProcAddressTable=(ULONG*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(VOID*)); + if (pRpcInterfaceInfo->ppProcAddressTable == NULL) { DEBUG_BREAK(); goto End; } + + for(i=0;iNumberOfProcedures;i++) + { + if (ReadProcessMemory(hProcess,((VOID PTR_T PTR_T)MidlServerInfo.DispatchTable)+i,&pProc,sizeof(VOID PTR_T),NULL)) + { + pRpcInterfaceInfo->ppProcAddressTable[i]= (ULONG) ((ULONG64)pProc - (ULONG64)pRpcInterfaceInfo->pLocationBase); + } + } + // + // Get the interface format string offset table + // + pRpcInterfaceInfo->pFormatStringOffsetTable=(USHORT*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(USHORT)); + if (pRpcInterfaceInfo->pFormatStringOffsetTable!=NULL) + { + ReadProcessMemory(hProcess,MidlServerInfo.FmtStringOffset,pRpcInterfaceInfo->pFormatStringOffsetTable,pRpcInterfaceInfo->NumberOfProcedures*sizeof(USHORT),NULL); + } + } + else + { + //!!!todo!!! + //GetInlineStubInfo(pRpcCoreInternalCtxt,hProcess,pRpcInterface,pRpcInterfaceInfo); + } + // + // Test if DCOM or simple RPC + // + if (pRpcInterfaceInfo->IfType==IfType_RPC) + { + pRpcInterfaceInfo->IfCallbackFn = RpcInterface.IfCallbackFn; + } + + if (RpcInterface.EpMapperFlags & RPC_IS_EPMAPPER_REGISTERED) + { + pRpcInterfaceInfo->bIsRegistered=TRUE; + sprintf_s((char*) pRpcInterfaceInfo->Annotation,sizeof(pRpcInterfaceInfo->Annotation),"%s",(const char*)RpcInterface.Annotation); + } + else + { + pRpcInterfaceInfo->bIsRegistered=FALSE; + } +End: + return (pRpcInterfaceInfo); +} + +int +DecompileInit( + _Inout_ PDECOMPILE_IT_CTXT Context +) +{ + WCHAR RefModuleName[MAX_PATH]; + HMODULE hMods[1024]; + DWORD ModulesSize; + + HANDLE hProcess = OpenProcess( + PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, + FALSE, + Context -> TargetPID + ); + + if (hProcess==NULL) + { + return GetLastError(); + } + Context -> hTargetProcess = hProcess; + + + if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &ModulesSize)) + { + return GetLastError(); + } + + // stop at the first if ModuleName is not set + if (!Context->ModuleName) + { + Context->ModuleBaseAddress = (uintptr_t) hMods[0]; + } + else + { + swprintf_s(RefModuleName, sizeof(RefModuleName) / sizeof(WCHAR), L"%hs", Context->ModuleName); + + for (auto ModuleIndex = 0; (unsigned int) ModuleIndex < (ModulesSize / sizeof(HMODULE)); ModuleIndex++ ) + { + WCHAR ModuleName[MAX_PATH]; + + + if (GetModuleBaseNameW( + hProcess, + hMods[ModuleIndex], + ModuleName, + sizeof(ModuleName) / sizeof(WCHAR) + )) + { + if (!_wcsicmp(ModuleName, RefModuleName)) + { + Context->ModuleBaseAddress = (uintptr_t) hMods[ModuleIndex]; + break; + } + } + } + } + + if (!Context->ModuleBaseAddress) + { + return GetLastError(); + } + + + Context->DescriptorAddress = Context->DescriptorOffset; + Context->FormatStrAddress = Context->FormatStrOffset; + if (!Context->bAbsoluteAddress) + { + Context->DescriptorAddress += Context->ModuleBaseAddress; + Context->FormatStrAddress += Context->ModuleBaseAddress; + } + + return 0; +} + + + +int +DecompileIt( + _In_ DECOMPILE_IT_CTXT Context +) +{ + uintptr_t DecompilerHelperAddr = NULL; + RpcDecompilerHelper_T* DecompilerHelper = NULL; + // + //RpcInterfaceInfo_T* RpcInterfaceInfo = NULL; + //void* RpcDecompilerContext; + MIDL_STUB_DESC MidlStubDesc; + size_t StubDescBytesRead; + size_t RpcInterfaceInformationStructSize; + RPC_CLIENT_INTERFACE RpcClientInterface; + //RPC_SERVER_INTERFACE RpcServerInterface; + RPC_IF_ID RpcInterfaceId; + ASSIGN_RPC_VIEW_STUB(RpcViewHelperStub, &Context); + + + // resolve RpcDecompilerHelper address + HMODULE hRpcDecompiler = LoadLibrary("RpcDecompiler"); + if (!hRpcDecompiler) + { + return -1; + } + + DecompilerHelperAddr = (uintptr_t) GetProcAddress(hRpcDecompiler, "RpcDecompilerHelper"); + if (!DecompilerHelperAddr) + { + return -1; + } + DecompilerHelper = (RpcDecompilerHelper_T*) DecompilerHelperAddr; + + if (!ReadProcessMemory( + Context.hTargetProcess, + (LPCVOID)Context.DescriptorAddress, + &MidlStubDesc, + sizeof(MidlStubDesc), + (SIZE_T*) &StubDescBytesRead + )) + { + return -1; + } + + if (!ReadProcessMemory( + Context.hTargetProcess, + MidlStubDesc.RpcInterfaceInformation, + &RpcInterfaceInformationStructSize, + sizeof(RpcInterfaceInformationStructSize), + (SIZE_T*) &StubDescBytesRead + )) + { + return -1; + } + + switch (RpcInterfaceInformationStructSize) + { + case sizeof(RPC_CLIENT_INTERFACE): + + if (!ReadProcessMemory( + Context.hTargetProcess, + MidlStubDesc.RpcInterfaceInformation, + &RpcClientInterface, + sizeof(RpcClientInterface), + (SIZE_T*) &StubDescBytesRead + )) + { + return -1; + } + + RpcInterfaceId.Uuid = RpcClientInterface.InterfaceId.SyntaxGUID; + RpcInterfaceId.VersMajor = RpcClientInterface.InterfaceId.SyntaxVersion.MajorVersion; + RpcInterfaceId.VersMinor= RpcClientInterface.InterfaceId.SyntaxVersion.MinorVersion; + + //RpcDecompilerInfoStub.pSyntaxId = &RpcClientInterface.InterfaceId; + break; + + //case sizeof(RPC_SERVER_INTERFACE): + default: + return -1; + } + + + /*RpcDecompilerInfoStub.Pid = Context.TargetPID; + RpcDecompilerInfoStub->pIfId = &RpcInterfaceId; + RpcDecompilerInfoStub->pModuleBase = Context.ModuleBaseAddress; + RpcDecompilerInfoStub->NDRVersion = MidlStubDesc.Version; + RpcDecompilerInfoStub->MIDLVersion = MidlStubDesc.MIDLVersion; + RpcDecompilerInfoStub->NDRFags = (UINT) MidlStubDesc.mFlags;*/ + + //RpcInterfaceInfo = InternalGetInterfaceInfo((PVOID) &Context, Context.hTargetProcess, (VOID*)MidlStubDesc.RpcInterfaceInformation, Context.TargetPID, RPC_INTERFACE_INFO_ALL); + //InitDecompilerInfo(RpcInterfaceInfo, &RpcDecompilerInfoStub); + + //// Init RpcDecompiler and decompile idl + //RpcDecompilerContext = DecompilerHelper->RpcDecompilerInitFn( + // &RpcViewHelperStub, + // &RpcDecompilerInfoStub + //); + //if (!RpcDecompilerContext) + //{ + // return -1; + //} + + //DecompilerHelper->RpcDecompilerPrintAllProceduresFn( + // RpcDecompilerContext + //); + + std::string IfaceName("DecompileItInterface"); + IdlInterface Interface(IfaceName, RpcInterfaceId, 1); + + + // Init stubs for RpcDecompiler + RpcDecompilerInfo_T RpcDecompilerInfoStub; + RpcDecompilerInfoStub.ppProcNameTable = new WCHAR*[1]; + RpcDecompilerInfoStub.ppProcNameTable[0] = NULL; + + RpcDecompilerInfoStub.pFormatStringOffsetTable = new USHORT[1]; + RpcDecompilerInfoStub.pFormatStringOffsetTable[0] = 0; + RpcDecompilerInfoStub.pProcFormatString = (RVA_T) Context.FormatStrOffset; + + RpcDecompilerInfoStub.pTypeFormatString = (RVA_T) (MidlStubDesc.pFormatTypes - Context.ModuleBaseAddress); + + RpcModuleInfo_T ModuleInfoStub = { + /*Pid = */Context.TargetPID, + /*pModuleBase = */Context.ModuleBaseAddress + }; + + RpcDecompilerCtxt_T DecompilerStubContext; + DecompilerStubContext.pRpcDecompilerInfo = &RpcDecompilerInfoStub; + DecompilerStubContext.pRpcModuleInfo = &ModuleInfoStub; + DecompilerStubContext.pRpcViewHelper = &RpcViewHelperStub; + + if (DS_SUCCESS == Interface.decode((PVOID)&DecompilerStubContext)) + { + //std::ostringstream ossIf; + std::cout << Interface; + + } + + return 0; +} + +int +DecompileUninit( + _In_ DECOMPILE_IT_CTXT Context +) +{ + if (Context.hTargetProcess == INVALID_HANDLE_VALUE) + { + CloseHandle(Context.hTargetProcess); + } + + return 0; +} + + +int main(int argc, char* argv[]) +{ + DECOMPILE_IT_CTXT Context = {0}; + char* EndPtr; + int status; + + if (argc < 7) + { + printf("Usage: %s --pid PID [--module MODULE] --descriptor DESC_OFFSET --format-str FORMAT_STRING_OFFSET [--absolute]\n", argv[0]); + printf(" --pid : PID of the target process. %s must be able to open a handle to read the target process memory.\n", argv[0]); + printf(" --module : module name to read memory from. If not set, %s read the target executable own module. Ignored if --absolute is set.\n", argv[0]); + printf(" --descriptor : offset to the rpc header descriptor for the interface. If --absolute is set, --descriptor is interpreted as a virtual address.\n"); + printf(" --format-str : offset to the rpc format string for the chosen proc. If --absolute is set, --format-str is interpreted as a virtual address.\n"); + printf(" --absolute : treat descriptor and format-str as absolute virtual addresses instead of offsets.\n"); + + return 0; + } + + + for (auto ArgIndex = 0; ArgIndex < argc; ArgIndex++) + { + char *CurrentArgument = argv[ArgIndex]; + + if (!_stricmp(CurrentArgument, "--pid")) + { + Context.TargetPID = (DWORD) strtoumax(argv[ArgIndex + 1], &EndPtr, 10); + } + if (!_stricmp(CurrentArgument, "--module")) + { + Context.ModuleName = argv[ArgIndex + 1]; + } + else if (!_stricmp(CurrentArgument, "--descriptor")) + { + Context.DescriptorOffset = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); + } + else if (!_stricmp(CurrentArgument, "--format-str")) + { + Context.FormatStrOffset = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); + } + else if (!_stricmp(CurrentArgument, "--absolute")) + { + Context.bAbsoluteAddress = true; + } + } + + + status = DecompileInit( + &Context + ); + if (status) + { + printf("Could not init the DecompileIt context : %d.\n", GetLastError()); + return status; + } + + status = DecompileIt(Context); + + + DecompileUninit(Context); + return status; +} \ No newline at end of file diff --git a/RpcDecompileIt/RpcDecompileIt.h b/RpcDecompileIt/RpcDecompileIt.h new file mode 100644 index 0000000..014b646 --- /dev/null +++ b/RpcDecompileIt/RpcDecompileIt.h @@ -0,0 +1,271 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + + +#include "..\RpcCore\RpcCore.h" +//#include "..\RpcCore\RpcInternalsCommon.h" +#include "..\RpcCommon\RpcView.h" +#include "..\RpcDecompiler\RpcDecompiler.h" + + +typedef struct _DECOMPILE_IT_CTXT { + + DWORD TargetPID; + HANDLE hTargetProcess; + + char* ModuleName; + uintptr_t ModuleBaseAddress; + + bool bAbsoluteAddress; + size_t DescriptorOffset; + uintptr_t DescriptorAddress; + size_t FormatStrOffset; + uintptr_t FormatStrAddress; + +} DECOMPILE_IT_CTXT, *PDECOMPILE_IT_CTXT; + + +#pragma region RpcInternalsCommon + +#define MAX_RPC_INTERFACE_ANNOTATION 64 +#define SIMPLE_DICT_SMALL_ARRAY 4 +#define RPC_IS_EPMAPPER_REGISTERED 0x20 + +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * + +typedef struct _LIST_ENTRY_T { + struct _LIST_ENTRY PTR_T Flink; + struct _LIST_ENTRY PTR_T Blink; +} LIST_ENTRY_T, *PLIST_ENTRY_T; + +typedef struct _RTL_CRITICAL_SECTION_DEBUG_T { + WORD Type; + WORD CreatorBackTraceIndex; + struct _RTL_CRITICAL_SECTION_T PTR_T CriticalSection; + LIST_ENTRY_T ProcessLocksList; + DWORD EntryCount; + DWORD ContentionCount; + DWORD Flags; + WORD CreatorBackTraceIndexHigh; + WORD SpareWORD; +} RTL_CRITICAL_SECTION_DEBUG_T, PTR_T PRTL_CRITICAL_SECTION_DEBUG_T; + +typedef struct _RTL_CRITICAL_SECTION_T { + PRTL_CRITICAL_SECTION_DEBUG_T DebugInfo; + // + // The following three fields control entering and exiting the critical + // section for the resource + // + LONG LockCount; + LONG RecursionCount; + VOID PTR_T OwningThread; // from the thread's ClientId->UniqueThread + VOID PTR_T LockSemaphore; + VOID PTR_T SpinCount; // force size on 64-bit systems when packed +} RTL_CRITICAL_SECTION_T, PTR_T PRTL_CRITICAL_SECTION_T; + +typedef struct _MUTEX_T { + RTL_CRITICAL_SECTION_T CriticalSection; +}MUTEX_T; + +typedef struct _EVENT_T { + ULONG hEvent; +} EVENT_T; + +typedef struct _SIMPLE_DICT_T { + VOID PTR_T PTR_T pArray; + UINT ArraySizeInBytes; //to change : countof array elements + UINT NumberOfEntries; + VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +}SIMPLE_DICT_T, PTR_T PSIMPLE_DICT_T; + +typedef struct _QUEUE_T { + VOID PTR_T Tail; + VOID PTR_T Head; + ULONG Lentgh; + VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +}QUEUE_T; + +typedef struct _NDR_EXPR_DESC_T +{ + const unsigned short PTR_T pOffset; + const unsigned char PTR_T pFormatExpr; +} NDR_EXPR_DESC_T; + +/* +* +* MIDL Stub Descriptor +*/ +typedef struct _MIDL_STUB_DESC_T { + void PTR_T RpcInterfaceInformation; + void PTR_T pfnAllocate; + void PTR_T pfnFree; + void PTR_T pAutoHandle; + const VOID PTR_T apfnNdrRundownRoutines; + const VOID PTR_T aGenericBindingRoutinePairs; + const VOID PTR_T apfnExprEval; + const VOID PTR_T aXmitQuintuple; + const unsigned char PTR_T pFormatTypes; + int fCheckBounds; + /* Ndr library version. */ + unsigned long Version; + VOID PTR_T pMallocFreeStruct; + long MIDLVersion; + const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; + // New fields for version 3.0+ + const VOID PTR_T aUserMarshalQuadruple; + // Notify routines - added for NT5, MIDL 5.0 + const VOID PTR_T NotifyRoutineTable; + /* + * Reserved for future use. + */ + ULONG_PTR_T mFlags; + // International support routines - added for 64bit post NT5 + const VOID PTR_T CsRoutineTables; + void PTR_T ProxyServerInfo; + const NDR_EXPR_DESC_T PTR_T pExprInfo; + // Fields up to now present in win2000 release. +} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; + +/* +* Server Interpreter's information strucuture. +*/ +typedef struct _MIDL_SERVER_INFO_T { + PMIDL_STUB_DESC_T pStubDesc; + const VOID PTR_T PTR_T DispatchTable; + const unsigned char PTR_T ProcString; + const unsigned short PTR_T FmtStringOffset; + const VOID PTR_T PTR_T ThunkTable; + RPC_IF_ID PTR_T pTransferSyntax; + ULONG_PTR_T nCount; + VOID PTR_T pSyntaxInfo; +} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; + +typedef struct _RPC_DISPATCH_TABLE_T { + UINT DispatchTableCount; + RPC_DISPATCH_FUNCTION PTR_T DispatchTable; + ULONG_PTR_T Reserved; +} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; + +//typedef struct _LocationInfo_T { +// WCHAR Location[MAX_PATH]; +// VOID* pBaseAddress; +// DWORD State; +// DWORD Type; +// SIZE_T Size; +//}LocationInfo_T; + +typedef struct _RPC_PROTSEQ_ENDPOINT_T { + UCHAR PTR_T RpcProtocolSequence; + UCHAR PTR_T Endpoint; +} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; + +typedef struct _RPC_SERVER_INTERFACE_T { + UINT Length; + RPC_IF_ID InterfaceId; + RPC_IF_ID TransferSyntax; + PRPC_DISPATCH_TABLE_T DispatchTable; + UINT RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; + RPC_MGR_EPV PTR_T DefaultManagerEpv; + void const PTR_T InterpreterInfo; + UINT Flags; +} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; + +#pragma pack(1) +typedef struct _RPC_SERVER_T { + MUTEX_T Mutex; + ULONG __bIslistening; + ULONG bIsListening; + ULONG MinimumCallThreads; + ULONG Wait; + ULONG OutCalls; + ULONG Unk1; + ULONG InCalls; + ULONG Unk2; + SIMPLE_DICT_T AddressDict; + ULONG lAvailableCalls; + ULONG Unk3; + SIMPLE_DICT_T _ProtSeqQueue; + ULONG Unk4[8]; + ULONG OutPackets; + ULONG Unk5; + MUTEX_T Mutex2; + ULONG MaxCalls; + ULONG Unk6; + VOID PTR_T hEvent; + ULONG Unk7[4]; + SIMPLE_DICT_T InterfaceDict; + ULONG _bIsListening; + ULONG bIsMaxCalls1234; + ULONG Unk8[6]; + ULONG InPackets; + ULONG Unk9; + RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; + ULONG Unk10[6]; + SIMPLE_DICT_T AuthenInfoDict; + LIST_ENTRY_T RpcIfGroupListEntry; + ULONG PTR_T __SRWLock; + LIST_ENTRY_T field_1E0; +}RPC_SERVER_T, PTR_T PRPC_SERVER_T; + +typedef struct _RPC_INTERFACE_T +{ + PRPC_SERVER_T pRpcServer; + ULONG Flags; + ULONG Unk1; + MUTEX_T Mutex; + ULONG EpMapperFlags; + ULONG Unk2; + RPC_MGR_EPV PTR_T pMgrEpv; + RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; + RPC_SERVER_INTERFACE_T RpcServerInterface; + PMIDL_SYNTAX_INFO pSyntaxInfo; + VOID PTR_T pTransfertSyntaxes; + ULONG TransfertSyntaxesCount; + ULONG __Field_C4; + ULONG NbTypeManager; + ULONG MaxRpcSize; + UUID_VECTOR PTR_T pUuidVector; + SIMPLE_DICT_T RpcInterfaceManagerDict; + UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; + ULONG IsCallSizeLimitReached; + ULONG currentNullManagerCalls; + ULONG __Field_150; + ULONG __Field_154; + ULONG __Field_158; + ULONG SecurityCallbackInProgress; + ULONG SecurityCacheEntry; + ULONG field_164; + VOID PTR_T __SecurityCacheEntries[16]; + SIMPLE_DICT_T FwEpDict; + ULONG Unk3[6]; + struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; +}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; +#pragma pack() + +#pragma endregion RpcInternalsCommon + + +#pragma region RpcViewStub + +void +DecompileItInitRpcViewStub +( + _Inout_ RpcViewHelper_T *RpcViewStub, + _In_ PVOID Context +); + + +#define ASSIGN_RPC_VIEW_STUB(RpcViewHelperStub, Context) \ +RpcViewHelper_T RpcViewHelperStub; \ +DecompileItInitRpcViewStub(&RpcViewHelperStub, (PVOID) Context) + + +#pragma endregion RpcViewStub diff --git a/RpcDecompiler/RpcDecompiler.h b/RpcDecompiler/RpcDecompiler.h index caea6e5..69dd3a2 100644 --- a/RpcDecompiler/RpcDecompiler.h +++ b/RpcDecompiler/RpcDecompiler.h @@ -24,7 +24,7 @@ typedef struct _RpcDecompilerInfo_T{ UINT64 pModuleBase; UINT NDRVersion; UINT MIDLVersion; - UINT NDRFags; + UINT NDRFags; // Typo here ! UINT NumberOfProcedures; RVA_T* ppProcAddressTable; //A table containing the address of each function RVA_T* ppDispatchProcAddressTable; From 2ae9787d1bd6fd9fb0fa448f2564a0ceb6e2db03 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 17:09:27 +0100 Subject: [PATCH 05/11] Correctly support address/offset arguments --- RpcDecompileIt/RpcDecompileIt.cpp | 25 +++++++++++++++++-------- RpcDecompileIt/RpcDecompileIt.h | 28 +++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index d8dca6a..adddb6b 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -473,16 +473,25 @@ DecompileInit( if (!Context->ModuleBaseAddress) { - return GetLastError(); + return -1; } + + if (Context->bAbsoluteAddress) + { + Context->DescriptorAddress = Context->DescriptorArg; + Context->DescriptorOffset = Context->DescriptorAddress - Context->ModuleBaseAddress; - Context->DescriptorAddress = Context->DescriptorOffset; - Context->FormatStrAddress = Context->FormatStrOffset; - if (!Context->bAbsoluteAddress) + Context->FormatStrAddress = Context->FormatStrArg; + Context->FormatStrOffset = Context->FormatStrAddress - Context->ModuleBaseAddress; + } + else { - Context->DescriptorAddress += Context->ModuleBaseAddress; - Context->FormatStrAddress += Context->ModuleBaseAddress; + Context->DescriptorOffset = Context->DescriptorArg; + Context->DescriptorAddress = Context->DescriptorOffset + Context->ModuleBaseAddress; + + Context->FormatStrOffset = Context->FormatStrArg; + Context->FormatStrAddress = Context->FormatStrOffset + Context->ModuleBaseAddress; } return 0; @@ -679,11 +688,11 @@ int main(int argc, char* argv[]) } else if (!_stricmp(CurrentArgument, "--descriptor")) { - Context.DescriptorOffset = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); + Context.DescriptorArg = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); } else if (!_stricmp(CurrentArgument, "--format-str")) { - Context.FormatStrOffset = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); + Context.FormatStrArg = (size_t) strtoumax(argv[ArgIndex + 1], &EndPtr, 16); } else if (!_stricmp(CurrentArgument, "--absolute")) { diff --git a/RpcDecompileIt/RpcDecompileIt.h b/RpcDecompileIt/RpcDecompileIt.h index 014b646..5a288d6 100644 --- a/RpcDecompileIt/RpcDecompileIt.h +++ b/RpcDecompileIt/RpcDecompileIt.h @@ -13,7 +13,8 @@ #include "..\RpcCommon\RpcView.h" #include "..\RpcDecompiler\RpcDecompiler.h" - +#pragma warning ( push ) +#pragma warning ( disable: 4201 ) typedef struct _DECOMPILE_IT_CTXT { DWORD TargetPID; @@ -23,12 +24,29 @@ typedef struct _DECOMPILE_IT_CTXT { uintptr_t ModuleBaseAddress; bool bAbsoluteAddress; - size_t DescriptorOffset; - uintptr_t DescriptorAddress; - size_t FormatStrOffset; - uintptr_t FormatStrAddress; + + union + { + uintptr_t DescriptorArg; + + struct { + size_t DescriptorOffset; + uintptr_t DescriptorAddress; + }; + }; + + union + { + uintptr_t FormatStrArg; + + struct { + size_t FormatStrOffset; + uintptr_t FormatStrAddress; + }; + }; } DECOMPILE_IT_CTXT, *PDECOMPILE_IT_CTXT; +#pragma warning ( pop ) #pragma region RpcInternalsCommon From a2c1b29efcd5231eec8751e16278345cbc39d0ed Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 17:20:38 +0100 Subject: [PATCH 06/11] Clean up dead code --- RpcDecompileIt/CMakeLists.txt | 6 +- RpcDecompileIt/RpcDecompileIt.cpp | 434 +---------------------------- RpcDecompileIt/RpcDecompileIt.h | 439 +++++++++++++++--------------- 3 files changed, 227 insertions(+), 652 deletions(-) diff --git a/RpcDecompileIt/CMakeLists.txt b/RpcDecompileIt/CMakeLists.txt index 870a958..9eac4c7 100644 --- a/RpcDecompileIt/CMakeLists.txt +++ b/RpcDecompileIt/CMakeLists.txt @@ -5,8 +5,7 @@ message("[RpcDecompileIt]") add_executable(RpcDecompileIt RpcDecompileIt.cpp DecompileItRpcStub.cpp - ../RpcCommon/Misc.c - ../RpcView/Pdb.c + RpcDecompileIt.h ) @@ -17,3 +16,6 @@ target_link_libraries(RpcDecompileIt Dbghelp.lib ) +target_include_directories(RpcDecompileIt PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/../" +) \ No newline at end of file diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index adddb6b..2ec97db 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -2,7 +2,8 @@ #include #include -#include "../RpcDecompiler/IdlInterface.h" + +#include "RpcDecompiler/IdlInterface.h" #if _WIN64 #define RPC_CORE_IS_WOW64 false @@ -10,410 +11,6 @@ #define RPC_CORE_IS_WOW64 true #endif -#pragma region TO_DELETE - -#include "..\RpcCommon\Misc.h" -#include "..\RpcView\Pdb.h" - - -#if (RPC_CORE_IS_WOW64==TRUE) -#define REG_PREFIX L"Wow6432Node\\" -#else -#define REG_PREFIX L"" -#endif - -//BOOL WINAPI GetRegValueData(HKEY hRootKey, WCHAR* pSubkeyName, WCHAR* pValueName, VOID* pData, UINT DataLength) -//{ -// DWORD Size; -// HKEY hKey = NULL; -// BOOL bResult = FALSE; -// -// if (RegOpenKeyExW(hRootKey, pSubkeyName, 0, KEY_READ, &hKey) != ERROR_SUCCESS) goto End; -// Size = DataLength; -// if (RegQueryValueExW(hKey, pValueName, NULL, NULL, (LPBYTE)pData, &Size) != ERROR_SUCCESS) goto End; -// bResult = TRUE; -//End: -// if (hKey != NULL) RegCloseKey(hKey); -// return (bResult); -//} - -//------------------------------------------------------------------------------ -BOOL NTAPI GetComInterfaceName(const RPC_IF_ID* pInterfaceId, WCHAR* pName, UINT NameLength) -{ - WCHAR SubKeyName[MAX_PATH]; - RPC_WSTR pUuidString = NULL; - BOOL bResult = FALSE; - - if (UuidToStringW(&pInterfaceId->Uuid, &pUuidString) != RPC_S_OK) goto End; - swprintf_s(SubKeyName, sizeof(SubKeyName), REG_PREFIX L"Interface\\{%ws}", (wchar_t*) pUuidString); - if (GetRegValueData(HKEY_CLASSES_ROOT, SubKeyName, NULL, pName, NameLength) == FALSE) goto End; - - bResult = TRUE; -End: - if (pUuidString != NULL) RpcStringFreeW(&pUuidString); - return (bResult); -} - -IfType_T WINAPI GetInterfaceType(const RPC_INTERFACE_T* pRpcInterface) -{ - WCHAR TmpPath[MAX_PATH]; - - if (pRpcInterface->Flags & RPC_IF_OLE) - { - return (IfType_OLE); - } - - if (GetComInterfaceName(&pRpcInterface->RpcServerInterface.InterfaceId, TmpPath, sizeof(TmpPath)) == FALSE) - { - return (IfType_RPC); - } - return (IfType_DCOM); -} - -BOOL __fastcall GetInterfaceName(RPC_IF_ID* pInterfaceId, WCHAR* pName, UINT NameLength) -{ - //WCHAR FullPath[MAX_PATH]; - RPC_WSTR pUuidString = NULL; - BOOL bResult = FALSE; - - if (pInterfaceId == NULL) goto End; - - pName[0] = 0; - bResult = GetComInterfaceName(pInterfaceId, pName, NameLength); - /*if (bResult == FALSE) - { - UuidToStringW(&pInterfaceId->Uuid, &pUuidString); - GetFullPathNameW(gInterfaceFile, _countof(FullPath), FullPath, NULL); - GetPrivateProfileStringW((LPCWSTR)pUuidString, L"Name", NULL, pName, NameLength / sizeof(WCHAR), FullPath); - }*/ -End: - if (pUuidString != NULL) RpcStringFreeW(&pUuidString); - return (bResult); -} - -void NTAPI InitDecompilerInfo(_In_ RpcInterfaceInfo_T* pRpcInterfaceInfo, _Out_ RpcDecompilerInfo_T* pRpcDecompilerInfo) -{ - UINT i; - UINT SymboleLength; - HANDLE hProcess = NULL; - void* hPdb = NULL; - WCHAR SymboleName[RPC_MAX_LENGTH]; - - if (pRpcDecompilerInfo == NULL) goto End; - if (pRpcInterfaceInfo == NULL) goto End; - - pRpcDecompilerInfo->pModuleBase = (UINT64)pRpcInterfaceInfo->pLocationBase; - pRpcDecompilerInfo->pIfId = &pRpcInterfaceInfo->If; - pRpcDecompilerInfo->Pid = pRpcInterfaceInfo->Pid; - swprintf_s(pRpcDecompilerInfo->InterfaceName, sizeof(pRpcDecompilerInfo->InterfaceName), L"%ws", pRpcInterfaceInfo->Name); - pRpcDecompilerInfo->pSyntaxId = &pRpcInterfaceInfo->TransfertSyntax; - - pRpcDecompilerInfo->MIDLVersion = pRpcInterfaceInfo->NdrInfo.MIDLVersion; - pRpcDecompilerInfo->NDRFags = (UINT) pRpcInterfaceInfo->NdrInfo.mFlags; - pRpcDecompilerInfo->NDRVersion = pRpcInterfaceInfo->NdrInfo.Version; - - pRpcDecompilerInfo->NumberOfProcedures = pRpcInterfaceInfo->NumberOfProcedures; - pRpcDecompilerInfo->ppProcAddressTable = pRpcInterfaceInfo->ppProcAddressTable; - pRpcDecompilerInfo->pTypeFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pTypeFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); - - pRpcDecompilerInfo->pFormatStringOffsetTable = pRpcInterfaceInfo->pFormatStringOffsetTable; - pRpcDecompilerInfo->pProcFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pProcFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); - - pRpcDecompilerInfo->apfnExprEval = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->apfnExprEval - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); - pRpcDecompilerInfo->bIsInlined = FALSE; - - pRpcDecompilerInfo->pExprOffset = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprOffset - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); - pRpcDecompilerInfo->pExprFormatString = (RVA_T)((ULONG_PTR)pRpcInterfaceInfo->pExprFormatString - (ULONG_PTR)pRpcInterfaceInfo->pLocationBase); - // - // Cannot decompile if we cannot get the ppProcAddressTable value!!! - // - if (pRpcDecompilerInfo->ppProcAddressTable == NULL) - { - printf("*** No procedure: %u\n", pRpcDecompilerInfo->NumberOfProcedures); - // ExitProcess(0); - // goto End; - } - - pRpcDecompilerInfo->ppProcNameTable = (WCHAR**)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(UCHAR*)); - if (pRpcDecompilerInfo->ppProcNameTable == NULL) goto End; - - hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pRpcInterfaceInfo->Pid); - if (hProcess == NULL) goto End; -#ifdef _WIN64 - pRpcDecompilerInfo->bIs64Bits = !pRpcInterfaceInfo->bWow64Process; -#else - pRpcDecompilerInfo->bIs64Bits = FALSE; -#endif - // - // Creates and initialiaze the pbFunctionInterpreted bool table - // TODO : should be really initialized - // - pRpcDecompilerInfo->pbFunctionInterpreted = (BOOL*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(BOOL)); - if (pRpcDecompilerInfo->pbFunctionInterpreted == NULL) goto End; - // - // Creates and initialiaze the ppProcFormatInlined RVA_T table - // TODO : should be really initialized - // - pRpcDecompilerInfo->ppProcFormatInlined = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(RVA_T)); - if (pRpcDecompilerInfo->ppProcFormatInlined == NULL) goto End; - // - // Creates and initialiaze the ppDispatchProcAddressTable RVA_T table - // TODO : should be really initialized - // - pRpcDecompilerInfo->ppDispatchProcAddressTable = (RVA_T*)OS_ALLOC(pRpcDecompilerInfo->NumberOfProcedures * sizeof(RVA_T)); - if (pRpcDecompilerInfo->ppDispatchProcAddressTable == NULL) goto End; - - hPdb = PdbInit(hProcess, pRpcInterfaceInfo->pLocationBase, (UINT) pRpcInterfaceInfo->LocationSize); - if (hPdb == NULL) goto End; - for (i = 0; iNumberOfProcedures; i++) - { - SymboleName[0] = 0; - if (PdbGetSymbolName(hPdb, (UCHAR*)pRpcInterfaceInfo->pLocationBase + pRpcDecompilerInfo->ppProcAddressTable[i], SymboleName, sizeof(SymboleName))) - { - SymboleLength = ((UINT)wcslen(SymboleName) + 1) * sizeof(WCHAR); - pRpcDecompilerInfo->ppProcNameTable[i] = (WCHAR*)OS_ALLOC(SymboleLength); - memcpy(pRpcDecompilerInfo->ppProcNameTable[i], SymboleName, SymboleLength); - } - } - PdbUninit(hPdb); -End: - if (hProcess != NULL) CloseHandle(hProcess); - return; -} -#pragma endregion TO_DELETE - -// copied from ../RpcCore/RpcCore.c -RpcInterfaceInfo_T* WINAPI InternalGetInterfaceInfo(PVOID Context, HANDLE hProcess, VOID* pRpcInterface, DWORD Pid, ULONG InterfaceInfoMask) -{ - MIDL_SERVER_INFO_T MidlServerInfo; - MIDL_STUB_DESC_T MidlStubDesc; - RPC_DISPATCH_TABLE_T RpcDispatchTbl; - RPC_INTERFACE_T RpcInterface; - MODULEENTRY32W ModuleEntry; - UINT i; - NDR_EXPR_DESC_T NdrExprDesc; - VOID PTR_T pProc = NULL; - WCHAR* pModuleName = NULL; - HANDLE hModulesSnapshot = NULL; - RpcInterfaceInfo_T* pRpcInterfaceInfo = NULL; - LocationInfo_T LocationInfo = {0}; - - UNREFERENCED_PARAMETER(Context); - // - // Get the RPC_INTERFACE - // - if (!ReadProcessMemory(hProcess, pRpcInterface, &RpcInterface, sizeof(RpcInterface), NULL)) - { - //printf("ReadProcessMemory failed RpcInterface\n"); - goto End; - } - - pRpcInterfaceInfo=(RpcInterfaceInfo_T*)OS_ALLOC(sizeof(RpcInterfaceInfo_T)); - if (pRpcInterfaceInfo == NULL) { DEBUG_BREAK(); goto End; } - // - // Get Default interface information - // - Pid - // - Flags - // - Type - // - UUID - // - Transfert Syntax GUID - // - Name - // -#ifdef _WIN64 - pRpcInterfaceInfo->bWow64Process = (sizeof(PVOID) != sizeof(uint64_t)) /*RPC_CORE_IS_WOW64*/; -#endif - pRpcInterfaceInfo->Pid = Pid; - pRpcInterfaceInfo->Flags = RpcInterface.Flags; - pRpcInterfaceInfo->IfType = GetInterfaceType(&RpcInterface); - // - memcpy(&pRpcInterfaceInfo->If,&RpcInterface.RpcServerInterface.InterfaceId,sizeof(pRpcInterfaceInfo->If)); - memcpy(&pRpcInterfaceInfo->TransfertSyntax,&RpcInterface.RpcServerInterface.TransferSyntax,sizeof(pRpcInterfaceInfo->TransfertSyntax)); - // - GetInterfaceName(&RpcInterface.RpcServerInterface.InterfaceId,pRpcInterfaceInfo->Name,sizeof(pRpcInterfaceInfo->Name)); - - //!!!!!!to change!!!!!! - if (InterfaceInfoMask == 0) goto End; - - switch(pRpcInterfaceInfo->IfType) - { - case IfType_DCOM: - case IfType_OLE: - goto End; //NO DCOM now!! - break; - // - case IfType_RPC: - { - if (GetLocationInfo(hProcess, (void*)RpcInterface.RpcServerInterface.DispatchTable, &LocationInfo)) - { - memcpy(pRpcInterfaceInfo->Location, LocationInfo.Location, sizeof(pRpcInterfaceInfo->Location)); - } - pRpcInterfaceInfo->pLocationBase = LocationInfo.pBaseAddress; - pRpcInterfaceInfo->LocationState = LocationInfo.State; - pRpcInterfaceInfo->LocationType = LocationInfo.Type; - pRpcInterfaceInfo->LocationSize = LocationInfo.Size; - } - break; - // - default: - break; - } - // - // If we have a module path then we can get its real base and size - // - if (LocationInfo.Location[0] != 0) - { - pModuleName = wcsrchr(pRpcInterfaceInfo->Location, '\\'); - if (pModuleName == NULL) pModuleName = pRpcInterfaceInfo->Location; - else pModuleName++; - // - // Get module base and size - // - hModulesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, Pid); - if (hModulesSnapshot != INVALID_HANDLE_VALUE) - { - ModuleEntry.dwSize = sizeof(ModuleEntry); - if (Module32FirstW(hModulesSnapshot, &ModuleEntry)) - do - { - if (_wcsicmp(pModuleName, ModuleEntry.szModule) == 0) - { - pRpcInterfaceInfo->pLocationBase = ModuleEntry.modBaseAddr; - pRpcInterfaceInfo->LocationSize = ModuleEntry.modBaseSize; - break; - } - } while (Module32NextW(hModulesSnapshot, &ModuleEntry)); - CloseHandle(hModulesSnapshot); - } - else - { - ULONG_PTR Base = 0; - WORD Magic = 0; - IMAGE_DOS_HEADER ImageDosHeader; - IMAGE_NT_HEADERS ImageNtHeaders; - // - // Last chance approach - // - Base = ((ULONG_PTR)pRpcInterfaceInfo->pLocationBase) & (~0xFFFF); - while (Magic != IMAGE_DOS_SIGNATURE) - { - ReadProcessMemory(hProcess, (PVOID)Base, &Magic, sizeof(Magic), NULL); - Base -= 0x1000; - } - pRpcInterfaceInfo->pLocationBase = (PVOID)(Base + 0x1000); - ReadProcessMemory(hProcess, pRpcInterfaceInfo->pLocationBase, &ImageDosHeader, sizeof(ImageDosHeader), NULL); - ReadProcessMemory(hProcess, (PVOID)((ULONG_PTR)pRpcInterfaceInfo->pLocationBase + ImageDosHeader.e_lfanew), &ImageNtHeaders, sizeof(ImageNtHeaders), NULL); - } - } - // - // Get module display name - // - GetModuleDescription(pRpcInterfaceInfo->Location,pRpcInterfaceInfo->Description,sizeof(pRpcInterfaceInfo->Description)); - // - // Get the interface procedures count ony for RPC interfaces - // - if (pRpcInterfaceInfo->IfType == IfType_RPC) - { - if (ReadProcessMemory(hProcess,RpcInterface.RpcServerInterface.DispatchTable,&RpcDispatchTbl,sizeof(RpcDispatchTbl),NULL)) - { - pRpcInterfaceInfo->NumberOfProcedures=RpcDispatchTbl.DispatchTableCount; - } - else - { - ZeroMemory(pRpcInterfaceInfo, sizeof(*pRpcInterfaceInfo)); - goto End; - } - } - // - // Interpreted stub - // - if (RpcInterface.RpcServerInterface.InterpreterInfo!=NULL) - { - if (pRpcInterfaceInfo->IfType==IfType_RPC) - { - pRpcInterfaceInfo->TypeOfStub=TypeOfStub_Interpreted; - } - // - // Get NDR info - // - ZeroMemory(&MidlServerInfo,sizeof(MidlServerInfo)); - ZeroMemory(&MidlStubDesc,sizeof(MidlStubDesc)); - if (!ReadProcessMemory(hProcess, RpcInterface.RpcServerInterface.InterpreterInfo, &MidlServerInfo, sizeof(MidlServerInfo), NULL)) - { - goto End; - } - if (!ReadProcessMemory(hProcess, MidlServerInfo.pStubDesc, &MidlStubDesc, sizeof(MidlStubDesc), NULL)) - { - goto End; - } - // - pRpcInterfaceInfo->NdrInfo.Version = MidlStubDesc.Version; - pRpcInterfaceInfo->NdrInfo.MIDLVersion = MidlStubDesc.MIDLVersion; - pRpcInterfaceInfo->NdrInfo.mFlags = MidlStubDesc.mFlags; - pRpcInterfaceInfo->pTypeFormatString = (UCHAR*)MidlStubDesc.pFormatTypes; - pRpcInterfaceInfo->apfnExprEval = (void*)MidlStubDesc.apfnExprEval; - - if (MidlStubDesc.pExprInfo != NULL) - { - if (ReadProcessMemory(hProcess, MidlStubDesc.pExprInfo, &NdrExprDesc, sizeof(NdrExprDesc), NULL)) - { - pRpcInterfaceInfo->pExprOffset = (USHORT*)NdrExprDesc.pOffset; - pRpcInterfaceInfo->pExprFormatString = (UCHAR*)NdrExprDesc.pFormatExpr; - } - else - { - //printf("Unable to read the pExprInfo at address %p in process %u\n", MidlStubDesc.pExprInfo, pRpcInterfaceInfo->Pid); - } - } - - pRpcInterfaceInfo->pProcFormatString = (UCHAR*)MidlServerInfo.ProcString; - // - // Get the interface procedure addresses table - // - pRpcInterfaceInfo->ppProcAddressTable=(ULONG*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(VOID*)); - if (pRpcInterfaceInfo->ppProcAddressTable == NULL) { DEBUG_BREAK(); goto End; } - - for(i=0;iNumberOfProcedures;i++) - { - if (ReadProcessMemory(hProcess,((VOID PTR_T PTR_T)MidlServerInfo.DispatchTable)+i,&pProc,sizeof(VOID PTR_T),NULL)) - { - pRpcInterfaceInfo->ppProcAddressTable[i]= (ULONG) ((ULONG64)pProc - (ULONG64)pRpcInterfaceInfo->pLocationBase); - } - } - // - // Get the interface format string offset table - // - pRpcInterfaceInfo->pFormatStringOffsetTable=(USHORT*)OS_ALLOC(pRpcInterfaceInfo->NumberOfProcedures * sizeof(USHORT)); - if (pRpcInterfaceInfo->pFormatStringOffsetTable!=NULL) - { - ReadProcessMemory(hProcess,MidlServerInfo.FmtStringOffset,pRpcInterfaceInfo->pFormatStringOffsetTable,pRpcInterfaceInfo->NumberOfProcedures*sizeof(USHORT),NULL); - } - } - else - { - //!!!todo!!! - //GetInlineStubInfo(pRpcCoreInternalCtxt,hProcess,pRpcInterface,pRpcInterfaceInfo); - } - // - // Test if DCOM or simple RPC - // - if (pRpcInterfaceInfo->IfType==IfType_RPC) - { - pRpcInterfaceInfo->IfCallbackFn = RpcInterface.IfCallbackFn; - } - - if (RpcInterface.EpMapperFlags & RPC_IS_EPMAPPER_REGISTERED) - { - pRpcInterfaceInfo->bIsRegistered=TRUE; - sprintf_s((char*) pRpcInterfaceInfo->Annotation,sizeof(pRpcInterfaceInfo->Annotation),"%s",(const char*)RpcInterface.Annotation); - } - else - { - pRpcInterfaceInfo->bIsRegistered=FALSE; - } -End: - return (pRpcInterfaceInfo); -} - int DecompileInit( _Inout_ PDECOMPILE_IT_CTXT Context @@ -581,30 +178,6 @@ DecompileIt( return -1; } - - /*RpcDecompilerInfoStub.Pid = Context.TargetPID; - RpcDecompilerInfoStub->pIfId = &RpcInterfaceId; - RpcDecompilerInfoStub->pModuleBase = Context.ModuleBaseAddress; - RpcDecompilerInfoStub->NDRVersion = MidlStubDesc.Version; - RpcDecompilerInfoStub->MIDLVersion = MidlStubDesc.MIDLVersion; - RpcDecompilerInfoStub->NDRFags = (UINT) MidlStubDesc.mFlags;*/ - - //RpcInterfaceInfo = InternalGetInterfaceInfo((PVOID) &Context, Context.hTargetProcess, (VOID*)MidlStubDesc.RpcInterfaceInformation, Context.TargetPID, RPC_INTERFACE_INFO_ALL); - //InitDecompilerInfo(RpcInterfaceInfo, &RpcDecompilerInfoStub); - - //// Init RpcDecompiler and decompile idl - //RpcDecompilerContext = DecompilerHelper->RpcDecompilerInitFn( - // &RpcViewHelperStub, - // &RpcDecompilerInfoStub - //); - //if (!RpcDecompilerContext) - //{ - // return -1; - //} - - //DecompilerHelper->RpcDecompilerPrintAllProceduresFn( - // RpcDecompilerContext - //); std::string IfaceName("DecompileItInterface"); IdlInterface Interface(IfaceName, RpcInterfaceId, 1); @@ -631,9 +204,10 @@ DecompileIt( DecompilerStubContext.pRpcModuleInfo = &ModuleInfoStub; DecompilerStubContext.pRpcViewHelper = &RpcViewHelperStub; + + // Decode function if (DS_SUCCESS == Interface.decode((PVOID)&DecompilerStubContext)) { - //std::ostringstream ossIf; std::cout << Interface; } diff --git a/RpcDecompileIt/RpcDecompileIt.h b/RpcDecompileIt/RpcDecompileIt.h index 5a288d6..dedb1bc 100644 --- a/RpcDecompileIt/RpcDecompileIt.h +++ b/RpcDecompileIt/RpcDecompileIt.h @@ -8,10 +8,9 @@ #include -#include "..\RpcCore\RpcCore.h" -//#include "..\RpcCore\RpcInternalsCommon.h" -#include "..\RpcCommon\RpcView.h" -#include "..\RpcDecompiler\RpcDecompiler.h" +#include "RpcCore\RpcCore.h" +#include "RpcCommon\RpcView.h" +#include "RpcDecompiler\RpcDecompiler.h" #pragma warning ( push ) #pragma warning ( disable: 4201 ) @@ -51,222 +50,222 @@ typedef struct _DECOMPILE_IT_CTXT { #pragma region RpcInternalsCommon -#define MAX_RPC_INTERFACE_ANNOTATION 64 -#define SIMPLE_DICT_SMALL_ARRAY 4 -#define RPC_IS_EPMAPPER_REGISTERED 0x20 - -#define ULONG_PTR_T ULONG_PTR -#define PTR_T * - -typedef struct _LIST_ENTRY_T { - struct _LIST_ENTRY PTR_T Flink; - struct _LIST_ENTRY PTR_T Blink; -} LIST_ENTRY_T, *PLIST_ENTRY_T; - -typedef struct _RTL_CRITICAL_SECTION_DEBUG_T { - WORD Type; - WORD CreatorBackTraceIndex; - struct _RTL_CRITICAL_SECTION_T PTR_T CriticalSection; - LIST_ENTRY_T ProcessLocksList; - DWORD EntryCount; - DWORD ContentionCount; - DWORD Flags; - WORD CreatorBackTraceIndexHigh; - WORD SpareWORD; -} RTL_CRITICAL_SECTION_DEBUG_T, PTR_T PRTL_CRITICAL_SECTION_DEBUG_T; - -typedef struct _RTL_CRITICAL_SECTION_T { - PRTL_CRITICAL_SECTION_DEBUG_T DebugInfo; - // - // The following three fields control entering and exiting the critical - // section for the resource - // - LONG LockCount; - LONG RecursionCount; - VOID PTR_T OwningThread; // from the thread's ClientId->UniqueThread - VOID PTR_T LockSemaphore; - VOID PTR_T SpinCount; // force size on 64-bit systems when packed -} RTL_CRITICAL_SECTION_T, PTR_T PRTL_CRITICAL_SECTION_T; - -typedef struct _MUTEX_T { - RTL_CRITICAL_SECTION_T CriticalSection; -}MUTEX_T; - -typedef struct _EVENT_T { - ULONG hEvent; -} EVENT_T; - -typedef struct _SIMPLE_DICT_T { - VOID PTR_T PTR_T pArray; - UINT ArraySizeInBytes; //to change : countof array elements - UINT NumberOfEntries; - VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; -}SIMPLE_DICT_T, PTR_T PSIMPLE_DICT_T; - -typedef struct _QUEUE_T { - VOID PTR_T Tail; - VOID PTR_T Head; - ULONG Lentgh; - VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; -}QUEUE_T; - -typedef struct _NDR_EXPR_DESC_T -{ - const unsigned short PTR_T pOffset; - const unsigned char PTR_T pFormatExpr; -} NDR_EXPR_DESC_T; - -/* -* -* MIDL Stub Descriptor -*/ -typedef struct _MIDL_STUB_DESC_T { - void PTR_T RpcInterfaceInformation; - void PTR_T pfnAllocate; - void PTR_T pfnFree; - void PTR_T pAutoHandle; - const VOID PTR_T apfnNdrRundownRoutines; - const VOID PTR_T aGenericBindingRoutinePairs; - const VOID PTR_T apfnExprEval; - const VOID PTR_T aXmitQuintuple; - const unsigned char PTR_T pFormatTypes; - int fCheckBounds; - /* Ndr library version. */ - unsigned long Version; - VOID PTR_T pMallocFreeStruct; - long MIDLVersion; - const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; - // New fields for version 3.0+ - const VOID PTR_T aUserMarshalQuadruple; - // Notify routines - added for NT5, MIDL 5.0 - const VOID PTR_T NotifyRoutineTable; - /* - * Reserved for future use. - */ - ULONG_PTR_T mFlags; - // International support routines - added for 64bit post NT5 - const VOID PTR_T CsRoutineTables; - void PTR_T ProxyServerInfo; - const NDR_EXPR_DESC_T PTR_T pExprInfo; - // Fields up to now present in win2000 release. -} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; - -/* -* Server Interpreter's information strucuture. -*/ -typedef struct _MIDL_SERVER_INFO_T { - PMIDL_STUB_DESC_T pStubDesc; - const VOID PTR_T PTR_T DispatchTable; - const unsigned char PTR_T ProcString; - const unsigned short PTR_T FmtStringOffset; - const VOID PTR_T PTR_T ThunkTable; - RPC_IF_ID PTR_T pTransferSyntax; - ULONG_PTR_T nCount; - VOID PTR_T pSyntaxInfo; -} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; - -typedef struct _RPC_DISPATCH_TABLE_T { - UINT DispatchTableCount; - RPC_DISPATCH_FUNCTION PTR_T DispatchTable; - ULONG_PTR_T Reserved; -} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; - -//typedef struct _LocationInfo_T { -// WCHAR Location[MAX_PATH]; -// VOID* pBaseAddress; -// DWORD State; -// DWORD Type; -// SIZE_T Size; -//}LocationInfo_T; - -typedef struct _RPC_PROTSEQ_ENDPOINT_T { - UCHAR PTR_T RpcProtocolSequence; - UCHAR PTR_T Endpoint; -} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; - -typedef struct _RPC_SERVER_INTERFACE_T { - UINT Length; - RPC_IF_ID InterfaceId; - RPC_IF_ID TransferSyntax; - PRPC_DISPATCH_TABLE_T DispatchTable; - UINT RpcProtseqEndpointCount; - PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; - RPC_MGR_EPV PTR_T DefaultManagerEpv; - void const PTR_T InterpreterInfo; - UINT Flags; -} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; - -#pragma pack(1) -typedef struct _RPC_SERVER_T { - MUTEX_T Mutex; - ULONG __bIslistening; - ULONG bIsListening; - ULONG MinimumCallThreads; - ULONG Wait; - ULONG OutCalls; - ULONG Unk1; - ULONG InCalls; - ULONG Unk2; - SIMPLE_DICT_T AddressDict; - ULONG lAvailableCalls; - ULONG Unk3; - SIMPLE_DICT_T _ProtSeqQueue; - ULONG Unk4[8]; - ULONG OutPackets; - ULONG Unk5; - MUTEX_T Mutex2; - ULONG MaxCalls; - ULONG Unk6; - VOID PTR_T hEvent; - ULONG Unk7[4]; - SIMPLE_DICT_T InterfaceDict; - ULONG _bIsListening; - ULONG bIsMaxCalls1234; - ULONG Unk8[6]; - ULONG InPackets; - ULONG Unk9; - RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; - ULONG Unk10[6]; - SIMPLE_DICT_T AuthenInfoDict; - LIST_ENTRY_T RpcIfGroupListEntry; - ULONG PTR_T __SRWLock; - LIST_ENTRY_T field_1E0; -}RPC_SERVER_T, PTR_T PRPC_SERVER_T; - -typedef struct _RPC_INTERFACE_T -{ - PRPC_SERVER_T pRpcServer; - ULONG Flags; - ULONG Unk1; - MUTEX_T Mutex; - ULONG EpMapperFlags; - ULONG Unk2; - RPC_MGR_EPV PTR_T pMgrEpv; - RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; - RPC_SERVER_INTERFACE_T RpcServerInterface; - PMIDL_SYNTAX_INFO pSyntaxInfo; - VOID PTR_T pTransfertSyntaxes; - ULONG TransfertSyntaxesCount; - ULONG __Field_C4; - ULONG NbTypeManager; - ULONG MaxRpcSize; - UUID_VECTOR PTR_T pUuidVector; - SIMPLE_DICT_T RpcInterfaceManagerDict; - UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; - ULONG IsCallSizeLimitReached; - ULONG currentNullManagerCalls; - ULONG __Field_150; - ULONG __Field_154; - ULONG __Field_158; - ULONG SecurityCallbackInProgress; - ULONG SecurityCacheEntry; - ULONG field_164; - VOID PTR_T __SecurityCacheEntries[16]; - SIMPLE_DICT_T FwEpDict; - ULONG Unk3[6]; - struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; -}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; -#pragma pack() +//#define MAX_RPC_INTERFACE_ANNOTATION 64 +//#define SIMPLE_DICT_SMALL_ARRAY 4 +//#define RPC_IS_EPMAPPER_REGISTERED 0x20 +// +//#define ULONG_PTR_T ULONG_PTR +//#define PTR_T * +// +//typedef struct _LIST_ENTRY_T { +// struct _LIST_ENTRY PTR_T Flink; +// struct _LIST_ENTRY PTR_T Blink; +//} LIST_ENTRY_T, *PLIST_ENTRY_T; +// +//typedef struct _RTL_CRITICAL_SECTION_DEBUG_T { +// WORD Type; +// WORD CreatorBackTraceIndex; +// struct _RTL_CRITICAL_SECTION_T PTR_T CriticalSection; +// LIST_ENTRY_T ProcessLocksList; +// DWORD EntryCount; +// DWORD ContentionCount; +// DWORD Flags; +// WORD CreatorBackTraceIndexHigh; +// WORD SpareWORD; +//} RTL_CRITICAL_SECTION_DEBUG_T, PTR_T PRTL_CRITICAL_SECTION_DEBUG_T; +// +//typedef struct _RTL_CRITICAL_SECTION_T { +// PRTL_CRITICAL_SECTION_DEBUG_T DebugInfo; +// // +// // The following three fields control entering and exiting the critical +// // section for the resource +// // +// LONG LockCount; +// LONG RecursionCount; +// VOID PTR_T OwningThread; // from the thread's ClientId->UniqueThread +// VOID PTR_T LockSemaphore; +// VOID PTR_T SpinCount; // force size on 64-bit systems when packed +//} RTL_CRITICAL_SECTION_T, PTR_T PRTL_CRITICAL_SECTION_T; +// +//typedef struct _MUTEX_T { +// RTL_CRITICAL_SECTION_T CriticalSection; +//}MUTEX_T; +// +//typedef struct _EVENT_T { +// ULONG hEvent; +//} EVENT_T; +// +//typedef struct _SIMPLE_DICT_T { +// VOID PTR_T PTR_T pArray; +// UINT ArraySizeInBytes; //to change : countof array elements +// UINT NumberOfEntries; +// VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +//}SIMPLE_DICT_T, PTR_T PSIMPLE_DICT_T; +// +//typedef struct _QUEUE_T { +// VOID PTR_T Tail; +// VOID PTR_T Head; +// ULONG Lentgh; +// VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; +//}QUEUE_T; +// +//typedef struct _NDR_EXPR_DESC_T +//{ +// const unsigned short PTR_T pOffset; +// const unsigned char PTR_T pFormatExpr; +//} NDR_EXPR_DESC_T; +// +///* +//* +//* MIDL Stub Descriptor +//*/ +//typedef struct _MIDL_STUB_DESC_T { +// void PTR_T RpcInterfaceInformation; +// void PTR_T pfnAllocate; +// void PTR_T pfnFree; +// void PTR_T pAutoHandle; +// const VOID PTR_T apfnNdrRundownRoutines; +// const VOID PTR_T aGenericBindingRoutinePairs; +// const VOID PTR_T apfnExprEval; +// const VOID PTR_T aXmitQuintuple; +// const unsigned char PTR_T pFormatTypes; +// int fCheckBounds; +// /* Ndr library version. */ +// unsigned long Version; +// VOID PTR_T pMallocFreeStruct; +// long MIDLVersion; +// const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; +// // New fields for version 3.0+ +// const VOID PTR_T aUserMarshalQuadruple; +// // Notify routines - added for NT5, MIDL 5.0 +// const VOID PTR_T NotifyRoutineTable; +// /* +// * Reserved for future use. +// */ +// ULONG_PTR_T mFlags; +// // International support routines - added for 64bit post NT5 +// const VOID PTR_T CsRoutineTables; +// void PTR_T ProxyServerInfo; +// const NDR_EXPR_DESC_T PTR_T pExprInfo; +// // Fields up to now present in win2000 release. +//} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; +// +///* +//* Server Interpreter's information strucuture. +//*/ +//typedef struct _MIDL_SERVER_INFO_T { +// PMIDL_STUB_DESC_T pStubDesc; +// const VOID PTR_T PTR_T DispatchTable; +// const unsigned char PTR_T ProcString; +// const unsigned short PTR_T FmtStringOffset; +// const VOID PTR_T PTR_T ThunkTable; +// RPC_IF_ID PTR_T pTransferSyntax; +// ULONG_PTR_T nCount; +// VOID PTR_T pSyntaxInfo; +//} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; +// +//typedef struct _RPC_DISPATCH_TABLE_T { +// UINT DispatchTableCount; +// RPC_DISPATCH_FUNCTION PTR_T DispatchTable; +// ULONG_PTR_T Reserved; +//} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; +// +////typedef struct _LocationInfo_T { +//// WCHAR Location[MAX_PATH]; +//// VOID* pBaseAddress; +//// DWORD State; +//// DWORD Type; +//// SIZE_T Size; +////}LocationInfo_T; +// +//typedef struct _RPC_PROTSEQ_ENDPOINT_T { +// UCHAR PTR_T RpcProtocolSequence; +// UCHAR PTR_T Endpoint; +//} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; +// +//typedef struct _RPC_SERVER_INTERFACE_T { +// UINT Length; +// RPC_IF_ID InterfaceId; +// RPC_IF_ID TransferSyntax; +// PRPC_DISPATCH_TABLE_T DispatchTable; +// UINT RpcProtseqEndpointCount; +// PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; +// RPC_MGR_EPV PTR_T DefaultManagerEpv; +// void const PTR_T InterpreterInfo; +// UINT Flags; +//} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; +// +//#pragma pack(1) +//typedef struct _RPC_SERVER_T { +// MUTEX_T Mutex; +// ULONG __bIslistening; +// ULONG bIsListening; +// ULONG MinimumCallThreads; +// ULONG Wait; +// ULONG OutCalls; +// ULONG Unk1; +// ULONG InCalls; +// ULONG Unk2; +// SIMPLE_DICT_T AddressDict; +// ULONG lAvailableCalls; +// ULONG Unk3; +// SIMPLE_DICT_T _ProtSeqQueue; +// ULONG Unk4[8]; +// ULONG OutPackets; +// ULONG Unk5; +// MUTEX_T Mutex2; +// ULONG MaxCalls; +// ULONG Unk6; +// VOID PTR_T hEvent; +// ULONG Unk7[4]; +// SIMPLE_DICT_T InterfaceDict; +// ULONG _bIsListening; +// ULONG bIsMaxCalls1234; +// ULONG Unk8[6]; +// ULONG InPackets; +// ULONG Unk9; +// RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; +// ULONG Unk10[6]; +// SIMPLE_DICT_T AuthenInfoDict; +// LIST_ENTRY_T RpcIfGroupListEntry; +// ULONG PTR_T __SRWLock; +// LIST_ENTRY_T field_1E0; +//}RPC_SERVER_T, PTR_T PRPC_SERVER_T; +// +//typedef struct _RPC_INTERFACE_T +//{ +// PRPC_SERVER_T pRpcServer; +// ULONG Flags; +// ULONG Unk1; +// MUTEX_T Mutex; +// ULONG EpMapperFlags; +// ULONG Unk2; +// RPC_MGR_EPV PTR_T pMgrEpv; +// RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; +// RPC_SERVER_INTERFACE_T RpcServerInterface; +// PMIDL_SYNTAX_INFO pSyntaxInfo; +// VOID PTR_T pTransfertSyntaxes; +// ULONG TransfertSyntaxesCount; +// ULONG __Field_C4; +// ULONG NbTypeManager; +// ULONG MaxRpcSize; +// UUID_VECTOR PTR_T pUuidVector; +// SIMPLE_DICT_T RpcInterfaceManagerDict; +// UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; +// ULONG IsCallSizeLimitReached; +// ULONG currentNullManagerCalls; +// ULONG __Field_150; +// ULONG __Field_154; +// ULONG __Field_158; +// ULONG SecurityCallbackInProgress; +// ULONG SecurityCacheEntry; +// ULONG field_164; +// VOID PTR_T __SecurityCacheEntries[16]; +// SIMPLE_DICT_T FwEpDict; +// ULONG Unk3[6]; +// struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; +//}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; +//#pragma pack() #pragma endregion RpcInternalsCommon From 66a16885d2fb9e7f237d916f958508353274f6e7 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 11 Mar 2018 22:33:26 +0100 Subject: [PATCH 07/11] Add support for decompiling several functions within the same interface --- RpcDecompileIt/RpcDecompileIt.cpp | 62 ++++++++++++++++++++++++++++--- RpcDecompileIt/RpcDecompileIt.h | 4 ++ 2 files changed, 60 insertions(+), 6 deletions(-) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index 2ec97db..a06182d 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -1,5 +1,6 @@ #include "RpcDecompileIt.h" +#include #include #include @@ -180,16 +181,20 @@ DecompileIt( std::string IfaceName("DecompileItInterface"); - IdlInterface Interface(IfaceName, RpcInterfaceId, 1); + IdlInterface Interface(IfaceName, RpcInterfaceId, Context.NumberOfProcedures); // Init stubs for RpcDecompiler RpcDecompilerInfo_T RpcDecompilerInfoStub; - RpcDecompilerInfoStub.ppProcNameTable = new WCHAR*[1]; - RpcDecompilerInfoStub.ppProcNameTable[0] = NULL; + RpcDecompilerInfoStub.ppProcNameTable = new WCHAR*[Context.NumberOfProcedures]; + for (size_t i = 0; i < Context.NumberOfProcedures; i++) + { + RpcDecompilerInfoStub.ppProcNameTable[i] = NULL; + } + - RpcDecompilerInfoStub.pFormatStringOffsetTable = new USHORT[1]; - RpcDecompilerInfoStub.pFormatStringOffsetTable[0] = 0; + RpcDecompilerInfoStub.pFormatStringOffsetTable = Context.FormatStrOffsets; + //RpcDecompilerInfoStub.pFormatStringOffsetTable[0] = 0; RpcDecompilerInfoStub.pProcFormatString = (RVA_T) Context.FormatStrOffset; RpcDecompilerInfoStub.pTypeFormatString = (RVA_T) (MidlStubDesc.pFormatTypes - Context.ModuleBaseAddress); @@ -237,17 +242,19 @@ int main(int argc, char* argv[]) if (argc < 7) { - printf("Usage: %s --pid PID [--module MODULE] --descriptor DESC_OFFSET --format-str FORMAT_STRING_OFFSET [--absolute]\n", argv[0]); + printf("Usage: %s --pid PID [--module MODULE] --descriptor DESC_OFFSET --format-str FORMAT_STRING_OFFSET [--absolute] [--format-str-offsets OFF1,OFF2,OFFn]\n", argv[0]); printf(" --pid : PID of the target process. %s must be able to open a handle to read the target process memory.\n", argv[0]); printf(" --module : module name to read memory from. If not set, %s read the target executable own module. Ignored if --absolute is set.\n", argv[0]); printf(" --descriptor : offset to the rpc header descriptor for the interface. If --absolute is set, --descriptor is interpreted as a virtual address.\n"); printf(" --format-str : offset to the rpc format string for the chosen proc. If --absolute is set, --format-str is interpreted as a virtual address.\n"); printf(" --absolute : treat descriptor and format-str as absolute virtual addresses instead of offsets.\n"); + printf(" --format-str-offsets : offsets within the format string for the various procedures (default:0).\n"); return 0; } + bool bFormatStrOffsetsProvided = false; for (auto ArgIndex = 0; ArgIndex < argc; ArgIndex++) { char *CurrentArgument = argv[ArgIndex]; @@ -272,6 +279,49 @@ int main(int argc, char* argv[]) { Context.bAbsoluteAddress = true; } + else if (!_stricmp(CurrentArgument, "--format-str-offsets")) + { + char *token = NULL, *previous_token = NULL; + size_t OffsetCount = 0; + bFormatStrOffsetsProvided = true; + + // counting offsets + token = argv[ArgIndex + 1]; + do { + OffsetCount++; + previous_token = token + 1; + token = strchr(previous_token, ','); + } while (token); + + Context.NumberOfProcedures = OffsetCount; + Context.FormatStrOffsets = new uint16_t[OffsetCount]; + + + // registering offsets + OffsetCount = 0; + token = argv[ArgIndex + 1]; + //token = strchr(previous_token, ','); + do { + Context.FormatStrOffsets[OffsetCount] = (uint16_t)strtoumax(token, &EndPtr, 16); + + OffsetCount++; + previous_token = token; + token = strchr(previous_token, ','); + if (token) + { + token += strlen(","); + } + + } while (token); + + } + } + + if (!bFormatStrOffsetsProvided) + { + Context.NumberOfProcedures = 1; + Context.FormatStrOffsets = new uint16_t[1]; + Context.FormatStrOffsets[0] = 0; } diff --git a/RpcDecompileIt/RpcDecompileIt.h b/RpcDecompileIt/RpcDecompileIt.h index dedb1bc..4c08a7e 100644 --- a/RpcDecompileIt/RpcDecompileIt.h +++ b/RpcDecompileIt/RpcDecompileIt.h @@ -44,6 +44,10 @@ typedef struct _DECOMPILE_IT_CTXT { }; }; + uint16_t *FormatStrOffsets; + + size_t NumberOfProcedures; + } DECOMPILE_IT_CTXT, *PDECOMPILE_IT_CTXT; #pragma warning ( pop ) From 7f7b0af85c62dd87b4f669b2957232bdf06b8f4c Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Tue, 13 Mar 2018 22:45:29 +0100 Subject: [PATCH 08/11] Cleanup code --- RpcDecompileIt/RpcDecompileIt.cpp | 216 ++++++++++++++-------------- RpcDecompileIt/RpcDecompileIt.h | 228 +----------------------------- 2 files changed, 116 insertions(+), 328 deletions(-) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index a06182d..790db00 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -12,7 +12,7 @@ #define RPC_CORE_IS_WOW64 true #endif -int +bool DecompileInit( _Inout_ PDECOMPILE_IT_CTXT Context ) @@ -71,7 +71,7 @@ DecompileInit( if (!Context->ModuleBaseAddress) { - return -1; + return false; } @@ -92,100 +92,119 @@ DecompileInit( Context->FormatStrAddress = Context->FormatStrOffset + Context->ModuleBaseAddress; } - return 0; + return true; } -int -DecompileIt( - _In_ DECOMPILE_IT_CTXT Context +bool +ReadRpcInterface( + _In_ RpcViewHelper_T *RpcViewHelper, + _In_ RpcModuleInfo_T ModuleInfo, + _In_ MIDL_STUB_DESC MidlDescription, + _Out_ RPC_IF_ID *RpcInterface ) { - uintptr_t DecompilerHelperAddr = NULL; - RpcDecompilerHelper_T* DecompilerHelper = NULL; - // - //RpcInterfaceInfo_T* RpcInterfaceInfo = NULL; - //void* RpcDecompilerContext; - MIDL_STUB_DESC MidlStubDesc; - size_t StubDescBytesRead; size_t RpcInterfaceInformationStructSize; RPC_CLIENT_INTERFACE RpcClientInterface; - //RPC_SERVER_INTERFACE RpcServerInterface; - RPC_IF_ID RpcInterfaceId; - ASSIGN_RPC_VIEW_STUB(RpcViewHelperStub, &Context); - - - // resolve RpcDecompilerHelper address - HMODULE hRpcDecompiler = LoadLibrary("RpcDecompiler"); - if (!hRpcDecompiler) - { - return -1; - } - DecompilerHelperAddr = (uintptr_t) GetProcAddress(hRpcDecompiler, "RpcDecompilerHelper"); - if (!DecompilerHelperAddr) - { - return -1; - } - DecompilerHelper = (RpcDecompilerHelper_T*) DecompilerHelperAddr; - if (!ReadProcessMemory( - Context.hTargetProcess, - (LPCVOID)Context.DescriptorAddress, - &MidlStubDesc, - sizeof(MidlStubDesc), - (SIZE_T*) &StubDescBytesRead - )) + if (!RpcInterface || !RpcViewHelper) { - return -1; + return false; } - if (!ReadProcessMemory( - Context.hTargetProcess, - MidlStubDesc.RpcInterfaceInformation, + // Read RPC_CLIENT_INTERFACE.size to know how many bytes we need to read + if (!RpcViewHelper->RpcGetProcessData( + &ModuleInfo, + (RVA_T) ( (uintptr_t) MidlDescription.RpcInterfaceInformation - ModuleInfo.pModuleBase), &RpcInterfaceInformationStructSize, - sizeof(RpcInterfaceInformationStructSize), - (SIZE_T*) &StubDescBytesRead + sizeof(RpcClientInterface.Length) )) { - return -1; + return false; } + switch (RpcInterfaceInformationStructSize) { + // RPC_SERVER_INTERFACE and RPC_CLIENT_INTERFACE are pretty much the same structure + //case sizeof(RPC_SERVER_INTERFACE): case sizeof(RPC_CLIENT_INTERFACE): - if (!ReadProcessMemory( - Context.hTargetProcess, - MidlStubDesc.RpcInterfaceInformation, + // Read the full structure + if (!RpcViewHelper->RpcGetProcessData( + &ModuleInfo, + (RVA_T)((uintptr_t)MidlDescription.RpcInterfaceInformation - ModuleInfo.pModuleBase), &RpcClientInterface, - sizeof(RpcClientInterface), - (SIZE_T*) &StubDescBytesRead + sizeof(RPC_CLIENT_INTERFACE) )) { - return -1; + return false; } - RpcInterfaceId.Uuid = RpcClientInterface.InterfaceId.SyntaxGUID; - RpcInterfaceId.VersMajor = RpcClientInterface.InterfaceId.SyntaxVersion.MajorVersion; - RpcInterfaceId.VersMinor= RpcClientInterface.InterfaceId.SyntaxVersion.MinorVersion; + RpcInterface->Uuid = RpcClientInterface.InterfaceId.SyntaxGUID; + RpcInterface->VersMajor = RpcClientInterface.InterfaceId.SyntaxVersion.MajorVersion; + RpcInterface->VersMinor= RpcClientInterface.InterfaceId.SyntaxVersion.MinorVersion; - //RpcDecompilerInfoStub.pSyntaxId = &RpcClientInterface.InterfaceId; break; - //case sizeof(RPC_SERVER_INTERFACE): default: - return -1; + return false; } + + return true; +} + +bool +DecompileIt( + _In_ DECOMPILE_IT_CTXT Context +) +{ + //uintptr_t DecompilerHelperAddr = NULL; + //RpcDecompilerHelper_T* DecompilerHelper = NULL; + MIDL_STUB_DESC MidlStubDesc; + size_t StubDescBytesRead; + RPC_IF_ID RpcInterfaceId; + RpcDecompilerInfo_T RpcDecompilerInfoStub; + RpcDecompilerCtxt_T DecompilerStubContext; + RpcViewHelper_T RpcViewHelperStub; + RpcModuleInfo_T ModuleInfoStub = { + /*Pid = */ Context.TargetPID, + /*pModuleBase = */ Context.ModuleBaseAddress + }; - std::string IfaceName("DecompileItInterface"); - IdlInterface Interface(IfaceName, RpcInterfaceId, Context.NumberOfProcedures); + + // init RpcView helper stubs in order to use RpcGetProcessData + DecompileItInitRpcViewStub(&RpcViewHelperStub, (PVOID) &Context); + + // Read MIDL_STUB_DESC and RPC_INTERFACE structures from remote target + if (!ReadProcessMemory( + Context.hTargetProcess, + (LPCVOID)Context.DescriptorAddress, + &MidlStubDesc, + sizeof(MidlStubDesc), + (SIZE_T*) &StubDescBytesRead + )) + { + printf("[x] Could not read MIDL_STUB_DESC structure from desc-offset rva.\n"); + return false; + } + + if (!ReadRpcInterface( + &RpcViewHelperStub, + ModuleInfoStub, + MidlStubDesc, + &RpcInterfaceId + )) + { + printf("[x] Could not retrieve a RPC_INTERFACE for the MIDL_STUB_DESC structure.\n"); + return false; + } // Init stubs for RpcDecompiler - RpcDecompilerInfo_T RpcDecompilerInfoStub; RpcDecompilerInfoStub.ppProcNameTable = new WCHAR*[Context.NumberOfProcedures]; for (size_t i = 0; i < Context.NumberOfProcedures; i++) { @@ -194,33 +213,27 @@ DecompileIt( RpcDecompilerInfoStub.pFormatStringOffsetTable = Context.FormatStrOffsets; - //RpcDecompilerInfoStub.pFormatStringOffsetTable[0] = 0; RpcDecompilerInfoStub.pProcFormatString = (RVA_T) Context.FormatStrOffset; - RpcDecompilerInfoStub.pTypeFormatString = (RVA_T) (MidlStubDesc.pFormatTypes - Context.ModuleBaseAddress); - RpcModuleInfo_T ModuleInfoStub = { - /*Pid = */Context.TargetPID, - /*pModuleBase = */Context.ModuleBaseAddress - }; - - RpcDecompilerCtxt_T DecompilerStubContext; DecompilerStubContext.pRpcDecompilerInfo = &RpcDecompilerInfoStub; DecompilerStubContext.pRpcModuleInfo = &ModuleInfoStub; DecompilerStubContext.pRpcViewHelper = &RpcViewHelperStub; // Decode function + std::string IfaceName("DecompileItInterface"); + IdlInterface Interface(IfaceName, RpcInterfaceId, Context.NumberOfProcedures); if (DS_SUCCESS == Interface.decode((PVOID)&DecompilerStubContext)) { std::cout << Interface; } - return 0; + return true; } -int +bool DecompileUninit( _In_ DECOMPILE_IT_CTXT Context ) @@ -230,7 +243,7 @@ DecompileUninit( CloseHandle(Context.hTargetProcess); } - return 0; + return true; } @@ -238,7 +251,7 @@ int main(int argc, char* argv[]) { DECOMPILE_IT_CTXT Context = {0}; char* EndPtr; - int status; + bool status; if (argc < 7) { @@ -281,38 +294,36 @@ int main(int argc, char* argv[]) } else if (!_stricmp(CurrentArgument, "--format-str-offsets")) { - char *token = NULL, *previous_token = NULL; - size_t OffsetCount = 0; bFormatStrOffsetsProvided = true; - // counting offsets - token = argv[ArgIndex + 1]; - do { - OffsetCount++; - previous_token = token + 1; - token = strchr(previous_token, ','); - } while (token); - - Context.NumberOfProcedures = OffsetCount; - Context.FormatStrOffsets = new uint16_t[OffsetCount]; - - - // registering offsets - OffsetCount = 0; - token = argv[ArgIndex + 1]; - //token = strchr(previous_token, ','); - do { - Context.FormatStrOffsets[OffsetCount] = (uint16_t)strtoumax(token, &EndPtr, 16); - - OffsetCount++; - previous_token = token; - token = strchr(previous_token, ','); - if (token) + // parsing offsets using STL since strtok sucks. + std::string offsets_str(argv[ArgIndex + 1]); + std::vector offsets; + + auto last_pos = 0; + auto pos = offsets_str.find(','); + + while (pos != std::string::npos) { + offsets.push_back(offsets_str.substr(last_pos, pos - last_pos)); + last_pos = ++pos; + pos = offsets_str.find(',', pos); + + if (pos == std::string::npos) { - token += strlen(","); + offsets.push_back( + offsets_str.substr(last_pos, offsets_str.length()) + ); } + + } - } while (token); + Context.NumberOfProcedures = offsets.size(); + Context.FormatStrOffsets = new uint16_t[Context.NumberOfProcedures]; + + for (size_t i = 0; i < offsets.size(); i++) + { + Context.FormatStrOffsets[i] = (uint16_t)strtoumax(offsets[i].c_str(), &EndPtr, 0); + } } } @@ -325,18 +336,17 @@ int main(int argc, char* argv[]) } - status = DecompileInit( + if (!DecompileInit( &Context - ); - if (status) + )) { printf("Could not init the DecompileIt context : %d.\n", GetLastError()); - return status; + return -1; } status = DecompileIt(Context); DecompileUninit(Context); - return status; + return !status; } \ No newline at end of file diff --git a/RpcDecompileIt/RpcDecompileIt.h b/RpcDecompileIt/RpcDecompileIt.h index 4c08a7e..177b2e1 100644 --- a/RpcDecompileIt/RpcDecompileIt.h +++ b/RpcDecompileIt/RpcDecompileIt.h @@ -52,228 +52,6 @@ typedef struct _DECOMPILE_IT_CTXT { #pragma warning ( pop ) -#pragma region RpcInternalsCommon - -//#define MAX_RPC_INTERFACE_ANNOTATION 64 -//#define SIMPLE_DICT_SMALL_ARRAY 4 -//#define RPC_IS_EPMAPPER_REGISTERED 0x20 -// -//#define ULONG_PTR_T ULONG_PTR -//#define PTR_T * -// -//typedef struct _LIST_ENTRY_T { -// struct _LIST_ENTRY PTR_T Flink; -// struct _LIST_ENTRY PTR_T Blink; -//} LIST_ENTRY_T, *PLIST_ENTRY_T; -// -//typedef struct _RTL_CRITICAL_SECTION_DEBUG_T { -// WORD Type; -// WORD CreatorBackTraceIndex; -// struct _RTL_CRITICAL_SECTION_T PTR_T CriticalSection; -// LIST_ENTRY_T ProcessLocksList; -// DWORD EntryCount; -// DWORD ContentionCount; -// DWORD Flags; -// WORD CreatorBackTraceIndexHigh; -// WORD SpareWORD; -//} RTL_CRITICAL_SECTION_DEBUG_T, PTR_T PRTL_CRITICAL_SECTION_DEBUG_T; -// -//typedef struct _RTL_CRITICAL_SECTION_T { -// PRTL_CRITICAL_SECTION_DEBUG_T DebugInfo; -// // -// // The following three fields control entering and exiting the critical -// // section for the resource -// // -// LONG LockCount; -// LONG RecursionCount; -// VOID PTR_T OwningThread; // from the thread's ClientId->UniqueThread -// VOID PTR_T LockSemaphore; -// VOID PTR_T SpinCount; // force size on 64-bit systems when packed -//} RTL_CRITICAL_SECTION_T, PTR_T PRTL_CRITICAL_SECTION_T; -// -//typedef struct _MUTEX_T { -// RTL_CRITICAL_SECTION_T CriticalSection; -//}MUTEX_T; -// -//typedef struct _EVENT_T { -// ULONG hEvent; -//} EVENT_T; -// -//typedef struct _SIMPLE_DICT_T { -// VOID PTR_T PTR_T pArray; -// UINT ArraySizeInBytes; //to change : countof array elements -// UINT NumberOfEntries; -// VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; -//}SIMPLE_DICT_T, PTR_T PSIMPLE_DICT_T; -// -//typedef struct _QUEUE_T { -// VOID PTR_T Tail; -// VOID PTR_T Head; -// ULONG Lentgh; -// VOID PTR_T SmallArray[SIMPLE_DICT_SMALL_ARRAY]; -//}QUEUE_T; -// -//typedef struct _NDR_EXPR_DESC_T -//{ -// const unsigned short PTR_T pOffset; -// const unsigned char PTR_T pFormatExpr; -//} NDR_EXPR_DESC_T; -// -///* -//* -//* MIDL Stub Descriptor -//*/ -//typedef struct _MIDL_STUB_DESC_T { -// void PTR_T RpcInterfaceInformation; -// void PTR_T pfnAllocate; -// void PTR_T pfnFree; -// void PTR_T pAutoHandle; -// const VOID PTR_T apfnNdrRundownRoutines; -// const VOID PTR_T aGenericBindingRoutinePairs; -// const VOID PTR_T apfnExprEval; -// const VOID PTR_T aXmitQuintuple; -// const unsigned char PTR_T pFormatTypes; -// int fCheckBounds; -// /* Ndr library version. */ -// unsigned long Version; -// VOID PTR_T pMallocFreeStruct; -// long MIDLVersion; -// const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; -// // New fields for version 3.0+ -// const VOID PTR_T aUserMarshalQuadruple; -// // Notify routines - added for NT5, MIDL 5.0 -// const VOID PTR_T NotifyRoutineTable; -// /* -// * Reserved for future use. -// */ -// ULONG_PTR_T mFlags; -// // International support routines - added for 64bit post NT5 -// const VOID PTR_T CsRoutineTables; -// void PTR_T ProxyServerInfo; -// const NDR_EXPR_DESC_T PTR_T pExprInfo; -// // Fields up to now present in win2000 release. -//} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; -// -///* -//* Server Interpreter's information strucuture. -//*/ -//typedef struct _MIDL_SERVER_INFO_T { -// PMIDL_STUB_DESC_T pStubDesc; -// const VOID PTR_T PTR_T DispatchTable; -// const unsigned char PTR_T ProcString; -// const unsigned short PTR_T FmtStringOffset; -// const VOID PTR_T PTR_T ThunkTable; -// RPC_IF_ID PTR_T pTransferSyntax; -// ULONG_PTR_T nCount; -// VOID PTR_T pSyntaxInfo; -//} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; -// -//typedef struct _RPC_DISPATCH_TABLE_T { -// UINT DispatchTableCount; -// RPC_DISPATCH_FUNCTION PTR_T DispatchTable; -// ULONG_PTR_T Reserved; -//} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; -// -////typedef struct _LocationInfo_T { -//// WCHAR Location[MAX_PATH]; -//// VOID* pBaseAddress; -//// DWORD State; -//// DWORD Type; -//// SIZE_T Size; -////}LocationInfo_T; -// -//typedef struct _RPC_PROTSEQ_ENDPOINT_T { -// UCHAR PTR_T RpcProtocolSequence; -// UCHAR PTR_T Endpoint; -//} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; -// -//typedef struct _RPC_SERVER_INTERFACE_T { -// UINT Length; -// RPC_IF_ID InterfaceId; -// RPC_IF_ID TransferSyntax; -// PRPC_DISPATCH_TABLE_T DispatchTable; -// UINT RpcProtseqEndpointCount; -// PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; -// RPC_MGR_EPV PTR_T DefaultManagerEpv; -// void const PTR_T InterpreterInfo; -// UINT Flags; -//} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; -// -//#pragma pack(1) -//typedef struct _RPC_SERVER_T { -// MUTEX_T Mutex; -// ULONG __bIslistening; -// ULONG bIsListening; -// ULONG MinimumCallThreads; -// ULONG Wait; -// ULONG OutCalls; -// ULONG Unk1; -// ULONG InCalls; -// ULONG Unk2; -// SIMPLE_DICT_T AddressDict; -// ULONG lAvailableCalls; -// ULONG Unk3; -// SIMPLE_DICT_T _ProtSeqQueue; -// ULONG Unk4[8]; -// ULONG OutPackets; -// ULONG Unk5; -// MUTEX_T Mutex2; -// ULONG MaxCalls; -// ULONG Unk6; -// VOID PTR_T hEvent; -// ULONG Unk7[4]; -// SIMPLE_DICT_T InterfaceDict; -// ULONG _bIsListening; -// ULONG bIsMaxCalls1234; -// ULONG Unk8[6]; -// ULONG InPackets; -// ULONG Unk9; -// RPC_FORWARD_FUNCTION PTR_T pRpcForwardFunction; -// ULONG Unk10[6]; -// SIMPLE_DICT_T AuthenInfoDict; -// LIST_ENTRY_T RpcIfGroupListEntry; -// ULONG PTR_T __SRWLock; -// LIST_ENTRY_T field_1E0; -//}RPC_SERVER_T, PTR_T PRPC_SERVER_T; -// -//typedef struct _RPC_INTERFACE_T -//{ -// PRPC_SERVER_T pRpcServer; -// ULONG Flags; -// ULONG Unk1; -// MUTEX_T Mutex; -// ULONG EpMapperFlags; -// ULONG Unk2; -// RPC_MGR_EPV PTR_T pMgrEpv; -// RPC_IF_CALLBACK_FN PTR_T IfCallbackFn; -// RPC_SERVER_INTERFACE_T RpcServerInterface; -// PMIDL_SYNTAX_INFO pSyntaxInfo; -// VOID PTR_T pTransfertSyntaxes; -// ULONG TransfertSyntaxesCount; -// ULONG __Field_C4; -// ULONG NbTypeManager; -// ULONG MaxRpcSize; -// UUID_VECTOR PTR_T pUuidVector; -// SIMPLE_DICT_T RpcInterfaceManagerDict; -// UCHAR Annotation[MAX_RPC_INTERFACE_ANNOTATION]; -// ULONG IsCallSizeLimitReached; -// ULONG currentNullManagerCalls; -// ULONG __Field_150; -// ULONG __Field_154; -// ULONG __Field_158; -// ULONG SecurityCallbackInProgress; -// ULONG SecurityCacheEntry; -// ULONG field_164; -// VOID PTR_T __SecurityCacheEntries[16]; -// SIMPLE_DICT_T FwEpDict; -// ULONG Unk3[6]; -// struct RPCP_INTERFACE_GROUP PTR_T pRpcpInterfaceGroup; -//}RPC_INTERFACE_T, PTR_T PRPC_INTERFACE_T; -//#pragma pack() - -#pragma endregion RpcInternalsCommon - - #pragma region RpcViewStub void @@ -284,9 +62,9 @@ DecompileItInitRpcViewStub ); -#define ASSIGN_RPC_VIEW_STUB(RpcViewHelperStub, Context) \ -RpcViewHelper_T RpcViewHelperStub; \ -DecompileItInitRpcViewStub(&RpcViewHelperStub, (PVOID) Context) +// #define ASSIGN_RPC_VIEW_STUB(RpcViewHelperStub, Context) \ +// RpcViewHelper_T RpcViewHelperStub; \ +// DecompileItInitRpcViewStub(&RpcViewHelperStub, (PVOID) Context) #pragma endregion RpcViewStub From dafd02354a8850750e179c4302c0b0431dae7dcf Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Wed, 14 Mar 2018 21:18:19 +0100 Subject: [PATCH 09/11] Add check between remote target and own process archs DecompileIt rely on reading remote process memory and applying undocumented C structures on it to parse rpc internals, and consequently need to be the same archness as the target process. --- RpcDecompileIt/RpcDecompileIt.cpp | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index 790db00..03522c2 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -20,6 +20,8 @@ DecompileInit( WCHAR RefModuleName[MAX_PATH]; HMODULE hMods[1024]; DWORD ModulesSize; + BOOL bOwnProcessWow64 = false; + BOOL bRemoteProcessWow64 = false; HANDLE hProcess = OpenProcess( PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, @@ -29,9 +31,27 @@ DecompileInit( if (hProcess==NULL) { - return GetLastError(); + printf("[x] Could not access the remote process : %d\n", GetLastError()); + return false; } - Context -> hTargetProcess = hProcess; + Context->hTargetProcess = hProcess; + + IsWow64Process(GetCurrentProcess(), &bOwnProcessWow64); + IsWow64Process(hProcess, &bRemoteProcessWow64); + + if (bOwnProcessWow64 != bRemoteProcessWow64) + { + #define PROCESS_ARCH(bIsWow64) (bIsWow64) ? "Wow64" : "x64" + + printf("[x] Remote process does not have the same arch as own process : %s != %s\n", + PROCESS_ARCH(bRemoteProcessWow64), + PROCESS_ARCH(bOwnProcessWow64) + ); + return false; + } + + + if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &ModulesSize)) @@ -105,8 +125,8 @@ ReadRpcInterface( _Out_ RPC_IF_ID *RpcInterface ) { - size_t RpcInterfaceInformationStructSize; - RPC_CLIENT_INTERFACE RpcClientInterface; + unsigned int RpcInterfaceInformationStructSize = 0; + RPC_CLIENT_INTERFACE RpcClientInterface = {0}; if (!RpcInterface || !RpcViewHelper) @@ -214,7 +234,7 @@ DecompileIt( RpcDecompilerInfoStub.pFormatStringOffsetTable = Context.FormatStrOffsets; RpcDecompilerInfoStub.pProcFormatString = (RVA_T) Context.FormatStrOffset; - RpcDecompilerInfoStub.pTypeFormatString = (RVA_T) (MidlStubDesc.pFormatTypes - Context.ModuleBaseAddress); + RpcDecompilerInfoStub.pTypeFormatString = (RVA_T) ((uintptr_t)MidlStubDesc.pFormatTypes - Context.ModuleBaseAddress); DecompilerStubContext.pRpcDecompilerInfo = &RpcDecompilerInfoStub; DecompilerStubContext.pRpcModuleInfo = &ModuleInfoStub; @@ -300,8 +320,8 @@ int main(int argc, char* argv[]) std::string offsets_str(argv[ArgIndex + 1]); std::vector offsets; - auto last_pos = 0; - auto pos = offsets_str.find(','); + size_t last_pos = 0; + size_t pos = offsets_str.find(','); while (pos != std::string::npos) { offsets.push_back(offsets_str.substr(last_pos, pos - last_pos)); From cbb504af8cf0afa1e1593b0b8666f75e8a2d1555 Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Sun, 18 Mar 2018 14:09:32 +0100 Subject: [PATCH 10/11] Set global variables before decompiling --- RpcDecompileIt/RpcDecompileIt.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index 03522c2..4536774 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -231,6 +231,11 @@ DecompileIt( RpcDecompilerInfoStub.ppProcNameTable[i] = NULL; } +#ifdef _AMD64_ + RpcDecompilerInfoStub.bIs64Bits = TRUE; +#else + RpcDecompilerInfoStub.bIs64Bits = FALSE; +#endif RpcDecompilerInfoStub.pFormatStringOffsetTable = Context.FormatStrOffsets; RpcDecompilerInfoStub.pProcFormatString = (RVA_T) Context.FormatStrOffset; @@ -241,6 +246,13 @@ DecompileIt( DecompilerStubContext.pRpcViewHelper = &RpcViewHelperStub; + // is it a 64 bits application ? + is64B = RpcDecompilerInfoStub.bIs64Bits; + + // robust flags case + robustFlagWasSet = (RpcDecompilerInfoStub.NDRVersion >= NDR_VERSION_5_2) ? TRUE : FALSE; + + // Decode function std::string IfaceName("DecompileItInterface"); IdlInterface Interface(IfaceName, RpcInterfaceId, Context.NumberOfProcedures); From e31fc8fd0d3eb1687806a561935c53cd931ccebe Mon Sep 17 00:00:00 2001 From: 1orenz0 <1orenz0@github> Date: Wed, 25 Apr 2018 20:20:01 +0200 Subject: [PATCH 11/11] Correctly set robust flag --- RpcDecompileIt/RpcDecompileIt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RpcDecompileIt/RpcDecompileIt.cpp b/RpcDecompileIt/RpcDecompileIt.cpp index 4536774..07fab04 100644 --- a/RpcDecompileIt/RpcDecompileIt.cpp +++ b/RpcDecompileIt/RpcDecompileIt.cpp @@ -250,7 +250,7 @@ DecompileIt( is64B = RpcDecompilerInfoStub.bIs64Bits; // robust flags case - robustFlagWasSet = (RpcDecompilerInfoStub.NDRVersion >= NDR_VERSION_5_2) ? TRUE : FALSE; + robustFlagWasSet = (MidlStubDesc.Version >= NDR_VERSION_5_2) ? TRUE : FALSE; // Decode function