mirror of
https://github.com/silverf0x/RpcView
synced 2026-06-08 17:26:38 +00:00
39ded8c54d
When the argument using to describe size_is is an out parameter, we don't know it's value and it cannot be used to describe the size of another parameter. That's why in that case we can only set a max range
973 lines
21 KiB
C++
973 lines
21 KiB
C++
#include "InternalComplexTypesMisc.h"
|
|
#include "internalRpcDecompiler.h"
|
|
#include "internalRpcUtils.h"
|
|
#include <string>
|
|
|
|
|
|
BOOL __fastcall processBindContext(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listProcTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
UNREFERENCED_PARAMETER(listProcTypes);
|
|
UNREFERENCED_PARAMETER(pType);
|
|
UNREFERENCED_PARAMETER(pContext);
|
|
|
|
oss << "[context_handle] void*";
|
|
displayPtrLevel(ParamDesc.getuPtrLevel(), oss);
|
|
oss <<" "<<ParamDesc.getStrTypeName();
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall process_FC_BLKHOLE(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listProcTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
short wOffsetRange = 0;
|
|
DWORD dwRangeBegin = 0;
|
|
DWORD dwRangeEnd = 0;
|
|
RVA_T pNewType = NULL;
|
|
BYTE bRead = 0;
|
|
|
|
|
|
pType += sizeof(BYTE) + sizeof(BYTE); // skip FC_TYPE and first BYTE
|
|
|
|
//read offset to complex type
|
|
RPC_GET_PROCESS_DATA(pType,&wOffsetRange,sizeof(wOffsetRange));
|
|
if(!bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
pNewType = pType + wOffsetRange;
|
|
pType += sizeof(wOffsetRange);
|
|
|
|
// read FC_TYPE at given offset
|
|
RPC_GET_PROCESS_DATA(pNewType,&bRead,sizeof(bRead));
|
|
if(bResult == FALSE)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// if type is a FC_BIND_CONTEXT range doesn't make sense
|
|
// todo : check why this happen
|
|
if((FC_TYPE) bRead != FC_BIND_CONTEXT)
|
|
{
|
|
//read range begin
|
|
RPC_GET_PROCESS_DATA(pType,&dwRangeBegin,sizeof(dwRangeBegin));
|
|
if(bResult == FALSE)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
pType += sizeof(dwRangeBegin);
|
|
|
|
//read range end
|
|
RPC_GET_PROCESS_DATA(pType,&dwRangeEnd,sizeof(dwRangeEnd));
|
|
if(bResult == FALSE)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] process_FC_BLKHOLE : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
oss<<"[range("<<dwRangeBegin<<","<<(UINT)dwRangeEnd<<")] ";
|
|
}
|
|
|
|
|
|
ParamDesc.setRva(pNewType);
|
|
|
|
bResult = rpcDumpType(
|
|
pContext,
|
|
ParamDesc,
|
|
listProcTypes,
|
|
oss);
|
|
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL __fastcall getFC_BLKHOLEMemorySize(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Out_ size_t* pszMemorySize,
|
|
_In_ BOOL bHasRangeOnConformance)
|
|
{
|
|
|
|
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
short offsetRange = 0;
|
|
RVA_T pNewType = NULL;
|
|
|
|
pType += sizeof(BYTE) + sizeof(BYTE); // skip FC_TYPE and first BYTE
|
|
|
|
//read offset to complex type
|
|
RPC_GET_PROCESS_DATA(pType,&offsetRange,sizeof(offsetRange));
|
|
if(!bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] getFC_BLKHOLEMemorySize : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
pNewType = pType + offsetRange;
|
|
|
|
bResult = getTypeMemorySize(pContext, pNewType, pszMemorySize, bHasRangeOnConformance);
|
|
|
|
|
|
return bResult;
|
|
|
|
}
|
|
|
|
|
|
BOOL __fastcall processRange(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listProcTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
std::ostringstream ossTmp;
|
|
|
|
Range_t range;
|
|
|
|
UNREFERENCED_PARAMETER(listProcTypes);
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &range, sizeof(range));
|
|
|
|
if(!bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processRange : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
processSimpleType(
|
|
pContext,
|
|
(FC_TYPE)(range.flags_type & 0xF), //type is on lower byte
|
|
ParamDesc,
|
|
ossTmp);
|
|
|
|
|
|
if(ParamDesc.getuPtrLevel() != 0)
|
|
{
|
|
oss << "/*";
|
|
}
|
|
oss << "[range(" << std::dec << range.lowValue << "," << range.highValue<< ")] ";
|
|
if(ParamDesc.getuPtrLevel() != 0)
|
|
{
|
|
oss << "*/";
|
|
}
|
|
|
|
|
|
oss<<ossTmp.str();
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall getRangeMemorySize(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Out_ size_t* pszMemorySize)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
Range_t range;
|
|
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &range, sizeof(range));
|
|
|
|
if(!bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] getRangeMemorySize : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
(*pszMemorySize) = getSimpleTypeMemorySize((FC_TYPE) (range.flags_type & 0xF));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall ProcessArrayRange(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::ostringstream& temp)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
|
|
Range_t range;
|
|
UNREFERENCED_PARAMETER(ParamDesc);
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &range, sizeof(range));
|
|
if(!bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] ProcessArrayRange : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
temp << "/*[range(" << std::dec << range.lowValue << "," << range.highValue<< ")]*/ ";
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
UINT getElementByOffset(std::vector <UINT> v, UINT offset)
|
|
{
|
|
for(UINT i=0; i<v.size(); i++)
|
|
{
|
|
if(v[i] == offset)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return (UINT)-1;
|
|
}
|
|
|
|
|
|
BOOL __fastcall processUserMarshal(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listProcTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
UserMarshal_t userMarshal;
|
|
RVA_T pUserMarshalTarget = NULL;
|
|
std::string strParamNameTmp;
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &userMarshal, sizeof(userMarshal));
|
|
|
|
if(FALSE == bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
oss << "/* WARNING : user_marshall should be defined in ACF file */ [user_marshall(";
|
|
|
|
// compute user marshal target offset
|
|
pUserMarshalTarget = pType + FIELD_OFFSET(UserMarshal_t, offset_to_the_transmitted_type) + userMarshal.offset_to_the_transmitted_type;
|
|
ParamDesc.setRva(pUserMarshalTarget);
|
|
|
|
strParamNameTmp = ParamDesc.getStrTypeName();
|
|
ParamDesc.setParamName("");
|
|
|
|
if (rpcDumpType(pContext, ParamDesc, listProcTypes, oss) == FALSE)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to dump type\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
oss << ")] " << strParamNameTmp;
|
|
|
|
// set user_marshal size ??
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall getUserMarshallMemorySize(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Out_ size_t* pszMemorySize)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
UserMarshal_t userMarshal;
|
|
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &userMarshal, sizeof(userMarshal));
|
|
|
|
if(FALSE == bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processUserMarshal : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
*pszMemorySize = userMarshal.user_type_memory_size;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall processPipe(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listProcTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
Pipe_t pipe;
|
|
RVA_T pPipeTarget = NULL;
|
|
std::string strParamNameTmp;
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &pipe, sizeof(pipe));
|
|
|
|
if(FALSE == bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processPipe : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// compute pipe target offset
|
|
pPipeTarget = pType + FIELD_OFFSET(Pipe_t, offsetToType ) + pipe.offsetToType;
|
|
ParamDesc.setRva(pPipeTarget);
|
|
|
|
|
|
oss << "pipe ";
|
|
|
|
if (rpcDumpType(pContext, ParamDesc, listProcTypes, oss) == FALSE)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] processPipe : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// set pipe size ??
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall getPipeMemorySize(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Out_ size_t* pszMemorySize,
|
|
_In_ BOOL bHasRangeOnConformance)
|
|
{
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
BOOL bResult = TRUE;
|
|
Pipe_t pipe;
|
|
RVA_T pPipeTarget = NULL;
|
|
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &pipe, sizeof(pipe));
|
|
|
|
if(FALSE == bResult)
|
|
{
|
|
RPC_DEBUG_FN((UCHAR*)"[ERROR] getPipeMemorySize : unable to read process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
// compute pipe target offset
|
|
pPipeTarget = pType + FIELD_OFFSET(Pipe_t, offsetToType ) + pipe.offsetToType;
|
|
|
|
bResult = getTypeMemorySize(pContext, pPipeTarget, pszMemorySize, bHasRangeOnConformance);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL __fastcall processCorrelationDescriptor(
|
|
_In_ VOID* pContext,
|
|
_In_ ConformanceDescr_T confDesc,
|
|
_Inout_ std::ostringstream& oss,
|
|
_Inout_ ParamDesc& paramDesc)
|
|
{
|
|
|
|
BOOL bResult = FALSE;
|
|
|
|
oss<<"[";
|
|
|
|
// display conformance type
|
|
switch(confDesc.confType)
|
|
{
|
|
case size_is:
|
|
oss<<"size_is(";
|
|
break;
|
|
case switch_is:
|
|
oss<<"switch_is(";
|
|
break;
|
|
case length_is:
|
|
oss<<"length_is(";
|
|
break;
|
|
case byte_count:
|
|
oss<<"byte_count(";
|
|
break;
|
|
default:
|
|
oss<<"unknow_corr_type(";
|
|
}
|
|
|
|
// Check on which pointer level conformance should be applied
|
|
{
|
|
UINT uPtrLevel = paramDesc.getuPtrLevel();
|
|
|
|
if(uPtrLevel > 1)
|
|
{
|
|
while(--uPtrLevel > 1)
|
|
{
|
|
oss << ",";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bResult = processCorrelationDescriptorNaked(pContext, confDesc, oss, paramDesc);
|
|
|
|
oss<<")]";
|
|
|
|
return bResult;
|
|
}
|
|
|
|
|
|
BOOL __fastcall processCorrelationDescriptorNaked(
|
|
_In_ VOID* pContext,
|
|
_In_ ConformanceDescr_T confDesc,
|
|
_Inout_ std::ostringstream& oss,
|
|
_Inout_ ParamDesc& paramDesc)
|
|
{
|
|
|
|
BOOL bResult;
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
|
|
std::string strCorrelationItem; // string describing X in size_is(X)
|
|
|
|
|
|
// special cases : OperationType == FC_EXPR || OperationType === FC_CALLBACK
|
|
if(confDesc.corrDesc.correlation_operator == FC_EXPR )
|
|
{
|
|
USHORT offset = 0;
|
|
|
|
// read offset
|
|
RPC_GET_PROCESS_DATA(
|
|
((RVA_T)pRpcDecompilerCtxt->pRpcDecompilerInfo->pExprOffset + confDesc.corrDesc.offset*sizeof(USHORT)),
|
|
&offset,
|
|
sizeof(USHORT));
|
|
|
|
if(bResult == FALSE)
|
|
{
|
|
oss << "/* ERROR unable to read ExprOffset table */";
|
|
return FALSE;
|
|
}
|
|
|
|
oss << "/* FC_EXPR */";
|
|
|
|
bResult = processFcExpr(
|
|
pContext,
|
|
pRpcDecompilerCtxt->pRpcDecompilerInfo->pExprFormatString + offset,
|
|
paramDesc,
|
|
confDesc,
|
|
oss);
|
|
|
|
return bResult;
|
|
}
|
|
if(confDesc.corrDesc.correlation_operator == FC_CALLBACK )
|
|
{
|
|
oss << "/*FC_CALLBACK not implemented */";
|
|
return TRUE;
|
|
}
|
|
|
|
// FIRST STEP : according to correlation type correlation item
|
|
|
|
// case of a FC_CONSTANT_CONFORMANCE
|
|
if(confDesc.corrDesc.correlation_type & FC_CONSTANT_CONFORMANCE)
|
|
{
|
|
INT32 iSize = ((confDesc.corrDesc.correlation_operator << 16) | confDesc.corrDesc.offset) & 0xFFFFFF;
|
|
|
|
oss<<std::dec<<iSize;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// case of a FC_TOP_LEVEL_CONFORMANCE
|
|
// only used in function definition ?
|
|
if(confDesc.corrDesc.correlation_type & FC_TOP_LEVEL_CONFORMANCE)
|
|
{
|
|
UINT uArgNbr = 0;
|
|
std::stringstream ss;
|
|
#ifdef DBG_DECOMP
|
|
oss <<"/*FC_TOP_LEVEL_CONFORMANCE*/";
|
|
#endif
|
|
uArgNbr = confDesc.corrDesc.offset / (VIRTUAL_STACK_OFFSET_GRANULARITY);
|
|
|
|
ss<<"arg_"<<std::dec<<uArgNbr;
|
|
strCorrelationItem = ss.str();
|
|
}
|
|
else if(confDesc.corrDesc.correlation_type & FC_POINTER_CONFORMANCE) // case of FC_POINTER_CONFORMANCE
|
|
{
|
|
std::stringstream ss;
|
|
UINT uCorrDescMember;
|
|
#ifdef DBG_DECOMP
|
|
oss<<"/*FC_POINTER_CONFORMANCE(" << std::dec << confDesc.corrDesc.offset << ") */" ;
|
|
#endif
|
|
// check if vectMemberOffset is correctly filled
|
|
if(paramDesc.getVectMembersOffset().size() == 0)
|
|
{
|
|
oss << " /* ERROR : FC_POINTER_CONFORMANCE but an empty vectMemberOffset has been provided (offset = " <<confDesc.corrDesc.offset<< ") */";
|
|
return FALSE;
|
|
}
|
|
|
|
// get corr desc member number according to its offset
|
|
uCorrDescMember = getElementByOffset(paramDesc.getVectMembersOffset(), confDesc.corrDesc.offset);
|
|
|
|
if(uCorrDescMember == -1)
|
|
{
|
|
oss << "/* ERROR invalid corrDescMember */";
|
|
return FALSE;
|
|
}
|
|
|
|
ss << "StructMember"<<std::dec<<uCorrDescMember;
|
|
strCorrelationItem = ss.str();
|
|
}
|
|
else if(confDesc.corrDesc.correlation_type & FC_POINTER_CONFORMANCE) // case of FC_TOP_LEVEL_MULTID_CONFORMANCE
|
|
{
|
|
// currently not implemented
|
|
oss<<"/*FC_TOP_LEVEL_MULTID_CONFORMANCE not implemented */)]";
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
// last remaining case is FC_NORMAL_CONFORMANCE
|
|
// Onlys used in structure definition ?
|
|
UINT uCorrDescMemberOffset;
|
|
UINT uCorrDescMember;
|
|
std::stringstream ss;
|
|
#ifdef DBG_DECOMP
|
|
oss<<"/*FC_NORMAL_CONFORMANCE ("<< std::dec << confDesc.corrDesc.offset<<")*/ ";
|
|
#endif
|
|
// check if vectMemberOffset is correctly filled
|
|
if(paramDesc.getVectMembersOffset().size() == 0)
|
|
{
|
|
oss << " /* ERROR : FC_NORMAL_CONFORMANCE but an empty vectMemberOffset has been provided */";
|
|
return FALSE;
|
|
}
|
|
|
|
// compute correlation member offset
|
|
if(paramDesc.getVectMembersOffset().size() <= paramDesc.getuStructMemberNum())
|
|
{
|
|
oss << "/* ERROR invalid structMemberNum */";
|
|
return FALSE;
|
|
}
|
|
|
|
// get member number according to its offset
|
|
uCorrDescMemberOffset = paramDesc.getVectMembersOffset()[paramDesc.getuStructMemberNum()] + confDesc.corrDesc.offset;
|
|
uCorrDescMember = getElementByOffset(paramDesc.getVectMembersOffset(), uCorrDescMemberOffset);
|
|
|
|
if(uCorrDescMember == -1)
|
|
{
|
|
oss << "/* ERROR invalid corrDescMember || corr desc offset = */" << std::dec << confDesc.corrDesc.offset;
|
|
return TRUE;
|
|
//return FALSE
|
|
}
|
|
|
|
ss << "StructMember"<<std::dec<<uCorrDescMember;
|
|
strCorrelationItem = ss.str();
|
|
|
|
}
|
|
|
|
// SECOND STEP : display correlation item according to correlation operator
|
|
switch(confDesc.corrDesc.correlation_operator)
|
|
{
|
|
|
|
case FC_DEREFERENCE:
|
|
|
|
// the correlation item describing the size of the current item
|
|
// can derive from an out parameter. In that case, we can only set it
|
|
// has a max range and not the exact size since it's not known before the call.
|
|
// Ex :
|
|
// HRESULT Proc0 (
|
|
// [in] int arg1,
|
|
// [out] int *arg2,
|
|
// [out][size_is( , *arg2)] int **arg2
|
|
// );
|
|
if (paramDesc.isOut())
|
|
{
|
|
oss << ", *" << strCorrelationItem;
|
|
}
|
|
else
|
|
{
|
|
oss << "*" << strCorrelationItem;
|
|
}
|
|
|
|
break;
|
|
|
|
case FC_ADD_1:
|
|
oss << strCorrelationItem << "+1";
|
|
break;
|
|
|
|
case FC_SUB_1:
|
|
oss << strCorrelationItem << "-1";
|
|
break;
|
|
|
|
case FC_DIV_2:
|
|
oss << strCorrelationItem << "/2";
|
|
break;
|
|
|
|
case FC_MULT_2:
|
|
oss << strCorrelationItem << "*2";
|
|
break;
|
|
|
|
case FC_EXPR:
|
|
oss << "/* FC_EXPR not implemented */";
|
|
break;
|
|
|
|
case FC_CALLBACK:
|
|
oss << "/* FC_CALLBACK not implemented */";
|
|
|
|
default:
|
|
oss << strCorrelationItem;
|
|
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
UINT __fastcall processFcExpr(
|
|
_In_ VOID* pContext,
|
|
_Out_ RVA_T pExpr,
|
|
_In_ ParamDesc& paramDesc,
|
|
_In_ ConformanceDescr_T confDesc,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
EXPR_OPERATOR operation;
|
|
EXPR_CONST32 constante32;
|
|
//EXPR_CONST64 constante64; Not used as of yet. Maybe with NDR64?
|
|
EXPR_VAR var;
|
|
UINT32 varNb;
|
|
BOOL bResult;
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
|
|
UINT sizeToAdvance = 0;
|
|
UINT sizeOfExpr = 0;
|
|
|
|
RPC_GET_PROCESS_DATA(
|
|
pExpr,
|
|
&operation,
|
|
sizeof(EXPR_OPERATOR)
|
|
);
|
|
|
|
switch(operation.ExprType)
|
|
{
|
|
case FC_EXPR_OPER:
|
|
if(operation.Operator >= OP_UNARY_PLUS && operation.Operator <= OP_UNARY_AND) // Unary operator
|
|
{
|
|
oss << getOperatorType(operation);
|
|
|
|
pExpr += sizeof(EXPR_OPERATOR);
|
|
sizeToAdvance += sizeof(EXPR_OPERATOR);
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss);
|
|
sizeToAdvance += sizeOfExpr;
|
|
}else if(operation.Operator >= OP_PLUS && operation.Operator <= OP_LOGICAL_OR) // binary operator
|
|
{
|
|
std::string tmpOper = getOperatorType(operation);
|
|
oss << "(";
|
|
pExpr += sizeof(EXPR_OPERATOR);
|
|
sizeToAdvance += sizeof(EXPR_OPERATOR);
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss);
|
|
|
|
pExpr += sizeOfExpr;
|
|
sizeToAdvance += sizeOfExpr;
|
|
|
|
oss <<" "<< tmpOper.c_str()<<" ";
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss);
|
|
|
|
sizeToAdvance += sizeOfExpr;
|
|
|
|
oss << ")";
|
|
}else{ // Ternary operator => (expr ? expr1 : expr2)
|
|
std::ostringstream tmpIfYes;
|
|
std::ostringstream tmpIfNo;
|
|
|
|
pExpr += sizeof(EXPR_OPERATOR);
|
|
sizeToAdvance += sizeof(EXPR_OPERATOR);
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, tmpIfYes);
|
|
sizeToAdvance += sizeOfExpr;
|
|
pExpr += sizeOfExpr;
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc,confDesc, tmpIfNo);
|
|
sizeToAdvance += sizeOfExpr;
|
|
pExpr += sizeOfExpr;
|
|
|
|
oss << "(";
|
|
|
|
sizeOfExpr = processFcExpr(pContext, pExpr, paramDesc, confDesc, oss);
|
|
sizeToAdvance += sizeOfExpr;
|
|
|
|
oss << "?";
|
|
oss << tmpIfYes.str();
|
|
oss << ":";
|
|
oss << tmpIfNo.str();
|
|
oss << ")";
|
|
}
|
|
break;
|
|
case FC_EXPR_VAR:
|
|
RPC_GET_PROCESS_DATA(pExpr, &var, sizeof(EXPR_VAR));
|
|
|
|
if(confDesc.corrDesc.correlation_type & FC_TOP_LEVEL_CONFORMANCE)
|
|
{
|
|
varNb = var.Offset / VIRTUAL_STACK_OFFSET_GRANULARITY;
|
|
oss << "arg_" << std::dec << varNb;
|
|
}else{
|
|
INT uCorrDescMemberOffset;
|
|
INT uCorrDescMember;
|
|
std::stringstream ss;
|
|
// get member number according to its offset
|
|
if(paramDesc.getArrayIsAttributedPointer())
|
|
{
|
|
uCorrDescMemberOffset = var.Offset;
|
|
}else{
|
|
uCorrDescMemberOffset = paramDesc.getVectMembersOffset()[paramDesc.getuStructMemberNum()] + var.Offset;
|
|
}
|
|
uCorrDescMember = getElementByOffset(paramDesc.getVectMembersOffset(), uCorrDescMemberOffset);
|
|
|
|
if(uCorrDescMember == -1)
|
|
{
|
|
oss << "/* [ERROR] invalid corrDescMember || var offset = " << std::dec << var.Offset << "*/";
|
|
return FALSE;
|
|
}
|
|
|
|
oss << "StructMember"<<std::dec<<uCorrDescMember;
|
|
}
|
|
|
|
|
|
sizeToAdvance += sizeof(EXPR_VAR);
|
|
break;
|
|
case FC_EXPR_CONST32:
|
|
|
|
RPC_GET_PROCESS_DATA(pExpr, &constante32, sizeof(EXPR_CONST32));
|
|
|
|
oss << std::dec << constante32.ConstValue;
|
|
|
|
sizeToAdvance += sizeof(EXPR_CONST32);
|
|
break;
|
|
case FC_EXPR_CONST64:
|
|
// TODO
|
|
break;
|
|
default:
|
|
oss << "/*[ERROR] unknown expression type */";
|
|
break;
|
|
}
|
|
|
|
return sizeToAdvance;
|
|
}
|
|
|
|
|
|
std::string __fastcall getOperatorType(
|
|
_In_ EXPR_OPERATOR oper)
|
|
{
|
|
std::string result;
|
|
switch(oper.Operator)
|
|
{
|
|
|
|
case OP_UNARY_PLUS:
|
|
result = "+";
|
|
break;
|
|
case OP_UNARY_MINUS:
|
|
result = "-";
|
|
break;
|
|
case OP_UNARY_NOT:
|
|
result = "!";
|
|
break;
|
|
case OP_UNARY_COMPLEMENT:
|
|
result = "~";
|
|
break;
|
|
case OP_UNARY_CAST:
|
|
switch(oper.CastType)
|
|
{
|
|
case FC_SMALL:
|
|
result = "(byte)" ;
|
|
break;
|
|
case FC_USMALL:
|
|
result = "(char)";
|
|
break;
|
|
case FC_USHORT:
|
|
result = "(unsigned short)";
|
|
break;
|
|
case FC_LONG:
|
|
result = "(long)";
|
|
break;
|
|
case FC_ULONG:
|
|
result = "(unsigned long)";
|
|
break;
|
|
default:
|
|
result = "/* unknown cast type */";
|
|
break;
|
|
}
|
|
break;
|
|
case OP_UNARY_INDIRECTION:
|
|
result = "*";
|
|
break;
|
|
case OP_UNARY_AND:
|
|
result = "&";
|
|
break;
|
|
case OP_PLUS:
|
|
result = "+";
|
|
break;
|
|
case OP_MINUS:
|
|
result = "-";
|
|
break;
|
|
case OP_STAR:
|
|
result = "*";
|
|
break;
|
|
case OP_SLASH:
|
|
result = "/";
|
|
break;
|
|
case OP_MOD:
|
|
result = "%";
|
|
break;
|
|
case OP_LEFT_SHIFT:
|
|
result = "<<";
|
|
break;
|
|
case OP_RIGHT_SHIFT:
|
|
result = ">>";
|
|
break;
|
|
case OP_LESS:
|
|
result = "<";
|
|
break;
|
|
case OP_LESS_EQUAL:
|
|
result = "<=";
|
|
break;
|
|
case OP_GREATER_EQUAL:
|
|
result = ">=";
|
|
break;
|
|
case OP_GREATER:
|
|
result = ">";
|
|
break;
|
|
case OP_EQUAL:
|
|
result = "==";
|
|
break;
|
|
case OP_NOT_EQUAL:
|
|
result = "!=";
|
|
break;
|
|
case OP_AND:
|
|
result = "&";
|
|
break;
|
|
case OP_OR:
|
|
result = "|";
|
|
break;
|
|
case OP_XOR:
|
|
result = "^";
|
|
break;
|
|
case OP_LOGICAL_AND:
|
|
result = "&&";
|
|
break;
|
|
case OP_LOGICAL_OR:
|
|
result = "||";
|
|
break;
|
|
case OP_EXPRESSION:
|
|
break;
|
|
default:
|
|
result = "/*[ERROR] unknown operation */" ;
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
BOOL __fastcall processTransmitRepresentAs(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Inout_ ParamDesc& ParamDesc,
|
|
_Inout_ std::list<TypeToDefine>& listAdditionalTypes,
|
|
_Inout_ std::ostringstream& oss)
|
|
{
|
|
BOOL bResult;
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
TransmitRepresentAs_t transmit;
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &transmit, sizeof(TransmitRepresentAs_t));
|
|
|
|
RVA_T pTransmittedType = pType + sizeof(TransmitRepresentAs_t) + transmit.transmitted_type_offset - sizeof(transmit.transmitted_type_offset);
|
|
|
|
oss << "/* data transmitted as */";
|
|
ParamDesc.setRva(pTransmittedType);
|
|
if( rpcDumpType(pContext, ParamDesc, listAdditionalTypes, oss) == FALSE)
|
|
{
|
|
RPC_DEBUG_FN("[ERROR] processTransmitRepresentAs : dump type failed \n");
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL __fastcall getTransmitAsRepresentAsMemorySize(
|
|
_In_ VOID* pContext,
|
|
_In_ RVA_T pType,
|
|
_Out_ size_t* pszMemorySize)
|
|
{
|
|
BOOL bResult;
|
|
RpcDecompilerCtxt_T * pRpcDecompilerCtxt = (RpcDecompilerCtxt_T *) pContext;
|
|
TransmitRepresentAs_t transmit;
|
|
|
|
RPC_GET_PROCESS_DATA(pType, &transmit, sizeof(TransmitRepresentAs_t));
|
|
|
|
if(bResult == FALSE)
|
|
{
|
|
RPC_DEBUG_FN("[ERROR] getTransmitAsRepresentAsMemorySize : unable to get process data\n");
|
|
return FALSE;
|
|
}
|
|
|
|
// TODO : check if this is this size and not target size that is used for conformance
|
|
*pszMemorySize = transmit.presented_type_memory_size;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
UINT getCorrelationDescriptorSize(
|
|
_In_ BOOL bRobustFlagWasSet,
|
|
_In_ BOOL bHasRangeOnConformance)
|
|
{
|
|
|
|
UINT uSize = 0;
|
|
|
|
UNREFERENCED_PARAMETER(bRobustFlagWasSet);
|
|
|
|
if(robustFlagWasSet)
|
|
{
|
|
uSize = sizeof(CorrelationDescriptorRobust_t);
|
|
}
|
|
else
|
|
{
|
|
uSize = sizeof(CorrelationDescriptorNonRobust_t);
|
|
}
|
|
|
|
if(bHasRangeOnConformance)
|
|
{
|
|
uSize += sizeof(Range_t);
|
|
}
|
|
|
|
return uSize;
|
|
} |