I'm attempting to learn reversing techniques using IDA on an exe built with VC/MFC, and could use a little initial help learning some patterns for simplifying the decompiled code.
IDA found approximately 30K subroutines in my exe, and they make heavy use of the CString class, so that seems like a good place to start. I've read a lot of IDA tutorials and articles, but haven't found anything that covers this specifically.
Here's a relatively simple example, unmodified by me:
void __cdecl sub_428258(int a1, int a2, int a3)
{
int v3; // esi
int v4; // eax
int v5; // eax
char v6; // [esp+10h] [ebp-10h]
int v7; // [esp+1Ch] [ebp-4h]
v7 = 0;
v3 = ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::ReverseFind(&a1, 92);// Find '\'
if ( v3 < 0
&& (v3 = ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::ReverseFind(&a1, 47), v3 < 0) )// Find '/'
{
ATL::CSimpleStringT<wchar_t,1>::Empty(a2);
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator=(a3, &a1);// Return empty string in a3
}
else
{
v4 = ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Left(&a1, &v6, v3);
LOBYTE(v7) = 1;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator=(a2, v4);
LOBYTE(v7) = 0;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v6);
v5 = ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Right(
&a1,
&v6,
*(_DWORD *)(a1 - 12) - v3 - 1);
LOBYTE(v7) = 2;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::operator=(a3, v5);
LOBYTE(v7) = 0;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&v6);
}
v7 = -1;
ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::~CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>(&a1);
}
Because IDA was able to use the MFC PDB file and RTTI, the logic is pretty easy to follow in this case. It seems to be doing something like splitting the first CString param on '\' or '/', and returning the split strings in the second and third CString params, i.e.:
void Split(CString source, CString &left, CString &right);
Questions:
- Is this likely a class member function, and if so, how do you know?
- Why is V7 being set before each call to the CString functions?
- What is "*(_DWORD *)(a1 - 12) - v3 - 1" doing?
- Is there a way to tell IDA to just use "CString" instead of the fully expanded type?
- Can I define a CString struct to help simplify the code?
My guess is that it is a member function, and that the answers to #2 and #3 have to do with the class definition, but I'm just not sure. An example of the simplified code would really help.