1

We all know that reversing STL code is no fun. To make it easier, I usually create some of the strucutres so I can reference the created STL structures in another custom structure.

For example, msvc - std::string structure:

00000000 std::string     struc ; (sizeof=0x1C)
00000000 alloc           dd ?                    ; void *
00000004 Buffer          db 16 dup(?)            ; string(C)
00000014 Length          dd ?                    ; int
00000018 LengthMax       dd ?                    ; int
0000001C std::string     ends

or std::vector:

00000000 std::vector     struc ; (sizeof=0x10)
00000000 alloc           dd ?                    ; void *
00000004 NumberOfItems   dd ?                    ; int
00000008 MaxSize         dd ?                    ; int
0000000C Data            dd ?                    ; 
00000010 std::vector     ends

Doing this and then in decompilation using these structures, makes the code much more readable.

I sometimes find it difficult figuring out other structures, i.e. std::queue, looking in the implementation I can see its container type is actually a typedef to std::deque, which has the content of std::_Compressed_pair.

Is there a way to recreate these STL types, with proper naming as I did for vector and string, so I can reference to them in other structures in order to a have cleaner decompilation? What would a std::queue structure look like?

Thanks a lot in advance.

3
  • 1
    By the way, you're clearly discussing the MSVC implementation of STL here, given the fact that you referenced _Compressed_pair. Note that neither std::string nor std::vector have a vTable field -- you should delete them from both structure declarations. Anyway, I have a specific answer to the substance of your question, but I will eventually write a blog entry about it rather than go into it now. Commented Oct 10, 2020 at 0:27
  • Sorry for the late joining to the party but, im having familiar stuff going on with reverse engeneering certain game compiled with vc7.1 toolset. Im planning to install the IDE and compile lots of different templated versions with the same (I'll try to mimic them) compile setting. Then I'll be at the point where I'm not sure what to do next, create a DLL with debug symbols and try to force load them into my idb? (That wont' resolve the functions addresses properly, pretty sure, thus I'm just gonna end up with the useless templated classes definitions). Other option seems to generate the flirt
    – kthxbai2
    Commented Oct 22, 2020 at 0:51
  • You're totally right @RolfRolles, I should've probably mentioned this. Regarding the vtable thing, for STL structures they are allocators, instead of virtual tables. Looking forward to read your blog post. Would appreciate if you post it here. Commented Oct 30, 2020 at 17:44

2 Answers 2

2

as i commented i used windbg to dump those structures

sample code used for walk through

#include <iostream>                                                     //01
#include <list>                                                         //02
#include <vector>                                                       //03
#include <map>                                                          //04
#include <queue>                                                        //05
#include <string>                                                       //06
int main(void)                                                          //07
{                                                                       //08
    std::string             ms;                                         //09
    std::wstring            mw;                                         //10
    std::map< char,int >    mm;                                         //11
    std::vector<int>        mv1,mv2,mv3,mv4;                            //12
    std::queue<std::vector<int>> mq;                                    //13
                                                                        //14
    ms = "This is a big Ascii string for that matter to avoid sso";     //15
    mw = L"This is a big Wide string for that matter to avoid sso";     //16
    mm = {{'a',0x61},{'b',0x62},{'c',0x63},{'d',0x64}};                 //17
    mv1.insert(mv1.end(), {mm['a'],mm['b'],mm['c'],mm['d']});           //18
    mv2.insert(mv2.end(), {mm['b'],mm['c'],mm['a'],mm['d']});           //19
    mv3.insert(mv3.end(), {mm['d'],mm['b'],mm['a'],mm['c']});           //20
    mv4.insert(mv4.end(), {mm['c'],mm['b'],mm['a'],mm['d']});           //21
    mq.push(mv1);                                                       //22
    mq.push(mv2);                                                       //23
    mq.push(mv3);                                                       //24
    mq.push(mv4);                                                       //25
    std::cout << ms << "\n";                                            //26
    std::wcout << mw << "\n";                                           //27
    std::cout << mm.begin()->first << "\n";                             //28
    std::cout << *mv1.begin() << "\n";                                  //29
    std::cout << *mq.front().begin() << "\n";                           //30
    std::cout << *mq.back().begin() << "\n";                            //31
}                                                                       //32

compiled and linked on vs2017 devcmd prompt as x86 with

:>cat complink.bat
pushd .
call "c:\Program Files\Microsoft Visual Studio\2017\Community\Common7\Tools\vsdevcmd.bat"
popd
cl /Zi /W4 /analyze /EHsc /nologo /Od nsstd.cpp /link /release
:>

load it in windbg execute till line 26 to initialize all the variables.
run the script given below to dump the queue's->vector's->maps's->integer values and quit.

windbg script

.for(r$t0=0;@$t0<4;r$t0=@$t0+1) 
{
    .for(r $t1=0;@$t1<4;r$t1 =@$t1+1) 
    {
        .printf "%c\t" , @@c++( mq.c._Mypair._Myval2._Map[@$t0]->_Mypair._Myval2._Myfirst[@$t1] )
    }
    .printf "\n"
}

result

:>cdb -c "g `nsstd!nsstd.cpp:26`;$$>a< dumpq.wds;q" nsstd.exe | awk "/Reading/,/quit/"
0:000> cdb: Reading initial command 'g `nsstd!nsstd.cpp:26`;$$>a< dumpq.wds;q'
WARNING: Line information loading disabled
ModLoad: 6c700000 6c703000   C:\Windows\system32\api-ms-win-core-synch-l1-2-0.DLL
a       b       c       d
b       c       a       d
d       b       a       c
c       b       a       d
quit:
1

you created those structures or you pulled it from somewhere ?
basically these are template classes and not structures

where did you get the size of 0x1c for std::string
it is 0x18
0x10 for buffer or Pointer (static small string or malloced() bigstring )
0x4 for Actualsize or_Mysize
0x4 for Reservedsize or _Myres

like

typedef struct _FOO {
union _Bx {
char buff[16];
Pointer ptr;
};
ULONG _Mysize;
ULONG _Myres;
}Foo,*PFoo;

these classes are defined in the header files like xstring , vector etc for example string_val is defined in xstring

C:\Program Files\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\include\xstring

:\>grep -r -n -i  class.*string_val *
xstring:1768:           // CLASS TEMPLATE _String_val
xstring:1770:   class _String_val

like wise you can get queue also lookfor queue_val in deque header

0:000> ?? myqueue

class std::queue<std::vector<int,std::allocator<int> >,std::deque<std::vector<int,std::allocator<int> >,std::allocator<std::vector<int,std::allocator<int> > > > >
   +0x000 c                : std::deque<std::vector<int,std::allocator<int> >,std::allocator<std::vector<int,std::allocator<int> > > >

0:000> ?? sizeof(myqueue)
unsigned int 0x14

0:000> ?? myqueue.c._Mypair._Myval2
class std::_Deque_val<std::_Deque_simple_types<std::vector<int,std::allocator<int> > > >
   +0x000 _Myproxy         : 0x0057b598 std::_Container_proxy
   +0x004 _Map             : 0x0057b960  -> 0x0057b998 std::vector<int,std::allocator<int> >
   +0x008 _Mapsize         : 8
   +0x00c _Myoff           : 0
   +0x010 _Mysize          : 1
3
  • Thanks for your promoted answer! Yes, I created them. I should have probably mentioned the compiler version is msvc-9, so the STL structures changed over time of course. On older compilers, i.e. VC6 they didn't even reserve 16 bytes on the stack for the string buffer, it was just a pointer to the buffer. I'm aware that they are template classes, but they help constructing a structure after all, which what makes it difficult on some scenarios to RE, depending on the data structure of course. Commented Sep 24, 2020 at 8:16
  • I'm a little bit confused by your queue example. What was your approach reaching to that structure? You are using radera2 there, am I right? Thanks again! Commented Sep 24, 2020 at 8:19
  • i was using windbg for dumping those structure i added another answer with code and walk through take a look
    – blabb
    Commented Sep 25, 2020 at 19:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.