reversing scripts moved to df_misc

develop
Ben Lubar 2020-03-26 13:38:37 -05:00
parent 78c24adffb
commit 63f774dfef
No known key found for this signature in database
GPG Key ID: 92939677AB59EDA4
28 changed files with 0 additions and 11310 deletions

@ -1,75 +0,0 @@
.rodata:08773064 t_building_templest
.rodata:08772FE4 t_building_dark_towerst
.rodata:08772EE4 t_building_home_apartment_roomst
.rodata:08772F24 t_building_home_apartmentst
.rodata:08772F64 t_building_home_singlest
.rodata:08773024 t_building_keepst
.rodata:08772FA4 t_building_mead_hallst
.rodata:087730A4 t_building_storest
.rodata:08776784 23building_constructionst
.rodata:087771E4 21building_road_pavedst
.rodata:08777064 20building_road_dirtst
.rodata:08777AC4 15building_roadst
.rodata:08779424 16building_wagonst
.rodata:087792A4 21building_tradedepotst
.rodata:087789C4 19building_workshopst
.rodata:08778E44 18building_furnacest
.rodata:08778244 21building_animaltrapst
.rodata:08778FC4 19building_farmplotst
.rodata:08777644 17building_windowst
.rodata:087777C4 17building_statuest
.rodata:08777944 15building_wellst
.rodata:08777364 17building_coffinst
.rodata:087795A4 15building_shopst
.rodata:087783C4 16building_chairst
.rodata:08777C44 16building_tablest
.rodata:08777C44 14building_bedst
.rodata:08778B44 22building_siegeenginest
.rodata:08776D64 15building_cagest
.rodata:08776EE4 16building_chainst
.rodata:08776184 19building_windmillst
.rodata:08776304 22building_water_wheelst
.rodata:08776004 21building_screw_pumpst
.rodata:08778844 24building_archerytargetst
.rodata:08778544 17building_weaponst
.rodata:087786C4 18building_supportst
.rodata:08776604 24building_axle_verticalst
.rodata:08776484 26building_axle_horizontalst
.rodata:08776BE4 24building_gear_assemblyst
.rodata:08778CC4 15building_trapst
.rodata:08779EA4 21building_bars_floorst
.rodata:0877A024 24building_bars_verticalst
.rodata:0877A324 22building_grate_floorst
.rodata:0877A1A4 21building_grate_wallst
.rodata:0877A4A4 20building_floodgatest
.rodata:08779D24 17building_bridgest
.rodata:08779A24 16building_hatchst
.rodata:08779BA4 15building_doorst
.rodata:08777DC4 21building_armorstandst
.rodata:08777F44 21building_weaponrackst
.rodata:087798A4 18building_cabinetst
.rodata:08779724 14building_boxst
.rodata:08776A64 17building_actualst
.rodata:08779144 18building_civzonest
.rodata:087774E4 20building_stockpilest
0:FFFFFFFF 21building_window_gemst
0:FFFFFFFF 23building_window_glassst
.rodata:08787664 t_building_interactst
.rodata:08788DE4 n_building_selectorst
.rodata:08788E44 n_building_permit_foreign_armorst
.rodata:08788E24 n_building_permit_itemst
.rodata:08788E64 n_building_permit_foreign_siegeammost
.rodata:08788E84 n_building_permit_foreign_weaponst
.rodata:08788EA4 n_building_permit_trapcompst
.rodata:08788F04 n_building_new_jobst
.rodata:08788EC4 n_building_category_selectorst
.rodata:08788EE4 n_building_material_selectorst
0:FFFFFFFF f_building_well_tagst
0:FFFFFFFF E_BUILDING_TEMPLE
0:FFFFFFFF E_BUILDING_KEEP
0:FFFFFFFF f_building_civzone_assignedst
0:FFFFFFFF f_building_triggerst
0:FFFFFFFF f_building_triggertargetst
0:FFFFFFFF f_building_chainst
0:FFFFFFFF f_building_cagedst
0:FFFFFFFF f_building_holderst

@ -1,5 +0,0 @@
FF - retractable
00 - west
01 - east
02 - north
03 - south

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

@ -1,81 +0,0 @@
0x00cdfd950
0x0000 e8 69 6c 08
0x0004 90 00 00 00
0x0008 8f 00 00 00
0x000c 90 00 00 00
0x0010 90 00 00 00
0x0014 8f 00 00 00
0x0018 8f 00 00 00
0x001c 0f 00 00 00
0x0020 01 00 00 00
0x0024 01 00 87 00
0x0028 00 00 00 00
0x002c f8 dc 0d 10
0x0030 f8 c6 0d 10
0x0034 78 c2 0d 10
0x0038 b0 7c 0d 10
0x003c fe 52 01 00
0x0040 a6 00 df 0a
0x0044 1b ee 00 00
0x0048 30 96 a7 10
0x004c 30 96 a7 10
0x0050 34 96 a7 10
0x0054 00 00 00 00
0x0058 00 00 00 00
0x005c 00 00 00 00
0x0060 00 00 00 00
0x0064 00 00 00 00
0x0068 00 00 00 00
0x006c 00 00 00 00
0x0070 00 00 00 00
0x0074 00 00 00 00
0x0078 00 00 00 00
0x007c 00 00 00 00
0x0080 00 00 00 00
0x0084 00 00 00 00
0x0088 00 00 00 00
0x008c 00 00 00 00
0x0090 00 00 00 00
0x0094 00 00 00 00
0x0098 01 00 00 00
0x009c 00 47 e4 0d
0x00a0 18 47 e4 0d
0x00a4 18 47 e4 0d
0x00a8 00 00 00 00
0x00ac 00 00 00 00
0x00b0 00 00 00 00
0x00b4 00 00 00 00
0x00b8 80 47 e4 0d
0x00bc 94 47 e4 0d
0x00c0 94 47 e4 0d
0x00c4 00 00 00 00
0x00c8 00 00 00 00
0x00cc 00 00 00 00
0x00d0 00 00 00 00
0x00d4 00 00 00 00
0x00d8 00 00 00 00
0x00dc 00 00 00 00
0x00e0 c0 c6 2d 00
0x00e4 05 00 00 00
0x00e8 14 00 00 00
0x00ec 01 07 01 07
0x00f0 10 00 00 00
0x00f4 b9 00 00 00
0x00f8 68 59 6c 08
0x00fc 98 00 00 00
Done. Press any key to continue

@ -1,81 +0,0 @@
0x00cdfd950
0x0000 e8 69 6c 08
0x0004 90 00 00 00
0x0008 8f 00 00 00
0x000c 90 00 00 00
0x0010 90 00 00 00
0x0014 8f 00 00 00
0x0018 8f 00 00 00
0x001c 0f 00 00 00
0x0020 01 00 00 00
0x0024 01 00 87 00
0x0028 00 00 00 00
0x002c f8 dc 0d 10
0x0030 f8 c6 0d 10
0x0034 78 c2 0d 10
0x0038 b0 7c 0d 10
0x003c 34 51 01 00
0x0040 a6 00 df 0a
0x0044 1b ee 00 00
0x0048 00 00 00 00
0x004c 00 00 00 00
0x0050 00 00 00 00
0x0054 00 00 00 00
0x0058 00 00 00 00
0x005c 00 00 00 00
0x0060 00 00 00 00
0x0064 00 00 00 00
0x0068 00 00 00 00
0x006c 00 00 00 00
0x0070 00 00 00 00
0x0074 00 00 00 00
0x0078 00 00 00 00
0x007c 00 00 00 00
0x0080 00 00 00 00
0x0084 00 00 00 00
0x0088 00 00 00 00
0x008c 00 00 00 00
0x0090 00 00 00 00
0x0094 00 00 00 00
0x0098 01 00 00 00
0x009c 00 47 e4 0d
0x00a0 18 47 e4 0d
0x00a4 18 47 e4 0d
0x00a8 00 00 00 00
0x00ac 00 00 01 00
0x00b0 00 00 00 00
0x00b4 00 00 00 00
0x00b8 80 47 e4 0d
0x00bc 94 47 e4 0d
0x00c0 94 47 e4 0d
0x00c4 00 00 00 00
0x00c8 00 00 00 00
0x00cc 00 00 00 00
0x00d0 00 00 00 00
0x00d4 00 00 00 00
0x00d8 00 00 00 00
0x00dc 00 00 00 00
0x00e0 c0 c6 2d 00
0x00e4 05 00 00 00
0x00e8 14 00 00 00
0x00ec 01 07 01 07
0x00f0 10 00 00 00
0x00f4 b9 00 00 00
0x00f8 68 59 6c 08
0x00fc 98 00 00 00
Done. Press any key to continue

