chore(binana): update files

This commit is contained in:
phaneron 2024-07-13 17:42:21 -04:00
parent 1400de8b1f
commit c30e1199d7
24 changed files with 35645 additions and 4286 deletions

View file

@ -0,0 +1 @@
CDataRecyler__Clear 0095CEC0 f end=0095CF39

View file

@ -23,6 +23,7 @@ typedef struct CGxAppRenderState CGxAppRenderState;
typedef struct CGxPushedRenderState CGxPushedRenderState;
typedef struct ShaderConstants ShaderConstants;
typedef struct CGxDevice CGxDevice;
typedef struct CGxDevice__vtable CGxDevice__vtable;
struct CGxAppRenderState {
CGxStateBom m_value;
@ -44,16 +45,110 @@ struct ShaderConstants {
uint32_t unk2;
};
// 84 functions
struct CGxDevice__vtable {
// void ITexMarkAsUpdated(CGxTex*, unsigned int);
void* v_fn_0_ITexMarkAsUpdated;
// void IRsSendToHw(EGxRenderState);
void* v_fn_1_IRsSendToHw;
// void ICursorCreate(CGxFormat const&);
void* v_fn_2_ICursorCreate;
// void ICursorDestroy();
void* v_fn_3_ICursorDestroy;
// void ICursorDraw();
void* v_fn_4_ICursorDraw;
void* v_fn_5;
void* v_fn_6;
void* v_fn_7;
void* v_fn_8;
void* v_fn_9;
void* v_fn_10_DeviceCreate;
void* v_fn_11;
void* v_fn_12;
void* v_fn_13_DeviceSetFormat;
void* v_fn_14_DeviceSetBaseMipLevel;
void* v_fn_15_DeviceSetGamma;
void* v_fn_16;
void* v_fn_17;
void* v_fn_18;
void* v_fn_19;
void* v_fn_20;
void* v_fn_21;
void* v_fn_22;
void* v_fn_23;
void* v_fn_24;
void* v_fn_25;
void* v_fn_26;
void* v_fn_27;
void* v_fn_28;
void* v_fn_29;
void* v_fn_30;
void* v_fn_31;
void* v_fn_32;
void* v_fn_33;
void* v_fn_34;
void* v_fn_35_CapsWindowSize;
void* v_fn_36;
void* v_fn_37;
void* v_fn_38;
void* v_fn_39;
void* v_fn_40;
void* v_fn_41;
void* v_fn_42;
void* v_fn_43;
void* v_fn_44;
void* v_fn_45;
void* v_fn_46;
void* v_fn_47;
void* v_fn_48;
void* v_fn_49;
void* v_fn_50;
void* v_fn_51;
void* v_fn_52;
void* v_fn_53;
void* v_fn_54;
void* v_fn_55;
void* v_fn_56;
void* v_fn_57;
void* v_fn_58;
void* v_fn_59;
void* v_fn_60;
void* v_fn_61;
void* v_fn_62;
void* v_fn_63;
void* v_fn_64;
void* v_fn_65;
void* v_fn_66;
void* v_fn_67;
void* v_fn_68;
void* v_fn_69;
void* v_fn_70;
void* v_fn_71;
void* v_fn_72;
void* v_fn_73;
void* v_fn_74;
void* v_fn_75;
void* v_fn_76;
void* v_fn_77;
void* v_fn_78;
void* v_fn_79;
void* v_fn_80;
void* v_fn_81;
void* v_fn_82;
void* v_fn_83;
};
// this class is at least 14688 bytes in size
struct CGxDevice {
// TODO: pointer to struct CGxDevice__vtable
void* v_vtable;
CGxDevice__vtable* v_vtable; // 0x0
TSGrowableArray_CGxPushedRenderState m_pushedStates;
TSGrowableArray_uint32_t m_stackOffsets;
TSGrowableArray_EGxRenderState m_dirtyStates;
uint32_t m_unk[73];
CRect m_defWindowRect;
CRect m_curWindowRect;
EGxApi m_api;
CRect m_curWindowRect; // 0x174
EGxApi m_api; // 0x1b4
CGxFormat m_format;
CGxCaps m_caps;
// TSHashTable_CGxShader_HASHKEY_STRI m_shaderList[GxShTargets_Last];

View file

@ -22,6 +22,7 @@
#include "gx/types.h"
// include files that define the use of template classes for standard library types
// template classes for whoa types should be entered immediately after where the type is
#include "storm/array/uint32_t.h"

View file

@ -1,9 +1,17 @@
SetPaths 00402b20 f
CommonMain 00406c70 f
InitializeGlobal 004067f0 f
DestroyGlobal 00406b70 f
CmdLineProcess 0047b720 f
NDCToDDCHeight 0047c080 f
TextBlockCreate 004bdaa0 f
TextBlockGenerateFont 004be9c0 f
ScrnLayerCreate 004a8bb0 f
SetPaths 00402B20 f end=00402B8B
CommonMain 00406C70 f end=00406D64
InitializeGlobal 004067F0 f end=00406B67
DestroyGlobal 00406B70 f end=00406C65
CmdLineProcess 0047B720 f end=0047B736
CSRWLock__Enter 0047D0E0 f
CSRWLock__Leave 00481390 f
NDCToDDCHeight 0047C080 f end=0047C08E
NDCToDDC 0047BFF0 f end=0047C019
DDCToNDC 0047C020 f end=0047C049
ConvertPosition 0047FC90 f end=0047FDD4
TextBlockCreate 004BDAA0 f end=004BDBE4
TextBlockGenerateFont 004BE9C0 f end=004BEB8C
TextBlockGetFontPtr 004BD9D0 f end=004BD9EA
ScrnLayerCreate 004A8BB0 f end=004A8C83
ScrnLayerSetRect 004A8500 f end=004A8522
ClientKillTimer 004033B0 f end=004033B9

View file

@ -1,38 +1,41 @@
CVar__Register 00767fc0 f
CVar__Initialize 00768340 f
CVar__Set 007668c0 f
CVar__Destroy 007673f0 f
CVarSaveFile 00767100 f
CVarLoadFile 00766530 f
ConsoleAccessGetEnabled 00769230 f
ConsoleCommand_Quit 00768410 f
ConsoleCommandExecute 007658a0 f
ConsoleCommandHistory 00768440 f
ConsoleCommandHistoryDepth 0095bfb0 f
ConsoleCommandHistoryPrev 00763b40 f ; UC
ConsoleCommandHistoryNext 00763b90 f ; UC
ConsoleCommandRegister 00769100 f
ConsoleCommandUnregister 007689e0 f
ConsoleDeviceInitialize 0076ab80 f
ConsolePostClose 00763c50 f
ConsoleScreenInitialize 00766140 f
ConsoleWrite 00765270 f
ConsoleWriteA 007653b0 f
EventCloseCallback 00763d60 f
PaintBackground 007643f0 f
PaintText 007645e0 f
OnChar 00764990 f
OnIdle 007659c0 f
OnKeyDown 00765af0 f
OnKeyUp 00763be0 f
OnKeyDownRepeat 00764b90 f
MakeCommandCurrent 00763a60 f
ReserveInputSpace 007637d0 f
GetInputLine 00764520 f
PasteInInputLine 00764800 f
SetInputString 00763730 f ; UC
ResetHighlight 00763830 f
UpdateHighlight 00763860 f
DrawCaret 007641a0 f
DrawBackground 00763df0 f
DrawHighLight 00764040 f
CVar__Set 007668C0 f end=00766936
CVar__Destroy 007673F0 f end=00767434
CVar__Register 00767FC0 f end=007681E9
CVar__Initialize 00768340 f end=00768402
CVarSaveFile 00767100 f end=0076719C
CVarLoadFile 00766530 f end=007665C2
ConsoleAccessGetEnabled 00769230 f end=00769236
ConsoleCommand_Quit 00768410 f end=0076841B
ConsoleCommandExecute 007658A0 f end=007659BF
ConsoleCommandHistory 00768440 f end=0076845B
ConsoleCommandHistoryDepth 0095BFB0 f end=0095BFB6
ConsoleCommandHistoryPrev 00763B40 f end=00763B83 ; UC
ConsoleCommandHistoryNext 00763B90 f end=00763BD6 ; UC
ConsoleCommandRegister 00769100 f end=007691B3
ConsoleCommandUnregister 007689E0 f end=00768A19
ConsoleDeviceInitialize 0076AB80 f end=0076B287
ConsolePostClose 00763C50 f end=00763C5D
ConsoleScreenInitialize 00766140 f end=00766295
ConsoleWrite 00765270 f end=00765359
ConsoleWriteA 007653B0 f end=00765400
EventCloseCallback 00763D60 f end=00763D71
PaintBackground 007643F0 f end=00764413
PaintText 007645E0 f end=00764788
OnChar 00764990 f end=00764A03
OnIdle 007659C0 f end=00765AE5
OnKeyDown 00765AF0 f end=00765FB2
OnKeyUp 00763BE0 f end=00763C0A
OnKeyDownRepeat 00764B90 f end=00764E4F
OnMouseDown 00764A10 f end=00764B88
OnMouseUp 007639A0 f end=007639CF
OnMouseMove 007639D0 f end=00763A54
MakeCommandCurrent 00763A60 f end=00763AAA
ReserveInputSpace 007637D0 f end=0076382B
GetInputLine 00764520 f end=007645D3
PasteInInputLine 00764800 f end=00764985
SetInputString 00763730 f end=007637CD ; UC
ResetHighlight 00763830 f end=00763855
UpdateHighlight 00763860 f end=00763996
DrawBackground 00763DF0 f end=00764039
DrawHighLight 00764040 f end=00764196
DrawCaret 007641A0 f end=007643EA

View file

@ -1,10 +1,45 @@
EventCreateContextEx 0047d080 f
EventDoMessageLoop 0047f2d0 f
EventIsKeyDown 0047d230 f
EventPostCloseEx 0047d290 f
EventRegister 0x47d770 f
EventRegisterEx 0047d3c0 f
EventSetConfirmCloseCallback 0047d090 f
EventSetMouseMode 0x47d690 f
EventUnregister 0047d790 f
IEvtSchedulerProcess 0047f230 f
EventDestroy 0047D030 f end=0047D04E
EventDestroy_cleanup 00480EA0 f end=00480ED9
EventInitialize 0047CFF0 f end=0047D02D
EventCreateContextEx 0047D080 f end=0047D089
EventSetConfirmCloseCallback 0047D090 f end=0047D099
EventIsButtonDown 0047D1D0 f end=0047D230
EventIsKeyDown 0047D230 f end=0047D290
EventPostCloseEx 0047D290 f end=0047D305
EventRegisterEx 0047D3C0 f end=0047D443
EventSetMouseMode 0047D690 f end=0047D6FD
EventRegister 0047D770 f end=0047D78D
EventUnregister 0047D790 f end=0047D7A9
EventUnregisterEx 0047D450 f end=0047D4B7
EventDoMessageLoop 0047F2D0 f end=0047F2EC
EventForceIdleProcessing 0047DCA0 f end=0047DE09
EventKillTimer 0047D620 f end=0047D683
IEvtInputProcess 00480410 f end=004804A8
IEvtInputGetMousePosition 004800A0 f end=004800EF
IEvtInputSetConfirmCloseCallback 0047FC20 f end=0047FC36
IEvtInputSetMouseMode 0047FBB0 f end=0047FC17
IEvtInputDestroy 0047FB80 f end=0047FB92
IEvtQueueCheckSyncKeyState 00480A50 f end=00480AC2
IEvtQueueCheckSyncMouseState 004804C0 f end=004804E6
IEvtQueueDestroy 004804B0 f end=004804BA
IEvtQueueDispatch 00480AD0 f end=00480BCB
IEvtQueueDispatchAll 00480BD0 f end=00480D28
IEvtQueueRegister 004804F0 f end=004805F4
IEvtQueueUnregister 00480D30 f end=00480DD1
IEvtSchedulerCreateContext 0047F5C0 f end=0047F6B9
IEvtSchedulerInitialize 0047F2F0 f end=0047F5BA
IEvtSchedulerDestroy 0047DEA0 f end=0047E117
IEvtSchedulerShutdown 0047D990 f end=0047D9EB
SchedulerThreadProc 0047F230 f end=0047F2C1 ; IEvtSchedulerProcess appears to be optimized out
SchedulerThreadProcProcess 0047EFF0 f end=0047F225
IEvtTimerDispatch 00481100 f end=00481289
IEvtTimerGetNextTime 00480F70 f end=00480FCA
IEvtTimerKill 00481290 f end=0048138F
PostMouseModeChanged 0047FAC0 f end=0047FB22
PropSelectContext 0047CBF0 f end=0047CC08
PropSet 0047CC50 f end=0047CC70
PropGet 0047CC20 f end=0047CC41
InitializeSchedulerThread 0047E910 f end=0047EA69
SynthesizeIdle 0047DBC0 f end=0047DC14
SynthesizePaint 0047DC50 f end=0047DC8D
SynthesizePoll 0047DC20 f end=0047DC50

View file

@ -1,23 +1,29 @@
GxDevApi 00682d20 f
GxDrawLockedElements 00682340 f
GxLog 006817e0 f
GxRsPush 00409670 f
GxRsPop 00685fb0 f
GxPrimIndexPtr 00681ab0 f
GxPrimLockVertexPtrs 006828c0 f
GxPrimVertexPtr_FFP 00682400 f ; this is one of the functions named 'GxPrimVertexPtr' that uses the fixed-function pipeline
GxuDetermineQuotedCode 006bd5a0 f
GxuFontClearBatch 006be390 f
GxuFontAddToBatch 006bce10 f
GxuFontCreateBatch 006bf160 f
GxuFontCreateString 006be2b0 f
GxuFontDestroyString 006bdfc0 f
GxuFontGetMaxCharsWithinWidth 006bcea0 f
GxuFontGetTextExtent 006bce60 f
GxuFontRenderBatch 006bce40 f
GxuFontSetStringPosition 006bd0a0 f
CGxDevice__CGxDevice 00688690 f
CGxDevice__MasterEnableSet 00685eb0 f
CGxDevice__IRsForceUpdate 006859e0 f
CGxDeviceOpenGl__CGxDeviceOpenGl 0068bbc0 f
CGxDeviceD3d__CGxDeviceD3d 0068fd50 f
GxDevCreate 00681290 f end=00681301
GxDevApi 00682D20 f end=00682D27
GxDrawLockedElements 00682340 f end=0068239E
GxLog 006817E0 f end=006817F5
GxRsPush 00409670 f end=004096CC
GxRsPop 00685FB0 f end=00686116
GxPrimIndexPtr 00681AB0 f end=00681AFB
GxPrimVertexPtr_FFP 00682400 f end=00682781 ; this is one of the functions named 'GxPrimVertexPtr' that uses the fixed-function pipeline
GxPrimLockVertexPtrs 006828C0 f end=006828FE
GxuFontAddToBatch 006BCE10 f end=006BCE32
GxuFontRenderBatch 006BCE40 f end=006BCE52
GxuFontGetTextExtent 006BCE60 f end=006BCE98
GxuFontGetMaxCharsWithinWidth 006BCEA0 f end=006BCEE7
GxuFontSetStringPosition 006BD0A0 f end=006BD0BE
GxuDetermineQuotedCode 006BD5A0 f end=006BD89D
GxuFontDestroyString 006BDFC0 f end=006BE014
GxuFontCreateString 006BE2B0 f end=006BE390
GxuFontClearBatch 006BE390 f end=006BE3AD
GxuFontCreateBatch 006BF160 f end=006BF202
CGxDevice__CGxDevice 00688690 f end=0068903F
CGxDevice__MasterEnableSet 00685EB0 f end=00685F33
CGxDevice__IRsForceUpdate 006859E0 f end=00685A65
CGxDevice__NewOpenGl 0068BF20 f end=0068BF44
CGxDevice__NewD3d 00689EF0 f end=00689F14
CGxDevice__NewD3d9Ex 0068C220 f end=0068C244
CGxDeviceOpenGl__CGxDeviceOpenGl 0068BBC0 f end=0068BD15
CGxDeviceD3d__CGxDeviceD3d 0068FD50 f end=0068FE80
CGxDeviceD3d9Ex__CGxDeviceD3d9Ex 006A1A90 f end=006A1C24
OnPaint 004A8720 f end=004A8B58

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,30 @@
OsCreateFile 00406b70 f
OsGetFileSize 00461bd0 f
OsReadFile 00461b50 f
OsCloseFile 00461b00 f
OsSystemEnableCpuLog 0086b0c0 f
OsCreateFile 00461FA0 f end=00461FFA
OsCloseFile 00461B00 f end=00461B09
OsReadFile 00461B50 f end=00461B88
OsGetFileSize 00461BD0 f end=00461BF4
OsSetCurrentDirectory 00461DB0 f end=00461DD7
OsCreateFile 00461FA0 f end=00461FFA
OsInputDestroy 00869760 f end=008697D3
OsInputInitialize 00869720 f end=00869757 ; actually called by IEvtInputInitialize, but this is optimized out
OsInputGet 00869E00 f end=0086A01A
OsInputGetMousePosition 0086A0D0 f end=0086A130
OsInputSetMousePosition 0086A130 f end=0086A194
OsInputSetMouseMode 0086A020 f end=0086A063
OsInputSetEventPollProc 00869D90 f end=00869D9D
CenterMouse 00869DB0 f end=00869DF6
RestoreMouse 008695B0 f end=008695FB
OsGetAsyncTimeMs 0086AE20 f end=0086AE2B
OsSystemEnableCpuLog 0086B0C0 f end=0086B0CB
OsGetProcessorCount 0086B240 f end=0086B27D
OsGetExeName 0086BBD0 f end=0086BC2F
OsPathGetRootChars 0086BC30 f end=0086BC9E
OsPathStripFilename 0086BE50 f end=0086BE9B
OsGetExePath 0086BEA0 f end=0086BEBE
OsGuiGetWindow 0086C6A0 f end=0086C6CE
OsGetDefaultWindowRect 0086A1A0 f end=0086A20C
OsIMEInitialize 0086D0A0 f end=0086D0B8
OsIMEDestroy 0086D0C0 f end=0086D0Df
OsClipboardPutString 008722A0 f end=008722BF
OsCallSetContext 0086F5A0 f end=0086F5EA
OsCallInitializeContext 0086F880 f end=0086F902
OsCallInitialize 0086F760 f end=0086F875

File diff suppressed because it is too large Load diff

View file

@ -1,30 +1,35 @@
SCmdProcess 00773890 f
SCmdProcessCommandLine 00773990 f
SCmdRegisterArgList 00773590 f
SErrCatchUnhandledExceptions 00772b20 f
SErrDisplayAppFatal 005eeb70 f
SErrRegisterHandler 00771b80 f
SErrSetLogTitleCallback 00771900 f
SErrSetLogTitleString 00771890 f
SMemAlloc 0076e540 f
SMemFree 0076e5a0 f
SRegLoadValue 00770840 f
SRegSaveValue 007709a0 f
SStrChr 0076e6e0 f
SStrCmp 0076e760 f
SStrCmpI 0076e780 f
SStrCopy 0076ed20 f
SStrHashHT 0076f640 f
SStrLen 0076ee30 f
SStrPack 0076ef70 f ; double-check this
SStrPrintf 0076f070 f
SStrVPrintf 0076f0a0 f
SStrTokenize 0076f1e0 f
SEvent__Set 00774720 f
SEvent__Reset 00774730 f
StormInitialize 007739e0 f
TSList__LinkNode 004f71a0 f
SCritSect__Enter 00774640 f
SCritSect__Leave 00774650 f
SCritSect__SCritSect 00774620 f
StormSetOption 00773a80 f
SCmdRegisterArgList 00773590 f end=007737C2
SCmdProcess 00773890 f end=00773986
SCmdProcessCommandLine 00773990 f end=007739AD
SErrDisplayAppFatal 005EEB70 f end=005EEB71
SErrSetLogTitleString 00771890 f end=007718F2
SErrSetLogTitleCallback 00771900 f end=00771957
SErrRegisterHandler 00771B80 f end=00771C15
SErrCatchUnhandledExceptions 00772B20 f end=00772B2C
SMemAlloc 0076E540 f end=0076E59A
SMemFree 0076E5A0 f end=0076E5C4
SMemSetDebugFlags 0076E4A0 f end=0076E4D2
SRegLoadValue 00770840 f end=007708E9
SRegSaveValue 007709A0 f end=007709E8
SStrChr 0076E6E0 f end=0076E712
SStrCmp 0076E760 f end=0076E77B
SStrCmpI 0076E780 f end=0076E79B
SStrCopy 0076ED20 f end=0076ED98
SStrLen 0076EE30 f end=0076EE5E
SStrPack 0076EF70 f end=0076F001
SStrPrintf 0076F070 f end=0076F09E
SStrVPrintf 0076F0A0 f end=0076F0CE
SStrTokenize 0076F1E0 f end=0076F331
SStrHashHT 0076F640 f end=0076F6B9
SEvent__Set 00774720 f end=0077472A
SEvent__Reset 00774730 f end=0077473A
SSyncObject__Wait 00774690 f end=007746A4
StormInitialize 007739E0 f end=007739F4
StormSetOption 00773A80 f end=00773C81
TSList__LinkNode 004F71A0 f end=004F724D
SCritSect__SCritSect 00774620 f end=0077462E
SCritSect__Enter 00774640 f end=00774648
SCritSect__Leave 00774650 f end=00774658
SCritSect__destructor 00774630 f end=00774638
SRgnCreate 00777980 f end=00777A78
SRgnDelete 00777940 f end=00777971

30638
3.3.5a/x32dbg/game.dd32 Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,36 @@
from ghidra.program.model.symbol.SourceType import *
functionManager = currentProgram.getFunctionManager()
file_location = askFile("Choose a file to write to", "Go baby go!")
listing = currentProgram.getListing()
def export_function_symbols(file):
monitor.setMessage("Exporting function symbols...")
for f in functionManager.getFunctionsNoStubs(1):
monitor.checkCanceled() # throws exception if canceled
if f.isExternal() or f.isThunk():
continue
func_name = f.getName()
if func_name.startswith("FUN_"):
continue
func_start_address = f.getBody().getMinAddress().getOffset()
func_end_address = f.getBody().getMaxAddress().getOffset() + 1
line_template = "{name} {start_address:08X} f end={end_address:08X}\n"
func_line = line_template.format(name = func_name, start_address = func_start_address, end_address = func_end_address)
file.write(func_line)
return
with open(file_location.absolutePath, "w") as file:
export_function_symbols(file)
file.close()

11
go.mod Normal file
View file

@ -0,0 +1,11 @@
module github.com/thunderbrewhq/binana
go 1.22.0
require github.com/spf13/cobra v1.8.1
require (
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/spf13/pflag v1.0.5 // indirect
)

12
go.sum Normal file
View file

@ -0,0 +1,12 @@
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

0
go/cmd/binana/LICENSE Normal file
View file

44
go/cmd/binana/cmd/root.go Normal file
View file

@ -0,0 +1,44 @@
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"os"
"github.com/spf13/cobra"
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "binana",
Short: "Binana helper tool",
}
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.binana.yaml)")
// Cobra also supports local flags, which will only run
// when this action is called directly.
// rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
x64dbg_gen.Flags().StringP("game", "g", "3.3.5a", "the game profile")
x64dbg_gen.Flags().StringP("module-name", "m", "wow.exe", "the name of the module")
x64dbg_gen.Flags().StringP("base-address", "b", "00400000", "the base address of the module")
x64dbg_gen.Flags().BoolP("compress", "c", false, "enable/disable lz4 compression of the x64dbg database")
rootCmd.AddCommand(x64dbg_gen)
}

