#include "InternalComplexTypesMisc.h" #include "internalRpcDecompiler.h" #include "internalRpcUtils.h" #include BOOL __fastcall processBindContext( _In_ VOID* pContext, _In_ RVA_T pType, _Inout_ ParamDesc& ParamDesc, _Inout_ std::list& listProcTypes, _Inout_ std::ostringstream& oss) { UNREFERENCED_PARAMETER(listProcTypes); UNREFERENCED_PARAMETER(pType); UNREFERENCED_PARAMETER(pContext); oss << "[context_handle] void*"; displayPtrLevel(ParamDesc.getuPtrLevel(), oss); oss <<" "<& 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("<& 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< v, UINT offset) { for(UINT i=0; i& 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& 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<= 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"<& 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; }