@ -1,23 +0,0 @@
< OFF
> ON
20c20
< 15 0x003c 1c 53 01 00
---
> 15 0x003c 39 55 01 00
28,30c28,30
< 21 0x0054 00 00 00 00
< 22 0x0058 00 00 00 00
< 23 0x005c 00 00 00 00
---
> 21 0x0054 e0 53 a1 01
> 22 0x0058 e0 53 a1 01
> 23 0x005c e4 53 a1 01
this is a good candidate for lever state
82c82
< 64 0x0100 00 00 00 00
---
> 64 0x0100 00 00 01 00

File diff suppressed because it is too large Load Diff

@ -1,75 +0,0 @@
import ghidra.app.script.*;
import ghidra.program.model.address.*;
import ghidra.program.model.data.*;
import ghidra.program.model.mem.*;
public class find_df_globals extends GhidraScript {
public void run() throws Exception {
int ptrSize = currentProgram.getDefaultPointerSize();
byte[] dfInit = new byte[ptrSize * 2];
int i = 0;
dfInit[i++] = 0x78;
dfInit[i++] = 0x56;
dfInit[i++] = 0x34;
dfInit[i++] = 0x12;
if (ptrSize >= 8) {
dfInit[i++] = 0x78;
dfInit[i++] = 0x56;
dfInit[i++] = 0x34;
dfInit[i++] = 0x12;
dfInit[i++] = 0x21;
dfInit[i++] = 0x43;
dfInit[i++] = 0x65;
dfInit[i++] = (byte)0x87;
}
dfInit[i++] = 0x21;
dfInit[i++] = 0x43;
dfInit[i++] = 0x65;
dfInit[i++] = (byte)0x87;
byte[] mask = new byte[ptrSize * 2];
for (i = 0; i < ptrSize * 2; i++) {
mask[i] = (byte)0xff;
}
DataTypeManager dtm = currentProgram.getDataTypeManager();
StructureDataType dfGlobalsMapElement = new StructureDataType("df_globals_map_element", 0);
dfGlobalsMapElement.add(new PointerDataType(CharDataType.dataType, ptrSize), "name", null);
dfGlobalsMapElement.add(new PointerDataType(DataType.DEFAULT, ptrSize), "addr", null);
StructureDataType dfGlobalsMap = new StructureDataType("df_globals_map", 0);
dfGlobalsMap.add(DWordDataType.dataType, "magic0", "12345678");
if (ptrSize < 8) {
dfGlobalsMap.add(DWordDataType.dataType, "magic1", "87654321");
} else {
dfGlobalsMap.add(DWordDataType.dataType, "magic1", "12345678");
dfGlobalsMap.add(DWordDataType.dataType, "magic2", "87654321");
dfGlobalsMap.add(DWordDataType.dataType, "magic3", "87654321");
}
Memory mem = currentProgram.getMemory();
Address globalAddr = mem.findBytes(currentProgram.getMinAddress(), dfInit, mask, true, monitor);
int globalCount = 0;
while (mem.getLong(globalAddr.add((globalCount + 1) * ptrSize * 2)) != 0) {
globalCount++;
Address nameAddr;
Address dataAddr;
if (ptrSize >= 8) {
nameAddr = globalAddr.getNewAddress(mem.getLong(globalAddr.add(globalCount * ptrSize * 2)));
dataAddr = globalAddr.getNewAddress(mem.getLong(globalAddr.add(globalCount * ptrSize * 2 + ptrSize)));
} else {
nameAddr = globalAddr.getNewAddress(mem.getInt(globalAddr.add(globalCount * ptrSize * 2)));
dataAddr = globalAddr.getNewAddress(mem.getInt(globalAddr.add(globalCount * ptrSize * 2 + ptrSize)));
}
String name = StringDataInstance.getStringDataInstance(DataUtilities.createData(currentProgram, nameAddr, TerminatedStringDataType.dataType, 0, false, DataUtilities.ClearDataMode.CLEAR_ALL_CONFLICT_DATA)).getStringValue();
createLabel(dataAddr, name, true);
}
dfGlobalsMap.add(new ArrayDataType(dfGlobalsMapElement, globalCount, ptrSize * 2), "globals", null);
dtm.addDataType(dfGlobalsMapElement, DataTypeConflictHandler.DEFAULT_HANDLER);
dtm.addDataType(dfGlobalsMap, DataTypeConflictHandler.DEFAULT_HANDLER);
currentProgram.getListing().createData(globalAddr, dfGlobalsMap);
}
}

File diff suppressed because it is too large Load Diff

@ -1 +0,0 @@
.rodata:08779424 16building_wagonst

@ -1,816 +0,0 @@
//Microsoft Visual C++ Win32 SEH/C++ EH info parser
//Version 3.0 2006.03.02 Igor Skochinsky <skochinsky@mail.ru>
#include <idc.idc>
#define __INCLUDED
#include <ms_rtti.idc>
static getEHRec()
{
auto id;
id = GetStrucIdByName("EHRegistrationNode");
if (id==-1)
{
id = AddStruc(-1,"EHRegistrationNode");
ForceDWMember(id, 0, "pNext");
ForceDWMember(id, 4, "frameHandler");
ForceDWMember(id, 8, "state");
}
return id;
}
static getEHRecCatch()
{
auto id;
id = GetStrucIdByName("EHRegistrationNodeCatch");
if (id==-1)
{
id = AddStruc(-1,"EHRegistrationNodeCatch");
ForceDWMember(id, 0, "SavedESP");
ForceDWMember(id, 4, "pNext");
ForceDWMember(id, 8, "frameHandler");
ForceDWMember(id, 12, "state");
}
return id;
}
static CommentStackEH(start, hasESP, EHCookie, GSCookie)
{
if (hasESP)
CommentStack(start,-16, "__$EHRec$", getEHRecCatch());
else
CommentStack(start,-12, "__$EHRec$", getEHRec());
if (GSCookie)
CommentStack(start,-GSCookie, "__$GSCookie$",-1);
if (EHCookie)
CommentStack(start,-EHCookie, "__$EHCookie$",-1);
}
/* from frame.obj
typedef struct _s_FuncInfo {
unsigned int magicNumber;
int maxState;
const struct _s_UnwindMapEntry * pUnwindMap;
unsigned int nTryBlocks;
const struct _s_TryBlockMapEntry * pTryBlockMap;
unsigned int nIPMapEntries;
void * pIPtoStateMap;
const struct _s_ESTypeList * pESTypeList;
} FuncInfo;
*/
//handler:
// mov eax, offset funcInfo
// jmp ___CxxFrameHandler
static ParseCxxHandler(func, handler, fixFunc)
{
auto x, start, y, z, end, i, count, t, u, i2, cnt2, a, hasESP;
auto EHCookieOffset, GSCookieOffset;
start = func;
x = handler;
y = x;
z = x;
EHCookieOffset=0; GSCookieOffset=0;
// 8B 54 24 08 mov edx, [esp+8]
if (matchBytes(x,"8B5424088D02"))
x = x+6;
// 8D 02 lea eax, [edx]
else if (matchBytes(x,"8B5424088D42"))
x = x+7;
// 8D 42 xx lea eax, [edx+XXh]
else if (matchBytes(x,"8B5424088D82"))
x = x+10;
// 8D 82 xx xx xx xx lea eax, [edx+XXh]
else {
Message("Function at %08X not recognized as exception handler!\n",x);
return;
}
//EH cookie check:
// 8B 4A xx mov ecx, [edx-XXh]
// OR
// 8B 8A xx xx xx xx mov ecx, [edx-XXh]
// 33 C8 xor ecx, eax
// E8 xx xx xx xx call __security_check_cookie
if (matchBytes(x,"8B4A??33C8E8"))
{
//byte argument
EHCookieOffset = (~Byte(x+2)+1)&0xFF;
EHCookieOffset = 12 + EHCookieOffset;
x = x+10;
}
else if (matchBytes(x,"8B8A????????33C8E8"))
{
//dword argument
EHCookieOffset = (~Dword(x+2)+1);
EHCookieOffset = 12 + EHCookieOffset;
x = x+13;
}
if (matchBytes(x,"83C0"))
x = x + 3;
// 8B 4A xx add eax, XXh
if (matchBytes(x,"8B4A??33C8E8"))
{
// 8B 4A xx mov ecx, [edx-XXh]
// 33 C8 xor ecx, eax
// E8 xx xx xx xx call __security_check_cookie
GSCookieOffset = (~Byte(x+2)+1)&0xFF;
GSCookieOffset = 12 + GSCookieOffset;
x = x+10;
}
else if (matchBytes(x,"8B8A????????33C8E8"))
{
//dword argument
GSCookieOffset = (~Dword(x+9)+1);
GSCookieOffset = 12 + GSCookieOffset;
x = x+13;
}
//Message("EH3: EH Cookie=%02X, GSCookie=%02X\n",EHCookieOffset, GSCookieOffset);
if (Byte(x)==0xB8) {
// 8B 4A xx xx xx mov eax, offset FuncInfo
x = Dword(x+1);
}
else {
Message("\"mov eax, offset FuncInfo\" not found at offset %08X!\n",x);
return;
}
if (Dword(x)-0x19930520>0xF) {
Message("Magic is not 1993052Xh!\n");
return;
}
Message(form("Detected function start at %08X\n",start));
u = x; //FuncInfo;
//parse unwind handlers
count = Dword(u+4); //maxState
i=0;
x = Dword(u+8); //pUnwindMap
while (i<count) {
t = Dword(x+4); //unwind action address
if (t<MAXADDR && t>y) y=t; //find lowest
if (t!=0 && t<z) z=t; //find highest
x = x+8;
i = i+1;
}
if (y==0) {
Message("All pointers are NULL!\n");
return;
}
if (z>y)
{
Message("Something's very wrong!\n");
return;
}
end = FindFuncEnd(y);
if (end==BADADDR) {
if (fixFunc) MakeUnkn(y, 1);
if (BADADDR == FindFuncEnd(y))
{
Message(form("Can't find function end at 0x%08X\n",y));
return;
}
}
Message(form("Handlers block: %08X-%08X\n", z, y));
if (GetFunctionFlags(start) == -1)
{
if (fixFunc)
{
MakeUnkn(start, 1);
MakeCode(start);
MakeFunction(start, BADADDR);
}
else
{
Message("There is no function defined at 0x%08X!\n", start);
return;
}
}
a = FindFuncEnd(start);
Message("Function end: %08X\n", a);
if (fixFunc) AnalyseArea(start,a);
if (1)//(z>a) && ((z-a)>0x20))
{
//the handlers block is too far from the function end, make it a separate chunk
if (fixFunc)
{
Message("Making separate handlers block\n");
Unknown(z, y-z);
MakeCode(z);
MakeFunction(z,y);
AnalyseArea(z,y);
MakeCode(y);
MakeFunction(y,BADADDR);
}
SetFunctionFlags(z, GetFunctionFlags(start) | FUNC_FRAME);
SetFunctionCmt(z, form("Unwind handlers of %08X", start), 0);
}
else if (fixFunc)
{
Message("Merging handlers block with main function.\n");
Unknown(start, y-start);
MakeCode(start);
MakeFunction(start,y);
AnalyseArea(start,y);
}
/*
typedef const struct _s_TryBlockMapEntry {
int tryLow; //00
int tryHigh; //04
int catchHigh; //08
int nCatches; //0C
const struct _s_HandlerType * pHandlerArray; //10
} TryBlockMapEntry;
typedef const struct _s_HandlerType {
unsigned int adjectives; //00
struct TypeDescriptor * pType; //04
int dispCatchObj; //08
void * addressOfHandler; //0C
}
*/
//parse catch blocks
y = 0;
z = 0x7FFFFFFF;
i=0;
count = Dword(u+12); //nTryBlocks
x = Dword(u+16); //pTryBlocksMap
Message("%d try blocks\n",count);
while (i<count) {
cnt2 = Dword(x+12); //nCatches
a = Dword(x+16); //pHandlerArray
i2 = 0;
Message(" %d catches\n",cnt2);
while (i2<cnt2)
{
t = Dword(a+12);
//Message(" t=0x%08.8X\n",t);
if (t!=BADADDR && t>y)
y=t; //find lowest
if (z>t)
z=t; //find highest
a = a+16;
i2 = i2+1;
}
x = x+20;
i = i+1;
}
hasESP = 0;
if (count>0)
{
hasESP = 1;
//Message("y=0x%08.8X, z=0x%08.8X\n",y,z);
end = FindFuncEnd(y);
if (end==BADADDR) {
if (fixFunc)
{
MakeUnkn(y, 1);
MakeCode(y);
}
if (BADADDR == FindFuncEnd(y))
{
Message(form("Can't find function end at 0x%08X\n",y));
return;
}
}
Message(form("Catch blocks: %08X-%08X\n", z, end));
y = FindFuncEnd(start);
if (y ==-1 || end > y)
{
if (fixFunc)
{
Message("Merging catch blocks with main function.\n");
Unknown(start, end-start);
MakeCode(start);
MakeFunction(start,end);
AnalyseArea(start,end);
}
else
Message("Catch blocks are not inside the function!\n");
}
}
//comment unwind handlers
i=0;
count = Dword(u+4); //maxState
x = Dword(u+8); //pUnwindMap
while (i<count) {
t = Dword(x+4); //unwind action address
if (t!=0)
MakeComm(t, form("state %d -> %d",i, Dword(x)));
x = x+8;
i = i+1;
}
Parse_FuncInfo(u, 0);
CommentStackEH(func, hasESP, EHCookieOffset, GSCookieOffset);
}
static fixCxx(s, doSEH, fixFunc) {
auto x, start;
start = s;
if ((Word(start) != 0xA164) || (Dword(start+2)!=0)) {
Message("Should start with \"move eax, large fs:0\"!\n");
return;
}
if ( !doSEH && (Byte(start-10) == 0x55) && (Dword(start-9) == 0xFF6AEC8B))
{
//(ebp frame)
//00: 55 push ebp
//01: 8B EC mov ebp, esp
//03: 6A FF push 0FFFFFFFFh
//05: 68 xx xx xx xx push loc_xxxxxxxx
//0A: 64 A1 00 00 00 00 mov eax, large fs:0
//10: 50 push eax
//11: 64 89 25 00 00 00 00 mov large fs:0, esp
start = start - 10;
x = Dword(start+6);
//Message("Match 1\n");
}
else if (!doSEH && (Word(start+9) == 0xFF6A) && (Byte(start+11)==0x68))
{
//00: 64 A1 00 00 00 00 mov eax, large fs:0
//06: xx xx xx
//09: 6A FF push 0FFFFFFFFh
//0B: 68 xx xx xx xx push loc_xxxxxxxx
//10: 50 push eax
//
x = Dword(start+12);
//Message("Match 2\n");
}
else if (!doSEH && (Word(start-7) == 0xFF6A) && (Byte(start-5)==0x68))
{
//-7: 6A FF push 0FFFFFFFFh
//-5: 68 xx xx xx xx push loc_xxxxxxxx
//00: 64 A1 00 00 00 00 mov eax, large fs:0
//06: 50 push eax
//07: 64 89 25 00 00 00 00 mov large fs:0, esp
//
x = Dword(start-4);
start = start-7;
//Message("Match 3\n");
}
else if (!doSEH && (Word(start+6) == 0xFF6A) && (Byte(start+8)==0x68))
{
//00: 64 A1 00 00 00 00 mov eax, large fs:0
//06: 6A FF push 0FFFFFFFFh
//08: 68 xx xx xx xx push loc_xxxxxxxx
//0D: 50 push eax
//0E: 64 89 25 00 00 00 00 mov large fs:0, esp
x = Dword(start+9);
//Message("Match 4\n");
}
else if (doSEH && (Byte(start-5)==0x68) && (Byte(start-10)==0x68) && (Dword(start-15)==0x6AEC8B55))
{
//-15: 55 push ebp
//-14: 8B EC mov ebp, esp
//-12: 6A F? push 0FFFFFFF?h
//-10: 68 xx xx xx xx push offset __sehtable$_func1
//-5 : 68 xx xx xx xx push offset _except_handlerx
//00 : 64 A1 00 00 00 00 mov eax, large fs:0
x = Dword(start-9);
//Message("Match 5\n");
if (Byte(start-11) == 0xFF) //-1 = SEH3
fixSEHFunc(start-15,x, 3, fixFunc);
else if (Byte(start-11) == 0xFE) //-2 = SEH4
fixSEHFunc(start-15,x, 4, fixFunc);
else
Message("Unknown SEH handler!\n");
return;
}
else {
//probably a custom handler
//Message("\"push 0FFFFFFFFh; push offset loc\" not found!\n");
return;
}
Message(form("Fixing function at 0x%08X\n",start));
ParseCxxHandler(start, x, fixFunc);
}
static doEHProlog(name,fixFunc)
{
auto i,s,a;
a=LocByName(name);
if (a==BADADDR)
return;
Message("%s = %08X\n",name,a);
i=RfirstB(a);
while(i!=BADADDR)
{
Message("- %08X - ",i);
// -5: mov eax, offset loc_XXXXXX
// 0: call __EH_prolog
if (Byte(i-5)==0xB8)
ParseCxxHandler(i-5, Dword(i-4),fixFunc);
else
{
Message(form("No mov eax, offset loc_XXXXXX at %08X!!!\n",i-5));
return;
}
if (SetFunctionFlags(i,GetFunctionFlags(i) | FUNC_FRAME))
{
MakeFrame(i,GetFrameLvarSize(i), 4, GetFrameArgsSize(i));
if (fixFunc) AnalyseArea(i, FindFuncEnd(i)+1);
Message("OK\n");
}
else
Message("Error\n");
i=RnextB(a,i);
}
}
static doEHPrologs(name, fixFunc)
{
doEHProlog("j"+name,fixFunc);
doEHProlog("j_"+name,fixFunc);
doEHProlog(name,fixFunc);
doEHProlog("_"+name,fixFunc);
}
static fixEHPrologs(fixFunc)
{
doEHPrologs("_EH_prolog",fixFunc);
doEHPrologs("_EH_prolog3",fixFunc);
doEHPrologs("_EH_prolog3_catch",fixFunc);
doEHPrologs("_EH_prolog3_GS",fixFunc);
doEHPrologs("_EH_prolog3_catch_GS",fixFunc);
}
static isInCodeSeg(a)
{
if (SegName(a)==".text")
return 1;
else
return 0;
}
//check a scopetable entry
static checkEntry(a,i,ver)
{
auto x;
x = Dword(a);
//EnclosingLevel should be negative or less than i
if (x&0x80000000)
{
if (ver==3 && x!=0xFFFFFFFF)
return 0;
if (ver==4 && x!=0xFFFFFFFE)
return 0;
}
else if (x>=i)
return 0;
x = Dword(a+4);
if ((x!=0) && !isInCodeSeg(x)) //filter should be zero or point to the code
return 0;
x = Dword(a+8);
if (!isInCodeSeg(x)) //handler should point to the code
return 0;
//check if there are xref to fields (i.e. after the end of the scopetable)
if (((ver!=3)||(i>0)) && isRef(GetFlags(a)))
return 0;
if (isRef(GetFlags(a+4)) || isRef(GetFlags(a+8)))
return 0;
return 1;
}
//check if there's a valid scopetable and calculate number of entries in it
static checkScopeTable(a, ver)
{
auto i,k;
if (ver==4)
{
k = Dword(a);
if ((k&0x80000000)==0) //first field should be negative
return 0;
if ((k!=0xFFFFFFFE) && (k&3)!=0) //GS cookie offset should be -2 or dword-aligned
return 0;
k = Dword(a+8);
if ((k&0x80000000)==0) //offset should be negative
return 0;
if ((k&3)!=0) //EH cookie offset should be dword-aligned
return 0;
a = a+16; //move to the scope entries list
}
i = 0;
while (checkEntry(a,i,ver))
{
i = i+1;
a = a+12;
}
return i;
}
/*
struct _EH4_EXCEPTION_REGISTRATION_RECORD {
void* SavedESP;
_EXCEPTION_POINTERS* ExceptionPointers;
_EXCEPTION_REGISTRATION_RECORD* Next;
enum _EXCEPTION_DISPOSITION (*Handler)(_EXCEPTION_RECORD*, void*, _CONTEXT*, void*);
DWORD EncodedScopeTable;
unsigned long TryLevel;
};
*/
static getSEHRec()
{
auto id;
id = GetStrucIdByName("SEHRegistrationNode");
if (id==-1)
{
id = AddStruc(-1,"SEHRegistrationNode");
ForceDWMember(id, 0, "SavedESP");
ForceDWMember(id, 4, "ExceptionPointers");
ForceDWMember(id, 8, "Next");
ForceDWMember(id, 12, "Handler");
ForceDWMember(id, 16, "EncodedScopeTable");
ForceDWMember(id, 20, "TryLevel");
}
return id;
}
static CommentStackSEH(start, scopetable)
{
auto x;
CommentStack(start,-24, "__$SEHRec$", getSEHRec());
if (scopetable)
{
x = Dword(scopetable);
if (x!=-2)
CommentStack(start,x, "__$GSCookie$", -1);
x = Dword(scopetable+8);
CommentStack(start,x, "__$EHCookie$", -1);
}
}
static fixSEHFunc(func, scopetable, ver, fixFunc)
{
auto k,i,t,u,x,y,z,hasESP,end;
k = checkScopeTable(scopetable, ver);
if (k==0)
{
Message("Bad scopetable\n");
return;
}
Message("function: %08X, scopetable: %08X (%d entries)\n", func, scopetable, k);
x = scopetable;
if (ver==4) x = x+16;
//parse the scopetable!
y = 0;
z = 0x7FFFFFFF;
i = 0;
hasESP = 0;
while (i<k) {
t = Dword(x+4);
if (t) {
hasESP=1;
if (t>y) y=t; //find lowest
if (z>t) z=t; //find highest
//Message("t=0x%08.8X\n",t);
//check the code just before, it could be jump to the end of try
if (Byte(t-2)==0xEB)
t = getRelJmpTarget(t-2);
else if (Byte(t-5)==0xE9)
t = getRelJmpTarget(t-5);
//Message("t=0x%08.8X\n",t);
if (t>y) y=t; //find lowest
if (z>t) z=t; //find highest
}
t = Dword(x+8);
//check the code just before, it could be jump to the end of try
if (t>y) y=t; //find lowest
if (z>t) z=t; //find highest
//Message("t=0x%08.8X\n",t);
if (Byte(t-2)==0xEB)
t = getRelJmpTarget(t-2);
else if (Byte(t-5)==0xE9)
t = getRelJmpTarget(t-5);
//Message("t=0x%08.8X\n",t);
if (t>y) y=t; //find lowest
if (z>t) z=t; //find highest
x = x+12;
i = i+1;
}
//Message("y=0x%08.8X, z=0x%08.8X\n",y,z);
if (1)
{
end = FindFuncEnd(y);
if (end==BADADDR) {
if (fixFunc)
{
MakeUnkn(y, 1);
MakeCode(y);
}
if (BADADDR == FindFuncEnd(y))
{
Message(form("Can't find function end at 0x%08X\n",y));
return;
}
}
//Message(form("Except blocks: %08X-%08X\n", z, end));
z = FindFuncEnd(func);
if (z ==-1 || end > z && fixFunc)
{
//Message("Merging except blocks with main function.\n");
Unknown(func, end-func);
MakeCode(func);
MakeFunction(func,end);
AnalyseArea(func,end);
}
}
//walk once more and fix finally entries
x = scopetable;
if (ver==4) x = x+16;
i = 0;
while (fixFunc && i<k) {
if (Dword(x+4)==0 && Dword(x+8)==y)
{
//the last handler is a finally handler
//check that it ends with a ret, call or jmp
z = FindFuncEnd(y);
if (z!=BADADDR &&
!(Byte(z-1)==0xC3 || Byte(z-5)==0xE9 || Byte(z-5)==0xE8 ||
Byte(z-2)==0xEB || Byte(z-1)==0xCC || Word(z-6)==0x15FF) )
{
//we need to add the following funclet to our function
end = FindFuncEnd(z);
if (end!=BADADDR)
{
Unknown(z, end-z);
MakeCode(z);
SetFunctionEnd(func,end);
}
}
}
x = x+12;
i = i+1;
}
//comment the table and handlers
x = scopetable;
ExtLinA(x,0,form("; SEH scopetable for %08X",func));
if (ver==4)
{
OffCmt(x,"GSCookieOffset");
OffCmt(x+4,"GSCookieXOROffset");
OffCmt(x+8,"EHCookieOffset");
OffCmt(x+12,"EHCookieXOROffset");
x = x+16;
CommentStackSEH(func,scopetable);
}
else
CommentStackSEH(func,0);
i = 0;
while (i<k) {
ForceDword(x);
SoftOff(x+4);
SoftOff(x+8);
MakeComm(x, form("try block %d, enclosed by %d",i, Dword(x)));
t = Dword(x+4); //exception filter
if (t!=0)
ExtLinA(t,0,form("; __except() filter for try block %d",i));
u = Dword(x+8);
if (t!=0)
ExtLinA(u,0,form("; __except {} handler for try block %d",i));
else
ExtLinA(u,0,form("; __finally {} handler for try block %d",i));
x = x+12;
i = i+1;
}
}
static doSEHProlog(name, ver, fixFunc)
{
auto i,s,locals,scopetable,k,l,func,a;
a=LocByName(name);
if (a==BADADDR)
return;
Message("%s = %08X\n",name,a);
i=RfirstB(a);
while(i!=BADADDR)
{
Message("- %08X - ",i);
// -10 68 xx xx xx xx push xx
// or
// -7 6A xx push xx
// -5 68 xx xx xx xx push OFFSET __sehtable$_func
// 0 e8 00 00 00 00 call __SEH_prolog
//
//
locals = -1; scopetable=0;
if (Byte(i-5)==0x68)
{
scopetable = Dword(i-4);
if (Byte(i-7)==0x6A)
{
func = i-7;
locals = Byte(func+1);
}
else if (Byte(i-10)==0x68)
{
func = i-10;
locals = Dword(func+1);
}
if (GetFunctionFlags(func)==-1 && fixFunc)
{
MakeUnkn(func, 1);
MakeCode(func);
MakeFunction(func, BADADDR);
}
if (SetFunctionFlags(func,GetFunctionFlags(func)|FUNC_FRAME))
{
MakeFrame(func, GetFrameLvarSize(func), 4, GetFrameArgsSize(func));
fixSEHFunc(func, scopetable, ver, fixFunc);
Message("OK\n");
}
else
Message("Error\n");
}
i=RnextB(a,i);
}
}
static doSEHPrologs(name, ver, fixFunc)
{
doSEHProlog("j"+name, ver, fixFunc);
doSEHProlog("j_"+name, ver, fixFunc);
doSEHProlog(name, ver, fixFunc);
doSEHProlog("_"+name, ver, fixFunc);
}
static fixSEHPrologs(fixFunc)
{
doSEHPrologs("_SEH_prolog",3, fixFunc);
doSEHPrologs("__SEH_prolog",3, fixFunc);
doSEHPrologs("_SEH_prolog4",4, fixFunc);
doSEHPrologs("__SEH_prolog4",4, fixFunc);
doSEHPrologs("_SEH_prolog4_GS",4, fixFunc);
doSEHPrologs("__SEH_prolog4_GS",4, fixFunc);
}
static findFunc(name)
{
auto a;
a = LocByName("j_"+name);
if (a==BADADDR)
a = LocByName(name);
return a;
}
static doSEH(fixFunc)
{
auto start, a;
start = 0;
while (1) {
//mov eax, large fs:0
start = FindBinary(start+1, 3, "64 A1 00 00 00 00");
if (start==BADADDR)
break;
fixCxx(start,1,fixFunc);
}
fixSEHPrologs(fixFunc);
}
static doEH(fixFunc)
{
auto start, a;
start = 0;
while (1) {
//mov eax, large fs:0
start = FindBinary(start+1, 3, "64 A1 00 00 00 00");
if (start==BADADDR)
break;
fixCxx(start,0,fixFunc);
}
fixEHPrologs(fixFunc);
}
static main(void)
{
auto seh, fixseh, eh, fixeh;
seh = AskYN(1, "Do you wish to parse all Win32 SEH handlers?");
if (seh==-1) return;
if (seh) {
fixseh = AskYN(1, "Do you wish to fix function boundaries as needed?");
if (fixseh==-1) return;
}
eh = AskYN(1, "Do you wish to parse all C++ EH handlers?");
if (eh==-1) return;
if (eh) {
fixeh = AskYN(1, "Do you wish to fix function boundaries as needed?");
if (fixeh==-1) return;
}
if (seh) doSEH(fixseh);
if (eh) doEH(fixeh);
//fixCxx(ScreenEA());
}

File diff suppressed because it is too large Load Diff

@ -1,660 +0,0 @@
#include <idc.idc>
#include "vtable.idc"
#include "ms_rtti.idc"
static GetAsciizStr(x)
{
auto s,c;
s = "";
while (c=Byte(x))
{
s = form("%s%c",s,c);
x = x+1;
}
return s;
}
// ??1?$CEventingNode@VCMsgrAppInfoImpl@@PAUIMsgrUser@@ABUtagVARIANT@@@@UAE@XZ
// ??_G CWin32Heap@ATL @@UAEPAXI@Z
// ATL::CWin32Heap::`scalar deleting destructor'(uint)
// .?AV?$CEventingNode@VCMsgrAppInfoImpl@@PAUIMsgrUser@@ABUtagVARIANT@@@@
// ??_7?$CEventingNode@VCMsgrAppInfoImpl@@PAUIMsgrUser@@ABUtagVARIANT@@@@6B@
// ??_G?$CEventingNode@VCMsgrAppInfoImpl@@PAUIMsgrUser@@ABUtagVARIANT@@@@@@UAEPAXI@Z
#define SN_constructor 1
#define SN_destructor 2
#define SN_vdestructor 3
#define SN_scalardtr 4
#define SN_vectordtr 5
static MakeSpecialName(name, type, adj)
{
auto basename;
//.?AUA@@ = typeid(struct A)
//basename = A@@
basename = substr(name,4,-1);
if (type==SN_constructor)
{
//??0A@@QAE@XZ = public: __thiscall A::A(void)
if (adj==0)
return "??0"+basename+"QAE@XZ";
else
return "??0"+basename+"W"+MangleNumber(adj)+"AE@XZ";
}
else if (type==SN_destructor)
{
//??1A@@QAE@XZ = "public: __thiscall A::~A(void)"
if (adj==0)
return "??1"+basename+"QAE@XZ";
else
return "??1"+basename+"W"+MangleNumber(adj)+"AE@XZ";
}
else if (type==SN_vdestructor)
{
//??1A@@UAE@XZ = public: virtual __thiscall A::~A(void)
if (adj==0)
return "??1"+basename+"UAE@XZ";
else
return "??1"+basename+"W"+MangleNumber(adj)+"AE@XZ";
}
else if (type==SN_scalardtr) //
{
//??_GA@@UAEPAXI@Z = public: virtual void * __thiscall A::`scalar deleting destructor'(unsigned int)
if (adj==0)
return "??_G"+basename+"UAEPAXI@Z";
else
return "??_G"+basename+"W"+MangleNumber(adj)+"AEPAXI@Z";
}
else if (type==SN_vectordtr)
{
//.?AUA@@ = typeid(struct A)
//??_EA@@UAEPAXI@Z = public: virtual void * __thiscall A::`vector deleting destructor'(unsigned int)
if (adj==0)
return "??_E"+basename+"QAEPAXI@Z";
else
return "??_E"+basename+"W"+MangleNumber(adj)+"AEPAXI@Z";
}
}
static DumpNestedClass2(x, indent, contained, f)
{
auto indent_str,i,a,n,p,s,off;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
i=0;
//indent=indent+1;
a = x;
while(i<contained)
{
p = Dword(a);
off = Dword(p+8);
s = form("%.4X: ",off);
//Message("%s%s%s\n", s, indent_str, GetClassName(p));
fprintf(f, form("%s%s%s\n",s,indent_str,GetClassName(p)));
n = Dword(p+4);
if (n>0) //check numContainedBases
DumpNestedClass2(a+4, indent+1, n, f); //nested classes following
a=a+4*(n+1);
i=i+n+1;
}
}
static Parse_CHD2(x, indent, f)
{
auto indent_str,i,a,n,p,s,off;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
a = Dword(x+4);
if ((a&3)==1)
p = "(MI)";
else if ((a&3)==2)
p = "(VI)";
else if ((a&3)==3)
p = "(MI VI)";
else
p="(SI)";
fprintf(f, form("%s%s\n",indent_str,p));
a=Dword(x+12);
n=Dword(x+8);
DumpNestedClass2(a, indent, n, f);
}
static GetTypeName2(col)
{
auto x, s, c;
//Message("GetTypeName2(%X)\n",col)
x = Dword(col+12);
if ((!x) || (x==BADADDR)) return "";
return GetAsciizStr(x+8);
}
static GetVtblName2(col)
{
auto i, s, s2;
s = GetTypeName2(col);
i = Dword(col+16); //CHD
i = Dword(i+4); //Attributes
if ((i&3)==0 && Dword(col+4)==0)
{
//Single inheritance, so we don't need to worry about duplicate names (several vtables)
s=substr(s,4,-1);
return "??_7"+s+"6B@";
}
else //if ((i&3)==1) //multiple inheritance
{
s2 = GetVtableClass(col);
s2 = substr(s2,4,-1);
s = substr(s,4,-1);
s = s+"6B"+s2+"@";
return "??_7"+s;
}
return "";
}
//check if Dword(vtbl-4) points to typeinfo record and extract the type name from it
static IsValidCOL(col)
{
auto x, s, c;
x = Dword(col+12);
if ((!x) || (x==BADADDR)) return "";
x = Dword(x+8);
if ((x&0xFFFFFF) == 0x413F2E) //.?A
return 1;
else
return 0;
}
static funcStart(ea)
{
if (GetFunctionFlags(ea) == -1)
return -1;
if ((GetFlags(ea)&FF_FUNC)!=0)
return ea;
else
return PrevFunction(ea);
}
// Add ea to "Sorted Address List"
static AddAddr(ea)
{
auto id, idx, val;
if ( (id = GetArrayId("AddrList")) == -1 )
{
id = CreateArray("AddrList");
SetArrayLong(id, 0, ea);
return;
}
for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) )
{
val = GetArrayElement(AR_LONG, id, idx);
if ( val == ea )
return;
if ( val > ea ) // InSort
{
for ( ; idx != -1; idx = GetNextIndex(AR_LONG, id, idx) )
{
val = GetArrayElement(AR_LONG, id, idx);
SetArrayLong(id, idx, ea);
ea = val;
}
}
}
SetArrayLong(id, GetLastIndex(AR_LONG, id) + 1, ea);
}
static getArraySize(id)
{
auto idx, count;
count = 0;
for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) )
{
count++;
}
return count;
}
static doAddrList(name,f)
{
auto idx, id, val, ctr, dtr;
id = GetArrayId("AddrList");
ctr = 0; dtr = 0;
if ( name!=0 && id != -1 )
{
Message("refcount:%d\n",getArraySize(id));
if (getArraySize(id)!=2)
return;
for ( idx = GetFirstIndex(AR_LONG, id); idx != -1; idx = GetNextIndex(AR_LONG, id, idx) )
{
val = GetArrayElement(AR_LONG, id, idx);
if (Byte(val)==0xE9)
val = getRelJmpTarget(val);
if ((substr(Name(val),0,3)=="??1"))
dtr = val;
else
ctr = val;
}
}
if (ctr!=0 && dtr!=0)
{
Message(" constructor at %a\n",ctr);
fprintf(f, " constructor: %08.8Xh\n",ctr);
MakeName(ctr, MakeSpecialName(name,SN_constructor,0));
}
DeleteArray(GetArrayId("AddrList"));
}
//check if there's a vtable at a and dump into to f
//returns position after the end of vtable
static DoVtable(a,f)
{
auto x,y,s,p,q,i,name;
//check if it looks like a vtable
y = GetVtableSize(a);
if (y==0)
return a+4;
s = form("%08.8Xh: possible vtable (%d methods)\n", a, y);
Message(s);
fprintf(f,s);
//check if it's named as a vtable
name = Name(a);
if (substr(name,0,4)!="??_7") name=0;
x = Dword(a-4);
//otherwise try to get it from RTTI
if (IsValidCOL(x))
{
Parse_Vtable(a);
if (name==0)
name = GetVtblName2(x);
//only output object tree for main vtable
if (Dword(x+4)==0)
Parse_CHD2(Dword(x+16),0,f);
MakeName(a, name);
}
if (name!=0)
{
s = Demangle(name, 0x00004006);
Message("%s\n",s);
fprintf(f, "%s\n", s);
//convert vtable name into typeinfo name
name = ".?AV"+substr(name, 4, strstr(name,"@@6B")+2);
}
{
DeleteArray(GetArrayId("AddrList"));
Message(" referencing functions: \n");
fprintf(f," referencing functions: \n");
q = 0; i = 1;
for ( x=DfirstB(a); x != BADADDR; x=DnextB(a,x) )
{
p = funcStart(x);
if (p!=-1)
{
if (q==p)
i++;
else
{
if (q) {
if (i>1) s = form(" %a (%d times)",q,i);
else s = form(" %a",q);
//if (strstr(Name(p),"sub_")!=0 && strstr(Name(p),"j_sub_")!=0)
if (hasName(GetFlags(q)))
s = s+" ("+Demangle(Name(q),8)+")";
s = s+"\n";
Message(s);fprintf(f,s);
AddAddr(q);
}
i = 1;
q = p;
}
}
}
if (q)
{
if (i>1) s = form(" %a (%d times)",q,i);
else s = form(" %a",q);
if (hasName(GetFlags(q)))
s = s+" ("+Demangle(Name(q),8)+")";
s = s+"\n";
Message(s);fprintf(f,s);
AddAddr(q);
}
x = a;
while (y>0)
{
p = Dword(x);
if (GetFunctionFlags(p) == -1)
{
MakeCode(p);
MakeFunction(p, BADADDR);
}
checkSDD(p,name,a,0,f);
y--;
x = x+4;
}
doAddrList(name,f);
Message("\n");
fprintf(f,"\n");
}
return x;
}
static scan_for_vtables(void)
{
auto rmin, rmax, cmin, cmax, s, a, x, y,f;
s = FirstSeg();
f = fopen("objtree.txt","w");
rmin = 0; rmax = 0;
while (s!=BADADDR)
{
if (SegName(s)==".rdata")
{
rmin = s;
rmax = NextSeg(s);
}
else if (SegName(s)==".text")
{
cmin = s;
cmax = NextSeg(s);
}
s = NextSeg(s);
}
if (rmin==0) {rmin=cmin; rmax=cmax;}
a = rmin;
Message(".rdata: %08.8Xh - %08.8Xh, .text %08.8Xh - %08.8Xh\n", rmin, rmax, cmin, cmax);
while (a<rmax)
{
x = Dword(a);
if (x>=cmin && x<cmax) //methods should reside in .text
{
a = DoVtable(a,f);
}
else
a = a + 4;
}
Message("Done\n");
fclose(f);
}
//check for `scalar deleting destructor'
static checkSDD(x,name,vtable,gate,f)
{
auto a,s,t;
//Message("checking function at %a\n",x);
t = 0; a = BADADDR;
if ((name!=0) && (substr(Name(x),0,3)=="??_") && (strstr(Name(x),substr(name,4,-1))==4))
name=0; //it's already named
if (Byte(x)==0xE9 || Byte(x)==0xEB) {
//E9 xx xx xx xx jmp xxxxxxx
return checkSDD(getRelJmpTarget(x),name,vtable,1,f);
}
else if (matchBytes(x,"83E9??E9")) {
//thunk
//83 E9 xx sub ecx, xx
//E9 xx xx xx xx jmp class::`scalar deleting destructor'(uint)
a = getRelJmpTarget(x+3);
Message(" %a: thunk to %a\n",x,a);
t = checkSDD(a,name,vtable,0,f);
if (t && name!=0)
{
//rename this function as a thunk
MakeName(x, MakeSpecialName(name,t,Byte(x+2)));
}
return t;
}
else if (matchBytes(x,"81E9????????E9")) {
//thunk
//81 E9 xx xx xx xx sub ecx, xxxxxxxx
//E9 xx xx xx xx jmp class::`scalar deleting destructor'(uint)
a = getRelJmpTarget(x+6);
Message(" %a: thunk to %a\n",x,a);
t = checkSDD(a,name,vtable,0,f);
if (t && name!=0)
{
//rename this function as a thunk
MakeName(x, MakeSpecialName(name,t,Dword(x+2)));
}
return t;
}
else if (matchBytes(x,"568BF1E8????????F64424080174") && matchBytes(x+15+Byte(x+14),"8BC65EC20400"))
{
//56 push esi
//8B F1 mov esi, ecx
//E8 xx xx xx xx call class::~class()
//F6 44 24 08 01 test [esp+arg_0], 1
//74 07 jz short @@no_free
//56 push esi
//
// call operator delete();
// @@no_free:
//8B C6 mov eax, esi
//5E pop esi
//C2 04 00 retn 4
t = SN_scalardtr;
a = getRelCallTarget(x+3);
if (gate && Byte(a)==0xE9)
{
//E9 xx xx xx xx jmp xxxxxxx
a = getRelJmpTarget(a);
}
}
else if (matchBytes(x,"568BF1FF15????????F64424080174") && matchBytes(x+16+Byte(x+15),"8BC65EC20400"))
{
//56 push esi
//8B F1 mov esi, ecx
//FF 15 xx xx xx xx call class::~class() //dllimport
//F6 44 24 08 01 test [esp+arg_0], 1
//74 07 jz short @@no_free
//56 push esi
//
// call operator delete();
// @@no_free:
//8B C6 mov eax, esi
//5E pop esi
//C2 04 00 retn 4
t = SN_scalardtr;
/*a = getRelCallTarget(x+3);
if (gate && Byte(a)==0xE9)
{
//E9 xx xx xx xx jmp xxxxxxx
a = getRelJmpTarget(a);
}*/
}
else if (matchBytes(x,"558BEC51894DFC8B4DFCE8????????8B450883E00185C0740C8B4DFC51E8????????83C4048B45FC8BE55DC20400") ||
matchBytes(x,"558BEC51894DFC8B4DFCE8????????8B450883E00185C074098B4DFC51E8????????8B45FC8BE55DC20400"))
{
//55 push ebp
//8B EC mov ebp, esp
//51 push ecx
//89 4D FC mov [ebp+var_4], ecx
//8B 4D FC mov ecx, [ebp+var_4]
//E8 xx xx xx xx call sub_10001099
//8B 45 08 mov eax, [ebp+arg_0]
//83 E0 01 and eax, 1
//85 C0 test eax, eax
//74 0C jz short skip
//8B 4D FC mov ecx, [ebp+var_4]
//51 push ecx
//E8 F0 56 05 00 call operator delete(void *)
//83 C4 04 add esp, 4
//
// skip:
//8B 45 FC mov eax, [ebp+var_4]
//8B E5 mov esp, ebp
//5D pop ebp
//C2 04 00 retn 4
t = SN_scalardtr;
a = getRelCallTarget(x+10);
if (gate && Byte(a)==0xE9)
{
//E9 xx xx xx xx jmp xxxxxxx
a = getRelJmpTarget(a);
}
}
else if (matchBytes(x,"568D71??578D7E??8BCFE8????????F644240C01"))
{
//56 push esi
//8D 71 xx lea esi, [ecx-XX]
//57 push edi
//8D 7E xx lea edi, [esi+XX]
//8B CF mov ecx, edi
//E8 xx xx xx xx call class::~class()
//F6 44 24 0C 01 test [esp+4+arg_0], 1
a = getRelCallTarget(x+10);
if (gate && Byte(a)==0xE9)
{
a = getRelJmpTarget(a);
}
t=SN_scalardtr;
}
else if (matchBytes(x,"568DB1????????578DBE????????8BCFE8????????F644240C01"))
{
//56 push esi
//8D B1 xx xx xx xx lea esi, [ecx-XX]
//57 push edi
//8D BE xx xx xx xx lea edi, [esi+XX]
//8B CF mov ecx, edi
//E8 xx xx xx xx call class::~class()
//F6 44 24 0C 01 test [esp+4+arg_0], 1
a = getRelCallTarget(x+16);
if (gate && Byte(a)==0xE9)
{
a = getRelJmpTarget(a);
}
t = SN_scalardtr;
}
else if ((matchBytes(x,"F644240401568BF1C706") /*&& Dword(x+10)==vtable*/) ||
(matchBytes(x,"8A442404568BF1A801C706") /*&& Dword(x+11)==vtable */) ||
(matchBytes(x,"568BF1C706????????E8????????F64424080174") && matchBytes(x+21+Byte(x+20),"8BC65EC20400"))
)
{
//F6 44 24 04 01 test [esp+arg_0], 1
//56 push esi
//8B F1 mov esi, ecx
// OR
//8A 44 24 04 mov al, [esp+arg_0]
//56 push esi
//8B F1 mov esi, ecx
//A8 01 test al, 1
//C7 06 xx xx xx xx mov dword ptr [esi], xxxxxxx //offset vtable
// <inlined destructor>
//74 07 jz short @@no_free
//56 push esi
//E8 CA 2D 0D 00 call operator delete(void *)
//59 pop ecx
// @@no_free:
//8B C6 mov eax, esi
//5E pop esi
//C2 04 00 retn 4
t = SN_scalardtr;
}
else if (matchBytes(x,"538A5C2408568BF1F6C302742B8B46FC578D7EFC68????????506A??56E8") ||
matchBytes(x,"538A5C2408F6C302568BF1742E8B46FC5768????????8D7EFC5068????????56E8"))
{
//53 push ebx
//8A 5C 24 08 mov bl, [esp+arg_0]
//56 push esi
//8B F1 mov esi, ecx
//F6 C3 02 test bl, 2
//74 2B jz short loc_100037F8
//8B 46 FC mov eax, [esi-4]
//57 push edi
//8D 7E FC lea edi, [esi-4]
//68 xx xx xx xx push offset class::~class(void)
//50 push eax
//6A xx push xxh
//56 push esi
//E8 xx xx xx xx call `eh vector destructor iterator'(void *,uint,int,void (*)(void *))
t = SN_vectordtr;
Message(" vector deleting destructor at %a\n",x);
if (name!=0)
a = Dword(x+21);
if (gate && Byte(a)==0xE9)
{
a = getRelJmpTarget(a);
}
}
if (t>0)
{
if (t==SN_vectordtr)
s = "vector";
else
s = "scalar";
Message(" %s deleting destructor at %a\n",s,x);
fprintf(f, " %s deleting destructor: %08.8Xh\n",s,x);
if (name!=0)
MakeName(x, MakeSpecialName(name,t,0));
if (a!=BADADDR)
{
Message(" virtual destructor at %a\n",a);
fprintf(f, " destructor: %08.8Xh\n",a);
if (name!=0)
MakeName(a, MakeSpecialName(name,SN_vdestructor,0));
}
CommentStack(x, 4, "__flags$",-1);
}
return t;
}
static ParseVtbl2()
{
auto a, n;
a = ScreenEA();
if (GetVtableSize(a)==0)
{
Warning("This location doesn't look like a vtable!");
return;
}
if (!hasName(GetFlags(a)) && !IsValidCOL(Dword(a-4)))
{
n = AskStr("","Enter class name");
if (n!=0)
MakeName(a,"??_7"+n+"@@6B@");
}
DoVtable(a,0);
}
static AddHotkeys()
{
AddHotkey("Alt-F7","ParseFI");
AddHotkey("Alt-F8","ParseVtbl2");
AddHotkey("Alt-F9","ParseExc");
Message("Use Alt-F7 to parse FuncInfo\n");
Message("Use Alt-F8 to parse vtable\n");
Message("Use Alt-F9 to parse throw info\n");
}
static main(void)
{
if(AskYN(1, "Do you wish to scan the executable for vtables/RTTI?"))
{
Message("Scanning...");
scan_for_vtables();
//Message("See objtree.txt for the class list/hierarchy.\n");
Exec("objtree.txt");
}
AddHotkeys();
}

