#1
|
|||
|
|||
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> 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; } |
The Following User Says Thank You to jonwil For This Useful Post: | ||
Indigo (07-19-2019) |
#2
|
|||
|
|||
It is strange because I see no references to those structures at the end in the code. The comments in the code seem to be inferred somehow from those data structures. Perhaps the compiler optimized out the try-catch already and just left in some extra metadata.
RTTI is Run-time Type Information, its basically a reflection metadata system for C++ especially for class hierarchy identification to allow for virtual destructors and the like. It does not necessarily mean it was referenced in the code as I think its merely a compiler option. Please refer to MSDN or even here: Quote:
I don't understand the question further as the first dump shows where a try { block starts and also gives a comment as to its end so it should be easy for you to add those to your clone function. You can basically merge the contiguous try blocks as the close brace is misleading. There is just one try and one catch. Code:
.text:10038B34 ; try { .text:10038C4F ; } // starts at 10038B34 .text:10038C55 ; try { .text:10038C78 ; } // starts at 10038C55 .text:10038C7E ; try { .text:10038D28 ; } // starts at 10038C7E .text:10038D2E ; try { .text:10038D38 ; catch(ErrorClass) // owned by 10038B34 .text:10038D38 ; catch(ErrorClass) // owned by 10038C55 .text:10038D6B ; } // starts at 10038D2E Possibly you just wrap the entire code block you show up to W3dExportClass::PrintTotalVertexCount(); in: Code:
try { (original clone) } catch (ErrorClass* ec) { //.text:10038D38 mov esi, [ebp+i] really [ebp+0x10] so some error class with a zero terminated ascii string at 0x10 bytes in which we call szMessage MessageBox(NULL, ec->szMessage, "Error", MB_SETFOREGROUND); //0x10000=MB_SETFOREGROUND } //.text:10038D5F mov eax, offset loc_10038D65 W3dExportClass::PrintTotalVertexCount(); e.g. Code:
if ( !r.Open(2) ) { MessageBoxA(NULL, "Unable to open file.", "Error", MB_SETFOREGROUND); return 1; //or goto return_loc //...return_loc: return 1; } Code:
if ( !(W3DExportClass::DoExportDialog(this, suppressPrompts) && (this->ExportStruct.ExportSkeleton || this->ExportStruct.ExportAnimation || this->ExportStruct.ExportGeometry)) ) return 1; //or goto return_loc Last edited by chants; 04-10-2019 at 03:34. |
The Following User Says Thank You to chants For This Useful Post: | ||
Indigo (07-19-2019) |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
iOS Reverse Engineering | sope | General Discussion | 0 | 05-13-2016 13:09 |
Legality of reverse engineering. | Fade | General Discussion | 6 | 05-07-2006 05:13 |