View Single Post
  #1  
Old 04-09-2019, 20:19
jonwil jonwil is offline
VIP
 
Join Date: Feb 2004
Posts: 387
Rept. Given: 2
Rept. Rcvd 21 Times in 9 Posts
Thanks Given: 2
Thanks Rcvd at 65 Times in 34 Posts
jonwil Reputation: 21
Reverse engineering MS C++ exception handling

I have a function (compiled originally with VS .NET 2003) in IDA that looks like this:
Code:
.text:10038AD0 ; int __thiscall W3dExportClass::DoExport(W3dExportClass *this, const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options)
.text:10038AD0 W3dExportClass__DoExport proc near      ; DATA XREF: .rdata:1007AE04↓o
.text:10038AD0
.text:10038AD0 anonymous_0     = dword ptr -0E58h
.text:10038AD0 var_E50         = dword ptr -0E50h
.text:10038AD0 var_23C         = RawFileClass ptr -23Ch
.text:10038AD0 var_220         = dword ptr -220h
.text:10038AD0 Caption         = byte ptr -21Ch
.text:10038AD0 Dir             = byte ptr -118h
.text:10038AD0 var_14          = dword ptr -14h
.text:10038AD0 var_10          = dword ptr -10h
.text:10038AD0 var_C           = dword ptr -0Ch
.text:10038AD0 var_4           = dword ptr -4
.text:10038AD0 name            = dword ptr  8
.text:10038AD0 ei              = dword ptr  0Ch
.text:10038AD0 i               = dword ptr  10h
.text:10038AD0 suppressPrompts = dword ptr  14h
.text:10038AD0 options         = dword ptr  18h
.text:10038AD0
.text:10038AD0 ; FUNCTION CHUNK AT .text:10072A00 SIZE 0000000B BYTES
.text:10038AD0
.text:10038AD0 ; __unwind { // SEH_10038AD0
.text:10038AD0                 push    ebp
.text:10038AD1                 mov     ebp, esp
.text:10038AD3                 push    0FFFFFFFFh
.text:10038AD5                 push    offset SEH_10038AD0
.text:10038ADA                 mov     eax, large fs:0
.text:10038AE0                 push    eax
.text:10038AE1                 mov     large fs:0, esp
.text:10038AE8                 sub     esp, 0E44h
.text:10038AEE                 mov     eax, ___security_cookie
.text:10038AF3                 push    ebx
.text:10038AF4                 push    esi
.text:10038AF5                 mov     esi, ecx
.text:10038AF7                 push    edi
.text:10038AF8                 mov     edi, [ebp+i]
.text:10038AFB                 xor     ebx, ebx
.text:10038AFD                 mov     [ebp+var_14], eax
.text:10038B00                 mov     eax, [ebp+ei]
.text:10038B03                 mov     ecx, edi        ; this
.text:10038B05                 mov     [esi+W3dExportClass.ExpInt], eax
.text:10038B0B                 mov     [esi+W3dExportClass.Int], edi
.text:10038B11                 mov     [esi+W3dExportClass.field_47C], ebx
.text:10038B17                 mov     [esi+W3dExportClass.OriginNodeList], ebx
.text:10038B1D                 mov     [esi+W3dExportClass.DamageNodeList], ebx
.text:10038B23                 mov     [esi+W3dExportClass.HierarchyStruct], ebx
.text:10038B29                 mov     edx, [ecx]
.text:10038B2B                 mov     [ebp+var_10], esp
.text:10038B2E                 mov     [ebp+var_220], esi
.text:10038B34 ;   try {
.text:10038B34                 mov     [ebp+var_4], ebx
.text:10038B37                 call    [edx+InterfaceVtable.GetTime]
.text:10038B3D                 mov     [esi+W3dExportClass.Time], eax
.text:10038B43                 call    ds:GetFrameRate(void)
.text:10038B49                 mov     [esi+W3dExportClass.FrameRate], eax
.text:10038B4F                 push    ebx             ; Ext
.text:10038B50                 lea     eax, [ebp+Caption]
.text:10038B56                 push    eax             ; Filename
.text:10038B57                 mov     eax, [ebp+name]
.text:10038B5A                 lea     ecx, [ebp+Dir]
.text:10038B60                 push    ecx             ; Dir
.text:10038B61                 lea     edx, [ebp+ei]
.text:10038B64                 push    edx             ; Drive
.text:10038B65                 push    eax             ; FullPath
.text:10038B66                 mov     [esi+W3dExportClass.field_478], 2
.text:10038B70                 call    __splitpath
.text:10038B75                 lea     ecx, [ebp+Dir]
.text:10038B7B                 push    ecx
.text:10038B7C                 lea     edx, [ebp+ei]
.text:10038B7F                 push    edx
.text:10038B80                 push    offset aSS      ; "%s%s"
.text:10038B85                 push    offset buf ; char *
.text:10038B8A                 call    _sprintf
.text:10038B8F                 lea     eax, [ebp+Caption]
.text:10038B95                 add     esp, 24h
.text:10038B98                 lea     edx, [eax+1]
.text:10038B9B                 jmp     short loc_10038BA0
.text:10038B9B ; ---------------------------------------------------------------------------
.text:10038B9D                 align 10h
.text:10038BA0
.text:10038BA0 loc_10038BA0:                           ; CODE XREF: W3dExportClass__DoExport+CB↑j
.text:10038BA0                                         ; W3dExportClass__DoExport+D5↓j
.text:10038BA0                 mov     cl, [eax]
.text:10038BA2                 inc     eax
.text:10038BA3                 cmp     cl, bl
.text:10038BA5                 jnz     short loc_10038BA0
.text:10038BA7                 sub     eax, edx
.text:10038BA9                 cmp     eax, 0Fh
.text:10038BAC                 jbe     short loc_10038BC5
.text:10038BAE                 cmp     [ebp+suppressPrompts], ebx
.text:10038BB1                 jnz     short loc_10038BC5
.text:10038BB3                 push    ebx             ; uType
.text:10038BB4                 push    offset aWarning ; "Warning"
.text:10038BB9                 push    offset aWarningW3dFile ; "Warning: W3D filenames should be 15 cha"...
.text:10038BBE                 push    ebx             ; hWnd
.text:10038BBF                 call    ds:MessageBoxA
.text:10038BC5
.text:10038BC5 loc_10038BC5:                           ; CODE XREF: W3dExportClass__DoExport+DC↑j
.text:10038BC5                                         ; W3dExportClass__DoExport+E1↑j
.text:10038BC5                 mov     eax, [edi]
.text:10038BC7                 mov     ecx, edi        ; Interface *
.text:10038BC9                 call    [eax+InterfaceVtable.GetCurFilePath]
.text:10038BCF                 mov     ecx, eax
.text:10038BD1                 call    ds:CStr::operator char *(void)
.text:10038BD7                 push    ebx             ; Ext
.text:10038BD8                 push    ebx             ; Filename
.text:10038BD9                 lea     ecx, [ebp+Dir]
.text:10038BDF                 push    ecx             ; Dir
.text:10038BE0                 lea     edx, [ebp+ei]
.text:10038BE3                 push    edx             ; Drive
.text:10038BE4                 push    eax             ; FullPath
.text:10038BE5                 call    __splitpath
.text:10038BEA                 lea     eax, [ebp+Dir]
.text:10038BF0                 push    eax
.text:10038BF1                 lea     ecx, [ebp+ei]
.text:10038BF4                 push    ecx
.text:10038BF5                 lea     edx, [esi+W3dExportClass.Path]
.text:10038BF8                 push    offset aSS      ; "%s%s"
.text:10038BFD                 push    edx             ; char *
.text:10038BFE                 call    _sprintf
.text:10038C03                 mov     eax, [ebp+suppressPrompts]
.text:10038C06                 add     esp, 24h
.text:10038C09                 push    eax             ; suppressPrompts
.text:10038C0A                 mov     ecx, esi        ; this
.text:10038C0C                 call    W3DExportClass__DoExportDialog
.text:10038C11                 cmp     al, bl
.text:10038C13                 jz      loc_10038DA5
.text:10038C19                 cmp     [esi+W3dExportClass.ExportStruct.ExportSkeleton], bl
.text:10038C1F                 jnz     short loc_10038C35
.text:10038C21                 cmp     [esi+W3dExportClass.ExportStruct.ExportAnimation], bl
.text:10038C27                 jnz     short loc_10038C35
.text:10038C29                 cmp     [esi+W3dExportClass.ExportStruct.ExportGeometry], bl
.text:10038C2F                 jz      loc_10038DA5
.text:10038C35
.text:10038C35 loc_10038C35:                           ; CODE XREF: W3dExportClass__DoExport+14F↑j
.text:10038C35                                         ; W3dExportClass__DoExport+157↑j
.text:10038C35                 push    ebx
.text:10038C36                 call    CreateLogDialog
.text:10038C3B                 mov     ecx, [ebp+name]
.text:10038C3E                 add     esp, 4
.text:10038C41                 push    ecx             ; filename
.text:10038C42                 lea     ecx, [ebp+var_23C] ; this
.text:10038C48                 call    RawFileClass__RawFileClass
.text:10038C4D                 push    2               ; a2
.text:10038C4F                 lea     ecx, [ebp+var_23C] ; this
.text:10038C4F ;   } // starts at 10038B34
.text:10038C55 ;   try {
.text:10038C55                 mov     byte ptr [ebp+var_4], 1
.text:10038C59                 call    RawFileClass::Open(int)
.text:10038C5E                 cmp     eax, ebx
.text:10038C60                 jnz     short loc_10038C8B
.text:10038C62                 push    10000h          ; uType
.text:10038C67                 push    offset aError   ; "Error"
.text:10038C6C                 push    offset aUnableToOpenFi ; "Unable to open file."
.text:10038C71                 push    ebx             ; hWnd
.text:10038C72                 call    ds:MessageBoxA
.text:10038C78                 lea     ecx, [ebp+var_23C] ; this
.text:10038C78 ;   } // starts at 10038C55
.text:10038C7E ;   try {
.text:10038C7E                 mov     byte ptr [ebp+var_4], bl
.text:10038C81                 call    RawFileClass::~RawFileClass()
.text:10038C86                 jmp     loc_10038DA5
.text:10038C8B ; ---------------------------------------------------------------------------
.text:10038C8B
.text:10038C8B loc_10038C8B:                           ; CODE XREF: W3dExportClass__DoExport+190↑j
.text:10038C8B                 lea     edx, [ebp+var_23C]
.text:10038C91                 push    edx             ; _DWORD
.text:10038C92                 lea     ecx, [ebp+var_E50]
.text:10038C98                 call    ChunkSaveClass::ChunkSaveClass(FileClass *)
.text:10038C9D                 mov     ecx, esi        ; this
.text:10038C9F                 call    W3dExportClass__CreateOriginNodeList
.text:10038CA4                 cmp     eax, ebx
.text:10038CA6                 jz      short loc_10038CBD
.text:10038CA8                 lea     eax, [ebp+var_E50]
.text:10038CAE                 push    eax             ; int
.text:10038CAF                 lea     ecx, [ebp+Caption]
.text:10038CB5                 push    ecx             ; lpCaption
.text:10038CB6                 mov     ecx, esi
.text:10038CB8                 call    W3dExportClass__ExportData
.text:10038CBD
.text:10038CBD loc_10038CBD:                           ; CODE XREF: W3dExportClass__DoExport+1D6↑j
.text:10038CBD                 lea     ecx, [ebp+var_23C]
.text:10038CC3                 call    RawFileClass::Close(void)
.text:10038CC8                 mov     edi, [esi+48Ch]
.text:10038CCE                 cmp     edi, ebx
.text:10038CD0                 jz      short loc_10038CE8
.text:10038CD2                 mov     ecx, edi        ; this
.text:10038CD4                 call    HierarchySave__DHierarchySave
.text:10038CD9                 push    edi             ; void *
.text:10038CDA                 call    MAX_delete(void *)
.text:10038CDF                 add     esp, 4
.text:10038CE2                 mov     [esi+W3dExportClass.HierarchyStruct], ebx
.text:10038CE8
.text:10038CE8 loc_10038CE8:                           ; CODE XREF: W3dExportClass__DoExport+200↑j
.text:10038CE8                 mov     edi, [esi+W3dExportClass.OriginNodeList]
.text:10038CEE                 cmp     edi, ebx
.text:10038CF0                 jz      short loc_10038D08
.text:10038CF2                 mov     ecx, edi        ; this
.text:10038CF4                 call    INodeListClass__destructor2
.text:10038CF9                 push    edi             ; void *
.text:10038CFA                 call    MAX_delete(void *)
.text:10038CFF                 add     esp, 4
.text:10038D02                 mov     [esi+W3dExportClass.OriginNodeList], ebx
.text:10038D08
.text:10038D08 loc_10038D08:                           ; CODE XREF: W3dExportClass__DoExport+220↑j
.text:10038D08                 mov     edi, [esi+W3dExportClass.DamageNodeList]
.text:10038D0E                 cmp     edi, ebx
.text:10038D10                 jz      short loc_10038D28
.text:10038D12                 mov     ecx, edi        ; this
.text:10038D14                 call    INodeListClass__destructor2
.text:10038D19                 push    edi             ; void *
.text:10038D1A                 call    MAX_delete(void *)
.text:10038D1F                 add     esp, 4
.text:10038D22                 mov     [esi+W3dExportClass.DamageNodeList], ebx
.text:10038D28
.text:10038D28 loc_10038D28:                           ; CODE XREF: W3dExportClass__DoExport+240↑j
.text:10038D28                 lea     ecx, [ebp+var_23C] ; this
.text:10038D28 ;   } // starts at 10038C7E
.text:10038D2E ;   try {
.text:10038D2E                 mov     byte ptr [ebp+var_4], bl
.text:10038D31                 call    RawFileClass::~RawFileClass()
.text:10038D36                 jmp     short loc_10038D6D
.text:10038D38 ; ---------------------------------------------------------------------------
.text:10038D38
.text:10038D38 loc_10038D38:                           ; DATA XREF: .rdata:stru_10086C44↓o
.text:10038D38 ;   catch(ErrorClass) // owned by 10038B34
.text:10038D38 ;   catch(ErrorClass) // owned by 10038C55
.text:10038D38                 mov     esi, [ebp+i]
.text:10038D3B                 push    10000h          ; uType
.text:10038D40                 push    offset aError   ; "Error"
.text:10038D45                 push    esi             ; lpText
.text:10038D46                 xor     ebx, ebx
.text:10038D48                 push    ebx             ; hWnd
.text:10038D49                 call    ds:MessageBoxA
.text:10038D4F                 cmp     esi, ebx
.text:10038D51                 jz      short loc_10038D5F
.text:10038D53                 mov     edx, ds:void (*MAX_free)(void *)
.text:10038D59                 push    esi
.text:10038D5A                 call    dword ptr [edx]
.text:10038D5C                 add     esp, 4
.text:10038D5F
.text:10038D5F loc_10038D5F:                           ; CODE XREF: W3dExportClass__DoExport+281↑j
.text:10038D5F                 mov     eax, offset loc_10038D65
.text:10038D64                 retn
.text:10038D65 ; ---------------------------------------------------------------------------
.text:10038D65
.text:10038D65 loc_10038D65:                           ; CODE XREF: W3dExportClass__DoExport+294↑j
.text:10038D65                                         ; DATA XREF: W3dExportClass__DoExport:loc_10038D5F↑o
.text:10038D65                 mov     esi, [ebp+var_220]
.text:10038D6B                 xor     ebx, ebx
.text:10038D6B ;   } // starts at 10038D2E
.text:10038D6D
.text:10038D6D loc_10038D6D:                           ; CODE XREF: W3dExportClass__DoExport+266↑j
.text:10038D6D                 mov     [ebp+var_4], 0FFFFFFFFh
.text:10038D74                 call    W3dExportClass__PrintTotalVertexCount
.text:10038D79                 xor     eax, eax
.text:10038D7B                 mov     al, [esi+W3dExportClass.ExportStruct.ReviewLog]
.text:10038D81                 push    eax             ; a1
.text:10038D82                 call    W3dExportClass__DestroyLogDialog
.text:10038D87                 mov     ecx, [esi+W3dExportClass.Int] ; this
.text:10038D8D                 mov     edi, [ecx]
.text:10038D8F                 add     esp, 4
.text:10038D92                 push    ebx
.text:10038D93                 push    8
.text:10038D95                 call    [edi+InterfaceVtable.GetTime]
.text:10038D9B                 mov     ecx, [esi+W3dExportClass.Int] ; Interface *
.text:10038DA1                 push    eax             ; t
.text:10038DA2                 call    [edi+InterfaceVtable.RedrawViews]
.text:10038DA5
.text:10038DA5 loc_10038DA5:                           ; CODE XREF: W3dExportClass__DoExport+143↑j
.text:10038DA5                                         ; W3dExportClass__DoExport+15F↑j ...
.text:10038DA5                 mov     ecx, [ebp+var_C]
.text:10038DA8                 mov     large fs:0, ecx
.text:10038DAF                 mov     ecx, [ebp+var_14]
.text:10038DB2                 mov     eax, 1
.text:10038DB7                 call    __security_check_cookie(x)
.text:10038DBC                 pop     edi
.text:10038DBD                 pop     esi
.text:10038DBE                 pop     ebx
.text:10038DBF                 mov     esp, ebp
.text:10038DC1                 pop     ebp
.text:10038DC2                 retn    14h
.text:10038DC2 ; } // starts at 10038AD0
.text:10038DC2 W3dExportClass__DoExport endp

