diff --git a/3.3.5a/include/datarecycler/func.sym b/3.3.5a/include/datarecycler/func.sym deleted file mode 100644 index 74b7d5d..0000000 --- a/3.3.5a/include/datarecycler/func.sym +++ /dev/null @@ -1 +0,0 @@ -CDataRecyler__Clear 0095CEC0 f end=0095CF39 \ No newline at end of file diff --git a/3.3.5a/symbol/datarecycler/func.sym b/3.3.5a/symbol/datarecycler/func.sym new file mode 100644 index 0000000..508447b --- /dev/null +++ b/3.3.5a/symbol/datarecycler/func.sym @@ -0,0 +1 @@ +CDataRecycler__Clear 0095CEC0 f end=0095CF39 \ No newline at end of file diff --git a/3.3.5a/x32dbg/types.json b/3.3.5a/x32dbg/types.json new file mode 100644 index 0000000..e7a7f49 --- /dev/null +++ b/3.3.5a/x32dbg/types.json @@ -0,0 +1,2206 @@ +{ + "types": [ + { + "type": "int32_t", + "name": "ptrdiff_t" + }, + { + "type": "uint32_t", + "name": "uintptr_t" + }, + { + "type": "int32_t", + "name": "intptr_t" + }, + { + "type": "int", + "name": "EGxPoolHintBits" + }, + { + "type": "int", + "name": "EGxPoolTarget" + }, + { + "type": "int", + "name": "EGxPoolUsage" + }, + { + "type": "int", + "name": "EGxVertexAttrib" + }, + { + "type": "int", + "name": "EGxVertexBufferFormat" + }, + { + "type": "int", + "name": "EGxColorFormat" + }, + { + "type": "int", + "name": "BlitAlpha" + }, + { + "type": "int", + "name": "BlitFormat" + }, + { + "type": "int", + "name": "EGxApi" + }, + { + "type": "int", + "name": "EGxBlend" + }, + { + "type": "int", + "name": "EGxFontHJusts" + }, + { + "type": "int", + "name": "EGxFontVJusts" + }, + { + "type": "int", + "name": "EGxMasterEnables" + }, + { + "type": "int", + "name": "EGxPrim" + }, + { + "type": "int", + "name": "EGxPrimMask" + }, + { + "type": "int", + "name": "EGxRenderState" + }, + { + "type": "int", + "name": "EGxShPS" + }, + { + "type": "int", + "name": "EGxShTarget" + }, + { + "type": "int", + "name": "EGxShVS" + }, + { + "type": "int", + "name": "EGxTexCommand" + }, + { + "type": "int", + "name": "EGxTexFilter" + }, + { + "type": "int", + "name": "EGxTexFormat" + }, + { + "type": "int", + "name": "EGxTexTarget" + }, + { + "type": "int", + "name": "EGxTexWrapMode" + }, + { + "type": "int", + "name": "EGxXform" + }, + { + "type": "int", + "name": "EGxuDrawListCategory" + }, + { + "type": "int", + "name": "EGxWM" + }, + { + "type": "int", + "name": "COLOR_FILE_FORMAT" + }, + { + "type": "int", + "name": "PIXEL_FORMAT" + }, + { + "type": "int", + "name": "CGxFormat__Format" + }, + { + "type": "int", + "name": "CGxMatrixStack__EMatrixFlags" + } + ], + "structs": [ + { + "name": "HASHKEY_PTR", + "members": [ + { + "type": "void*", + "name": "m_key" + } + ] + }, + { + "name": "HASHKEY_STR", + "members": [ + { + "type": "char*", + "name": "m_str" + } + ] + }, + { + "name": "HASHKEY_STRI", + "members": [ + { + "type": "char*", + "name": "m_str" + } + ] + }, + { + "name": "HASHKEY_NONE" + }, + { + "name": "CAaBox", + "members": [ + { + "type": "C3Vector", + "name": "b" + }, + { + "type": "C3Vector", + "name": "t", + "offset": 12 + } + ] + }, + { + "name": "CBoundingBox", + "members": [ + { + "type": "CRange", + "name": "x" + }, + { + "type": "CRange", + "name": "y", + "offset": 8 + }, + { + "type": "CRange", + "name": "z", + "offset": 16 + } + ] + }, + { + "name": "C3Vector", + "members": [ + { + "type": "float", + "name": "x" + }, + { + "type": "float", + "name": "y", + "offset": 4 + }, + { + "type": "float", + "name": "z", + "offset": 8 + } + ] + }, + { + "name": "CRange", + "members": [ + { + "type": "float", + "name": "l" + }, + { + "type": "float", + "name": "h", + "offset": 4 + } + ] + }, + { + "name": "C2Vector", + "members": [ + { + "type": "float", + "name": "x" + }, + { + "type": "float", + "name": "y", + "offset": 4 + } + ] + }, + { + "name": "C2iVector", + "members": [ + { + "type": "int32_t", + "name": "x" + }, + { + "type": "int32_t", + "name": "y", + "offset": 4 + } + ] + }, + { + "name": "C4Vector", + "members": [ + { + "type": "float", + "name": "x" + }, + { + "type": "float", + "name": "y", + "offset": 4 + }, + { + "type": "float", + "name": "z", + "offset": 8 + }, + { + "type": "float", + "name": "w", + "offset": 12 + } + ] + }, + { + "name": "CImVector", + "members": [ + { + "type": "uint8_t", + "name": "b" + }, + { + "type": "uint8_t", + "name": "g", + "offset": 1 + }, + { + "type": "uint8_t", + "name": "r", + "offset": 2 + }, + { + "type": "uint8_t", + "name": "a", + "offset": 3 + } + ] + }, + { + "name": "CiRange", + "members": [ + { + "type": "int32_t", + "name": "l" + }, + { + "type": "int32_t", + "name": "h", + "offset": 4 + } + ] + }, + { + "name": "C33Matrix", + "members": [ + { + "type": "float", + "name": "a0" + }, + { + "type": "float", + "name": "a1", + "offset": 4 + }, + { + "type": "float", + "name": "a2", + "offset": 8 + }, + { + "type": "float", + "name": "b0", + "offset": 12 + }, + { + "type": "float", + "name": "b1", + "offset": 16 + }, + { + "type": "float", + "name": "b2", + "offset": 20 + }, + { + "type": "float", + "name": "c0", + "offset": 24 + }, + { + "type": "float", + "name": "c1", + "offset": 28 + }, + { + "type": "float", + "name": "c2", + "offset": 32 + } + ] + }, + { + "name": "C34Matrix", + "members": [ + { + "type": "float", + "name": "a0" + }, + { + "type": "float", + "name": "a1", + "offset": 4 + }, + { + "type": "float", + "name": "a2", + "offset": 8 + }, + { + "type": "float", + "name": "b0", + "offset": 12 + }, + { + "type": "float", + "name": "b1", + "offset": 16 + }, + { + "type": "float", + "name": "b2", + "offset": 20 + }, + { + "type": "float", + "name": "c0", + "offset": 24 + }, + { + "type": "float", + "name": "c1", + "offset": 28 + }, + { + "type": "float", + "name": "c2", + "offset": 32 + }, + { + "type": "float", + "name": "d0", + "offset": 36 + }, + { + "type": "float", + "name": "d1", + "offset": 40 + }, + { + "type": "float", + "name": "d2", + "offset": 44 + } + ] + }, + { + "name": "C44Matrix", + "members": [ + { + "type": "float", + "name": "a0" + }, + { + "type": "float", + "name": "a1", + "offset": 4 + }, + { + "type": "float", + "name": "a2", + "offset": 8 + }, + { + "type": "float", + "name": "a3", + "offset": 12 + }, + { + "type": "float", + "name": "b0", + "offset": 16 + }, + { + "type": "float", + "name": "b1", + "offset": 20 + }, + { + "type": "float", + "name": "b2", + "offset": 24 + }, + { + "type": "float", + "name": "b3", + "offset": 28 + }, + { + "type": "float", + "name": "c0", + "offset": 32 + }, + { + "type": "float", + "name": "c1", + "offset": 36 + }, + { + "type": "float", + "name": "c2", + "offset": 40 + }, + { + "type": "float", + "name": "c3", + "offset": 44 + }, + { + "type": "float", + "name": "d0", + "offset": 48 + }, + { + "type": "float", + "name": "d1", + "offset": 52 + }, + { + "type": "float", + "name": "d2", + "offset": 56 + }, + { + "type": "float", + "name": "d3", + "offset": 60 + } + ] + }, + { + "name": "C4Plane", + "members": [ + { + "type": "C3Vector", + "name": "n" + }, + { + "type": "float", + "name": "d", + "offset": 12 + } + ] + }, + { + "name": "C4Quaternion", + "members": [ + { + "type": "float", + "name": "x" + }, + { + "type": "float", + "name": "y", + "offset": 4 + }, + { + "type": "float", + "name": "z", + "offset": 8 + }, + { + "type": "float", + "name": "w", + "offset": 12 + } + ] + }, + { + "name": "CRect", + "members": [ + { + "type": "float", + "name": "minY" + }, + { + "type": "float", + "name": "minX", + "offset": 4 + }, + { + "type": "float", + "name": "maxY", + "offset": 8 + }, + { + "type": "float", + "name": "maxX", + "offset": 12 + } + ] + }, + { + "name": "CiRect", + "members": [ + { + "type": "int32_t", + "name": "minY" + }, + { + "type": "int32_t", + "name": "minX", + "offset": 4 + }, + { + "type": "int32_t", + "name": "maxY", + "offset": 8 + }, + { + "type": "int32_t", + "name": "maxX", + "offset": 12 + } + ] + }, + { + "name": "CAaSphere", + "members": [ + { + "type": "C3Vector", + "name": "n" + }, + { + "type": "float", + "name": "d", + "offset": 12 + } + ] + }, + { + "name": "ubyte4", + "members": [ + { + "type": "ubyte4__0000", + "name": "" + } + ] + }, + { + "name": "CGxVertexAttrib", + "members": [ + { + "type": "EGxVertexAttrib", + "name": "attrib" + }, + { + "type": "uint32_t", + "name": "type", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "offset", + "offset": 8 + }, + { + "type": "uint32_t", + "name": "bufSize", + "offset": 12 + } + ] + }, + { + "name": "CGxVertexPBNT2", + "members": [ + { + "type": "C3Vector", + "name": "p" + }, + { + "type": "ubyte4", + "name": "bw", + "offset": 12 + }, + { + "type": "ubyte4", + "name": "bi", + "offset": 16 + }, + { + "type": "C3Vector", + "name": "n", + "offset": 20 + }, + { + "type": "C2Vector", + "name": "tc", + "arrsize": 2, + "offset": 32 + } + ] + }, + { + "name": "CGxVertexPCT", + "members": [ + { + "type": "C3Vector", + "name": "p" + }, + { + "type": "CImVector", + "name": "c", + "offset": 12 + }, + { + "type": "C2Vector", + "name": "tc", + "arrsize": 1, + "offset": 16 + } + ] + }, + { + "name": "CGxPool", + "members": [ + { + "type": "TSLinkedNode_CGxPool", + "name": "b_base" + }, + { + "type": "EGxPoolTarget", + "name": "m_target", + "offset": 8 + }, + { + "type": "EGxPoolUsage", + "name": "m_usage", + "offset": 12 + }, + { + "type": "int32_t", + "name": "m_size", + "offset": 16 + }, + { + "type": "void*", + "name": "m_apiSpecific", + "offset": 20 + }, + { + "type": "void*", + "name": "m_mem", + "offset": 24 + }, + { + "type": "int32_t", + "name": "unk1C", + "offset": 28 + }, + { + "type": "TSList_CGxBuf", + "name": "m_bufList", + "offset": 32 + }, + { + "type": "EGxPoolHintBits", + "name": "m_hint", + "offset": 44 + }, + { + "type": "char*", + "name": "m_name", + "offset": 48 + } + ] + }, + { + "name": "CGxBuf", + "members": [ + { + "type": "TSLinkedNode_CGxBuf", + "name": "b_base" + }, + { + "type": "CGxPool*", + "name": "m_pool", + "offset": 8 + }, + { + "type": "uint32_t", + "name": "m_itemSize", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_itemCount", + "offset": 16 + }, + { + "type": "uint32_t", + "name": "m_size", + "offset": 20 + }, + { + "type": "uint32_t", + "name": "m_index", + "offset": 24 + }, + { + "type": "uint8_t", + "name": "unk1C", + "offset": 28 + }, + { + "type": "uint8_t", + "name": "unk1D", + "offset": 29 + }, + { + "type": "uint8_t", + "name": "unk1E", + "offset": 30 + }, + { + "type": "uint8_t", + "name": "unk1F", + "offset": 31 + } + ] + }, + { + "name": "TSLinkedNode_CGxPool", + "members": [ + { + "type": "TSLink_CGxPool", + "name": "m_link" + } + ] + }, + { + "name": "TSList_CGxBuf", + "members": [ + { + "type": "ptrdiff_t", + "name": "m_linkoffset" + }, + { + "type": "TSLink_CGxBuf", + "name": "m_terminator", + "offset": 4 + } + ] + }, + { + "name": "TSLinkedNode_CGxBuf", + "members": [ + { + "type": "TSLink_CGxBuf", + "name": "m_link" + } + ] + }, + { + "name": "TSLink_CGxBuf", + "members": [ + { + "type": "TSLink_CGxBuf*", + "name": "m_prevlink" + }, + { + "type": "CGxBuf*", + "name": "m_next", + "offset": 4 + } + ] + }, + { + "name": "TSList_CGxPool", + "members": [ + { + "type": "ptrdiff_t", + "name": "m_linkoffset" + }, + { + "type": "TSLink_CGxPool", + "name": "m_terminator", + "offset": 4 + } + ] + }, + { + "name": "TSLink_CGxPool", + "members": [ + { + "type": "TSLink_CGxPool*", + "name": "m_prevlink" + }, + { + "type": "CGxPool*", + "name": "m_next", + "offset": 4 + } + ] + }, + { + "name": "CGxCaps", + "members": [ + { + "type": "int32_t", + "name": "m_numTmus" + }, + { + "type": "int32_t", + "name": "m_pixelCenterOnEdge", + "offset": 4 + }, + { + "type": "int32_t", + "name": "m_texelCenterOnEdge", + "offset": 8 + }, + { + "type": "int32_t", + "name": "m_numStreams", + "offset": 12 + }, + { + "type": "int32_t", + "name": "int10", + "offset": 16 + }, + { + "type": "EGxColorFormat", + "name": "m_colorFormat", + "offset": 20 + }, + { + "type": "uint32_t", + "name": "m_maxIndex", + "offset": 24 + }, + { + "type": "int32_t", + "name": "m_generateMipMaps", + "offset": 28 + }, + { + "type": "int32_t", + "name": "m_texFmt", + "arrsize": 13, + "offset": 32 + }, + { + "type": "int32_t", + "name": "m_texTarget", + "arrsize": 4, + "offset": 84 + }, + { + "type": "uint32_t", + "name": "m_texMaxSize", + "arrsize": 4, + "offset": 100 + }, + { + "type": "int32_t", + "name": "m_shaderTargets", + "arrsize": 6, + "offset": 116 + }, + { + "type": "int32_t", + "name": "m_texFilterTrilinear", + "offset": 140 + }, + { + "type": "int32_t", + "name": "m_texFilterAnisotropic", + "offset": 144 + }, + { + "type": "uint32_t", + "name": "m_maxTexAnisotropy", + "offset": 148 + }, + { + "type": "int32_t", + "name": "m_depthBias", + "offset": 152 + }, + { + "type": "int32_t", + "name": "int130", + "offset": 156 + }, + { + "type": "int32_t", + "name": "int134", + "offset": 160 + }, + { + "type": "int32_t", + "name": "int138", + "offset": 164 + } + ] + }, + { + "name": "C4Pixel", + "members": [ + { + "type": "char", + "name": "b" + }, + { + "type": "char", + "name": "g", + "offset": 1 + }, + { + "type": "char", + "name": "r", + "offset": 2 + }, + { + "type": "char", + "name": "a", + "offset": 3 + } + ] + }, + { + "name": "MipBits", + "members": [ + { + "type": "C4Pixel*", + "name": "mip", + "arrsize": 1 + } + ] + }, + { + "name": "TSGrowableArray_EGxRenderState", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "EGxRenderState*", + "name": "m_data", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_chunk", + "offset": 16 + } + ] + }, + { + "name": "CGxAppRenderState", + "members": [ + { + "type": "CGxStateBom", + "name": "m_value" + }, + { + "type": "uint32_t", + "name": "m_stackDepth", + "offset": 16 + }, + { + "type": "int32_t", + "name": "m_dirty", + "offset": 20 + } + ] + }, + { + "name": "CGxPushedRenderState", + "members": [ + { + "type": "EGxRenderState", + "name": "m_which" + }, + { + "type": "CGxStateBom", + "name": "m_value", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_stackDepth", + "offset": 20 + } + ] + }, + { + "name": "ShaderConstants", + "members": [ + { + "type": "C4Vector", + "name": "constants", + "arrsize": 256 + }, + { + "type": "uint32_t", + "name": "unk1", + "offset": 4096 + }, + { + "type": "uint32_t", + "name": "unk2", + "offset": 4100 + } + ] + }, + { + "name": "CGxDevice", + "members": [ + { + "type": "CGxDevice__vtable*", + "name": "v_vtable" + }, + { + "type": "TSGrowableArray_CGxPushedRenderState", + "name": "m_pushedStates", + "offset": 4 + }, + { + "type": "TSGrowableArray_uint32_t", + "name": "m_stackOffsets", + "offset": 24 + }, + { + "type": "TSGrowableArray_EGxRenderState", + "name": "m_dirtyStates", + "offset": 44 + }, + { + "type": "uint32_t", + "name": "m_unk", + "arrsize": 73, + "offset": 64 + }, + { + "type": "CRect", + "name": "m_defWindowRect", + "offset": 356 + }, + { + "type": "CRect", + "name": "m_curWindowRect", + "offset": 372 + }, + { + "type": "EGxApi", + "name": "m_api", + "offset": 388 + }, + { + "type": "CGxFormat", + "name": "m_format", + "offset": 392 + }, + { + "type": "CGxCaps", + "name": "m_caps", + "offset": 436 + }, + { + "type": "TSHashTable_CGxShader_HASHKEY_STRI", + "name": "m_shaderList", + "arrsize": 6, + "offset": 604 + }, + { + "type": "void**", + "name": "m_windowProc", + "offset": 844 + }, + { + "type": "int32_t", + "name": "m_context", + "offset": 848 + }, + { + "type": "int32_t", + "name": "intF5C", + "offset": 852 + }, + { + "type": "int32_t", + "name": "m_windowVisible", + "offset": 856 + }, + { + "type": "int32_t", + "name": "intF64", + "offset": 860 + }, + { + "type": "int32_t", + "name": "intF6C", + "offset": 864 + }, + { + "type": "CBoundingBox", + "name": "m_viewport", + "offset": 868 + }, + { + "type": "C44Matrix", + "name": "m_projection", + "offset": 892 + }, + { + "type": "C44Matrix", + "name": "m_projNative", + "offset": 956 + }, + { + "type": "CGxMatrixStack", + "name": "m_xforms", + "arrsize": 11, + "offset": 1020 + }, + { + "type": "uint32_t", + "name": "m_appMasterEnables", + "offset": 4100 + }, + { + "type": "uint32_t", + "name": "m_hwMasterEnables", + "offset": 4104 + }, + { + "type": "TSList_CGxPool", + "name": "m_poolList", + "offset": 4108 + }, + { + "type": "CGxBuf*", + "name": "m_bufLocked", + "arrsize": 2, + "offset": 4120 + }, + { + "type": "CGxPool*", + "name": "m_vertexPool", + "offset": 4128 + }, + { + "type": "CGxPool*", + "name": "m_indexPool", + "offset": 4132 + }, + { + "type": "CGxBuf*", + "name": "m_streamBufs", + "arrsize": 2, + "offset": 4136 + }, + { + "type": "CGxVertexAttrib", + "name": "m_primVertexFormatAttrib", + "arrsize": 14, + "offset": 4144 + }, + { + "type": "CGxBuf*", + "name": "m_primVertexFormatBuf", + "arrsize": 14, + "offset": 4368 + }, + { + "type": "uint32_t", + "name": "m_primVertexMask", + "offset": 4424 + }, + { + "type": "uint32_t", + "name": "m_primVertexDirty", + "offset": 4428 + }, + { + "type": "EGxVertexBufferFormat", + "name": "m_primVertexFormat", + "offset": 4432 + }, + { + "type": "CGxBuf*", + "name": "m_primVertexBuf", + "offset": 4436 + }, + { + "type": "uint32_t", + "name": "m_primVertexSize", + "offset": 4440 + }, + { + "type": "CGxBuf*", + "name": "m_primIndexBuf", + "offset": 4444 + }, + { + "type": "int32_t", + "name": "m_primIndexDirty", + "offset": 4448 + }, + { + "type": "TSFixedArray_CGxAppRenderState", + "name": "m_appRenderStates", + "offset": 4452 + }, + { + "type": "TSFixedArray_CGxStateBom", + "name": "m_hwRenderStates", + "offset": 4468 + }, + { + "type": "uint32_t", + "name": "m_baseMipLevel", + "offset": 4484 + } + ] + }, + { + "name": "CGxDevice__vtable", + "members": [ + { + "type": "void*", + "name": "v_fn_0_ITexMarkAsUpdated" + }, + { + "type": "void*", + "name": "v_fn_1_IRsSendToHw", + "offset": 4 + }, + { + "type": "void*", + "name": "v_fn_2_ICursorCreate", + "offset": 8 + }, + { + "type": "void*", + "name": "v_fn_3_ICursorDestroy", + "offset": 12 + }, + { + "type": "void*", + "name": "v_fn_4_ICursorDraw", + "offset": 16 + }, + { + "type": "void*", + "name": "v_fn_5", + "offset": 20 + }, + { + "type": "void*", + "name": "v_fn_6", + "offset": 24 + }, + { + "type": "void*", + "name": "v_fn_7", + "offset": 28 + }, + { + "type": "void*", + "name": "v_fn_8", + "offset": 32 + }, + { + "type": "void*", + "name": "v_fn_9", + "offset": 36 + }, + { + "type": "void*", + "name": "v_fn_10_DeviceCreate", + "offset": 40 + }, + { + "type": "void*", + "name": "v_fn_11", + "offset": 44 + }, + { + "type": "void*", + "name": "v_fn_12", + "offset": 48 + }, + { + "type": "void*", + "name": "v_fn_13_DeviceSetFormat", + "offset": 52 + }, + { + "type": "void*", + "name": "v_fn_14_DeviceSetBaseMipLevel", + "offset": 56 + }, + { + "type": "void*", + "name": "v_fn_15_DeviceSetGamma", + "offset": 60 + }, + { + "type": "void*", + "name": "v_fn_16", + "offset": 64 + }, + { + "type": "void*", + "name": "v_fn_17", + "offset": 68 + }, + { + "type": "void*", + "name": "v_fn_18", + "offset": 72 + }, + { + "type": "void*", + "name": "v_fn_19", + "offset": 76 + }, + { + "type": "void*", + "name": "v_fn_20", + "offset": 80 + }, + { + "type": "void*", + "name": "v_fn_21", + "offset": 84 + }, + { + "type": "void*", + "name": "v_fn_22", + "offset": 88 + }, + { + "type": "void*", + "name": "v_fn_23", + "offset": 92 + }, + { + "type": "void*", + "name": "v_fn_24", + "offset": 96 + }, + { + "type": "void*", + "name": "v_fn_25", + "offset": 100 + }, + { + "type": "void*", + "name": "v_fn_26", + "offset": 104 + }, + { + "type": "void*", + "name": "v_fn_27", + "offset": 108 + }, + { + "type": "void*", + "name": "v_fn_28", + "offset": 112 + }, + { + "type": "void*", + "name": "v_fn_29", + "offset": 116 + }, + { + "type": "void*", + "name": "v_fn_30", + "offset": 120 + }, + { + "type": "void*", + "name": "v_fn_31", + "offset": 124 + }, + { + "type": "void*", + "name": "v_fn_32", + "offset": 128 + }, + { + "type": "void*", + "name": "v_fn_33", + "offset": 132 + }, + { + "type": "void*", + "name": "v_fn_34", + "offset": 136 + }, + { + "type": "void*", + "name": "v_fn_35_CapsWindowSize", + "offset": 140 + }, + { + "type": "void*", + "name": "v_fn_36", + "offset": 144 + }, + { + "type": "void*", + "name": "v_fn_37", + "offset": 148 + }, + { + "type": "void*", + "name": "v_fn_38", + "offset": 152 + }, + { + "type": "void*", + "name": "v_fn_39", + "offset": 156 + }, + { + "type": "void*", + "name": "v_fn_40", + "offset": 160 + }, + { + "type": "void*", + "name": "v_fn_41", + "offset": 164 + }, + { + "type": "void*", + "name": "v_fn_42", + "offset": 168 + }, + { + "type": "void*", + "name": "v_fn_43", + "offset": 172 + }, + { + "type": "void*", + "name": "v_fn_44", + "offset": 176 + }, + { + "type": "void*", + "name": "v_fn_45", + "offset": 180 + }, + { + "type": "void*", + "name": "v_fn_46", + "offset": 184 + }, + { + "type": "void*", + "name": "v_fn_47", + "offset": 188 + }, + { + "type": "void*", + "name": "v_fn_48", + "offset": 192 + }, + { + "type": "void*", + "name": "v_fn_49", + "offset": 196 + }, + { + "type": "void*", + "name": "v_fn_50", + "offset": 200 + }, + { + "type": "void*", + "name": "v_fn_51", + "offset": 204 + }, + { + "type": "void*", + "name": "v_fn_52", + "offset": 208 + }, + { + "type": "void*", + "name": "v_fn_53", + "offset": 212 + }, + { + "type": "void*", + "name": "v_fn_54", + "offset": 216 + }, + { + "type": "void*", + "name": "v_fn_55", + "offset": 220 + }, + { + "type": "void*", + "name": "v_fn_56", + "offset": 224 + }, + { + "type": "void*", + "name": "v_fn_57", + "offset": 228 + }, + { + "type": "void*", + "name": "v_fn_58", + "offset": 232 + }, + { + "type": "void*", + "name": "v_fn_59", + "offset": 236 + }, + { + "type": "void*", + "name": "v_fn_60", + "offset": 240 + }, + { + "type": "void*", + "name": "v_fn_61", + "offset": 244 + }, + { + "type": "void*", + "name": "v_fn_62", + "offset": 248 + }, + { + "type": "void*", + "name": "v_fn_63", + "offset": 252 + }, + { + "type": "void*", + "name": "v_fn_64", + "offset": 256 + }, + { + "type": "void*", + "name": "v_fn_65", + "offset": 260 + }, + { + "type": "void*", + "name": "v_fn_66", + "offset": 264 + }, + { + "type": "void*", + "name": "v_fn_67", + "offset": 268 + }, + { + "type": "void*", + "name": "v_fn_68", + "offset": 272 + }, + { + "type": "void*", + "name": "v_fn_69", + "offset": 276 + }, + { + "type": "void*", + "name": "v_fn_70", + "offset": 280 + }, + { + "type": "void*", + "name": "v_fn_71", + "offset": 284 + }, + { + "type": "void*", + "name": "v_fn_72", + "offset": 288 + }, + { + "type": "void*", + "name": "v_fn_73", + "offset": 292 + }, + { + "type": "void*", + "name": "v_fn_74", + "offset": 296 + }, + { + "type": "void*", + "name": "v_fn_75", + "offset": 300 + }, + { + "type": "void*", + "name": "v_fn_76", + "offset": 304 + }, + { + "type": "void*", + "name": "v_fn_77", + "offset": 308 + }, + { + "type": "void*", + "name": "v_fn_78", + "offset": 312 + }, + { + "type": "void*", + "name": "v_fn_79", + "offset": 316 + }, + { + "type": "void*", + "name": "v_fn_80", + "offset": 320 + }, + { + "type": "void*", + "name": "v_fn_81", + "offset": 324 + }, + { + "type": "void*", + "name": "v_fn_82", + "offset": 328 + }, + { + "type": "void*", + "name": "v_fn_83", + "offset": 332 + } + ] + }, + { + "name": "CGxStateBom", + "members": [ + { + "type": "CGxStateBom__m_data", + "name": "m_data" + }, + { + "type": "int32_t", + "name": "filler", + "offset": 12 + } + ] + }, + { + "name": "TSGrowableArray_CGxPushedRenderState", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "CGxPushedRenderState*", + "name": "m_data", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_chunk", + "offset": 16 + } + ] + }, + { + "name": "TSGrowableArray_uint32_t", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "uint32_t*", + "name": "m_data", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_chunk", + "offset": 16 + } + ] + }, + { + "name": "CGxFormat", + "members": [ + { + "type": "bool", + "name": "hwTnL" + }, + { + "type": "int8_t", + "name": "window", + "offset": 1 + }, + { + "type": "int32_t", + "name": "maximize", + "offset": 4 + }, + { + "type": "CGxFormat__Format", + "name": "depthFormat", + "offset": 8 + }, + { + "type": "C2iVector", + "name": "size", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "sampleCount", + "offset": 20 + }, + { + "type": "CGxFormat__Format", + "name": "colorFormat", + "offset": 24 + }, + { + "type": "uint32_t", + "name": "refreshRate", + "offset": 28 + }, + { + "type": "uint32_t", + "name": "vsync", + "offset": 32 + }, + { + "type": "C2iVector", + "name": "pos", + "offset": 36 + } + ] + }, + { + "name": "TSHashTable_CGxShader_HASHKEY_STRI", + "members": [ + { + "type": "TSList_CGxShader", + "name": "m_fulllist" + }, + { + "type": "uint32_t", + "name": "m_fullnessIndicator", + "offset": 12 + }, + { + "type": "TSGrowableArray_TSList_CGxShader", + "name": "m_slotlistarray", + "offset": 16 + }, + { + "type": "uint32_t", + "name": "m_slotmask", + "offset": 36 + } + ] + }, + { + "name": "CGxMatrixStack", + "members": [ + { + "type": "uint32_t", + "name": "m_level" + }, + { + "type": "int8_t", + "name": "m_dirty", + "offset": 4 + }, + { + "type": "C44Matrix", + "name": "m_mtx", + "arrsize": 4, + "offset": 8 + }, + { + "type": "uint32_t", + "name": "m_flags", + "arrsize": 4, + "offset": 264 + } + ] + }, + { + "name": "TSFixedArray_CGxAppRenderState", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "CGxAppRenderState*", + "name": "m_data", + "offset": 12 + } + ] + }, + { + "name": "TSFixedArray_CGxStateBom", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "CGxStateBom*", + "name": "m_data", + "offset": 12 + } + ] + }, + { + "name": "CGxShader", + "members": [ + { + "type": "TSHashObject_CGxShader_HASHKEY_STRI", + "name": "b_base" + }, + { + "type": "uint32_t", + "name": "refCount", + "offset": 24 + }, + { + "type": "void*", + "name": "apiSpecific", + "offset": 28 + }, + { + "type": "int32_t", + "name": "target", + "offset": 32 + }, + { + "type": "int32_t", + "name": "int28", + "offset": 36 + }, + { + "type": "int32_t", + "name": "valid", + "offset": 40 + }, + { + "type": "int32_t", + "name": "loaded", + "offset": 44 + }, + { + "type": "int32_t", + "name": "int34", + "offset": 48 + }, + { + "type": "int32_t", + "name": "patched", + "offset": 52 + }, + { + "type": "int32_t", + "name": "int3C", + "offset": 56 + }, + { + "type": "int32_t", + "name": "int40", + "offset": 60 + }, + { + "type": "int16_t", + "name": "int44", + "offset": 64 + }, + { + "type": "int16_t", + "name": "int46", + "offset": 66 + }, + { + "type": "TSGrowableArray_uint8_t", + "name": "code", + "offset": 68 + } + ] + }, + { + "name": "TSHashObject_CGxShader_HASHKEY_STRI", + "members": [ + { + "type": "uint32_t", + "name": "m_hashval" + }, + { + "type": "TSLink_CGxShader", + "name": "m_linktoslot", + "offset": 4 + }, + { + "type": "TSLink_CGxShader", + "name": "m_linktofull", + "offset": 12 + }, + { + "type": "HASHKEY_STRI", + "name": "m_key", + "offset": 20 + } + ] + }, + { + "name": "TSGrowableArray_uint8_t", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "uint8_t*", + "name": "m_data", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_chunk", + "offset": 16 + } + ] + }, + { + "name": "TSList_CGxShader", + "members": [ + { + "type": "ptrdiff_t", + "name": "m_linkoffset" + }, + { + "type": "TSLink_CGxShader", + "name": "m_terminator", + "offset": 4 + } + ] + }, + { + "name": "TSGrowableArray_TSList_CGxShader", + "members": [ + { + "type": "void**", + "name": "vtable" + }, + { + "type": "uint32_t", + "name": "m_alloc", + "offset": 4 + }, + { + "type": "uint32_t", + "name": "m_count", + "offset": 8 + }, + { + "type": "TSList_CGxShader*", + "name": "m_data", + "offset": 12 + }, + { + "type": "uint32_t", + "name": "m_chunk", + "offset": 16 + } + ] + }, + { + "name": "TSLink_CGxShader", + "members": [ + { + "type": "TSLink_CGxShader*", + "name": "m_prevlink" + }, + { + "type": "CGxShader*", + "name": "m_next", + "offset": 4 + } + ] + }, + { + "name": "TSLinkedNode_CGxShader", + "members": [ + { + "type": "TSLink_CGxShader", + "name": "m_link" + } + ] + } + ], + "unions": [ + { + "name": "ubyte4__0000", + "members": [ + { + "type": "uint8_t", + "name": "b", + "arrsize": 4 + }, + { + "type": "uint32_t", + "name": "u" + } + ] + }, + { + "name": "CGxStateBom__m_data", + "members": [ + { + "type": "int32_t", + "name": "i", + "arrsize": 3 + }, + { + "type": "uint32_t", + "name": "u", + "arrsize": 3 + }, + { + "type": "float", + "name": "f", + "arrsize": 3 + }, + { + "type": "void*", + "name": "p" + } + ] + } + ] +} diff --git a/README.md b/README.md index 806db5b..23c4308 100644 --- a/README.md +++ b/README.md @@ -1,56 +1,65 @@ -# binana - -This repository hosts some work related to studying the original game binaries. - -You can use the information here to get a headstart when working on the [Whoa project](https://github.com/whoahq/whoa). - -# Header files - -To make reverse engineering easier, C header files matching the original memory layout are provided. - -## Importing headers - -To use these headers in Ghidra, - - 1. go to `File` > `Parse C Source...`. - 2. Select `clib.prf` as your parse configuration, and clear all source files and input paths. - 3. Add the header `/include/main.h` to the `Source files to parse` combo box. - 4. Add the path to `/include` to the `Include paths` combo box. - 5. press `Parse to Program`. - -TODO: equivalent guide for IDA Pro. - -## Maintaining headers - -Headers should be restricted at all times to the C programming language only. C++ syntax will break type analysis. - -To convert C++ namespaces, use double-underscores. For instance: - -```cpp -void Name::Space::Thing(); -``` - -should become: - -```c -void Name__Space__Thing(); -``` - -# Symbol files - -Symbol files are text files that map function names and data labels to addresses. - -In this repo, `script/compile-symbols` is used to concatenate our organized symbol files into one big file (`/symbol/main.sym`). - -To import this file to your Ghidra project, - - 1. go to `Window` > `Script Manager` - 2. In the table view, lookup `ImportSymbolsScript.py` - 3. Run the script - 4. Enter the path to `/symbol/main.sym` - -To refresh the `main.sym` file after changing one of the constituent symbol files: - -```bash -script/compile-symbols -``` \ No newline at end of file +# binana + +This repository hosts some work related to studying the original game binaries. + +You can use the information here to get a headstart when working on the [Whoa project](https://github.com/whoahq/whoa). + +# Header files + +To make reverse engineering easier, C header files to match the original executable's memory layout are provided. + +# Symbol files + +Symbol files are text files that map addresses to functions and variables/data labels. + +In this repo, `script/compile-symbols` is used to concatenate our organized symbol files into one big file (`/symbol/main.sym`). + +To refresh the gigantic `main.sym` file after changing one of the source symbol files: + +```bash +script/compile-symbols +``` + +# Loading information into Ghidra + +## Importing headers + +To import the main header file into your Ghidra project, + + 1. go to `File` > `Parse C Source...`. + 2. Select `clib.prf` as your parse configuration, and clear all source files and input paths. + 3. Add the header `/include/main.h` to the `Source files to parse` combo box. + 4. Add the path to `/include` to the `Include paths` combo box. + 5. press `Parse to Program`. + +If all goes well, Data Type Manager will now contain the data structures from the headers. + +## Importing symbols + +To import the symbol file into your Ghidra project, + + 1. go to `Window` > `Script Manager` + 2. In the table view, lookup `ImportSymbolsScript.py` + 3. Run the script + 4. Enter the path to `/symbol/main.sym` + +# Loading information into x64dbg (x32dbg) + +For ease of debugging, we provide x64dbg databases (generated by the Go tool from symbol maps), as well as x64dbg type information (generated by the same Go tool from the C headers). + +## Importing database + +To load the database information into x64dbg: + + 1. Open x96dbg.exe or x32dbg.exe directly + 2. Load your game binary + 3. Go to `File` > `Database` > `Import database` + 4. Navigate to /x32dbg/game.dd32`. + +## Importing types + +To load the type information JSON file: + + 1. Open the binary in x32dbg.exe + 2. in the console, type: `LoadTypes \x32dbg\types.json` + diff --git a/go.mod b/go.mod index bd3b615..6d0f679 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,17 @@ module github.com/thunderbrewhq/binana go 1.22.0 -require github.com/spf13/cobra v1.8.1 +require ( + github.com/spf13/cobra v1.8.1 + modernc.org/cc/v3 v3.41.0 +) require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/pierrec/lz4/v4 v4.1.21 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/spf13/pflag v1.0.5 // indirect + lukechampine.com/uint128 v1.3.0 // indirect + modernc.org/mathutil v1.6.0 // indirect + modernc.org/strutil v1.2.0 // indirect + modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index b2e456d..ba62a6b 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,12 @@ github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= 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= @@ -10,3 +14,13 @@ 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= +lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= +lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= +modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/go/cmd/binana/cmd/root.go b/go/cmd/binana/cmd/root.go index b4d64eb..93d0e91 100644 --- a/go/cmd/binana/cmd/root.go +++ b/go/cmd/binana/cmd/root.go @@ -38,7 +38,6 @@ func init() { 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) } diff --git a/go/cmd/binana/cmd/x64dbg_gen.go b/go/cmd/binana/cmd/x64dbg_gen.go index 5d32e4f..130e232 100644 --- a/go/cmd/binana/cmd/x64dbg_gen.go +++ b/go/cmd/binana/cmd/x64dbg_gen.go @@ -1,117 +1,50 @@ -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) - } -} +package cmd + +import ( + "fmt" + "os" + "strconv" + + "github.com/spf13/cobra" + "github.com/thunderbrewhq/binana/go/profile" +) + +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) { + // get command line arguments + 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) + } + + // parse the base address of game EXE + base_address, err := strconv.ParseUint(base_address_s, 16, 64) + if err != nil { + panic(err) + } + + game_profile_directory, err := cmd.Flags().GetString("game") + if err != nil { + panic(err) + } + + game_profile, err := profile.Open(game_profile_directory) + if err != nil { + panic(err) + } + + if err = game_profile.CreateX64dbgFiles(module_name, base_address); err != nil { + fmt.Println(err) + os.Exit(1) + } +} diff --git a/go/profile/include/stdbool.h b/go/profile/include/stdbool.h new file mode 100644 index 0000000..4b11d10 --- /dev/null +++ b/go/profile/include/stdbool.h @@ -0,0 +1,6 @@ +#ifndef SYSTEM_STD_BOOL_H +#define SYSTEM_STD_BOOL_H + +typedef char bool; + +#endif \ No newline at end of file diff --git a/go/profile/include/stdint.h b/go/profile/include/stdint.h new file mode 100644 index 0000000..d944acf --- /dev/null +++ b/go/profile/include/stdint.h @@ -0,0 +1,17 @@ +#ifndef SYSTEM_STD_INT_H +#define SYSTEM_STD_INT_H + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; +typedef long long int64_t; +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; + +typedef int32_t ptrdiff_t; +typedef uint32_t uintptr_t; +typedef int32_t intptr_t; + +#endif \ No newline at end of file diff --git a/go/profile/open.go b/go/profile/open.go new file mode 100644 index 0000000..adb754f --- /dev/null +++ b/go/profile/open.go @@ -0,0 +1,51 @@ +package profile + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/thunderbrewhq/binana/go/symfile" +) + +type Profile struct { + Directory string + SymbolTable *symfile.InMemoryTable +} + +func Open(profile_directory string) (profile *Profile, err error) { + var dir fs.FileInfo + dir, err = os.Stat(profile_directory) + if err != nil { + return + } + + if !dir.IsDir() { + err = fmt.Errorf("profile: game profile is not a directory") + return + } + + fmt.Println("Opening profile", profile_directory) + + profile = new(Profile) + profile.Directory = profile_directory + + path_to_symbols_file := filepath.Join(profile_directory, "symbol", "main.sym") + var symbols_file *os.File + symbols_file, err = os.Open(path_to_symbols_file) + if err != nil { + return + } + + profile.SymbolTable = new(symfile.InMemoryTable) + + if err = symfile.Load(profile.SymbolTable, symbols_file); err != nil { + return + } + + symbols_file.Close() + + // + return +} diff --git a/go/profile/x64dbg.go b/go/profile/x64dbg.go new file mode 100644 index 0000000..8f8b2de --- /dev/null +++ b/go/profile/x64dbg.go @@ -0,0 +1,13 @@ +package profile + +func (profile *Profile) CreateX64dbgFiles(module_name string, base_address uint64) (err error) { + if err = profile.generate_x64dbg_database(module_name, base_address); err != nil { + return + } + + if err = profile.generate_x64dbg_types(); err != nil { + return + } + + return +} diff --git a/go/profile/x64dbg_generate_database.go b/go/profile/x64dbg_generate_database.go new file mode 100644 index 0000000..6850488 --- /dev/null +++ b/go/profile/x64dbg_generate_database.go @@ -0,0 +1,66 @@ +package profile + +import ( + "fmt" + "path/filepath" + + "github.com/thunderbrewhq/binana/go/symfile" + "github.com/thunderbrewhq/binana/go/x64dbg" +) + +func hex_address(u uint64) string { + return fmt.Sprintf("0x%x", u) +} + +func (profile *Profile) generate_x64dbg_database(module_name string, base_address uint64) (err error) { + // Convert symbol table into x64dbg database + var dd x64dbg.Database + + for _, entry := range profile.SymbolTable.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("Strange 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) + } + } + + // save database + dd_path := filepath.Join(profile.Directory, "x32dbg", "game.dd32") + if err = x64dbg.SaveDatabase(dd_path, &dd); err != nil { + return + } + + fmt.Println("database generated!", dd_path) + + return +} diff --git a/go/profile/x64dbg_generate_types.go b/go/profile/x64dbg_generate_types.go new file mode 100644 index 0000000..39ae8fc --- /dev/null +++ b/go/profile/x64dbg_generate_types.go @@ -0,0 +1,236 @@ +package profile + +import ( + "fmt" + "path/filepath" + "slices" + "sort" + + "github.com/thunderbrewhq/binana/go/x64dbg" + "modernc.org/cc/v3" +) + +func sort_string_ids(ids []cc.StringID) { + sort.Slice(ids, func(i, j int) bool { + return ids[i] < ids[j] + }) +} + +func cc_type_to_struct_member_type(t cc.Type) (m x64dbg.StructMemberType) { + var s string + var arrsize int32 = 1 + var array bool + +loop: + for t != nil { + if t.Name().String() != "" { + s = t.Name().String() + s + break + } + + switch t.Kind() { + case cc.Ptr: + s = "*" + s + case cc.Array: + array = true + arrsize *= int32(t.Len()) + case cc.Function: + s = "void*" + s + break loop + default: + s = t.Kind().String() + s + break loop + } + + t = t.Elem() + } + + if array { + m.ArraySize = arrsize + } + + m.Offset = -1 + m.Type = s + + return +} + +func cc_type_to_typedef(t cc.Type) (m x64dbg.Type) { + var s string + var arrsize int32 = 1 + var array bool + +loop: + for t != nil { + + if t.Name().String() != "" && t.Kind() != cc.Enum { + s = t.Name().String() + s + break + } + + switch t.Kind() { + case cc.Enum: + s = t.EnumType().String() + s + break loop + case cc.Ptr: + s = "*" + s + case cc.Array: + array = true + arrsize *= int32(t.Len()) + case cc.Function: + s = "void*" + s + default: + s = t.Kind().String() + s + break loop + } + + t = t.Elem() + } + + if array { + m.ArraySize = arrsize + } + + m.Type = s + + return +} + +// parses the C headers and generates a matching x64dbg types.json file +func (profile *Profile) generate_x64dbg_types() (err error) { + // parse C headers + var cc_config cc.Config + cc_config.ABI, err = cc.NewABI("windows", "386") + if err != nil { + panic(err) + } + + cc_include_paths := []string{ + filepath.Join(profile.Directory, "include"), + } + + cc_system_include_paths := []string{ + filepath.Join("go", "profile", "include"), + } + + cc_sources := []cc.Source{ + cc.Source{ + Name: filepath.Join(profile.Directory, "include", "main.h"), + }, + } + + var ast *cc.AST + ast, err = cc.Translate(&cc_config, cc_include_paths, cc_system_include_paths, cc_sources) + if err != nil { + return + } + + var x64_types x64dbg.Types + + // Parse integer types + var scope_ids []cc.StringID + for name := range ast.Scope { + scope_ids = append(scope_ids, name) + } + + sort_string_ids(scope_ids) + + // these types needed by the C parser can't be included in x64dbg json + ignore_types := []string{ + "int8_t", + "int16_t", + "int32_t", + "int64_t", + + "uint8_t", + "uint16_t", + "uint32_t", + "uint64_t", + + "bool", + } + + for _, scope_id := range scope_ids { + scope := ast.Scope[scope_id] + for _, node := range scope { + if declarator, ok := node.(*cc.Declarator); ok { + if declarator.IsTypedefName { + if declarator.Type().Kind() != cc.Struct { + var x64_type x64dbg.Type = cc_type_to_typedef(declarator.Type()) + x64_type.Name = scope_id.String() + if !slices.Contains(ignore_types, x64_type.Name) { + x64_types.Types = append(x64_types.Types, x64_type) + } + } + } + } + } + } + + var struct_names []cc.StringID + for struct_name := range ast.StructTypes { + struct_names = append(struct_names, struct_name) + } + sort.Slice(struct_names, func(i, j int) bool { + return struct_names[i] < struct_names[j] + }) + + for _, struct_name := range struct_names { + struct_type := ast.StructTypes[struct_name] + + var x64_struct x64dbg.StructType + x64_struct.Name = struct_name.String() + + for i := range struct_type.NumField() { + struct_member := struct_type.FieldByIndex([]int{i}) + + // If struct member is a union + if struct_member.Type().Kind() == cc.Union { + union_member_name := struct_member.Name().String() + if union_member_name == "" { + // union is anonymous + union_member_name = fmt.Sprintf("%04d", struct_member.Offset()) + } + + union_type_name := fmt.Sprintf("%s__%s", struct_name.String(), union_member_name) + + var x64_union x64dbg.UnionType + x64_union.Name = union_type_name + + for i := range struct_member.Type().NumField() { + union_field := struct_member.Type().FieldByIndex([]int{i}) + var x64_union_member x64dbg.Type = cc_type_to_typedef(union_field.Type()) + x64_union_member.Name = union_field.Name().String() + x64_union.Members = append(x64_union.Members, x64_union_member) + } + + x64_types.Unions = append(x64_types.Unions, x64_union) + + x64_struct_member := x64dbg.StructMemberType{} + x64_struct_member.Type = union_type_name + x64_struct_member.Name = struct_member.Name().String() + x64_struct_member.Offset = int32(struct_member.Offset()) + x64_struct.Members = append(x64_struct.Members, x64_struct_member) + } else { + + x64_struct_member := cc_type_to_struct_member_type(struct_member.Type()) + x64_struct_member.Name = struct_member.Name().String() + x64_struct_member.Offset = int32(struct_member.Offset()) + x64_struct.Members = append(x64_struct.Members, x64_struct_member) + } + } + + x64_types.Structs = append(x64_types.Structs, x64_struct) + } + + types_file_path := filepath.Join(profile.Directory, "x32dbg", "types.json") + + err = x64dbg.SaveTypes(types_file_path, &x64_types) + if err != nil { + return + } + + fmt.Println("types generated!", types_file_path) + + return +} diff --git a/go/symfile/memory_table.go b/go/symfile/memory_table.go index 7068e50..265b0b0 100644 --- a/go/symfile/memory_table.go +++ b/go/symfile/memory_table.go @@ -1,29 +1,33 @@ -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) -} +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) +} + +func NewInMemoryTable() *InMemoryTable { + return new(InMemoryTable) +} diff --git a/go/symfile/symfile.go b/go/symfile/symfile.go index 100a646..bc7367e 100644 --- a/go/symfile/symfile.go +++ b/go/symfile/symfile.go @@ -1,44 +1,43 @@ -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 -} +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) +} + +func Load(table Table, text io.Reader) (err error) { + err = load(text, table) + return +} diff --git a/go/x64dbg/database.go b/go/x64dbg/database.go index 2653c36..617fa6b 100644 --- a/go/x64dbg/database.go +++ b/go/x64dbg/database.go @@ -1,91 +1,77 @@ -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 -} +package x64dbg + +import ( + "encoding/json" + "os" +) + +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) (err error) { + var file *os.File + file, err = os.Create(name) + if err != nil { + return + } + + e := json.NewEncoder(file) + e.SetIndent("", " ") + if err = e.Encode(database); err != nil { + return + } + + err = file.Close() + return +} diff --git a/go/x64dbg/types.go b/go/x64dbg/types.go new file mode 100644 index 0000000..c591bd4 --- /dev/null +++ b/go/x64dbg/types.go @@ -0,0 +1,61 @@ +package x64dbg + +import ( + "encoding/json" + "os" +) + +type Type struct { + Type string `json:"type"` + Name string `json:"name"` + ArraySize int32 `json:"arrsize,omitempty"` +} + +type StructMemberType struct { + Type string `json:"type"` + Name string `json:"name"` + ArraySize int32 `json:"arrsize,omitempty"` + Offset int32 `json:"offset,omitempty"` +} + +type StructType struct { + Name string `json:"name"` + Members []StructMemberType `json:"members,omitempty"` +} + +type UnionType struct { + Name string `json:"name"` + Members []Type `json:"members,omitempty"` +} + +type FunctionType struct { + ReturnType string `json:"rettype"` + CallConvention string `json:"callconv"` + NoReturn bool `json:"noreturn"` + Name string `json:"name"` + Arguments []Type `json:"arguments,omitempty"` +} + +type Types struct { + Types []Type `json:"types,omitempty"` + Structs []StructType `json:"structs,omitempty"` + Unions []UnionType `json:"unions,omitempty"` + Functions []FunctionType `json:"functions,omitempty"` +} + +func SaveTypes(name string, types *Types) (err error) { + var file *os.File + file, err = os.Create(name) + if err != nil { + return + } + + e := json.NewEncoder(file) + e.SetIndent("", " ") + if err = e.Encode(types); err != nil { + return + } + + err = file.Close() + return +} diff --git a/script/compile-symbols b/script/compile-symbols index 0a37405..f154478 100755 --- a/script/compile-symbols +++ b/script/compile-symbols @@ -1,11 +1,11 @@ -#!/usr/bin/env bash - -# this script just collects symbols into one file for convenience - -if [ $# -eq 0 ] - then - echo "Select a version to use" - exit 1 -fi - -awk 1 $1/symbol/*/*.sym | sort -k2 -t' ' > $1/symbol/main.sym +#!/usr/bin/env bash + +# this script just collects symbols into one file for convenience + +if [ $# -eq 0 ] + then + echo "Select a version to use" + exit 1 +fi + +awk 1 $1/symbol/*/*.sym | sort -k2 -t' ' > $1/symbol/main.sym