C++ Logo


Advanced search

Re: [std-proposals] Extend std::type_info with more information

From: Sebastian Wittmeier <wittmeier_at_[hidden]>
Date: Tue, 9 Apr 2024 16:13:28 +0200
Hi Frederick,   I think reverse-engineering MSVC is really off-topic (!) for this list, even if it later could lead to a paper. Nevertheless here are some pointers:   https://www.openrce.org/articles/full_view/23 https://ofekshilon.com/?s=viewing+types https://www.blackhat.com/presentations/bh-dc-07/Sabanal_Yason/Paper/bh-dc-07-Sabanal_Yason-WP.pdf https://blog.quarkslab.com/visual-c-rtti-inspection.html https://github.com/colinsenner/rtti-plugin-x64dbg   If you want to find flags, follow Thiago's advice: It's easier to get the typeinfos for different types and see what the compiler generates.     Please keep this mailing list for discussion of actual papers and ideas instead of for lots of code versions trying to read RTTI information.   Sebastian     -----Ursprüngliche Nachricht----- Von:Frederick Virchanza Gotham via Std-Proposals <std-proposals_at_[hidden]> Gesendet:Di 09.04.2024 13:51 Betreff:Re: [std-proposals] Extend std::type_info with more information An:std-proposals_at_[hidden]; CC:Frederick Virchanza Gotham <cauldwell.thomas_at_[hidden]>; On Tue, Apr 9, 2024 at 8:13 AM Frederick Virchanza Gotham wrote: > > Over the next few days I'll try to figure out what it's doing to see what information > I can get from Microsoft's std::type_info. In order to see what information is available in Microsoft's implementation of "std::typeinfo", I've tried to generate C/C++ code from the assembler for "__RTDynamicCast", and you can see my full attempt in thi s post if you scroll down to the end. There are some very interesting lines in it such as:    int32_t *p_something_interesting0 = (int32_t*) *(*p_type_info_RCX - 1); The above line seems to find a pointer at the beginning of the type_info, and dereferences it to find something else (not sure what yet -- but something juicy no doubt). Then we have:    char *p_something_interesting1 = (char *)p_type_info_RCX                                     - p_something_interesting0[1]                                     - offset; which uses the aforementioned pointer to find some more intriguing data, and seems to apply an offset (treating the aforementioned pointer as pointing to an array and getting its 3rd element). Also I see a 32-Bit integer which is a bitmask of flags -- I hope those flags are things like IsPointer, IsPointerToMember, IsPolymorphic, and so forth. If anyone has ever dissected Microsoft's type_info before then could you please chime in here? I'll figure out what those pointers point to . . . and what those bitmask flags are . . . and I bet ya I can find an array of pointers to all the base classes' type_info's. Here's my attempted generation of C/C++ from the assembler (might not be perfect): void *_RTDynamicCast(type_info *p_type_info_RCX, void *p_object, type_info *p_type_info_from_R8, type_info *p_type_info_to_R9, bool whether_to_throw) {    if ( nullptr == p_type_info_RCX ) return nullptr;    // Backup the arguments before the registers get re-used    type_info *p_type_info_to_R15   = p_type_info_to_R9;    type_info *p_type_info_from_R12 = p_type_info_from_R8;    int32_t *p_something_interesting0 = (int32_t*) *(* (uint64_t**)p_type_info_RCX - 1  );    uint32_t offset = 0u;    if ( p_something_interesting0[2] )    {        char *p = (char*)p_type_info_RCX - p_something_interesting0[2];        offset = *(uint32_t*)p;    }    char *p_something_interesting1 = (char*)p_type_info_RCX                                     - p_something_interesting0[1]                                     - offset;    char *some_important_address;    if ( *p_something_interesting0 )    {        some_important_address = (char*)p_something_interesting0 - p_something_interesting0[5];    }    else    {        void *dummy;        some_important_address = (char*)RtlPcToFileHeader(p_something_interesting0, &dummy);    }    uint32_t const some_bitmask_of_flags = *(uint32_t*)( some_important_address + p_something_interesting0[4] + 4 );    int32_t *p_base_class;    char *some_important_address2;    type_info *p_type_info_to_STACK;    if ( some_bitmask_of_flags & 1 )    {        some_important_address2 = some_important_address;        p_type_info_to_STACK = p_type_info_to_R15;        void (*some_secret_function)(void*,void*) = (some_bitmask_of_flags & 2) ? &secret_function0 : &secret_function1;        p_base_class = some_secret_function(p_something_interesting1, p_something_interesting0);    }    else    {        p_base_class = secret_function2(p_something_interesting0, p_type_info_from_R12, p_type_info_to_R15);    }    if ( p_base_class )    {        int64_t temp = 0;        if ( p_base_class[3] >= 0 )        {            temp = p_base_class[3];            uint64_t const temp2 = *(uint64_t*)(p_something_interesting1 + p_base_class[3])            temp += *(int32_t*)(temp2 + p_base_class[4]);        }        return p_something_interesting1 + temp + p_base_class[2];    }    // control reaches here if the dynamic_cast failed    char dummy_object_to_throw;    if ( boolean_whether_to_throw )    {        secret_function3(            &dummy_object_to_throw,            "Bad dynamic_cast!",            p_type_info_from_R8,            p_base_class,            p_type_info_to_STACK,            some_important_address2);        CxxThrowException(&dummy_object_to_throw, &ThrowInfo_for_bad_cast);    }    return nullptr; } -- Std-Proposals mailing list Std-Proposals_at_[hidden] https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

Received on 2024-04-09 14:13:32