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