.text:10072A0B SEH_10038AD0    proc near               ; DATA XREF: W3dExportClass__DoExport+5↑o
.text:10072A0B                                         ; .rdata:1008556C↓o
.text:10072A0B                 mov     eax, offset stru_10086C68
.text:10072A10                 jmp     ___CxxFrameHandler
.text:10072A10 SEH_10038AD0    endp

.rdata:10086C68 stru_10086C68   FuncInfo_V1 <19930520h, 3, offset stru_10086C2C, 1, \
.rdata:10086C68                                         ; DATA XREF: SEH_10038AD0↑o
.rdata:10086C68                              offset stru_10086C54, 0, 0>

.rdata:10086C2C stru_10086C2C   UnwindMapEntry <-1, 0>  ; DATA XREF: .rdata:stru_10086C68↓o
.rdata:10086C34                 UnwindMapEntry <0, offset loc_10072A00>
.rdata:10086C3C                 UnwindMapEntry <-1, 0>

.text:10072A00 loc_10072A00:                           ; DATA XREF: .rdata:10086C34↓o
.text:10072A00 ; __unwind { // SEH_10038AD0            ; this
.text:10072A00 ;   cleanup() // owned by 10038C55
.text:10072A00 ;   cleanup() // owned by 10038C7E
.text:10072A00 ;   cleanup() // owned by 10038D2E
.text:10072A00                 lea     ecx, [ebp+var_23C]
.text:10072A06                 jmp     RawFileClass::~RawFileClass()
.text:10072A06 ; } // starts at 10072A00