View file

@ -0,0 +1,117 @@
package cmd
import (
"fmt"
"os"
"path/filepath"
"strconv"
"github.com/spf13/cobra"
"github.com/thunderbrewhq/binana/go/symfile"
"github.com/thunderbrewhq/binana/go/x64dbg"
)
func hex_address(u uint64) string {
return fmt.Sprintf("0x%x", u)
}
// rootCmd represents the base command when called without any subcommands
var x64dbg_gen = &cobra.Command{
Use: "x64dbg-gen",
Short: "Generate x64dbg database using a symfile",
Run: x64dbg_gen_func,
}
func x64dbg_gen_func(cmd *cobra.Command, args []string) {
compress, err := cmd.Flags().GetBool("compress")
if err != nil {
panic(err)
}
module_name, err := cmd.Flags().GetString("module-name")
if err != nil {
panic(err)
}
base_address_s, err := cmd.Flags().GetString("base-address")
if err != nil {
panic(err)
}
base_address, err := strconv.ParseUint(base_address_s, 16, 64)
if err != nil {
panic(err)
}
game_profile, err := cmd.Flags().GetString("game")
if err != nil {
panic(err)
}
symfile_path := filepath.Join(game_profile, "symbol", "main.sym")
file, err := os.Open(symfile_path)
if err != nil {
fmt.Println(err)
os.Exit(1)
return
}
table := new(symfile.InMemoryTable)
if err := symfile.Load(table, file); err != nil {
fmt.Println(err)
os.Exit(1)
return
}
file.Close()
fmt.Printf("loaded %d symbols\n", table.Len())
var dd x64dbg.Database
for _, entry := range table.Entries {
relative_start_address := entry.StartAddress - base_address
relative_end_address := relative_start_address
if entry.EndAddress != 0 {
relative_end_address = entry.EndAddress - base_address
// for x64dbg, the end address is the last instruction.
// for us, the end address is the address immediately after the last instruction.
relative_end_address -= 1
}
if relative_end_address < relative_start_address || relative_end_address-relative_start_address >= 10000 {
fmt.Printf("Wtf symbol %s %08x %08x (offset %d)\n", entry.Name, relative_start_address, relative_end_address, relative_end_address-relative_start_address)
}
// create label
var label x64dbg.Label
label.Manual = true
label.Address = hex_address(relative_start_address)
label.Text = entry.Name
label.Module = module_name
dd.Labels = append(dd.Labels, label)
if entry.Kind == symfile.Function {
var fn x64dbg.Function
fn.Manual = true
fn.Start = hex_address(relative_start_address)
fn.End = hex_address(relative_end_address)
fn.Module = module_name
fn.InstructionCount = hex_address(0)
fn.Parent = hex_address(relative_start_address)
dd.Functions = append(dd.Functions, fn)
}
}
dd_path := filepath.Join(game_profile, "x32dbg", "game.dd32")
if err = x64dbg.SaveDatabase(dd_path, &dd, compress); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

7
go/cmd/binana/main.go Normal file
View file

@ -0,0 +1,7 @@
package main
import "github.com/thunderbrewhq/binana/go/cmd/binana/cmd"
func main() {
cmd.Execute()
}

139
go/symfile/loader.go Normal file
View file

@ -0,0 +1,139 @@
package symfile
import (
"bufio"
"errors"
"fmt"
"io"
"slices"
"strconv"
"strings"
)
const min_columns = 3
type loader struct {
input *bufio.Reader
table Table
line_number int
}
func (l *loader) read_line() (line string, err error) {
l.line_number++
line, err = l.input.ReadString('\n')
if err != nil {
return
}
line = strings.TrimRight(line, "\r\n")
return
}
func (l *loader) parse_line(line string) (err error) {
// trim extraneous whitespace
line = strings.Trim(line, " \t")
// split into columns
columns := strings.Split(line, " ")
// validate
if len(columns) < min_columns {
// this line is discarded but not in error
return
}
var (
start_address uint64
comment_text string
)
// get name of symbol
name_column := columns[0]
if name_column == "" {
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid name '%s", l.line_number, name_column)
}
start_address, err = strconv.ParseUint(columns[1], 16, 64)
if err != nil {
return
}
kind_column := columns[2]
if len(kind_column) != 1 {
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid kind", l.line_number)
}
kind := EntryKind(kind_column[0])
if !slices.Contains(valid_kinds, kind) {
return fmt.Errorf("symfile: (*loader).parse_line: line %d: entry has invalid kind", l.line_number)
}
// find index of comment column
index_of_comment := slices.Index(columns, ";")
var num_semantic_columns int
if index_of_comment != -1 {
num_semantic_columns = index_of_comment
comment_text_columns := columns[index_of_comment+1:]
comment_text = strings.Join(comment_text_columns, " ")
} else {
num_semantic_columns = len(columns)
}
// Start to build entry
var entry Entry
entry.Name = name_column
entry.StartAddress = start_address
entry.Kind = kind
entry.Comment = comment_text
// build attributes
if num_semantic_columns > 3 {
for _, column := range columns[3:] {
key, value, found := strings.Cut(column, "=")
if found {
switch key {
case "end":
entry.EndAddress, err = strconv.ParseUint(value, 16, 64)
if err != nil {
return
}
default:
return fmt.Errorf("symfile: (*loader).parse_line: line %d: unknown attribute '%s'", l.line_number, key)
}
}
}
}
err = l.table.Insert(&entry)
return
}
func load(text io.Reader, table Table) (err error) {
l := new(loader)
l.input = bufio.NewReader(text)
l.table = table
var (
line string
)
for {
line, err = l.read_line()
if err != nil {
if errors.Is(err, io.EOF) {
err = nil
break
} else {
return
}
}
if err = l.parse_line(line); err != nil {
return
}
}
return
}

View file

@ -0,0 +1,29 @@
package symfile
import (
"slices"
"sort"
)
// Most tables are reasonably-sized and can be kept in memory
type InMemoryTable struct {
Entries []Entry
}
func (t *InMemoryTable) Insert(entry *Entry) (err error) {
i := sort.Search(len(t.Entries), func(i int) bool {
return t.Entries[i].StartAddress >= entry.StartAddress
})
if i < len(t.Entries) {
t.Entries = slices.Insert(t.Entries, i, *entry)
} else {
t.Entries = append(t.Entries, *entry)
}
return
}
func (t *InMemoryTable) Len() int {
return len(t.Entries)
}

44
go/symfile/symfile.go Normal file
View file

@ -0,0 +1,44 @@
package symfile
import (
"io"
)
// What kind of Entry is this?
type EntryKind uint8
const (
// Something that can be executed
Function EntryKind = 'f'
// Something that is read or written to
DataLabel EntryKind = 'l'
)
var (
valid_kinds = []EntryKind{Function, DataLabel}
)
// An entry in the table
type Entry struct {
// Undecorated, raw name
Name string
// Offset to the start of the function or data
StartAddress uint64
// What kind of Entry is this?
Kind EntryKind
// Any table entry can have a comment after a ';' column
Comment string
// Attributes
// end=AABBCCEEDD
EndAddress uint64
}
type Table interface {
Insert(entry *Entry) (err error)
// Find() (iter func() (entry *Entry, err error))
}
func Load(table Table, text io.Reader) (err error) {
err = load(text, table)
return
}

91
go/x64dbg/database.go Normal file
View file

@ -0,0 +1,91 @@
package x64dbg
import (
"encoding/json"
"io"
"os"
"github.com/pierrec/lz4/v4"
)
type Function struct {
Manual bool `json:"manual,omitempty"`
Start string `json:"start,omitempty"`
End string `json:"end,omitempty"`
Module string `json:"module,omitempty"`
InstructionCount string `json:"icount,omitempty"`
Parent string `json:"parent,omitempty"`
}
type Comment struct {
Manual bool `json:"manual,omitempty"`
Module string `json:"module,omitempty"`
Text string `json:"text,omitempty"`
Address string `json:"address,omitempty"`
}
type Label struct {
Manual bool `json:"manual,omitempty"`
Module string `json:"module,omitempty"`
Text string `json:"text,omitempty"`
Address string `json:"address,omitempty"`
}
type Bookmark struct {
Manual bool `json:"manual,omitempty"`
Module string `json:"module,omitempty"`
Address string `json:"address,omitempty"`
}
type Breakpoint struct {
Address string `json:"address,omitempty"`
CommandText string `json:"commandText,omitempty"`
Enabled bool `json:"enabled,omitempty"`
FastResume string `json:"fastResume,omitempty"`
OldBytes string `json:"oldbytes,omitempty"`
Type string `json:"type,omitempty"`
Module string `json:"module,omitempty"`
TitanType string `json:"titantype,omitempty"`
Name string `json:"name,omitempty"`
BreakCondition string `json:"breakCondition,omitempty"`
LogText string `json:"logText,omitempty"`
LogCondition string `json:"logCondition,omitempty"`
Silent string `json:"silent,omitempty"`
CommandCondition string `json:"commandCondition,omitempty"`
}
type Database struct {
Functions []Function `json:"functions,omitempty"`
Comments []Comment `json:"comments,omitempty"`
Labels []Label `json:"labels,omitempty"`
Bookmarks []Bookmark `json:"bookmarks,omitempty"`
Breakpoints []Breakpoint `json:"breakpoints,omitempty"`
}
func SaveDatabase(name string, database *Database, compress bool) (err error) {
var file *os.File
file, err = os.Create(name)
if err != nil {
return
}
var writecloser io.WriteCloser = file
if compress {
lz4_writer := lz4.NewWriter(file)
writecloser = lz4_writer
}
e := json.NewEncoder(writecloser)
e.SetIndent("", " ")
if err = e.Encode(database); err != nil {
return
}
if compress {
writecloser.Close()
}
err = file.Close()
return
}

View file

@ -8,4 +8,4 @@ if [ $# -eq 0 ]
exit 1
fi
awk 1 $1/symbol/*/*.sym | sort > $1/symbol/main.sym
awk 1 $1/symbol/*/*.sym | sort -k2 -t' ' > $1/symbol/main.sym