File diff suppressed because it is too large Load Diff

@ -1,8 +0,0 @@
#!/usr/bin/perl
#local $/ = "\n\n";
while(<>){
if(/([0-9A-Z]+).*?([a-z]+_.+?)st\n/s){
print "<class vtable=\"0x$1\" name=\"$2\" />\n";
}
}

@ -1,43 +0,0 @@
#include <idc.idc>
static main(void)
{
auto SearchString;
auto searchStart;
auto searchTest;
auto occurances;
auto szFilePath,hFile;
auto strSize;
auto vTablePtr;
auto vTableLoc;
auto myString;
auto nextAddress;
auto byteVal;
occurances = 0;
searchStart = 0;
SearchString = AskStr("", "What vtable binary to search?");
szFilePath = AskFile(1, "*.txt", "Select output dump file:");
hFile = fopen(szFilePath, "wb");
Message("Scanning...");
searchStart = FindBinary(searchStart, SEARCH_DOWN, SearchString);
while(searchStart != BADADDR){
MakeStr(searchStart-2, BADADDR);
myString = GetString(searchStart-2,-1,GetStringType(searchStart-2));
strSize = strlen(myString);
nextAddress = searchStart-2+strSize+1;
byteVal = Byte(nextAddress);
while(byteVal == 0){
nextAddress++;
byteVal = Byte(nextAddress);
}
MakeDword(nextAddress);
vTableLoc = FindBinary(141301056,SEARCH_DOWN, form("%X", nextAddress));
MakeDword(nextAddress+4);
fprintf(hFile,"%a\t%s\n",vTableLoc,myString);
searchStart = FindBinary(searchStart+1, SEARCH_DOWN, SearchString);
occurances++;
}
fclose(hFile);
Message("Found %i Occurances",occurances);
}

@ -1,114 +0,0 @@
#include <idc.idc>
static GetVtableSize(a)
{
auto b,c,f;
b = BADADDR;
f = GetFlags(a);
//Message("checking vtable at: %a\n",a);
do {
f = GetFlags(a);
if (b == BADADDR) //first entry
{
b=a;
if (!(isRef(f) && (hasName(f) || (f&FF_LABL))))
{
//Message("Start of vtable should have a xref and a name (auto or manual)\n");
return 0;
}
}
else if (isRef(f)) //might mean start of next vtable
break;
//Message("hasValue(f):%d, isData(f):%d, isOff0(f):%d, (f & DT_TYPE) != FF_DWRD:%d\n",
// hasValue(f), isData(f), isOff0(f), (f & DT_TYPE) != FF_DWRD);
if (!hasValue(f) || !isData(f) /*|| !isOff0(f) || (f & DT_TYPE) != FF_DWRD*/)
break;
c = Dword(a);
if (c)
{
f = GetFlags(c);
if (!hasValue(f) || !isCode(f) || Dword(c)==0)
break;
}
a = a+4;
}
while (1);
if (b!=BADADDR)
{
c = (a-b)/4;
//Message("vtable: %08X-%08X, methods: %d\n",b,a,c);
return c;
}
else
{
//Message("no vtable at this EA\n");
return 0;
}
}
static main(void)
{
auto a, c, k, name, i, struct_id, bNameMethods,e, methName;
a = ScreenEA();
k = GetVtableSize(a);
if (k>100)
{
if (1!=AskYN(0,form("%08X: This vtable appears to have %d methods. Are you sure you want to continue?",a,k)))
return;
}
if (hasName(GetFlags(a)))
name = Name(a);
else
name = "";
if (substr(name,0,4)=="??_7")
name = substr(name,4,strlen(name)-5);
name = AskStr(name,"Please enter the class name");
if (name==0)
return;
struct_id = GetStrucIdByName(name+"_vtable");
if (struct_id != -1)
{
i = AskYN(0,form("A vtable structure for %s already exists. Are you sure you want to remake it?",name));
if (i==-1)
return;
if (i==1)
{
DelStruc(struct_id);
struct_id = AddStrucEx(-1,name+"_vtable",0);
}
}
else
struct_id = AddStrucEx(-1,name+"_vtable",0);
if (struct_id == -1)
Warning("Could not create the vtable structure!.\nPlease check the entered class name.");
bNameMethods = (1==AskYN(0,form("Would you like to assign auto names to the virtual methods (%s_virtXX)?",name)));
for (i=0;i<k;i++)
{
c = Dword(a+i*4);
if (bNameMethods && !hasName(GetFlags(c)))
MakeName(c,form("%s_virt%02X",name,i*4));
if (hasName(GetFlags(c)))
{
methName = Name(c);
if (substr(methName,0,1)=="?")
{
methName = substr(methName,1,strstr(methName,"@"));
}
}
else
methName = form("virt%02X",i*4);
e = AddStrucMember(struct_id,methName,i*4,FF_DWRD|FF_DATA,-1,4);
if (0!=e)
{
if (e!=-2 && e!=-1)
{
Warning(form("Error adding a vtable entry (%d)!",e));
return;
}
else if (substr(GetMemberName(struct_id, i*4),0,6)=="field_")
SetMemberName(struct_id, i*4, form("virt%02X",i*4));
}
SetMemberComment(struct_id,i*4,form("-> %08X, args: 0x%X",c,GetFrameArgsSize(c)),1);
}
MakeName(a,"??_7"+name+"@@6B@");
}