.rdata:10086C54 stru_10086C54   TryBlockMapEntry <0, 1, 2, 1, offset stru_10086C44>
.rdata:10086C54                                         ; DATA XREF: .rdata:stru_10086C68↓o

.rdata:10086C44 stru_10086C44   HandlerType <0, offset ErrorClass `RTTI Type Descriptor', 16, \
.rdata:10086C44                                         ; DATA XREF: .rdata:stru_10086C54↓o
.rdata:10086C44                              offset loc_10038D38>
I have a clone of the function (without any try/catch statements in there) as follows:
Code:
int __thiscall W3dExportClass::DoExport(W3dExportClass *this, const TCHAR *name, ExpInterface *ei, Interface *i, BOOL suppressPrompts, DWORD options)
{
  this->ExpInt = ei;
  this->Int = i;
  this->field_47C = 0;
  this->OriginNodeList = NULL;
  this->DamageNodeList = NULL;
  this->HierarchyStruct = NULL;
  this->Time = i->GetTime(i);
  this->FrameRate = GetFrameRate();
  this->field_478 = 2;
  _splitpath(name, (char *)&ei, &Dir, &Caption, NULL);
  sprintf(buf, "%s%s", &ei, &Dir);
  if ( strlen(&Caption) > 0xF && !suppressPrompts )
    MessageBoxA(NULL, "Warning: W3D filenames should be 15 characters or less!", "Warning", 0);
  _splitpath((const char *)i->GetCurFilePath(), (char *)&ei, &Dir, NULL, NULL);
  sprintf(this->Path, "%s%s", &ei, &Dir);
  if ( W3DExportClass::DoExportDialog(this, suppressPrompts)
    && (this->ExportStruct.ExportSkeleton || this->ExportStruct.ExportAnimation || this->ExportStruct.ExportGeometry) )
  {
    CreateLogDialog(0);
    RawFileClass r(name);
    if ( r.Open(2) )
    {
      ChunkSaveClass::ChunkSaveClass(&r);
      if ( W3dExportClass::CreateOriginNodeList(this) )
        W3dExportClass::ExportData(this, &Caption, (int)&v21);
      r.Close();
      if ( this->HierarchyStruct )
      {
	delete this->HierarchyStruct;
        this->HierarchyStruct = NULL;
      }
      if ( this->OriginNodeList )
      {
        delete this->OriginNodeList;
        this->OriginNodeList = NULL;
      }
      if ( this->DamageNodeList )
      {
        delete this->DamageNodeList;
        this->DamageNodeList = NULL;
      }
      W3dExportClass::PrintTotalVertexCount();
      W3dExportClass::DestroyLogDialog(this->ExportStruct.ReviewLog);
      this->Int->RedrawViews(this->Int->GetTime() //not sure of full prototype for this function, may have more arguments);
    }
    else
    {
      MessageBoxA(NULL, "Unable to open file.", "Error", MB_SETFOREGROUND);
    }
  }
  return 1;
}
Can anyone tell me based on the ASM and the above clone where the try/catch statements and other EH stuff need to go to complete the clone? (if any further information is needed I can provide that)
Reply With Quote
The Following User Says Thank You to jonwil For This Useful Post:
Indigo (07-19-2019)