Skip to content

Instantly share code, notes, and snippets.

@oopsmishap
Created October 28, 2022 09:24
Show Gist options
  • Save oopsmishap/58651b5d2858981ef250fe7b8f23d7c5 to your computer and use it in GitHub Desktop.
Save oopsmishap/58651b5d2858981ef250fe7b8f23d7c5 to your computer and use it in GitHub Desktop.
STLTypes by Rolf Rolles with string
# (C) Rolf Rolles, Mobius Strip Reverse Engineering, 9/21/2021.
import idaapi
from functools import reduce
stl_map_keyvalue_fmt = ("struct {2}_{3}_keyvalue_t"
"{{"
"{0} key;"
"{1} value;"
"}};")
stl_map_node_fmt = ("struct _Tree_node_{2}_{3};" # FORWARD DECLARATION
"struct _Tree_node_{2}_{3}"
"{{ "
" _Tree_node_{2}_{3} *_Left;"
" _Tree_node_{2}_{3} *_Parent;"
" _Tree_node_{2}_{3} *_Right;"
" bool _Color;"
" bool _IsNil;"
" {2}_{3}_keyvalue_t KeyValue;"
"}};")
stl_map_fmt = ("struct __cppobj map_{2}_{3}"
"{{ "
" _Tree_node_{2}_{3} *_Myhead;"
" unsigned __int64 _Mysize;"
"}};")
stl_map_pairib = ("struct __cppobj map_{2}_{3}_iterator_pairib"
"{{ "
" _Tree_node_{2}_{3} *_Myhead;"
" bool _Second;"
"}};")
stl_map_templates = [stl_map_keyvalue_fmt, stl_map_node_fmt, stl_map_fmt, stl_map_pairib]
stl_map_func_insert_at = "_Tree_node_{2}_{3} **__fastcall map_{2}_{3}_insert_at(map_{2}_{3} *map, _Tree_node_{2}_{3} **it_out, bool IsLeft, _Tree_node_{2}_{3} *it1_in, {2}_{3}_keyvalue_t *keyValue, _Tree_node_{2}_{3} *it2_in);"
stl_map_func_insert_nohint = "map_{2}_{3}_iterator_pairib *__fastcall map_{2}_{3}_insert_nohint(map_{2}_{3} *map, map_{2}_{3}_iterator_pairib *itp_out, bool IsLeft, {2}_{3}_keyvalue_t *keyValue, _Tree_node_{2}_{3} *it2_in);"
stl_map_func_insert_hint = "_Tree_node_{2}_{3} **__fastcall map_{2}_{3}_insert_hint(map_{2}_{3} *map, _Tree_node_{2}_{3} **it_out, _Tree_node_{2}_{3} *it1_in, {2}_{3}_keyvalue_t *keyValue, _Tree_node_{2}_{3} *it2_in);"
stl_map_funcsigs = [stl_map_func_insert_at, stl_map_func_insert_nohint, stl_map_func_insert_hint]
def ParseOneDecl(declWithSemi):
retVal = idaapi.parse_decls(None, declWithSemi, None, idaapi.convert_pt_flags_to_hti(idaapi.PT_TYP))
return retVal is not None
def MakeMapTypes(sKeyType, sValType, sKeyName=None, sValName=None):
if sKeyName is None:
sKeyName = sKeyType
if sValName is None:
sValName = sValType
stl_types_reified = map(lambda s: s.format(sKeyType, sValType, sKeyName, sValName), stl_map_templates)
stl_types_reduced = reduce(lambda x, y: x + y, stl_types_reified)
if not ParseOneDecl(stl_types_reduced):
print("Could not parse declaration: %s" % stl_types_reduced)
return False
stl_funcs_reified = map(lambda s: s.format(sKeyType, sValType, sKeyName, sValName), stl_map_funcsigs)
stl_funcs_reduced = reduce(lambda x, y: x + "\n" + y, stl_funcs_reified)
return True
stl_set_node_fmt = ("struct _Tree_node_{1};" # FORWARD DECLARATION
"struct _Tree_node_{1}"
"{{ "
" _Tree_node_{1} *_Left;"
" _Tree_node_{1} *_Parent;"
" _Tree_node_{1} *_Right;"
" bool _Color;"
" bool _IsNil;"
" {0} _Key;"
"}};")
stl_set_fmt = ("struct __cppobj set_{1}"
"{{ "
" _Tree_node_{1} *_Myhead;"
" unsigned __int64 _Mysize;"
"}};")
stl_set_pairib = ("struct __cppobj set_{1}_iterator_pairib"
"{{ "
" _Tree_node_{1} *_Myhead;"
" bool _Second;"
"}};")
stl_set_templates = [stl_set_node_fmt, stl_set_fmt, stl_set_pairib]
def MakeSetTypes(sKeyType, sKeyName=None):
if sKeyName is None:
sKeyName = sKeyType
stl_types_reified = map(lambda s: s.format(sKeyType, sKeyName), stl_set_templates)
stl_types_reduced = reduce(lambda x, y: x + y, stl_types_reified)
if not ParseOneDecl(stl_types_reduced):
print("Could not parse declaration: %s" % stl_types_reduced)
return False
return True
stl_deque_cont = ("struct deque_{1} {{"
" void *_Myproxy;"
" {0} **_Map;"
" size_t _Mapsize;"
" _QWORD _Myoff;"
" _QWORD _Mysize;"
"}};")
def MakeDequeType(sEltType, sEltName=None):
if sEltName is None:
sEltName = sEltType
deque_type_reified = stl_deque_cont.format(sEltType, sEltName)
if not ParseOneDecl(deque_type_reified):
print("Could not parse declaration: %s" % deque_type_reified)
return False
return True
stl_vector_cont = ("struct vector_{1} {{"
" {0} *_Myfirst;"
" {0} *_Mylast;"
" {0} *_Myend;"
"}};")
def MakeVectorType(sEltType, sEltName=None):
if sEltName is None:
sEltName = sEltType
vector_type_reified = stl_vector_cont.format(sEltType, sEltName)
if not ParseOneDecl(vector_type_reified):
print("Could not parse declaration: %s" % vector_type_reified)
return False
return True
stl_list_node = ("struct _List_node_{1};" # FORWARD DECLARATION
"struct _List_node_{1}"
"{{ "
" _List_node_{1} *_Next;"
" _List_node_{1} *_Prev;"
" {0} _Myval;"
"}};")
stl_list_cont = ("struct list_{1}"
"{{ "
" _List_node_{1} *_Myhead;"
" size_t _Mysize;"
"}};")
stl_list_templates = [stl_list_node, stl_list_cont]
def MakeListTypes(sEltType, sEltName=None):
if sEltName is None:
sEltName = sEltType
stl_types_reified = map(lambda s: s.format(sEltType, sEltName), stl_list_templates)
stl_types_reduced = reduce(lambda x, y: x + y, stl_types_reified)
if not ParseOneDecl(stl_types_reduced):
print("Could not parse declaration: %s" % stl_types_reduced)
return False
return True
stl_ref_count_base_vtbl_fmt = ("struct _Ref_count_base_{1};"
"struct _Ref_count_base_{1}_vtbl {{"
" void (__fastcall *_Destroy)(_Ref_count_base_{1} *this);"
" void (__fastcall *_Delete_this)(_Ref_count_base_{1} *this);"
" void (__fastcall *Destructor)(_Ref_count_base_{1} *this);"
" void *(__fastcall *_Get_deleter)(_Ref_count_base_{1} *this);"
"}};")
stl_ref_count_base_fmt = ("struct _Ref_count_base_{1}_vtbl;"
"struct _Ref_count_base_{1} {{"
" _Ref_count_base_{1}_vtbl *__vftable;"
" volatile int _Uses;"
" volatile int _Weaks;"
"}};")
stl_ref_count_fmt = ("struct _Ref_count_base_{1};"
"struct _Ref_count_{1} : _Ref_count_base_{1} {{"
" {0} *_Ptr;"
"}};")
stl_ref_count_obj_fmt = ("struct _Ref_count_base_{1};"
"struct _Ref_count_obj_{1} : _Ref_count_base_{1} {{"
" {0} _Storage;"
"}};")
# Changed _Ref_count to _Ref_count_base
stl_shared_ptr_fmt = ("struct _Ref_count_base_{1};"
"struct shared_ptr_{1} {{"
" {0} *_Ptr;"
" _Ref_count_base_{1} *_Rep;"
"}};")
# FOR 64-BIT TYPES BECAUSE OF __shifted(X,16)
# OTHERWISE WOULD BE __shifted(X,12)
stl_shared_ptr_obj_fmt = ("struct _Ref_count_obj_{1};"
"struct shared_ptr_obj_{1} {{"
" {0} *__shifted(_Ref_count_obj_{1},16) _Ptr;"
" _Ref_count_obj_{1} *_Rep;"
"}};")
stl_shared_ptr_templates = [stl_ref_count_base_vtbl_fmt, stl_ref_count_base_fmt, stl_ref_count_fmt,
stl_ref_count_obj_fmt, stl_shared_ptr_fmt, stl_shared_ptr_obj_fmt]
def MakeSharedPtrTypes(sEltType, sEltName=None):
if sEltName is None:
sEltName = sEltType
stl_types_reified = map(lambda s: s.format(sEltType, sEltName), stl_shared_ptr_templates)
stl_types_reduced = reduce(lambda x, y: x + y, stl_types_reified)
if not ParseOneDecl(stl_types_reduced):
print("Could not parse declaration:")
return False
return True
stl_string_union = ("#pragma pack(push, 1)\n"
"union stl_string_union_{1} {{"
" unsigned char _Buf[16];"
" {0} *_Ptr;"
"}};\n"
"#pragma pack(pop)\n")
stl_string_cont = ("#pragma pack(push, 1)\n"
"struct stl_string_{1} {{"
" union stl_string_union_{1} _Bxty;"
" size_t _Mysize;"
" size_t _Myres;"
"}};\n"
"#pragma pack(pop)\n")
stl_string_templates = [stl_string_union, stl_string_cont]
def MakeStringType(sEltType, sEltName=None):
if sEltName is None:
sEltName = sEltType
stl_types_reified = map(lambda s: s.format(sEltType, sEltName), stl_string_templates)
stl_types_reduced = reduce(lambda x, y: x + y, stl_types_reified)
if not ParseOneDecl(stl_types_reduced):
print("Could not parse declaration: %s" % stl_types_reduced)
return False
return True
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment