Im making Atom fishing server emulator. It's 2d game written on delphi. I need you to check first "testserver1.py" file (but don't be sure that information in it are correct, i just guess) and after that i need you to decompile FFG.exe and find CMD=120 and CMD=125 full structure, fields, leght and etc.
XOR key (52 bytes) — found at 0x568e7c in FFG.exe XOR_KEY = b"sdfgDDdffkojeroxdfJKHNplmkOIJHjklnIOJifg33gjkfsdpgko" XOR_KEY_LEN = 52
GameData.pkg RC6 key — found at 0x482c34 in FFG.exe RC6_KEY = b"jklHnKrt"
I'll read the testserver1.py file and open the binary in Ghidra simultaneously.
Call workspace_read_file
Arguments
{"filepath": "/sandbox/testserver1.py"}
Tool result
{"result":"#!/usr/bin/env python3\n\"\"\"\nAtom Fishing Game Server Emulator\n===================================\nReverse-engineered from FFG.exe (client binary) and protocol analysis.\n\nPROTOCOL ANALYSIS (from FFG.exe binary reverse engineering):\n============================================================\n\nPACKET HEADER (20 bytes, big-endian):\n struct TPacketHeader {\n uint32_t cmd; // Command ID\n uint32_t flags; // 0 = text/KV payload, 1 = binary payload\n uint32_t length; // Payload length in bytes\n uint32_t seq; // Sequence number (server increments, client echoes)\n uint32_t csum; // Checksum: ((seq + cmd) * 3) ^ 0x1773\n };\n\nXOR ENCRYPTION (confirmed from 0x568e1b, 0x569231 in FFG.exe):\n KEY = b\"sdfgDDdffkojeroxdfJKHNplmkOIJHjklnIOJifg33gjkfsdpgko\" (52 bytes)\n encrypted[i] = plaintext[i] ^ KEY[i % 52] ^ (seq & 0xFF)\n - CMD=1 inbound: NOT encrypted (handshake)\n - All other payloads: XOR encrypted when sent by server\n\nCHECKSUM (confirmed from 0x569231 in FFG.exe):\n csum = ((seq + cmd) * 3) ^ 0x1773\n\"\"\"\n\nimport socket\nimport struct\nimport threading\nimport time\nimport hashlib\nimport os\nimport traceback\nimport random\nfrom datetime import datetime\n\n# ═══════════════════════════════════════════════════════════════════\n# PROTOCOL CONSTANTS\n# ═══════════════════════════════════════════════════════════════════\n\n# XOR key (52 bytes) — found at 0x568e7c in FFG.exe\nXOR_KEY = b\"sdfgDDdffkojeroxdfJKHNplmkOIJHjklnIOJifg33gjkfsdpgko\"\nXOR_KEY_LEN = 52\n\n# GameData.pkg RC6 key — found at 0x482c34 in FFG.exe\nRC6_KEY = b\"jklHnKrt\"\n\n# Delphi TDateTime epoch\nDELPHI_EPOCH = datetime(1899, 12, 30)\n\n# Server network settings\nSERVER_HOST = \"0.0.0.0\"\nSERVER_PORT = 11000\n\n# Location/map file directories — adjust to your installation\nLOC_DIR = r\"E:\\Atom Fishing\\Data\\Maps\\Locs\"\nBASE_DIR = r\"E:\\Atom Fishing\\Data\\Maps\\Base\"\n\ndef brute_one_id_all_structs(srv, conn, player, cmd_id=160):\n log(f\"===== BRUTE ONE ID={cmd_id} START =====\")\n\n payloads = []\n\n # ---- Пустые и простые ----\n payloads += [\n b\"\",\n b\"\\x00\",\n b\"\\x00\\x00\",\n b\"\\x00\\x00\\x00\\x00\",\n b\"\\xff\",\n b\"\\xff\\xff\\xff\\xff\",\n ]\n\n # ---- Integer (разные endian и размеры) ----\n for i in [0, 1, 2, 255, 256, 65535]:\n payloads.append(struct.pack(\">I\", i)) # big endian\n payloads.append(struct.pack(\"<I\", i)) # little endian\n payloads.append(struct.pack(\">H\", i % 65536))\n payloads.append(struct.pack(\"<H\", i % 65536))\n\n # ---- Несколько чисел ----\n payloads += [\n struct.pack(\">II\", 1, 1),\n struct.pack(\">III\", 1, 2, 3),\n struct.pack(\"<III\", 1, 2, 3),\n ]\n\n # ---- Строки ----\n payloads += [\n b\"id=1\",\n b\"opt=3\",\n b\"map=1\",\n b\"id=1\\r\\n\",\n b\"opt=3\\r\\n\",\n b\"map=1\\r\\n\",\n b\"AAAA\",\n b\"A\" * 32,\n b\"A\" * 128,\n ]\n\n # ---- Null-terminated ----\n payloads += [\n b\"id=1\\x00\",\n b\"test\\x00\",\n ]\n\n # ---- Случайные байты ----\n for _ in range(20):\n payloads.append(os.urandom(random.randint(1, 64)))\n\n # ---- Повторяющиеся паттерны ----\n payloads += [\n b\"\\x00\" * 16,\n b\"\\xff\" * 16,\n b\"\\x41\\x41\\x41\\x41\",\n ]\n\n # ---- Длины (edge cases) ----\n for size in [1, 2, 4, 8, 16, 32, 64, 128]:\n payloads.append(b\"A\" * size)\n\n # ---- Основной цикл ----\n for flags in (0, 1):\n for payload in payloads:\n try:\n log(f\"[BRUTE] CMD={cmd_id} flags={flags} len={len(payload)}\")\n\n srv.send_pkt(\n conn,\n cmd=cmd_id,\n payload=payload,\n flags=flags,\n encrypt=False\n )\n\n time.sleep(2)\n\n except Exception as e:\n log(f\"[ERR] → {e}\")\n return\n\n log(\"===== BRUTE END =====\")\n\ndef brute_opt4(srv, conn, player):\n log(\"===== BRUTE OPTID=3 START =====\")\n\n test_cmds = list(range(15, 17))\n payload = struct.pack(\"<II\", 1, 1) # 2x uint32\n\n for cmd in test_cmds:\n try:\n log(f\"[BRUTE] CMD={cmd} flags={1} len={len(payload)}\")\n\n srv.send_pkt(conn, cmd=cmd, payload=payload, flags=1, encrypt=False)\n # маленькая пауза чтобы клиент успел отреагировать\n time.sleep(2)\n \n except Exception as e:\n log(f\"[ERR] CMD={cmd} → {e}\")\n return\n\ndef brute_opt3(srv, conn, player):\n log(\"===== BRUTE OPTID=3 START =====\")\n\n test_cmds = list(range(201, 300))\n\n payloads = [\n b\"\", # пусто\n b\"\\x00\\x00\\x00\\x01\", # int=1\n struct.pack(\">I\", 1),\n struct.pack(\">II\", 1, 1),\n b\"map=1\\r\\n\",\n b\"id=1\\r\\n\",\n b\"opt=3\\r\\n\",\n ]\n\n for cmd in test_cmds:\n for flags in (0, 1):\n for payload in payloads:\n try:\n log(f\"[BRUTE] CMD={cmd} flags={flags} len={len(payload)}\")\n\n srv.send_pkt(conn, cmd=cmd, payload=payload, flags=flags, encrypt=False)\n\n # маленькая пауза чтобы клиент успел отреагировать\n time.sleep(0.15)\n\n except Exception as e:\n log(f\"[ERR] CMD={cmd} → {e}\")\n return\n\ndef brute_cmd201(srv, conn, player):\n log(\"===== BRUTE CMD=201 START =====\")\n\n cmd = 113\n\n payloads = []\n\n # ── 1. Пустые / контрольные ──\n payloads += [\n b\"\",\n b\"\\x00\",\n b\"\\x00\\x00\\x00\\x00\",\n ]\n\n # ── 2. 32-bit ints ──\n payloads += [\n struct.pack(\">I\", 1),\n struct.pack(\"<I\", 1),\n struct.pack(\">I\", 3),\n ]\n\n # ── 3. 2x int struct ──\n payloads += [\n struct.pack(\">II\", 1, 1),\n struct.pack(\"<II\", 1, 1),\n struct.pack(\">II\", 201, 1),\n ]\n\n # ── 4. text KV ──\n payloads += [\n b\"opt=3\\r\\n\",\n b\"optid=3\\r\\n\",\n b\"id=201\\r\\n\",\n b\"cmd=201\\r\\n\",\n ]\n\n # ── 5. возможный игровой стиль ──\n payloads += [\n b\"map=1\\r\",\n b\"mapid=1\\r\\n\",\n b\"type=3\\r\\n\",\n b\"subid=3\\r\\n\",\n ]\n\n # ── BRUTE LOOP ──\n for flags in (0, 1):\n for payload in payloads:\n try:\n log(f\"[BRUTE] CMD=201 flags={flags} len={len(payload)} data={payload!r}\")\n\n srv.send_pkt(\n conn,\n cmd=112,\n payload=payload,\n flags=flags,\n encrypt=False\n )\n\n time.sleep(0.10)\n\n except Exception as e:\n log(f\"[ERR] CMD=201 → {e}\")\n return\n\n log(\"===== BRUTE CMD=201 END =====\")\n\n log(\"===== BRUTE END =====\")\n\ndef handle_map_enter(srv, conn, player, mapid):\n log(f\"[ENTER MAP] id={mapid}\")\n\n # 1. отправить локацию\n send_location(srv, conn, loc_id=mapid, map_id=mapid)\n\n # 2. базовые данные\n send_player_data(srv, conn, player)\n\n # 3. окружение\n send_entities(srv, conn)\n send_tile_info(srv, conn)\n\n # 4. финализация\n send_server_time(srv, conn)\n\n# ═══════════════════════════════════════════════════════════════════\n# CRYPTO / CHECKSUM\n# ═══════════════════════════════════════════════════════════════════\n\n\ndef xor_crypt(data: bytes, seq: int) -> bytes:\n \"\"\"XOR cipher: data[i] ^= KEY[i % 52] ^ (seq & 0xFF)\"\"\"\n seq_byte = seq & 0xFF\n return bytes(b ^ XOR_KEY[i % XOR_KEY_LEN] ^ seq_byte for i, b in enumerate(data))\n\n\ndef make_csum(cmd: int, seq: int) -> int:\n \"\"\"Checksum: ((seq + cmd) * 3) ^ 0x1773 — confirmed at 0x569231\"\"\"\n return ((seq + cmd) * 3) ^ 0x1773\n\n\n# ═══════════════════════════════════════════════════════════════════\n# RAW SOCKET I/O\n# ═══════════════════════════════════════════════════════════════════\n\n\ndef recv_exact(conn: socket.socket, n: int) -> bytes:\n buf = b\"\"\n while len(buf) < n:\n chunk = conn.recv(n - len(buf))\n if not chunk:\n raise ConnectionError(\"Connection closed by client\")\n buf += chunk\n return buf\n\n\ndef recv_pkt(conn: socket.socket):\n \"\"\"\n Read one complete packet from the socket.\n Header: 5 × uint32 big-endian = 20 bytes\n Returns: (cmd, flags, seq, payload_decrypted)\n \"\"\"\n hdr = recv_exact(conn, 20)\n cmd, flags, length, seq, csum = struct.unpack(\">IIIII\", hdr)\n\n expected = make_csum(cmd, seq)\n csum_ok = csum == expected\n\n payload_raw = recv_exact(conn, length) if length > 0 else b\"\"\n\n # CMD=1 handshake payload is never XOR-encrypted\n if cmd != 1 and length > 0:\n payload = xor_crypt(payload_raw, seq)\n else:\n payload = payload_raw\n\n log(\n f\"<-- CMD={cmd} flags={flags} len={length} seq={seq} \"\n f\"csum={'OK' if csum_ok else f'BAD(exp=0x{expected:08X})'}\"\n )\n if payload and len(payload) < 512:\n try:\n log(f\" TXT: {payload.decode('utf-8', errors='replace')!r}\")\n except Exception:\n log(f\" HEX: {payload.hex()}\")\n\n return cmd, flags, seq, payload\n\n\n# ═══════════════════════════════════════════════════════════════════\n# SERVER STATE (per-connection)\n# ═══════════════════════════════════════════════════════════════════\n\n\nclass ServerState:\n def __init__(self):\n self.seq = 0 # server-side sequence counter (increments per send)\n\n def send_pkt(\n self,\n conn: socket.socket,\n cmd: int,\n payload: bytes,\n flags: int = 0,\n encrypt: bool = False,\n ):\n \"\"\"\n Build and transmit a packet.\n flags=0 → text/KV payload (plain)\n flags=1 → binary payload\n encrypt → apply XOR cipher to payload before sending\n \"\"\"\n self.seq += 1\n seq = self.seq\n data = xor_crypt(payload, seq) if encrypt else payload\n csum = make_csum(cmd, seq)\n hdr = struct.pack(\">IIIII\", cmd, flags, len(payload), seq, csum)\n conn.sendall(hdr + data)\n\n enc_str = \"XOR\" if encrypt else \"plain\"\n log(\n f\"--> CMD={cmd} flags={flags} seq={seq} len={len(payload)} \"\n f\"csum=0x{csum:08X} [{enc_str}]\"\n )\n if payload and len(payload) < 512:\n try:\n log(f\" TXT: {payload.decode('utf-8', errors='replace')!r}\")\n except Exception:\n log(f\" HEX: {payload.hex()}\")\n\n\n# ═══════════════════════════════════════════════════════════════════\n# UTILITIES\n# ═══════════════════════════════════════════════════════════════════\n\n\ndef log(msg: str):\n ts = datetime.now().strftime(\"%H:%M:%S.%f\")[:-3]\n print(f\"[{ts}] {msg}\")\n\n\ndef parse_kv(payload: bytes) -> dict:\n \"\"\"Parse key=value payload (\\\\r\\\\n or \\\\n separated) into dict.\"\"\"\n result = {}\n text = payload.replace(b\"\\r\\n\", b\"\\n\").replace(b\"\\r\", b\"\\n\")\n for line in text.split(b\"\\n\"):\n line = line.strip()\n if b\"=\" in line:\n k, _, v = line.partition(b\"=\")\n result[k.decode(\"utf-8\", errors=\"replace\").strip()] = v.decode(\n \"utf-8\", errors=\"replace\"\n ).strip()\n return result\n\n\ndef delphi_now() -> float:\n \"\"\"Current time as Delphi TDateTime (double: days since 1899-12-30).\"\"\"\n delta = datetime.now() - DELPHI_EPOCH\n return delta.days + delta.seconds / 86400.0 + delta.microseconds / 86_400_000_000.0\n\n\ndef delphi_datetime_str() -> str:\n \"\"\"\n Current date/time as Delphi-compatible string: D.M.YYYY H:MM:SS.0\n Used in the 'datetime=' field of CMD=100 player data.\n Delphi's StrToDateTime expects this exact format (no leading zeros in\n day/month/hour is fine; the decimal .0 represents milliseconds).\n \"\"\"\n now = datetime.now()\n return f\"{now.day}.{now.month}.{now.year} {now.hour}:{now.minute:02d}:{now.second:02d}.0\"\n\n\ndef get_game_time() -> tuple:\n \"\"\"\n Game time: 24 game-hours = 1 real hour.\n Step = 10 game-minutes = 25 real seconds.\n Returns: (real_datetime, game_hours, game_minutes)\n \"\"\"\n now = datetime.now()\n real_seconds = now.minute * 60 + now.second\n step = real_seconds // 25\n game_hours = step // 6\n game_minutes = (step % 6) * 10\n return now, game_hours, game_minutes\n\n\ndef get_loc_hash(loc_id: int, map_id: int) -> str:\n \"\"\"MD5 of the .loc or .base file for the given location.\"\"\"\n if loc_id > 0:\n filepath = os.path.join(LOC_DIR, f\"{loc_id}.loc\")\n else:\n filepath = os.path.join(BASE_DIR, f\"{map_id}.base\")\n\n if not os.path.exists(filepath):\n log(f\" [HASH] File not found: {filepath} → returning zero hash\")\n return \"00000000000000000000000000000000\"\n\n with open(filepath, \"rb\") as f:\n data = f.read()\n md5 = hashlib.md5(data).hexdigest().upper()\n log(f\" [HASH] {filepath} → {md5}\")\n return md5\n\n\n# ═══════════════════════════════════════════════════════════════════\n# PLAYER PROFILE BUILDER\n# ═══════════════════════════════════════════════════════════════════\n\n\ndef build_player_kv(\n login: str = \"player\",\n loc_id: int = 3,\n map_id: int = 1,\n player_id: int = 1,\n level: int = 100,\n raz: int = 20,\n daycount: int = 30,\n perkspoint: int = 4,\n blife: int = 100,\n life: int = 100,\n rad: int = 5,\n brad: int = 100,\n fishcount: int = 2,\n exp: int = 600,\n levexp: int = 1000,\n money: int = 1_000_000,\n rmoney: int = 1_000_000,\n invlines: int = 40,\n admlevel: int = 7,\n rating: int = 8,\n artelid: int = 0,\n artstat: int = 0,\n artcreator: int = 0,\n) -> bytes:\n \"\"\"\n Build the CMD=100 text response payload.\n Field names confirmed from FFG.exe strings @ 0x4e78d8 region.\n\n FIX: 'datetime=' field MUST be included with current server date/time\n in format D.M.YYYY H:MM:SS.0 (Delphi StrToDateTime compatible).\n Absence of this field causes the \"0.0.0 0:0:0.0 is not a valid date\n and time\" error in the client on login and every keepalive cycle.\n \"\"\"\n fields = [\n (\"no_login\", \"0\"),\n (\"id\", str(player_id)),\n (\"name\", login),\n (\"level\", str(level)),\n (\"raz\", str(raz)),\n (\"daycount\", str(daycount)),\n (\"perkspoint\", str(perkspoint)),\n (\"blife\", str(blife)),\n (\"life\", str(life)),\n (\"rad\", str(rad)),\n (\"brad\", str(brad)),\n (\"fishcount\", str(fishcount)),\n (\"exp\", str(exp)),\n (\"levexp\", str(levexp)),\n (\"money\""}Call ghidra_open_server
Arguments
{"filepath":"/sandbox/FFG.exe"}
Tool result
{"result":"compilerID: borlanddelphi\nimports[5]:\n - functions[2]: CoTaskMemAlloc,CoTaskMemFree\n name: OLE32.DLL\n - functions[11]: SysReAllocStringLen,SysFreeString,SysAllocStringLen,VariantInit,VariantClear,VariantCopy,SafeArrayCreate,SafeArrayGetLBound,SafeArrayGetUBound,SafeArrayPtrOfIndex,VariantChangeType\n name: OLEAUT32.DLL\n - functions[16]: BASS_SampleStop,BASS_MusicFree,BASS_Free,BASS_MusicLoad,BASS_MusicPlay,BASS_SampleLoad,BASS_SampleFree,BASS_SamplePlayEx,BASS_StreamFree,BASS_ChannelStop,BASS_ChannelSetAttributes,BASS_StreamCreateFile,BASS_StreamPlay,BASS_GetVersion,BASS_Init,BASS_Start\n name: BASS.DLL\n - functions[182]: CharNextA,MessageBoxA,LoadStringA,DefWindowProcA,DispatchMessageA,DispatchMessageW,EnumWindows,GetCapture,GetCursorPos,GetParent,GetPropA,GetWindow,GetWindowLongA,GetWindowThreadProcessId,IsDialogMessageA,IsDialogMessageW,IsIconic,IsWindowEnabled,IsWindowUnicode,IsWindowVisible,KillTimer,PeekMessageA,PeekMessageW,PtInRect,SendMessageA,SendMessageW,SetActiveWindow,SetTimer,SetWindowPos,SetWindowTextA,ShowOwnedPopups,ShowWindow,SystemParametersInfoA,TranslateMDISysAccel,TranslateMessage,UnhookWindowsHookEx,WaitMessage,WindowFromPoint,ActivateKeyboardLayout,CharLowerA,BeginPaint,CallNextHookEx,ChangeDisplaySettingsA,CharLowerBuffA,CharNextA,CharUpperBuffA,CheckMenuItem,ClientToScreen,CloseClipboard,CreateMenu,CreatePopupMenu,DeleteMenu,DestroyMenu,DestroyWindow,DrawEdge,DrawFrameControl,DrawMenuBar,DrawTextA,EnableMenuItem,EnableWindow,EndPaint,EnumClipboardFormats,EnumThreadWindows,EqualRect,FillRect,FindWindowA,FlashWindow,FrameRect,GetActiveWindow,GetClassInfoA,GetClassLongA,GetClassNameA,GetClipboardData,GetCursor,GetDC,GetDCEx,GetDesktopWindow,GetFocus,GetIconInfo,GetKeyNameTextA,GetKeyState,GetKeyboardLayout,GetKeyboardLayoutList,GetKeyboardLayoutNameA,GetLastActivePopup,GetMenu,GetMenuItemCount,GetMenuItemID,GetMenuItemInfoA,GetMenuState,GetMenuStringA,GetSubMenu,GetSysColor,GetSystemMenu,GetSystemMetrics,GetTopWindow,GetWindowPlacement,GetWindowRect,GetWindowTextA,InflateRect,InsertMenuA,InsertMenuItemA,IntersectRect,InvalidateRect,IsChild,IsWindow,LoadBitmapA,LoadCursorA,LoadIconA,MapVirtualKeyA,MapWindowPoints,MessageBoxA,MsgWaitForMultipleObjects,OemToCharA,OffsetRect,OpenClipboard,PostMessageA,PostQuitMessage,RedrawWindow,RegisterClassA,RegisterWindowMessageA,ReleaseCapture,ReleaseDC,RemoveMenu,RemovePropA,ScreenToClient,ScrollWindow,SetCapture,SetClassLongA,SetClipboardData,SetCursor,SetFocus,SetForegroundWindow,SetMenu,SetMenuItemInfoA,SetParent,SetPropA,SetRect,SetWindowLongA,SetWindowPlacement,SetWindowsHookExA,ShowCursor,UnregisterClassA,UpdateWindow,CreateWindowExA,CharToOemA,CreateIcon,EmptyClipboard,GetWindowLongW,LoadStringA,MessageBeep,SetWindowLongW,DrawIcon,GetKeyboardType,AdjustWindowRectEx,EnumChildWindows,GetClientRect,GetKeyboardState,GetMessagePos,GetWindowDC,IsRectEmpty,DestroyIcon,CallWindowProcA,DefFrameProcA,SetScrollInfo,RegisterClipboardFormatA,SetScrollRange,DestroyWindow,LoadKeyboardLayoutA,EnableScrollBar,DrawIconEx,GetSysColorBrush,GetScrollPos,ShowScrollBar,SetScrollPos,GetScrollRange,TrackPopupMenu,GetForegroundWindow,GetScrollInfo,IsZoomed,DestroyCursor,DefMDIChildProcA\n name: USER32.DLL\n - name: truncated... (more than 100 imports found)\n functions[1]: truncated\nexports[1]{address,name}:\n 0056c060,entry\nformat: Portable Executable (PE)\nlanguageID: \"x86:LE:32:default\"\nprocessor: x86\nendianess: Little Endian\nsegments[12]{name,start,end}:\n Headers,\"00400000\",004003ff\n .text,\"00401000\",0056a7ff\n .itext,0056b000,0056c1ff\n .data,0056d000,005713ff\n .bss,\"00572000\",0057e43b\n .idata,0057f000,005821ff\n .tls,\"00583000\",\"00583033\"\n .rdata,\"00584000\",005841ff\n .vmp0,\"00585000\",005a01ff\n .rsrc,005a1000,005a83ff\n .vmp1,005a9000,005a91ff\n .reloc,005aa000,005c51ff\naddressSize: 32 bit\nimageBase: \"00400000\"\nnamedFunctions[1]{address,name}:\n 0056c060,entry\nstrings[101]{address,value}:\n 00581c66,ImageList_GetIconSize\n 004e8fb4,SHOP_BAITES\n \"00454664\",traynotify\n 0054b298,spinid=\n 004dc530,\"[LOC]\"\n \"00441866\",TDockOverEvent\n 004a83f8,glClipPlane\n 0049c3a0,glMultiTexCoord2dvARB\n 00499dc0,glGetIntegerv\n 00542c58,error.wav\n \"00501498\",csIBM903\n \"00516268\",_KeyCraft\n 0049bbc0,glVertexAttrib4Nubv\n 0049d850,glColorFragmentOp2ATI\n 004fefcc,csISO25French\n 004ba52c,glGenAsyncMarkersSGIX\n \"00580242\",LoadLibraryExA\n 004684a0,LoadPlugin\n \"00500378\",iso-ir-146\n 0051df54,\"http://stat.atomfish.ru/login.php\"\n 0049fa6c,glBindTextureUnitParameterEXT\n 004aaa80,glPrioritizeTextures\n 004a6594,GL_EXT_color_subtable\n \"00430557\",ParentColor\n \"00500e34\",cp423\n 004dc954,turnend\n 004a8b2c,glCopyPixels\n 004b1be4,glVertexAttrib4sARB\n 004a77d4,GL_SGIX_framezoom\n 00581f38,BASS_Free\n 004aaae8,glPushClientAttrib\n \"0049e018\",glVertexStream3fATI\n 004ff39c,csISO60Norwegian1\n 004a65b4,GL_EXT_compiled_vertex_array\n 0049f1f4,glSecondaryColor3fEXT\n 004b81b8,glMultiTexCoord1hvNV\n 004b2a4c,glDeleteFragmentShaderATI\n 0051965c,Login\n 00581b98,SafeArrayPtrOfIndex\n 004274d4,clMenuText\n \"00427470\",clInfoBk\n 004a8d8c,glDepthRange\n 00468dac,Get2DPos\n 0051543c,travelBack.jpg\n 005014fc,CP905\n 0049af5c,glMultiTexCoord3d\n 0050a6ec,Password\n 004a2684,glGlobalAlphaFactordSUN\n 0049cdfc,glVertexAttrib2dARB\n 0041058c,VarBstrFromDate\n 004974b4,gluNurbsCallback\n 004b13c8,glVertexAttrib4usv\n 004bb3a0,glGlobalAlphaFactordSUN\n \"00536758\",baitid=\n 004594ac,OnMouseDownl;A\n 004ff61c,csISO87JISX0208\n \"00501744\",csEBCDICIT\n 005002ec,\"ISO_8859-5:1988\"\n 00499ea0,glGetTexEnviv\n 004ac854,glConvolutionFilter1D\n 004a2358,glDeformSGIX\n 0055f4a4,\"GUI\\\\WinHeader.bmp\"\n 004ae2fc,glWindowPos3dv\n 004af028,glMultiTexCoord3iARB\n 004df2a0,fmask=\n \"00454690\",window\n \"00580314\",ExitProcess\n 00499c94,glEvalCoord2dv\n 004b26dc,glWindowPos3ivARB\n 004b17e8,glVertexAttrib3fvARB\n 005011ec,csIBM863\n 0049c520,glMultiTexCoord4dvARB\n 004ffe84,\"ISO_8859-6:1987\"\n 0052b0b4,turntype_\n 004230d2,IniFiles\n 004a0ec0,glCombinerParameterfvNV\n 004a3ee0,glValidateProgramARB\n 005154c0,plight.tga\n 004ab860,glTexCoord3f\n 0056ed38,incomplete dynamic bit lengths tree\n 004a4234,glGetQueryivARB\n 0049cda4,glVertexAttrib1fARB\n 004b7160,glNormalPointervINTEL\n 004af378,glPointParameterfvARB\n 004a2bb4,glTexCoord2fColor3fVertex3fSUN\n 0055f390,\"GUI\\\\LightPanel.jpg\"\n 004aa070,glLoadMatrixd\n 00440b9c,Controls\n 004a5e6c,GL_ARB_multisample\n 0052c3c4,\"http://stat.atomfish.ru/turn.php?turnid=%d&ttype=%d&uname=%s\"\n 004dcd55,\" : %s %s\"\n 0043117d,ParentColor\n 00500d78,csIBM290\n \"004e7448\",optid\n 005017a8,EBCDIC-ES-A\n \"00499928\",glColor3bv\n 0049e2e8,glColorSubTableEXT\n 004a2174,glPollInstrumentsSGIX\n 00554ae0,fishingreel.ogg\n 004363b8,\"\\\\tOnEndDragl;A\"\n truncated... (more than 100 strings found),truncated\nfileSize: 1769472 bytes\nentryPoint: 0056c060"}Good. Now let me search for CMD=120 and CMD=125 handlers in the binary by looking at strings and the packet dispatch logic.
Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter": "cmd="}
Tool result
{"result":[]}Call ghidra_search_functions_by_name
Arguments
{"filepath": "/sandbox/FFG.exe", "query": "recv"}
Tool result
{"result":["No functions matching 'recv'"]}Call ghidra_search_functions_by_name
Arguments
{"filepath": "/sandbox/FFG.exe","query": "socket"}
Tool result
{"result":["No functions matching 'socket'"]}Call ghidra_list_strings
Arguments
{"filepath":"/sandbox/FFG.exe", "filter":"login"}
Tool result
{"result":["00422b58: \"TaskDialogIndirect\"","004e72cc: \"login\"","004e730c: \"no_login=1\"","004e9c60: \"User logined:\"","0051237c: \"http://stat.atomfish.ru/login.php\"","0051965c: \"Login\"","00519768: \"no_login\"","0051a110: \"Login_\"","0051a134: \"login\"","0051a158: \"Login\"","0051a48c: \"Login_\"","0051a4b0: \"login\"","0051a4d4: \"Login\"","0051a814: \"login=\"","0051ad50: \"login=\"","0051c310: \"login\"","0051c350: \"mmLogin\"","0051c74c: \"http://stat.atomfish.ru/login.php\"","0051c78c: \"Login\"","0051c7fc: \"http://stat.atomfish.ru/changepass.php?login=%s&eml=%s&srv=%d\"","0051c844: \"http://stat.atomfish.ru/changepass2.php?login=%s&eml=%s&srv=%d\"","0051c940: \"nologin\"","0051df54: \"http://stat.atomfish.ru/login.php\"","005207e0: \"[login]\""]}Let me look at the data region near 0x4e72cc (login/optid strings) and search for packet-related strings.
Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter": "optid"}
Tool result
{"result":["004e7448: \"optid\"","0051ff18: \"optid=10\\rsubid=\"","005315c4: \"optid=\"","00533434: \"optid\""]}Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter": "baitid"}
Tool result
{"result":["004e73e4: \"baitid\"","004e87e4: \"otbaitid\"","004e9c00: \"otbaitid\"","004ea0a0: \"otbaitid=\"","0051eec0: \"baitid=\"","00520a38: \"baitid\"","00536758: \"baitid=\"","00537c0c: \"baitid=\"","00545b14: \"FBaitID=\"","0054b288: \"baitid=\"","0054fa30: \"baitid=\"","00550064: \"otbaitid=\""]}Let me search for more relevant strings and find xrefs to key data strings to locate packet handlers.
Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter": "cast"}
Tool result
{"result":["00468e2c: \"CastShadowMap\"","005161d8: \"_ReCast\"","005161e8: \"_AltReCast\"","00521878: \"castrod\""]}Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter":"fish"}
Tool result
{"result":["004d7340: \"fishs\"","004d7360: \"Fish%d.dta\"","004d8784: \"[fish]\"","004dca68: \"removefish\"","004dcf50: \"fishsale\"","004e1028: \"[fish]\"","004e739c: \"fishid\"","004e7ea4: \"fish=%d/%d/%d\"","004e812c: \"fish=%d/%d/%d\"","004e8560: \"fishcount=\"","004e9b64: \"fishid\"","004e9f50: \"fishid=\"","0051237c: \"http://stat.atomfish.ru/login.php\"","00514f68: \"Fisher.tga\"","00515160: \"FishMarker.tga\"","00515178: \"FishMarker2.tga\"","00515294: \"fishonrod.tga\"","0051553c: \"Fish.dta\"","00515580: \"fishlight.dta\"","00516168: \"Data\\Textures\\Fish\\\"","00516254: \"_relFish\"","0051c6a4: \"http://stat.atomfish.ru/stat.php\"","0051c6d8: \"http://www.atomfish.ru/\"","0051c74c: \"http://stat.atomfish.ru/login.php\"","0051c7fc: \"http://stat.atomfish.ru/changepass.php?login=%s&eml=%s&srv=%d\"","0051c844: \"http://stat.atomfish.ru/changepass2.php?login=%s&eml=%s&srv=%d\"","0051d684: \"Music\\atomfishingMenu.ogg\"","0051df54: \"http://stat.atomfish.ru/login.php\"","005208a8: \"fishid\"","0052189c: \"fishtorod\"","00522170: \"wpfishid\"","0052220c: \"[fish]\"","00522a8c: \"wpfishid\"","00522b28: \"[fish]\"","00524008: \"turnfish=\"","005241fc: \"FISHES\"","00524838: \"fish selector\"","005288b4: \"tfishid\"","0052a1ac: \"http://stat.atomfish.ru/turn.php?turnid=%d&ttype=%d&uname=%s\"","0052a5c0: \"fishid\"","0052b9b4: \"http://stat.atomfish.ru/turn.php?turnid=%d&ttype=%d&uname=%s\"","0052bc30: \"fishid\"","0052c3c4: \"http://stat.atomfish.ru/turn.php?turnid=%d&ttype=%d&uname=%s\"","0052cca0: \"http://stat.atomfish.ru/turn.php?turnid=%d&ttype=%d&uname=%s\"","0052cef4: \"fishid\"","0052e270: \"FISHES\"","00530e18: \"FISHES\"","00533324: \"nosalefish\"","00534cd4: \"fishoid=\"","00534ce8: \"fishid=\"","00534cf8: \"fishname=\"","00534d0c: \"fishweight=\"","00536738: \"fishoid=\"","0053692c: \"fishoid=\"","00536940: \"fishsplash7.ogg\"","00537530: \"fishoid=\"","00537544: \"fishid=\"","005391dc: \"FISHES\"","005396bc: \"salebigfish\"","0053970c: \"salesmallfish\"","0053ddb8: \"[url=http://stat.atomfish.ru/trophy.php?tid=%d][img]http://stat.atomfish.ru/fimg/%d.GIF[/img][/url] %s\"","0053de28: \"[url=http://stat.atomfish.ru/trophy2.php?tid=%d][img]http://stat.atomfish.ru/fimg/%d.GIF[/img][/url] %s\"","0053df3c: \"[url=http://stat.atomfish.ru/trophy.php?tid=%d][img]http://stat.atomfish.ru/fimg/%d.GIF[/img][/url] %s\\r\\n\"","0053dfb0: \"[url=http://stat.atomfish.ru/trophy2.php?tid=%d][img]http://stat.atomfish.ru/fimg/%d.GIF[/img][/url] %s\\r\\n\"","0053e0d4: \"http://www.atomfish.ru\"","0053e108: \"http://www.atomfish.ru/statistics/\"","0053fe94: \"FISHES\"","0054570c: \"FFishID=\"","00545720: \"FFishImageID=\"","0054a250: \"http://updates.atomfish.ru/services/artimager/index.php?artid=%d&randc=%d&sid=%d&cntrl=%s&curimgname=%s&artname=%s\"","0054bb2c: \"FishLog.txt\"","0054bf0c: \"fishcount\"","0054e220: \"FISHES\"","0054f0c6: \"TRodFish|\"","00554ae0: \"fishingreel.ogg\"","00554b74: \"fishreelgo.ogg\"","005551fc: \"fishingreel.ogg\"","005552b4: \"fishsplash\"","00558b9c: \"fish_broke\"","0055949c: \"fishPosControl posControl Error\"","0055958c: \"fishPosControl posControl Error\""]}Let me get xrefs to the key fishing action strings to find packet handlers.
Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x00521878"}
Tool result
{"result":["From 00521739 in FUN_0052162c [PARAM]"]}Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x0052189c"}
Tool result
{"result":["From 005217b1 in FUN_0052162c [PARAM]"]}Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x004dc954"}
Tool result
{"result":["From 004dab22 in FUN_004d99d8 [PARAM]"]}Let me decompile FUN_0052162c (castrod/fishtorod handler) and also look for CMD-number dispatch.
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_0052162c"}
Tool result
{"result":"\nvoid FUN_0052162c(undefined4 param_1,int param_2)\n\n{\n char cVar1;\n int *piVar2;\n LPCSTR lpFile;\n HWND hwnd;\n short extraout_CX;\n int iVar3;\n undefined4 extraout_ECX;\n undefined4 extraout_ECX_00;\n undefined4 *in_FS_OFFSET;\n int local_c8 [2];\n int local_c0;\n int local_a0 [2];\n int local_98;\n int local_78 [2];\n int local_70;\n undefined4 uStackY_58;\n longlong *in_stack_ffffffb0;\n LPCSTR lpOperation;\n LPCSTR lpParameters;\n int in_stack_ffffffbc;\n LPCSTR lpDirectory;\n INT nShowCmd;\n undefined4 uStack_3c;\n undefined1 *puStack_38;\n undefined1 *local_34;\n undefined4 uStack_2c;\n undefined1 *puStack_28;\n undefined1 *puStack_24;\n undefined4 uStack_20;\n undefined1 *local_1c;\n int *local_18;\n \n iVar3 = 0x18;\n do {\n iVar3 = iVar3 + -1;\n } while (iVar3 != 0);\n local_18 = (int *)0x521651;\n FUN_00405b24((int)&stack0xffffffb4,(int)PTR_DAT_0041efec);\n local_1c = &LAB_0052183d;\n uStack_20 = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_20;\n puStack_24 = (undefined1 *)0x52166b;\n local_18 = (int *)&stack0xfffffffc;\n piVar2 = (int *)FUN_00404154((int *)PTR_PTR_0041475c,'\\x01',extraout_ECX);\n puStack_28 = &LAB_005217fc;\n uStack_2c = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_2c;\n puStack_24 = &stack0xfffffffc;\n (**(code **)(*piVar2 + 0x2c))(piVar2,*(undefined4 *)(param_2 + 0x34));\n iVar3 = (**(code **)(*piVar2 + 0x14))();\n if (-1 < iVar3 + -1) {\n local_1c = (undefined1 *)iVar3;\n (**(code **)(*piVar2 + 0xc))(piVar2,0,&stack0xffffffb0);\n FUN_0041f32c(in_stack_ffffffb0,(int *)&stack0xffffffb4);\n local_34 = (undefined1 *)0x5216d1;\n local_18 = (int *)FUN_0041fa5c((int *)PTR_DAT_0041f034,'\\x01',\n CONCAT31((int3)((uint)extraout_ECX_00 >> 8),0x7c),\n in_stack_ffffffbc);\n puStack_38 = &LAB_005217d3;\n uStack_3c = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_3c;\n local_34 = &stack0xfffffffc;\n cVar1 = FUN_0041fcac((int)&stack0xffffffb4,0x521854);\n if (cVar1 != '\\0') {\n nShowCmd = 0;\n lpDirectory = (LPCSTR)0x0;\n lpParameters = (LPCSTR)0x0;\n lpFile = FUN_004054f4((undefined *)0x0);\n lpOperation = \"open\";\n hwnd = (HWND)(**(code **)PTR_DAT_00570c7c)();\n uStackY_58 = 0x521716;\n ShellExecuteA(hwnd,lpOperation,lpFile,lpParameters,lpDirectory,nShowCmd);\n }\n cVar1 = FUN_0041fcac((int)&stack0xffffffb4,0x521868);\n if (cVar1 != '\\0') {\n FUN_0054fdf8(*(int *)PTR_DAT_00570c84,(int)local_34,extraout_CX);\n }\n cVar1 = FUN_0041fcac((int)&stack0xffffffb4,0x521878);\n if (cVar1 != '\\0') {\n FUN_0041fb1c((int)local_18,2,local_78);\n FUN_0041fb1c((int)local_18,1,local_a0);\n FUN_0041fb1c((int)local_18,0,local_c8);\n FUN_0054f594(*(int *)PTR_DAT_00570c84,local_c0,local_98,local_70);\n }\n cVar1 = FUN_0041fcac((int)&stack0xffffffb4,0x521888);\n if (cVar1 != '\\0') {\n FUN_005382e8();\n }\n FUN_0041fcac((int)&stack0xffffffb4,0x52189c);\n *in_FS_OFFSET = uStack_3c;\n local_34 = &DAT_005217da;\n puStack_38 = (undefined1 *)0x5217d2;\n FUN_00404184(local_18);\n return;\n }\n *in_FS_OFFSET = uStack_2c;\n puStack_24 = &LAB_00521803;\n puStack_28 = (undefined1 *)0x5217fb;\n FUN_00404184(piVar2);\n return;\n}\n\n"}Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x004e739c"}
Tool result
{"result":["From 004e6881 in FUN_004e6464 [PARAM]","From 004e6909 in FUN_004e6464 [PARAM]","From 004e6b38 in FUN_004e6464 [PARAM]","From 004e6a9a in FUN_004e6464 [PARAM]"]}FUN_004e6464 references fishid multiple times - likely the main packet handler. Let me decompile it.
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_004e6464"}
Tool result
{"result":"Succeeded and the artifact is saved at /sandbox/ghidra/decompiled_0x4e6464.txt. Please find the table of contents below. \n[{'funcName': 'FUN_00405088', 'lineNum': 137}, {'funcName': 'FUN_00405088', 'lineNum': 139}, {'funcName': 'FUN_00405088', 'lineNum': 141}, {'funcName': 'FUN_00405064', 'lineNum': 143}, {'funcName': 'FUN_004168a4', 'lineNum': 147}, {'funcName': 'FUN_004099ec', 'lineNum': 154}, {'funcName': 'FUN_004053f8', 'lineNum': 159}, {'funcName': 'FUN_0046984c', 'lineNum': 160}, {'funcName': 'FUN_004e5508', 'lineNum': 164}, {'funcName': 'FUN_004e5fc8', 'lineNum': 165}, {'funcName': 'FUN_004e8a58', 'lineNum': 166}, {'funcName': 'FUN_004e5fc8', 'lineNum': 167}, {'funcName': 'FUN_004e8994', 'lineNum': 168}, {'funcName': 'FUN_004e5fc8', 'lineNum': 169}, {'funcName': 'FUN_004e62f4', 'lineNum': 173}, {'funcName': 'FUN_004e6288', 'lineNum': 174}, {'funcName': 'FUN_004e6288', 'lineNum': 176}, {'funcName': 'FUN_004e6288', 'lineNum': 178}, {'funcName': 'FUN_004e7618', 'lineNum': 181}, {'funcName': 'FUN_004e6288', 'lineNum': 183}, {'funcName': 'FUN_004099ec', 'lineNum': 186}, {'funcName': 'FUN_004099ec', 'lineNum': 191}, {'funcName': 'FUN_004053f8', 'lineNum': 194}, {'funcName': 'FUN_004e5fc8', 'lineNum': 196}, {'funcName': 'FUN_004e6288', 'lineNum': 198}, {'funcName': 'FUN_0054daac', 'lineNum': 200}, {'funcName': 'FUN_004e6288', 'lineNum': 203}, {'funcName': 'FUN_004e81c8', 'lineNum': 206}, {'funcName': 'FUN_004e6288', 'lineNum': 208}, {'funcName': 'FUN_0054e824', 'lineNum': 211}, {'funcName': 'FUN_004e81c8', 'lineNum': 213}, {'funcName': 'FUN_004033f0', 'lineNum': 216}, {'funcName': 'FUN_004e5d88', 'lineNum': 218}, {'funcName': 'FUN_004e6288', 'lineNum': 221}, {'funcName': 'FUN_004e904c', 'lineNum': 223}, {'funcName': 'FUN_004e8210', 'lineNum': 225}, {'funcName': 'FUN_004e5fc8', 'lineNum': 227}, {'funcName': 'FUN_004e89ec', 'lineNum': 229}, {'funcName': 'FUN_004e5fc8', 'lineNum': 231}, {'funcName': 'FUN_004e8a58', 'lineNum': 233}, {'funcName': 'FUN_004e5fc8', 'lineNum': 235}, {'funcName': 'FUN_004e8994', 'lineNum': 237}, {'funcName': 'FUN_004e5fc8', 'lineNum': 239}, {'funcName': 'FUN_004e62f4', 'lineNum': 242}, {'funcName': 'FUN_004e90c0', 'lineNum': 243}, {'funcName': 'FUN_004e5fc8', 'lineNum': 245}, {'funcName': 'FUN_004e8210', 'lineNum': 248}, {'funcName': 'FUN_004e5fc8', 'lineNum': 251}, {'funcName': 'FUN_004e89ec', 'lineNum': 253}, {'funcName': 'FUN_004e5fc8', 'lineNum': 254}, {'funcName': 'FUN_0040b75c', 'lineNum': 257}, {'funcName': 'FUN_0040537c', 'lineNum': 258}, {'funcName': 'FUN_004e5fc8', 'lineNum': 259}, {'funcName': 'FUN_004e8580', 'lineNum': 260}, {'funcName': 'FUN_004e5fc8', 'lineNum': 261}, {'funcName': 'FUN_004e5508', 'lineNum': 262}, {'funcName': 'FUN_004e5fc8', 'lineNum': 263}, {'funcName': 'FUN_004e8a58', 'lineNum': 264}, {'funcName': 'FUN_004e5fc8', 'lineNum': 265}, {'funcName': 'FUN_004e8994', 'lineNum': 266}, {'funcName': 'FUN_004e5fc8', 'lineNum': 267}, {'funcName': 'FUN_0040ac40', 'lineNum': 272}, {'funcName': 'FUN_004e5fc8', 'lineNum': 273}, {'funcName': 'FUN_004e6288', 'lineNum': 277}, {'funcName': 'FUN_004e7758', 'lineNum': 278}, {'funcName': 'FUN_004e89ec', 'lineNum': 279}, {'funcName': 'FUN_004e5fc8', 'lineNum': 280}, {'funcName': 'FUN_004e89ec', 'lineNum': 283}, {'funcName': 'FUN_004e5fc8', 'lineNum': 284}, {'funcName': 'FUN_004e6288', 'lineNum': 287}, {'funcName': 'FUN_004e891c', 'lineNum': 288}, {'funcName': 'FUN_004e6288', 'lineNum': 289}, {'funcName': 'FUN_004e88e0', 'lineNum': 290}, {'funcName': 'FUN_0040ac40', 'lineNum': 295}, {'funcName': 'FUN_004e5fc8', 'lineNum': 296}, {'funcName': 'FUN_004e8acc', 'lineNum': 297}, {'funcName': '(ram, 0x4e6218, 8)', 'lineNum': 301}, {'funcName': 'FUN_004e6288', 'lineNum': 304}, {'funcName': 'FUN_004e6288', 'lineNum': 306}, {'funcName': 'FUN_004e7ef4', 'lineNum': 308}, {'funcName': 'FUN_004e8210', 'lineNum': 310}, {'funcName': 'FUN_004e5fc8', 'lineNum': 312}, {'funcName': 'FUN_004e89ec', 'lineNum': 314}, {'funcName': 'FUN_004e5fc8', 'lineNum': 316}, {'funcName': 'FUN_004e8580', 'lineNum': 318}, {'funcName': 'FUN_004e5fc8', 'lineNum': 320}, {'funcName': 'FUN_004e5fc8', 'lineNum': 322}, {'funcName': 'FUN_004e6288', 'lineNum': 325}, {'funcName': 'FUN_004e7f0c', 'lineNum': 326}, {'funcName': 'FUN_004e8210', 'lineNum': 327}, {'funcName': 'FUN_004e5fc8', 'lineNum': 328}, {'funcName': 'FUN_004e89ec', 'lineNum': 329}, {'funcName': 'FUN_004e5fc8', 'lineNum': 330}, {'funcName': 'FUN_004e8580', 'lineNum': 331}, {'funcName': 'FUN_004e5fc8', 'lineNum': 332}, {'funcName': 'FUN_004e5fc8', 'lineNum': 333}, {'funcName': 'FUN_004e5fc8', 'lineNum': 334}, {'funcName': 'FUN_004e7c68', 'lineNum': 337}, {'funcName': 'FUN_004e8210', 'lineNum': 338}, {'funcName': 'FUN_004e5fc8', 'lineNum': 339}, {'funcName': 'FUN_004e89ec', 'lineNum': 340}, {'funcName': 'FUN_004e5fc8', 'lineNum': 341}, {'funcName': 'FUN_004e8580', 'lineNum': 342}, {'funcName': 'FUN_004e5fc8', 'lineNum': 343}, {'funcName': 'FUN_004e5fc8', 'lineNum': 344}, {'funcName': 'FUN_004e6288', 'lineNum': 349}, {'funcName': 'FUN_004204a0', 'lineNum': 351}, {'funcName': 'FUN_004204a0', 'lineNum': 355}, {'funcName': 'FUN_004053f8', 'lineNum': 358}, {'funcName': 'FUN_004e5fc8', 'lineNum': 360}, {'funcName': 'FUN_004e862c', 'lineNum': 364}, {'funcName': 'FUN_004e8a58', 'lineNum': 367}, {'funcName': 'FUN_004e5fc8', 'lineNum': 368}, {'funcName': 'FUN_004e8994', 'lineNum': 369}, {'funcName': 'FUN_004e5fc8', 'lineNum': 370}, {'funcName': 'FUN_004e6288', 'lineNum': 373}, {'funcName': 'FUN_004e55a4', 'lineNum': 374}, {'funcName': 'FUN_004e6288', 'lineNum': 376}, {'funcName': 'FUN_004e6288', 'lineNum': 378}, {'funcName': 'FUN_004e6288', 'lineNum': 380}, {'funcName': 'FUN_004e6288', 'lineNum': 386}, {'funcName': 'FUN_004e53c4', 'lineNum': 388}, {'funcName': 'FUN_004e8acc', 'lineNum': 389}, {'funcName': 'FUN_004e61ac', 'lineNum': 392}, {'funcName': 'FUN_004e6288', 'lineNum': 394}, {'funcName': 'FUN_004e55a4', 'lineNum': 395}, {'funcName': 'FUN_004e77fc', 'lineNum': 397}, {'funcName': 'FUN_00409ad8', 'lineNum': 401}, {'funcName': 'FUN_004099ec', 'lineNum': 405}, {'funcName': 'FUN_004053f8', 'lineNum': 410}, {'funcName': 'FUN_004e5fc8', 'lineNum': 412}, {'funcName': 'FUN_004e53c4', 'lineNum': 415}, {'funcName': 'FUN_004e8958', 'lineNum': 416}, {'funcName': 'FUN_004e8acc', 'lineNum': 417}, {'funcName': 'FUN_004e8210', 'lineNum': 418}, {'funcName': 'FUN_004e5fc8', 'lineNum': 419}, {'funcName': 'FUN_00409ad8', 'lineNum': 422}, {'funcName': 'FUN_004099ec', 'lineNum': 426}, {'funcName': 'FUN_004053f8', 'lineNum': 431}, {'funcName': 'FUN_004e5fc8', 'lineNum': 433}, {'funcName': 'FUN_004e6288', 'lineNum': 439}, {'funcName': 'FUN_004e55cc', 'lineNum': 440}, {'funcName': 'FUN_004e78ac', 'lineNum': 444}, {'funcName': 'FUN_004e5fc8', 'lineNum': 446}, {'funcName': 'FUN_004e8210', 'lineNum': 447}, {'funcName': 'FUN_004e5fc8', 'lineNum': 448}, {'funcName': 'FUN_004e89ec', 'lineNum': 449}, {'funcName': 'FUN_004e5fc8', 'lineNum': 450}, {'funcName': 'FUN_004e56a0', 'lineNum': 453}, {'funcName': 'FUN_004e8958', 'lineNum': 456}, {'funcName': 'FUN_004e8acc', 'lineNum': 459}, {'funcName': 'FUN_004e5508', 'lineNum': 460}, {'funcName': 'FUN_004e5fc8', 'lineNum': 461}, {'funcName': 'FUN_004e8210', 'lineNum': 462}, {'funcName': 'FUN_004e5fc8', 'lineNum': 463}, {'funcName': 'FUN_004e6288', 'lineNum': 468}, {'funcName': 'FUN_004c8354', 'lineNum': 469}, {'funcName': 'FUN_00569fc8', 'lineNum': 471}, {'funcName': 'FUN_004e76e4', 'lineNum': 473}, {'funcName': 'FUN_00569fc8', 'lineNum': 474}, {'funcName': 'FUN_004e8958', 'lineNum': 475}, {'funcName': 'FUN_004e8acc', 'lineNum': 476}, {'funcName': 'FUN_004e8a58', 'lineNum': 477}, {'funcName': 'FUN_004e5fc8', 'lineNum': 478}, {'funcName': 'FUN_00416748', 'lineNum': 484}, {'funcName': 'FUN_004e6044', 'lineNum': 486}, {'funcName': 'FUN_00404184', 'lineNum': 488}]"}Let me read the decompiled function to find the CMD dispatch logic.
Call ghidra_read_artifact
Arguments
{"artifact_path": "/sandbox/ghidra/decompiled_0x4e6464.txt"}
Tool result
{"result":"\nvoid FUN_004e6464(int *param_1)\n\n{\n longlong *plVar1;\n char *pcVar2;\n undefined8 uVar3;\n char cVar4;\n undefined1 uVar5;\n undefined4 uVar6;\n int iVar7;\n int iVar8;\n int iVar9;\n undefined4 extraout_ECX;\n undefined4 extraout_ECX_00;\n undefined4 extraout_ECX_01;\n undefined4 extraout_ECX_02;\n undefined4 extraout_ECX_03;\n undefined4 extraout_ECX_04;\n undefined4 extraout_ECX_05;\n undefined4 extraout_ECX_06;\n undefined4 extraout_ECX_07;\n undefined4 extraout_ECX_08;\n undefined4 extraout_ECX_09;\n undefined4 extraout_ECX_10;\n undefined4 extraout_ECX_11;\n undefined4 extraout_ECX_12;\n undefined4 extraout_ECX_13;\n undefined4 extraout_ECX_14;\n undefined4 extraout_ECX_15;\n undefined4 extraout_ECX_16;\n undefined4 extraout_ECX_17;\n undefined4 extraout_ECX_18;\n undefined4 extraout_ECX_19;\n undefined4 extraout_ECX_20;\n undefined4 extraout_ECX_21;\n undefined4 extraout_ECX_22;\n undefined4 extraout_ECX_23;\n undefined4 extraout_ECX_24;\n undefined4 extraout_ECX_25;\n undefined4 extraout_ECX_26;\n undefined4 extraout_ECX_27;\n undefined4 extraout_ECX_28;\n undefined4 extraout_ECX_29;\n undefined4 extraout_ECX_30;\n undefined4 extraout_EDX;\n undefined4 extraout_EDX_00;\n uint *in_FS_OFFSET;\n float10 in_ST0;\n longlong *local_134;\n longlong *local_130;\n longlong *local_12c;\n longlong *local_128;\n longlong *local_124;\n undefined *local_120;\n int local_11c;\n longlong *local_118;\n longlong *local_114;\n undefined *local_110;\n int local_10c;\n longlong *local_108;\n undefined *local_104;\n int local_100;\n longlong *local_fc;\n longlong *local_f8;\n longlong *local_f4;\n longlong *local_f0;\n longlong *local_ec;\n longlong *local_e8;\n longlong *local_e4;\n longlong *local_e0;\n longlong *local_dc;\n longlong *local_d8;\n longlong *local_d4;\n longlong *local_d0;\n longlong *local_cc;\n longlong *local_c8;\n longlong *local_c4;\n longlong *local_c0;\n longlong *local_bc;\n longlong *local_b8;\n longlong *local_b4;\n int local_b0;\n int local_ac;\n int local_a8;\n char *local_a4;\n char *local_a0;\n longlong *local_9c;\n longlong *local_98;\n longlong *local_94;\n longlong *local_90;\n longlong *local_8c;\n undefined4 local_88;\n undefined1 local_84;\n undefined4 local_80;\n undefined1 local_7c;\n longlong *local_78;\n longlong *local_74;\n longlong *local_70;\n longlong *local_6c;\n longlong *local_68;\n longlong *local_64;\n longlong *local_60;\n longlong *local_5c;\n longlong *plVar10;\n char *local_54;\n undefined *local_50;\n undefined *local_4c;\n char *pcStack_48;\n char *local_44;\n undefined *local_34;\n char *local_30;\n undefined *local_2c;\n undefined *local_28;\n uint local_24;\n undefined1 *local_20;\n undefined4 uStack_1c;\n uint local_18;\n int *local_14;\n longlong *local_10;\n int *local_c;\n int *local_8;\n \n local_10 = (longlong *)&stack0xfffffffc;\n iVar9 = 0x26;\n do {\n iVar9 = iVar9 + -1;\n } while (iVar9 != 0);\n local_14 = (int *)&LAB_004e7281;\n local_18 = *in_FS_OFFSET;\n *in_FS_OFFSET = (uint)&local_18;\n local_8 = param_1;\n if (*(int *)(param_1[1] + 8) < 1) {\n *in_FS_OFFSET = local_18;\n local_10 = (longlong *)&LAB_004e7288;\n local_14 = (int *)0x4e725b;\n FUN_00405088((int *)&local_134,0x21);\n local_14 = (int *)0x4e726b;\n FUN_00405088((int *)&local_a4,7);\n local_14 = (int *)0x4e7278;\n FUN_00405088((int *)&local_78,0xc);\n local_14 = (int *)0x4e7280;\n FUN_00405064((int *)&local_10);\n return;\n }\n uStack_1c = (undefined1 *)0x4e64a1;\n local_c = (int *)FUN_004168a4((undefined4 *)param_1[1],0);\n local_20 = &LAB_004e7237;\n local_24 = *in_FS_OFFSET;\n *in_FS_OFFSET = (uint)&local_24;\n local_28 = &DAT_004e7294;\n local_2c = (undefined *)0x4e64d1;\n uStack_1c = &stack0xfffffffc;\n FUN_004099ec(*(uint *)(local_c[4] + 0x14),(int *)&local_50);\n local_2c = local_50;\n local_30 = \" Data:\";\n local_34 = &DAT_004e72c0;\n iVar9 = *(int *)(local_c[4] + 0x30);\n FUN_004053f8((int *)&local_4c,5);\n FUN_0046984c(*(int *)PTR_DAT_00570b54,local_8,(int)local_4c);\n iVar7 = *(int *)(iVar9 + 0x14);\n if (iVar7 < 0xa1) {\n if (iVar7 == 0xa0) {\n FUN_004e5508(*(int *)PTR_DAT_0057121c,1,&local_e8);\n FUN_004e5fc8((int)local_c,0xa0,local_e8);\n FUN_004e8a58(local_8[2],&local_ec,extraout_ECX_17);\n FUN_004e5fc8((int)local_c,0xa5,local_ec);\n FUN_004e8994(local_8[2],&local_f0,extraout_ECX_18);\n FUN_004e5fc8((int)local_c,0xa2,local_f0);\n }\n else if (iVar7 < 0x79) {\n if (iVar7 == 0x78) {\n FUN_004e62f4(iVar9,0x4e736c,&local_98);\n uVar6 = FUN_004e6288(iVar9,0x4e737c);\n local_44 = (char *)0x4e6880;\n local_44 = (char *)FUN_004e6288(iVar9,0x4e738c);\n pcStack_48 = (char *)0x4e688e;\n iVar7 = FUN_004e6288(iVar9,0x4e739c);\n pcVar2 = local_44;\n local_44 = (char *)0x4e689c;\n local_24 = FUN_004e7618(local_8[2],iVar7,(int)pcVar2,uVar6,local_98);\n local_44 = (char *)0x4e68ac;\n local_20 = (undefined1 *)FUN_004e6288(iVar9,0x4e73ac);\n local_44 = \"inid=\";\n pcStack_48 = (char *)0x4e68c2;\n FUN_004099ec((uint)local_20,(int *)&local_a0);\n pcStack_48 = local_a0;\n local_4c = &DAT_004e72c0;\n local_50 = &DAT_004e73cc;\n local_54 = (char *)0x4e68e0;\n FUN_004099ec(local_24,(int *)&local_a4);\n local_54 = local_a4;\n _local_5c = (double)CONCAT44(0x4e68f6,local_5c);\n FUN_004053f8((int *)&local_9c,5);\n _local_5c = (double)CONCAT44(0x4e6909,local_5c);\n FUN_004e5fc8((int)local_c,0x7d,local_9c);\n _local_5c = (double)CONCAT44(0x4e6916,local_5c);\n iVar7 = FUN_004e6288(iVar9,0x4e739c);\n _local_5c = (double)CONCAT44(0x4e6924,local_5c);\n iVar7 = FUN_0054daac(*(int *)PTR_DAT_00570ee0,iVar7,extraout_ECX_05);\n if (iVar7 != 0) {\n _local_5c = (double)CONCAT44(0x4e693e,local_5c);\n local_44 = (char *)FUN_004e6288(iVar9,0x4e737c);\n plVar10 = (longlong *)&local_ac;\n local_5c = (longlong *)0x4e6958;\n local_5c = (longlong *)FUN_004e81c8(local_8[2],8,extraout_ECX_06);\n local_60 = (longlong *)0x4e6966;\n iVar8 = FUN_004e6288(iVar9,0x4e738c);\n plVar1 = local_5c;\n _local_5c = (double)CONCAT44(plVar10,0x4e6971);\n FUN_0054e824(iVar7,iVar8,plVar1,(int *)plVar10);\n _local_5c = (double)CONCAT44(0x4e698a,local_5c);\n local_b0 = FUN_004e81c8(local_8[2],0xc,extraout_ECX_07);\n local_b0 = local_b0 * local_a8;\n _local_5c = (double)CONCAT44(0x4e69af,local_5c);\n iVar7 = FUN_004033f0();\n _local_5c = (double)CONCAT44(0x4e69c0,local_5c);\n FUN_004e5d88((int)local_c,iVar7,(int)local_44);\n }\n _local_5c = (double)CONCAT44(0x4e69cd,local_5c);\n local_24 = FUN_004e6288(iVar9,0x4e73e4);\n _local_5c = (double)CONCAT44(0x4e69e3,local_5c);\n FUN_004e904c(local_8[2],local_24,1);\n _local_5c = (double)CONCAT44(0x4e69f4,local_5c);\n FUN_004e8210(local_8[2],&local_b4);\n _local_5c = (double)CONCAT44(0x4e6a07,local_5c);\n FUN_004e5fc8((int)local_c,100,local_b4);\n _local_5c = (double)CONCAT44(0x4e6a18,local_5c);\n FUN_004e89ec(local_8[2],&local_b8,extraout_ECX_08);\n _local_5c = (double)CONCAT44(0x4e6a2b,local_5c);\n FUN_004e5fc8((int)local_c,0x69,local_b8);\n _local_5c = (double)CONCAT44(0x4e6a3c,local_5c);\n FUN_004e8a58(local_8[2],&local_bc,extraout_ECX_09);\n _local_5c = (double)CONCAT44(0x4e6a4f,local_5c);\n FUN_004e5fc8((int)local_c,0xa5,local_bc);\n _local_5c = (double)CONCAT44(0x4e6a60,local_5c);\n FUN_004e8994(local_8[2],&local_c0,extraout_ECX_10);\n _local_5c = (double)CONCAT44(0x4e6a73,local_5c);\n FUN_004e5fc8((int)local_c,0xa2,local_c0);\n }\n else if (iVar7 == 100) {\n FUN_004e62f4(iVar9,0x4e72cc,&local_54);\n cVar4 = FUN_004e90c0((int *)local_8[2],(int)local_54);\n if (cVar4 == '\\0') {\n FUN_004e5fc8((int)local_c,100,(longlong *)\"no_login=1\");\n }\n else {\n FUN_004e8210(local_8[2],&stack0xffffffa8);\n uVar3 = _local_5c;\n plVar10 = (longlong *)((ulonglong)_local_5c >> 0x20);\n FUN_004e5fc8((int)local_c,100,plVar10);\n _local_5c = (double)uVar3;\n FUN_004e89ec(local_8[2],&local_5c,extraout_ECX_00);\n FUN_004e5fc8((int)local_c,0x69,local_5c);\n local_44 = (char *)0x0;\n pcStack_48 = (char *)0x4e6632;\n FUN_0040b75c((int *)&local_64);\n FUN_0040537c((int *)&local_60,(longlong *)\"datetime=\",local_64);\n FUN_004e5fc8((int)local_c,0x100,local_60);\n FUN_004e8580(local_8[2],&local_68,extraout_ECX_01);\n FUN_004e5fc8((int)local_c,0x78,local_68);\n FUN_004e5508(*(int *)PTR_DAT_0057121c,1,&local_6c);\n FUN_004e5fc8((int)local_c,0xa0,local_6c);\n FUN_004e8a58(local_8[2],&local_70,extraout_ECX_02);\n FUN_004e5fc8((int)local_c,0xa5,local_70);\n FUN_004e8994(local_8[2],&local_74,extraout_ECX_03);\n FUN_004e5fc8((int)local_c,0xa2,local_74);\n local_88 = *(undefined4 *)(local_8[2] + 0xb4);\n local_84 = 0;\n local_80 = *(undefined4 *)(local_8[2] + 0xac);\n local_7c = 0;\n FUN_0040ac40((byte *)\"mapid=%d\\r\\nlocid=%d\",&local_88,1,(int *)&local_78);\n FUN_004e5fc8((int)local_c,0x6e,local_78);\n }\n }\n else if (iVar7 == 0x66) {\n iVar9 = FUN_004e6288(iVar9,0x4e7320);\n FUN_004e7758((int *)local_8[2],iVar9,1);\n FUN_004e89ec(local_8[2],&local_8c,extraout_ECX_04);\n FUN_004e5fc8((int)local_c,0x69,local_8c);\n }\n else if (iVar7 == 0x69) {\n FUN_004e89ec(local_8[2],&local_90,extraout_ECX);\n FUN_004e5fc8((int)local_c,0x69,local_90);\n }\n else if (iVar7 == 0x6e) {\n uVar6 = FUN_004e6288(iVar9,0x4e7330);\n FUN_004e891c(local_8[2],uVar6);\n uVar6 = FUN_004e6288(iVar9,0x4e7340);\n FUN_004e88e0(local_8[2],uVar6);\n local_88 = *(undefined4 *)(local_8[2] + 0xb4);\n local_84 = 0;\n local_80 = *(undefined4 *)(local_8[2] + 0xac);\n local_7c = 0;\n FUN_0040ac40((byte *)\"mapid=%d\\rlocid=%d\",&local_88,1,(int *)&local_94);\n FUN_004e5fc8((int)local_c,0x6e,local_94);\n FUN_004e8acc((int *)local_8[2]);\n }\n }\n else if (iVar7 == 0x84) {\n func_0x004e6218(iVar9,&DAT_004e73f4);\n _local_5c = (double)in_ST0;\n local_60 = (longlong *)0x4e6a99;\n local_60 = (longlong *)FUN_004e6288(iVar9,0x4e738c);\n local_64 = (longlong *)0x4e6aa7;\n FUN_004e6288(iVar9,0x4e739c);\n local_60 = (longlong *)0x4e6ab5;\n FUN_004e7ef4();\n _local_5c = (double)CONCAT44(0x4e6ac6,local_5c);\n FUN_004e8210(local_8[2],&local_c4);\n _local_5c = (double)CONCAT44(0x4e6ad9,local_5c);\n FUN_004e5fc8((int)local_c,100,local_c4);\n _local_5c = (double)CONCAT44(0x4e6aea,local_5c);\n FUN_004e89ec(local_8[2],&local_c8,extraout_ECX_11);\n _local_5c = (double)CONCAT44(0x4e6afd,local_5c);\n FUN_004e5fc8((int)local_c,0x69,local_c8);\n _local_5c = (double)CONCAT44(0x4e6b0e,local_5c);\n FUN_004e8580(local_8[2],&local_cc,extraout_ECX_12);\n _local_5c = (double)CONCAT44(0x4e6b21,local_5c);\n FUN_004e5fc8((int)local_c,0x78,local_cc);\n _local_5c = (double)CONCAT44(0x4e6b33,local_5c);\n FUN_004e5fc8((int)local_c,0x82,(longlong *)&DAT_004e7404);\n }\n else if (iVar7 == 0x86) {\n iVar9 = FUN_004e6288(iVar9,0x4e739c);\n FUN_004e7f0c((int *)local_8[2],iVar9,&local_10);\n FUN_004e8210(local_8[2],&local_d0);\n FUN_004e5fc8((int)local_c,100,local_d0);\n FUN_004e89ec(local_8[2],&local_d4,extraout_ECX_13);\n FUN_004e5fc8((int)local_c,0x69,local_d4);\n FUN_004e8580(local_8[2],&local_d8,extraout_ECX_14);\n FUN_004e5fc8((int)local_c,0x78,local_d8);\n FUN_004e5fc8((int)local_c,0x82,(longlong *)&DAT_004e7404);\n FUN_004e5fc8((int)local_c,0x8c,local_10);\n }\n else if (iVar7 == 0x88) {\n FUN_004e7c68((int *)local_8[2],&local_10);\n FUN_004e8210(local_8[2],&local_dc);\n FUN_004e5fc8((int)local_c,100,local_dc);\n FUN_004e89ec(local_8[2],&local_e0,extraout_ECX_15);\n FUN_004e5fc8((int)local_c,0x69,local_e0);\n FUN_004e8580(local_8[2],&local_e4,extraout_ECX_16);\n FUN_004e5fc8((int)local_c,0x78,local_e4);\n FUN_004e5fc8((int)local_c,0x8c,local_10);\n }\n }\n else if (iVar7 < 0xb5) {\n if (iVar7 == 0xb4) {\n iVar9 = FUN_004e6288(iVar9,0x4e7448);\n if (iVar9 == 2) {\n FUN_004204a0(*(int *)(local_8[2] + 0x1c),&local_100);\n local_44 = \"\\r\";\n pcStack_48 = \"bates=\";\n local_4c = (undefined *)0x4e6e0a;\n FUN_004204a0(*(int *)(local_8[2] + 0x20),(int *)&local_104);\n local_4c = local_104;\n local_50 = (undefined *)0x4e6e20;\n FUN_004053f8((int *)&local_fc,5);\n local_50 = (undefined *)0x4e6e33;\n FUN_004e5fc8((int)local_c,200,local_fc);\n }\n }\n else if (iVar7 == 0xa2) {\n FUN_004e862c(local_8[2],*(int *)(iVar9 + 0x30));\n }\n else if (iVar7 == 0xa5) {\n FUN_004e8a58(local_8[2],&local_f4,extraout_ECX);\n FUN_004e5fc8((int)local_c,0xa5,local_f4);\n FUN_004e8994(local_8[2],&local_f8,extraout_ECX_19);\n FUN_004e5fc8((int)local_c,0xa2,local_f8);\n }\n else if (iVar7 == 0xaa) {\n iVar7 = FUN_004e6288(iVar9,0x4e7410);\n local_14 = (int *)FUN_004e55a4(*(int *)PTR_DAT_0057121c,iVar7,extraout_ECX_20);\n if (local_14 != (int *)0x0) {\n iVar7 = FUN_004e6288(iVar9,0x4e7420);\n local_14[7] = iVar7;\n iVar7 = FUN_004e6288(iVar9,0x4e7430);\n local_14[8] = iVar7;\n iVar9 = FUN_004e6288(iVar9,0x4e743c);\n local_14[9] = iVar9;\n }\n }\n }\n else if (iVar7 == 0xd2) {\n iVar7 = FUN_004e6288(iVar9,0x4e7478);\n if (iVar7 == 0) {\n FUN_004e53c4(*(int *)PTR_DAT_0057121c,local_14[4],extraout_ECX_21);\n FUN_004e8acc((int *)local_8[2]);\n }\n else if (iVar7 == 1) {\n uVar5 = FUN_004e61ac(iVar9,0x4e7488);\n uStack_1c = (undefined1 *)CONCAT13(uVar5,(undefined3)uStack_1c);\n iVar9 = FUN_004e6288(iVar9,0x4e7410);\n local_14 = (int *)FUN_004e55a4(*(int *)PTR_DAT_0057121c,iVar9,extraout_ECX_22);\n if (local_14 != (int *)0x0) {\n local_28 = (undefined *)FUN_004e77fc(local_8[2],(int)local_14,extraout_ECX_23);\n if (uStack_1c._3_1_ == '\\0') {\n local_44 = (char *)local_14[4];\n pcStack_48 = (char *)0x4e6edc;\n FUN_00409ad8(&local_10c);\n local_44 = \"\\r\";\n pcStack_48 = \"cost=\";\n local_4c = (undefined *)0x4e6efa;\n FUN_004099ec((uint)local_28,(int *)&local_110);\n local_4c = local_110;\n local_50 = &DAT_004e72c0;\n local_54 = \"work=0\";\n _local_5c = (double)CONCAT44(0x4e6f1a,local_5c);\n FUN_004053f8((int *)&local_108,7);\n _local_5c = (double)CONCAT44(0x4e6f2d,local_5c);\n FUN_004e5fc8((int)local_c,0xd2,local_108);\n }\n else {\n FUN_004e53c4(*(int *)PTR_DAT_0057121c,local_14[4],extraout_ECX_24);\n FUN_004e8958(local_8[2],local_28 + *(int *)(local_8[2] + 0xa4));\n FUN_004e8acc((int *)local_8[2]);\n FUN_004e8210(local_8[2],&local_114);\n FUN_004e5fc8((int)local_c,100,local_114);\n local_44 = (char *)local_14[4];\n pcStack_48 = (char *)0x4e6fa7;\n FUN_00409ad8(&local_11c);\n local_44 = \"\\r\";\n pcStack_48 = \"cost=\";\n local_4c = (undefined *)0x4e6fc5;\n FUN_004099ec((uint)local_28,(int *)&local_120);\n local_4c = local_120;\n local_50 = &DAT_004e72c0;\n local_54 = \"work=1\";\n _local_5c = (double)CONCAT44(0x4e6fe5,local_5c);\n FUN_004053f8((int *)&local_118,7);\n _local_5c = (double)CONCAT44(0x4e6ff8,local_5c);\n FUN_004e5fc8((int)local_c,0xd2,local_118);\n }\n }\n }\n }\n else if (iVar7 == 0xdc) {\n iVar9 = FUN_004e6288(iVar9,0x4e74d8);\n local_18 = FUN_004e55cc(*(int *)PTR_DAT_0057121c,iVar9,extraout_ECX_25);\n if ((local_18 != 0) &&\n (iVar9 = *(int *)(local_18 + 0x34) * *(int *)(local_18 + 0x20),\n iVar9 - *(int *)(local_8[2] + 0xa4) == 0 || iVar9 < *(int *)(local_8[2] + 0xa4))) {\n FUN_004e78ac(local_8[2],*(undefined4 *)(local_18 + 0x10),&local_34);\n if ((int)\n\n... (truncated)"}Excellent! I found the CMD=0x78 (120) handler that sends CMD=0x7D (125) as a response. Now let me read the field names at those data addresses.
Call ghidra_get_data_by_address
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x4e736c"}
Tool result
{"result":"69h i"}Call ghidra_get_data_by_address
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x4e737c"}
Tool result
{"result":"\"otype\""}Call ghidra_get_data_by_address
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x4e738c"}
Tool result
{"result":"\"weigth\""}Call ghidra_get_data_by_address
Arguments
{"filepath":"/sandbox/FFG.exe", "address": "0x4e73ac"}
Tool result
{"result":"69h i"}Call ghidra_get_data_by_address
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x4e73cc"}
Tool result
{"result":"6Fh o"}Let me hexdump the field name table region to see all CMD=120 fields at once.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\nimport struct\nwith open('/sandbox/FFG.exe', 'rb') as f:\n # Image base 0x400000,so file offset = VA - 0x400000\n # Read from 0x4e736c-0x4e7400\n base = 0x400000\n start_va= 0x4e7360\n start_off = start_va - base\n f.seek(start_off)\n data = f.read(0x120)\n for i in range(0, len(data), 16):\n hex_part = ' '.join(f'{b:02x}' forb in data[i:i+16])\n ascii_part= ''.join(chr(b) if 32 <=b < 127 else '.' for bin data[i:i+16])\n print(f' {start_va+i:08x}: {hex_part:<48} {ascii_part}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":" 004e7360: 45 e0 83 7d e0 00 0f 8c 04 01 00 00 8b 45 fc 8b E..}.........E..\n 004e7370: 40 10 8b 55 e0 e8 e6 84 f3 ff 89 45 dc 8b 45 f8 @..U.......E..E.\n 004e7380: 8b 55 dc 3b 42 14 0f 85 d7 00 00 00 a1 e0 0e 57 .U.;B..........W\n 004e7390: 00 8b 00 8b 55 dc 8b 52 14 e8 0e 5b 06 00 89 45 ....U..R...[...E\n 004e73a0: d8 8b 45 d8 8b 40 3c 8b 55 dc 3b 42 18 7e 2c ff ..E..@<.U.;B.~,.\n 004e73b0: 45 f0 8d 45 cc 50 ba 08 00 00 00 8b 45 fc e8 05 E..E.P......E...\n 004e73c0: 02 00 00 8b c8 8b 45 dc 8b 50 18 8b 45 d8 e8 51 ......E..P..E..Q\n 004e73d0: 68 06 00 8b 45 cc 01 45 ec eb 72 8d 45 cc 50 ba h...E..E..r.E.P.\n 004e73e0: 08 00 00 00 8b 45 fc e8 dc 01 00 00 8b c8 8b 45 .....E.........E\n 004e73f0: dc 8b 50 18 8b 45 d8 e8 28 68 06 00 8b 45 cc 89 ..P..E..(h...E..\n 004e7400: 45 e4 8d 45 c8 50 8b 45 dc 8b 40 14 89 45 b0 c6 E..E.P.E..@..E..\n 004e7410: 45 b4 00 8b 45 dc 8b 40 18 89 45 b8 c6 45 bc 00 E...E..@..E..E..\n 004e7420: 8b 45 e4 89 45 c0 c6 45 c4 00 8d 55 b0 b9 02 00 .E..E..E...U....\n 004e7430: 00 00 b8 2c 81 4e 00 e8 04 2c f2 ff 8b 55 c8 8b ...,.N...,...U..\n 004e7440: 45 d4 8b 08 ff 51 38 8b 45 e4 01 45 e8 8b 45 dc E....Q8.E..E..E.\n 004e7450: e8 2f c1 f1 ff 8b 45 fc 8b 40 10 8b 55 e0 e8 51 ./....E..@..U..Q\n 004e7460: 83 f3 ff ff 4d e0 83 7d e0 00 0f 8d fc fe ff ff ....M..}........\n 004e7470: 8d 45 ac 50 8b 45 f0 89 45 cc c6 45 d0 00 8d 55 .E.P.E..E..E...U\n","stderr":""}The section offset calculation may be different for a PE file. Let me recalculate correctly.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\nimport pefile\npe= pefile.PE('/sandbox/FFG.exe')\nfor section in pe.sections:\n name = section.Name.rstrip(b'\\x00').decode()\n print(f'{name}: VA=0x{section.VirtualAddress+pe.OPTIONAL_HEADER.ImageBase:08x}, RawOffset=0x{section.PointerToRawData:08x}, RawSize=0x{section.SizeOfRawData:08x}')\n\" 2>/dev/null || python3 -c \"\nwith open('/sandbox/FFG.exe','rb') as f:\n data = f.read()\n# PE headeroffset\npe_off = int.from_bytes(data[0x3c:0x40],'little')\n# number of sections\nnsec=int.from_bytes(data[pe_off+6:pe_off+8],'little')\nopt_size = int.from_bytes(data[pe_off+20:pe_off+22],'little')\nsec_table = pe_off +24 + opt_size\nfor i in range(nsec):\n s = sec_table + i*40\n name =data[s:s+8].rstrip(b'\\x00').decode(errors='replace')\n vaddr=int.from_bytes(data[s+12:s+16],'little')\n raw_off =int.from_bytes(data[s+20:s+24],'little')\n raw_sz = int.from_bytes(data[s+16:s+20],'little')\n print(f'{name}: VA=0x{vaddr:08x}, RawOff=0x{raw_off:08x}, RawSz=0x{raw_sz:08x}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":".text: VA=0x00401000, RawOffset=0x00000400, RawSize=0x00169800\n.itext: VA=0x0056b000, RawOffset=0x00169c00, RawSize=0x00001200\n.data: VA=0x0056d000, RawOffset=0x0016ae00, RawSize=0x00004400\n.bss: VA=0x00572000, RawOffset=0x00000000, RawSize=0x00000000\n.idata: VA=0x0057f000, RawOffset=0x0016f200, RawSize=0x00003200\n.tls: VA=0x00583000, RawOffset=0x00000000, RawSize=0x00000000\n.rdata: VA=0x00584000, RawOffset=0x00172400, RawSize=0x00000200\n.vmp0: VA=0x00585000, RawOffset=0x00172600, RawSize=0x0001b200\n.rsrc: VA=0x005a1000, RawOffset=0x0018d800, RawSize=0x00007400\n.vmp1: VA=0x005a9000, RawOffset=0x00194c00, RawSize=0x00000200\n.reloc: VA=0x005aa000, RawOffset=0x00194e00, RawSize=0x0001b200\n","stderr":""}The previous hexdump used wrong offset math. Let me recalculate with correct section mapping.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\n# .text: VA=0x00401000, RawOffset=0x00000400\n# file_offset= 0x400 + (VA -0x401000)\ndefva2off(va):\n return 0x400 +(va - 0x401000)\n\nwith open('/sandbox/FFG.exe', 'rb') as f:\n # Field name table for CMD=120: addresses usedin FUN_004e6464\n addrs =[0x4e736c, 0x4e737c, 0x4e738c, 0x4e739c, 0x4e73ac, 0x4e73bc, 0x4e73cc, 0x4e73dc, 0x4e73e4, 0x4e73f4]\n for va in addrs:\n off = va2off(va)\n f.seek(off)\n raw = f.read(20)\ns = raw.split(b'\\x00')[0].decode('latin-1')\n print(f'0x{va:08x} (off=0x{off:06x}): {raw[:16].hex()} -> \\\"{s}\\\"')\n \nprint()\n # Read full regionfrom 0x4e7360to 0x4e7500\n start = 0x4e7360\n f.seek(va2off(start))\n data =f.read(0x1a0)\n for i in range(0, len(data), 16):\n hex_part = ' '.join(f'{b:02x}' for b in data[i:i+16])\n ascii_part = ''.join(chr(b) if 32<= b < 127else '.' for bin data[i:i+16])\n print(f' {start+i:08x}:{hex_part:<48} {ascii_part}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"0x004e736c (off=0x0e676c): 696e666f00000000ffffffff05000000 -> \"info\"\n0x004e737c (off=0x0e677c): 6f74797065000000ffffffff06000000 -> \"otype\"\n0x004e738c (off=0x0e678c): 7765696774680000ffffffff06000000 -> \"weigth\"\n0x004e739c (off=0x0e679c): 6669736869640000ffffffff04000000 -> \"fishid\"\n0x004e73ac (off=0x0e67ac): 696e696400000000ffffffff05000000 -> \"inid\"\n0x004e73bc (off=0x0e67bc): 696e69643d000000ffffffff04000000 -> \"inid=\"\n0x004e73cc (off=0x0e67cc): 6f69643d000000000000c8420000803f -> \"oid=\"\n0x004e73dc (off=0x0e67dc): ffffffff060000006261697469640000 -> \"ÿÿÿÿ\u0006\"\n0x004e73e4 (off=0x0e67e4): 6261697469640000ffffffff04000000 -> \"baitid\"\n0x004e73f4 (off=0x0e67f4): 74696d6500000000ffffffff01000000 -> \"time\"\n\n 004e7360: 64 00 00 00 ff ff ff ff 04 00 00 00 69 6e 66 6f d...........info\n 004e7370: 00 00 00 00 ff ff ff ff 05 00 00 00 6f 74 79 70 ............otyp\n 004e7380: 65 00 00 00 ff ff ff ff 06 00 00 00 77 65 69 67 e...........weig\n 004e7390: 74 68 00 00 ff ff ff ff 06 00 00 00 66 69 73 68 th..........fish\n 004e73a0: 69 64 00 00 ff ff ff ff 04 00 00 00 69 6e 69 64 id..........inid\n 004e73b0: 00 00 00 00 ff ff ff ff 05 00 00 00 69 6e 69 64 ............inid\n 004e73c0: 3d 00 00 00 ff ff ff ff 04 00 00 00 6f 69 64 3d =...........oid=\n 004e73d0: 00 00 00 00 00 00 c8 42 00 00 80 3f ff ff ff ff .......B...?....\n 004e73e0: 06 00 00 00 62 61 69 74 69 64 00 00 ff ff ff ff ....baitid......\n 004e73f0: 04 00 00 00 74 69 6d 65 00 00 00 00 ff ff ff ff ....time........\n 004e7400: 01 00 00 00 20 00 00 00 ff ff ff ff 05 00 00 00 .... ...........\n 004e7410: 77 70 6e 69 64 00 00 00 ff ff ff ff 04 00 00 00 wpnid...........\n 004e7420: 63 65 6c 6c 00 00 00 00 ff ff ff ff 02 00 00 00 cell............\n 004e7430: 78 70 00 00 ff ff ff ff 02 00 00 00 79 70 00 00 xp..........yp..\n 004e7440: ff ff ff ff 05 00 00 00 6f 70 74 69 64 00 00 00 ........optid...\n 004e7450: ff ff ff ff 04 00 00 00 77 70 6e 3d 00 00 00 00 ........wpn=....\n 004e7460: ff ff ff ff 06 00 00 00 62 61 74 65 73 3d 00 00 ........bates=..\n 004e7470: ff ff ff ff 04 00 00 00 6d 6f 64 65 00 00 00 00 ........mode....\n 004e7480: ff ff ff ff 04 00 00 00 77 6f 72 6b 00 00 00 00 ........work....\n 004e7490: ff ff ff ff 06 00 00 00 77 70 6e 69 64 3d 00 00 ........wpnid=..\n 004e74a0: ff ff ff ff 05 00 00 00 63 6f 73 74 3d 00 00 00 ........cost=...\n 004e74b0: ff ff ff ff 06 00 00 00 77 6f 72 6b 3d 30 00 00 ........work=0..\n 004e74c0: ff ff ff ff 06 00 00 00 77 6f 72 6b 3d 31 00 00 ........work=1..\n 004e74d0: ff ff ff ff 07 00 00 00 74 65 6d 70 6c 69 64 00 ........templid.\n 004e74e0: ff ff ff ff 0c 00 00 00 6d 73 67 3d 69 6e 76 5f ........msg=inv_\n 004e74f0: 66 75 6c 6c 00 00 00 00 55 8b ec 33 c0 55 68 29 full....U..3.Uh)\n","stderr":""}Now let me check the separator at DAT_004e72c0 and also look at FUN_004e8580 (what CMD=120 server→client contains).
Call sandbox_execute
Arguments
{"command":"python3 -c \"\ndef va2off(va):\n return 0x400 +(va - 0x401000)\n\nwith open('/sandbox/FFG.exe','rb') asf:\n #DAT_004e72c0 (separator usedinCMD=125 build)\n f.seek(va2off(0x4e72b8))\n data = f.read(32)\n print('0x4e72b8:', data[:24].hex(), '->', repr(data.split(b'\\x00')[0].decode('latin-1')))\n \nf.seek(va2off(0x4e72c0))\n data = f.read(16)\n print('0x4e72c0:', data.hex(), '->', repr(data[:8]))\n \n # Also look at 0x4e72cc (loginstring area)\n f.seek(va2off(0x4e72c0))\n data = f.read(80)\n for i in range(0, 80,16):\nhex_part = ' '.join(f'{b:02x}'for b indata[i:i+16])\n ascii_part = ''.join(chr(b) if32 <= b < 127else '.' for b in data[i:i+16])\n print(f' {0x4e72c0+i:08x}: {hex_part:<48} {ascii_part}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"0x4e72b8: ffffffff010000000d000000ffffffff050000006c6f6769 -> 'ÿÿÿÿ\\x01'\n0x4e72c0: 0d000000ffffffff050000006c6f6769 -> b'\\r\\x00\\x00\\x00\\xff\\xff\\xff\\xff'\n 004e72c0: 0d 00 00 00 ff ff ff ff 05 00 00 00 6c 6f 67 69 ............logi\n 004e72d0: 6e 00 00 00 ff ff ff ff 09 00 00 00 64 61 74 65 n...........date\n 004e72e0: 74 69 6d 65 3d 00 00 00 ff ff ff ff 12 00 00 00 time=...........\n 004e72f0: 6d 61 70 69 64 3d 25 64 0d 0a 6c 6f 63 69 64 3d mapid=%d..locid=\n 004e7300: 25 64 00 00 ff ff ff ff 0a 00 00 00 6e 6f 5f 6c %d..........no_l\n","stderr":""}Now let me find the client-side CMD=125 receiver and check FUN_004e8580 (CMD=120 server→client builder).
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_004e8580"}
Tool result
{"result":"\nvoid FUN_004e8580(int param_1,undefined4 param_2,undefined4 param_3)\n\n{\n int iVar1;\n int local_1c;\n int local_18;\n int *local_10;\n undefined4 local_c;\n int local_8;\n \n local_c = param_2;\n local_8 = param_1;\n local_10 = (int *)FUN_00404154((int *)PTR_PTR_0041475c,'\\x01',param_3);\n local_1c = FUN_004202b4(*(int *)(local_8 + 0x10));\n if (-1 < local_1c + -1) {\n local_18 = 0;\n do {\n iVar1 = FUN_00420460(*(int *)(local_8 + 0x10),local_18);\n FUN_004e9e08(iVar1,&local_10);\n local_18 = local_18 + 1;\n local_1c = local_1c + -1;\n } while (local_1c != 0);\n }\n (**(code **)(*local_10 + 0x1c))(local_10,local_c);\n FUN_00404184(local_10);\n return;\n}\n\n"}Call ghidra_search_functions_by_name
Arguments
{"filepath":"/sandbox/FFG.exe", "query": "0x7d"}
Tool result
{"result":["No functions matching '0x7d'"]}Let me search for CMD=125 (0x7d) references and the client-side dispatch function.
Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x004e8580"}
Tool result
{"result":["From 004e665b in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6b09 in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6ba9 in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6c4a in FUN_004e6464 [UNCONDITIONAL_CALL]"]}Call ghidra_search_functions_by_name
Arguments
{"filepath": "/sandbox/FFG.exe", "query": "packet"}
Tool result
{"result":["No functions matching 'packet'"]}Let me search for other CMD dispatch functions that handle 0x78 and 0x7d as received commands.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\n# Search for comparison with0x78 (CMD=120) and 0x7d (CMD=125) in .text\n# Lookfor patterns like'cmp reg, 0x78' or 'cmp reg, 0x7d'\n# Inx86: 83 F8 78 (cmp eax, 0x78),83 7? 0x78 (various)\n# or:3D 78 00 00 00 (cmp eax, 0x78), 81 F9 78 00 00 00 etc.\n\nwith open('/sandbox/FFG.exe', 'rb')as f:\n data = f.read()\n\ntext_start_va = 0x401000\ntext_raw_off= 0x400\ntext_size =0x169800\n\ntext = data[text_raw_off:text_raw_off + text_size]\n\nhits_78= []\nhits_7d = []\n\n#Lookfor: 83 F8 78 (cmp eax, 0x78),83 F978 (cmp ecx, 0x78), 83 FB 78 (cmp ebx, 0x78)\n# Also: 3D 78 00 00 00 (cmp eax, 0x78)\nimport re\n\nfor i in range(len(text)-4):\n b= text[i]\n b1 = text[i+1]\n b2 = text[i+2]\n \n# cmpreg8,imm8 pattern: 83 /7imm8\n if b== 0x83 and (b1 & 0xF8) ==0xF8 and b2 == 0x78:\n hits_78.append(text_start_va +i)\n if b ==0x83 and (b1 & 0xF8) == 0xF8 and b2==0x7d:\n hits_7d.append(text_start_va+ i)\n \n# cmp eax, imm32: 3D 78 00 00 00\n ifb == 0x3Dand b1 == 0x78 and text[i+2:i+5]== b'\\x00\\x00\\x00':\nhits_78.append(text_start_va +i)\n if b == 0x3D and b1 == 0x7d and text[i+2:i+5]== b'\\x00\\x00\\x00':\n hits_7d.append(text_start_va + i)\n\nprint(f'CMD=0x78 comparisons at: {[hex(a) for a in hits_78[:30]]}')\nprint(f'CMD=0x7d comparisons at:{[hex(a) fora in hits_7d[:30]]}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"CMD=0x78 comparisons at: ['0x4471eb', '0x4e6519']\nCMD=0x7d comparisons at: []\n","stderr":""}Found another CMD=0x78 comparison at 0x4471eb. Let me find what function that belongs to.
Call ghidra_get_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "0x4471eb"}
Tool result
{"result":"No function found at 0x4471eb"}Call sandbox_execute
Arguments
{"command": "python3 -c \"\n# Search morebroadly for 0x78and 0x7d asDWORD values indata sections\n# and incode as constants\n# Also look for 'cmp [mem], 78' or 'moveax, 78' patterns\nwith open('/sandbox/FFG.exe', 'rb') as f:\n data = f.read()\n\ntext_start_va = 0x401000\ntext_raw_off = 0x400\ntext_size = 0x169800\ntext = data[text_raw_off:text_raw_off +text_size]\n\nhits =[]\nfor iin range(len(text)-4):\n b= text[i:i+4]\n # Looking for comparisons to 0x78 or 0x7d as 32-bit in EAX\n# 3D7D 0000 00\n iftext[i] == 0x3D and text[i+1] in [0x7d, 0x78] andtext[i+2:i+5] == b'\\x00\\x00\\x00':\n hits.append((text_start_va+i, text[i+1]))\n # 81 F? 7D 00 00 00 or78 00 0000\n iftext[i] == 0x81 and(text[i+1] & 0xC0 in [0x80, 0xC0]) and text[i+2] in[0x7d, 0x78] andtext[i+3:i+6] == b'\\x00\\x00\\x00':\n hits.append((text_start_va+i,text[i+2]))\n\nprint('Hits:', [(hex(a), hex(v)) for a,v in hits[:30]])\n\"\n"}
Tool result
{"exitCode":0,"stdout":"Hits: []\n","stderr":""}Call sandbox_execute
Arguments
{"command": "python3 -c \"\n# Find function containing0x4471eb by looking for nearbyfunction starts\n# Let'sdisassemble the bytes around 0x4471eb\ndef va2off(va):\n return 0x400 + (va - 0x401000)\n\nwith open('/sandbox/FFG.exe', 'rb') as f:\n f.seek(va2off(0x4471d0))\n data = f.read(80)\n \nprint('Hex dump around 0x4471d0:')\nfor iin range(0, 80,16):\n hex_part = ' '.join(f'{b:02x}' for b in data[i:i+16])\n ascii_part = ''.join(chr(b) if 32 <= b <127 else'.' forb in data[i:i+16])\n print(f' {0x4471d0+i:08x}: {hex_part:<48} {ascii_part}')\n\n#Also check broader - look for all places where0x7d (125) appears as a \n#CMD number in send calls like 'push 0x7d'\nwithopen('/sandbox/FFG.exe', 'rb') as f:\n data = f.read()\n\ntext_raw_off = 0x400\ntext_size = 0x169800\ntext_start_va =0x401000\ntext = data[text_raw_off:text_raw_off + text_size]\n\nhits =[]\nfor i in range(len(text)-1):\n #'push imm8': 6A 7D\n if text[i] == 0x6Aand text[i+1]== 0x7D:\n hits.append((text_start_va+i, '6a 7d'))\n # 'push imm32': 68 7D 000000\nif text[i] == 0x68 and text[i+1] == 0x7D and text[i+2:i+5] == b'\\x00\\x00\\x00':\n hits.append((text_start_va+i, '68 7d'))\n #Also find push0x78 \n iftext[i] == 0x6A and text[i+1] == 0x78:\n hits.append((text_start_va+i, '6a 78'))\n iftext[i]== 0x68 and text[i+1] ==0x78 and text[i+2:i+5] == b'\\x00\\x00\\x00':\n hits.append((text_start_va+i, '68 78'))\n\nprint()\nprint('Push 0x78/0x7d instructions:')\nfor addr, pat in hits[:40]:\n print(f' {addr:08x}: {pat}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"Hex dump around 0x4471d0:\n 004471d0: 55 ff 8b c7 66 be e0 ff e8 a3 d1 fb ff 88 45 f6 U...f.........E.\n 004471e0: 8b 87 98 00 00 00 99 33 c2 2b c2 83 f8 78 7d 8b .......3.+...x}.\n 004471f0: 0f b6 45 f6 5f 5e 5b 8b e5 5d c2 04 00 8d 40 00 ..E._^[..]....@.\n 00447200: 53 56 57 83 c4 f4 8b f1 8d 7c 24 01 a5 a5 88 14 SVW......|$.....\n 00447210: 24 c6 44 24 09 00 66 83 b8 4a 01 00 00 00 74 1f $.D$..f..J....t.\n\nPush 0x78/0x7d instructions:\n 004c785e: 6a 78\n 004d28c8: 6a 7d\n 004ed5c2: 6a 7d\n 004f2de9: 6a 78\n 004f2e26: 6a 78\n 0051b34d: 6a 78\n 0051b40e: 6a 78\n 0051b484: 6a 78\n 0051b551: 6a 78\n 0051b926: 6a 78\n 0051b951: 6a 78\n 00535934: 6a 78\n 005417d8: 6a 78\n 00543138: 6a 7d\n 00544de3: 6a 7d\n 0054869e: 6a 78\n 00548828: 6a 7d\n 005490a1: 6a 7d\n","stderr":""}Let me look at FUN_004e9e08 (builds items for server→client CMD=120) and examine the push 0x78 locations for client→server structure.
Call ghidra_decompile_function
Arguments
{"filepath":"/sandbox/FFG.exe", "name_or_address":"FUN_004e9e08"}
Tool result
{"result":"\nvoid FUN_004e9e08(int param_1,undefined4 *param_2)\n\n{\n undefined4 uVar1;\n undefined4 *in_FS_OFFSET;\n float10 fVar2;\n longlong *local_30;\n int local_2c;\n int local_28;\n longlong *local_24;\n undefined2 local_20;\n undefined2 uStack_1e;\n longlong *local_1c;\n undefined1 *local_18;\n longlong *local_14;\n int local_10;\n undefined4 *local_c;\n int local_8;\n \n local_14 = (longlong *)&stack0xfffffffc;\n local_10 = 5;\n do {\n local_10 = local_10 + -1;\n } while (local_10 != 0);\n local_18 = &LAB_004e9f2a;\n local_1c = (longlong *)*in_FS_OFFSET;\n *in_FS_OFFSET = &local_1c;\n local_24 = *(longlong **)(param_1 + 0x10);\n local_20 = 0;\n uStack_1e = 0;\n local_28 = 0x4e9e3e;\n local_c = param_2;\n local_8 = param_1;\n FUN_00409ad8((int *)&local_14);\n local_20 = 0x9e4e;\n uStack_1e = 0x4e;\n FUN_0040537c(&local_10,(longlong *)&DAT_004e9f40,local_14);\n local_20 = 0x9e5b;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,local_10);\n local_20 = 0x9e69;\n uStack_1e = 0x4e;\n FUN_004099ec(*(uint *)(local_8 + 0x14),(int *)&local_1c);\n local_20 = 0x9e79;\n uStack_1e = 0x4e;\n FUN_0040537c((int *)&local_18,(longlong *)\"fishid=\",local_1c);\n local_20 = 0x9e86;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,local_18);\n local_20 = 0x9e94;\n uStack_1e = 0x4e;\n FUN_004099ec(*(uint *)(local_8 + 0x18),(int *)&local_24);\n local_20 = 0x9ea4;\n uStack_1e = 0x4e;\n FUN_0040537c((int *)&local_20,(longlong *)\"weigth=\",local_24);\n uVar1 = CONCAT22(uStack_1e,local_20);\n local_20 = 0x9eb1;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,uVar1);\n local_20 = 0x9ec4;\n uStack_1e = 0x4e;\n FUN_0040537c(&local_28,(longlong *)\"info=\",*(longlong **)(local_8 + 0x28));\n local_20 = 0x9ed1;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,local_28);\n fVar2 = (float10)*(double *)(local_8 + 0x20);\n local_28 = SUB104(fVar2,0);\n local_24 = (longlong *)((unkuint10)fVar2 >> 0x20);\n local_20 = (undefined2)((unkuint10)fVar2 >> 0x40);\n local_2c = 0x4e9ee6;\n FUN_0040b75c((int *)&local_30);\n local_20 = 0x9ef6;\n uStack_1e = 0x4e;\n FUN_0040537c(&local_2c,(longlong *)\"time=\",local_30);\n local_20 = 0x9f03;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,local_2c);\n local_20 = 0x9f0f;\n uStack_1e = 0x4e;\n (**(code **)(*(int *)*local_c + 0x38))((int *)*local_c,0);\n *in_FS_OFFSET = local_1c;\n local_14 = (longlong *)&LAB_004e9f31;\n local_18 = (undefined1 *)0x4e9f29;\n FUN_00405088((int *)&local_30,9);\n return;\n}\n\n"}Call sandbox_execute
Arguments
{"command": "python3 -c \"\ndef va2off(va):\n return 0x400 +(va - 0x401000)\n\n# Checkcontext around push 0x78 at 0x0051b34d\nwithopen('/sandbox/FFG.exe','rb') as f:\n for va in[0x004ed5c2, 0x0051b34d, 0x00535934,0x005417d8]:\n f.seek(va2off(va-32))\n d = f.read(80)\n print(f'=== {va:08x}===')\n for i in range(0, 80, 16):\n hex_part = ' '.join(f'{b:02x}' forb in d[i:i+16])\n ascii_part = ''.join(chr(b)if 32 <= b <127 else '.' for b in d[i:i+16])\n print(f' {va-32+i:08x}:{hex_part:<48} {ascii_part}')\n print()\n\"\n"}
Tool result
{"exitCode":0,"stdout":"=== 004ed5c2 ===\n 004ed5a2: 30 9b df e0 9e 76 04 c6 45 f7 00 8b 45 fc 8b 40 0....v..E...E..@\n 004ed5b2: 1c 81 78 14 f4 01 00 00 75 6e 80 7d f7 00 74 35 ..x.....un.}..t5\n 004ed5c2: 6a 7d 8b 45 f8 8b 40 28 83 e8 28 83 e8 16 50 6a j}.E..@(..(...Pj\n 004ed5d2: 64 6a 16 68 a0 d6 4e 00 68 70 b4 4e 00 6a 01 6a dj.h..N.hp.N.j.j\n 004ed5e2: 00 8b 45 f8 8b 48 14 b2 01 a1 b8 b2 55 00 e8 93 ..E..H......U...\n\n=== 0051b34d ===\n 0051b32d: 48 14 b2 01 a1 5c b8 55 00 e8 29 17 04 00 6a 23 H....\\.U..)...j#\n 0051b33d: 6a 37 68 e6 00 00 00 6a 6c 6a 00 68 20 20 20 00 j7h....jlj.h .\n 0051b34d: 6a 78 8b 45 f8 8b 48 14 b2 01 a1 68 b6 55 00 e8 jx.E..H....h.U..\n 0051b35d: 6f 66 04 00 6a 28 6a 3c 68 bc c3 51 00 6a 01 a1 of..j(j<h..Q.j..\n 0051b36d: b0 0b 57 00 8b 00 b9 dc c3 51 00 ba ec c3 51 00 ..W......Q....Q.\n\n=== 00535934 ===\n 00535914: 40 8b 45 f0 8b 40 14 50 6a 00 6a 00 8b 45 f4 8b @.E..@.Pj.j..E..\n 00535924: 48 14 b2 01 a1 d0 b5 55 00 e8 66 b3 02 00 6a 10 H......U..f...j.\n 00535934: 6a 78 8b 45 f4 8b 40 24 83 e8 20 50 8b 45 f4 8b jx.E..@$.. P.E..\n 00535944: 40 28 2d 2c 01 00 00 50 8b 45 f0 8b 40 1c 50 6a @(-,...P.E..@.Pj\n 00535954: 00 a1 78 0b 57 00 8b 00 50 8b 45 f4 8b 48 14 b2 ..x.W...P.E..H..\n\n=== 005417d8 ===\n 005417b8: 45 bc 50 6a 00 8b 45 e8 8b 48 14 b2 01 a1 b8 b2 E.Pj..E..H......\n 005417c8: 55 00 e8 b9 b7 01 00 c6 40 60 00 e9 6f 01 00 00 U.......@`..o...\n 005417d8: 6a 78 68 be 00 00 00 68 94 22 54 00 68 ff a0 00 jxh....h.\"T.h...\n 005417e8: 00 6a 00 6a 00 8b 45 e8 8b 48 14 b2 01 a1 5c b8 .j.j..E..H....\\.\n 005417f8: 55 00 e8 65 b2 01 00 8b 15 a8 11 57 00 8b 12 e8 U..e.......W....\n\n","stderr":""}FUN_004e9e08 builds per-fish entries with fields: fishid=, weigth=, info=, time=. Let me check DAT_004e9f40 and the function at 0x4ed5b2.
Call ghidra_get_data_by_address
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x004e9f40"}
Tool result
{"result":"66h f"}Call ghidra_get_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "0x004ed5a2"}
Tool result
{"result":"No function found at 0x004ed5a2"}Call sandbox_execute
Arguments
{"command": "python3 -c \"\ndef va2off(va):\n return 0x400 + (va -0x401000)\n\nwithopen('/sandbox/FFG.exe','rb') as f:\n# DAT_004e9f40\nf.seek(va2off(0x4e9f30))\n data = f.read(48)\n print('0x4e9f30 region:')\n for i in range(0, 48, 16):\n h =''.join(f'{b:02x}' for b in data[i:i+16])\n a = ''.join(chr(b) if 32 <= b < 127 else '.' for b in data[i:i+16])\n print(f' {0x4e9f30+i:08x}: {h:<48} {a}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"0x4e9f30 region:\n 004e9f30: eb 8b e5 5d c3 00 00 00 ff ff ff ff 04 00 00 00 ...]............\n 004e9f40: 66 69 64 3d 00 00 00 00 ff ff ff ff 07 00 00 00 fid=............\n 004e9f50: 66 69 73 68 69 64 3d 00 ff ff ff ff 07 00 00 00 fishid=.........\n","stderr":""}Let me decompile FUN_004e7618 (fishing action processor) and also the function at 0x535900 (likely client-side CMD=120 send).
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_004e7618"}
Tool result
{"result":"\nvoid FUN_004e7618(int param_1,int param_2,int param_3,undefined4 param_4,longlong *param_5)\n\n{\n undefined4 extraout_ECX;\n undefined4 extraout_ECX_00;\n undefined4 extraout_ECX_01;\n undefined4 *in_FS_OFFSET;\n undefined4 uStack_2c;\n undefined1 *puStack_28;\n undefined1 *puStack_24;\n int local_1c;\n int *local_18;\n undefined4 local_14;\n int local_10;\n int local_c;\n int local_8;\n \n puStack_24 = (undefined1 *)0x4e762f;\n local_10 = param_3;\n local_c = param_2;\n local_8 = param_1;\n FUN_004054e4((int)param_5);\n puStack_28 = &LAB_004e76d3;\n uStack_2c = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_2c;\n local_14 = 0xffffffff;\n puStack_24 = &stack0xfffffffc;\n local_1c = FUN_0054daac(*(int *)PTR_DAT_00570ee0,local_c,extraout_ECX);\n if (local_1c != 0) {\n local_18 = FUN_0042099c((int *)PTR_DAT_004e7534,'\\x01',extraout_ECX_00);\n *(int *)(local_8 + 0x7c) = *(int *)(local_8 + 0x7c) + 1;\n local_18[4] = *(int *)(local_8 + 0x7c);\n local_18[5] = local_c;\n local_18[6] = local_10;\n FUN_004050b8(local_18 + 10,param_5);\n FUN_0041ff48(*(int *)(local_8 + 0x10),local_18,extraout_ECX_01,local_18[5],local_18[5] >> 0x1f);\n local_14 = *(undefined4 *)(local_8 + 0x7c);\n }\n *in_FS_OFFSET = uStack_2c;\n puStack_24 = &LAB_004e76da;\n puStack_28 = (undefined1 *)0x4e76d2;\n FUN_00405064((int *)¶m_5);\n return;\n}\n\n"}Call ghidra_get_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "0x005358e0"}
Tool result
{"result":"No function found at 0x005358e0"}Call ghidra_get_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "0x00535900"}
Tool result
{"result":"No function found at 0x00535900"}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address":"0x00535870"}
Tool result
{"result":"Function not found"}Call sandbox_execute
Arguments
{"command": "python3 -c \"\ndef va2off(va):\n return 0x400 + (va - 0x401000)\n\nwith open('/sandbox/FFG.exe','rb') as f:\n # Look back from 0x535934 to find function start\n # Functionstarts usuallybegin with 'push ebp; mov ebp,esp' -> 55 8B EC\nf.seek(va2off(0x535600))\n data = f.read(0x400)\n \n #Find last 55 8B ECbefore 0x535934\n base= 0x535600\n starts = []\n for i in range(len(data)-2):\nif data[i] == 0x55 and data[i+1] == 0x8B and data[i+2] == 0xEC:\nstarts.append(base + i)\n \n print('Function startsnear 0x535934:', [hex(a) for a instarts[-5:]])\n \n # Also look right at the preceding bytes\n f.seek(va2off(0x5358e0))\n d = f.read(16)\n print('0x5358e0:', d.hex())\n \n f.seek(va2off(0x535840))\n d = f.read(16)\n print('0x535840:',d.hex())\n\"\n"}
Tool result
{"exitCode":0,"stdout":"Function starts near 0x535934: ['0x5356ac', '0x53581c']\n0x5358e0: 60006a01a1a81157008b00508b45f48b\n0x535840: 0c57008b008b55fce8c37701008945f0\n","stderr":""}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_0053581c"}
Tool result
{"result":"\nvoid FUN_0053581c(int param_1,uint param_2)\n\n{\n int iVar1;\n undefined4 *in_FS_OFFSET;\n undefined4 uVar2;\n undefined *puVar3;\n undefined4 uStack_28;\n undefined1 *puStack_24;\n undefined1 *puStack_20;\n int local_1c;\n int local_18;\n int *local_14;\n int local_10;\n uint local_c;\n int local_8;\n \n puStack_20 = &stack0xfffffffc;\n local_18 = 0;\n local_1c = 0;\n puStack_24 = &LAB_00535a0d;\n uStack_28 = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_28;\n local_c = param_2;\n local_8 = param_1;\n local_14 = FUN_0054d010(*(int *)PTR_DAT_00570c9c,param_1,0);\n local_10 = FUN_0055e99c(*(int *)PTR_DAT_00570fe0,0x1a4,400,0,(longlong *)0x0);\n FUN_005619d0((int *)PTR_PTR_0055b668,'\\x01',*(int *)(local_10 + 0x14),0xfa,0,0xa7d0d4,\n *(int *)(local_10 + 0x28) + -0x10,*(int *)(local_10 + 0x24) + -0x10,8,8);\n puVar3 = &DAT_00535a20;\n FUN_00567a28(local_c,&local_1c);\n iVar1 = local_1c;\n FUN_004053f8(&local_18,3);\n FUN_0055ca64((int *)PTR_PTR_0055b85c,'\\x01',*(int *)(local_10 + 0x14),*(int *)PTR_DAT_005711a8,1,\n 0x600000,local_18,iVar1,(int)puVar3);\n iVar1 = (int)*(uint *)(local_10 + 0x24) >> 1;\n if (iVar1 < 0) {\n iVar1 = iVar1 + (uint)((*(uint *)(local_10 + 0x24) & 1) != 0);\n }\n FUN_00560c98((int *)PTR_PTR_0055b5d0,'\\x01',*(int *)(local_10 + 0x14),(longlong *)0x0,0,\n local_14[5],0x40,0x40,0x32,iVar1 + -0x20);\n iVar1 = FUN_005621b0((int *)PTR_PTR_0055b49c,'\\x01',*(int *)(local_10 + 0x14),\n *(int *)PTR_DAT_00570b78,'\\0',local_14[7],*(int *)(local_10 + 0x28) + -300,\n *(int *)(local_10 + 0x24) + -0x20,0x78,0x10);\n *(undefined1 *)(iVar1 + 0xa1) = 1;\n iVar1 = FUN_005621b0((int *)PTR_PTR_0055b49c,'\\x01',*(int *)(local_10 + 0x14),\n *(int *)PTR_DAT_0057126c,'\\0',local_14[8],100,\n *(int *)(local_10 + 0x24) + -0x20,0xe0,0x10);\n *(undefined1 *)(iVar1 + 0xa1) = 1;\n iVar1 = (int)*(uint *)(local_10 + 0x24) >> 1;\n if (iVar1 < 0) {\n iVar1 = iVar1 + (uint)((*(uint *)(local_10 + 0x24) & 1) != 0);\n }\n uVar2 = 0;\n FUN_0055cf88((int *)PTR_PTR_0055b2b8,'\\x01',*(int *)(local_10 + 0x14),(longlong *)0x0,0,0x55bc8c,\n (longlong *)&DAT_00535a30,0x16,100,*(int *)(local_10 + 0x28) + -0x32,iVar1 + -0x32);\n *in_FS_OFFSET = uVar2;\n FUN_00405088(&local_1c,2);\n return;\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath":"/sandbox/FFG.exe", "name_or_address": "FUN_005356ac"}
Tool result
{"result":"Function not found"}Call sandbox_execute
Arguments
{"command":"python3 -c \"\ndef va2off(va):\n return 0x400+ (va - 0x401000)\n\nwith open('/sandbox/FFG.exe','rb') as f:\n # Look atpush 0x78 at 0x535934 andsurroundingcontext more carefully\nf.seek(va2off(0x5358f0))\n data= f.read(0x100)\n print('0x5358f0 - 0x5359f0:')\n for i in range(0, 0x100, 16):\n h =' '.join(f'{b:02x}' for b in data[i:i+16])\n a = ''.join(chr(b) if 32 <= b< 127 else '.' for bin data[i:i+16])\nprint(f' {0x5358f0+i:08x}: {h:<48} {a}')\n\"\n"}
Tool result
{"exitCode":0,"stdout":"0x5358f0 - 0x5359f0:\n 005358f0: 48 14 b2 01 a1 5c b8 55 00 e8 66 71 02 00 8b 45 H....\\.U..fq...E\n 00535900: f4 8b 40 24 d1 f8 79 03 83 d0 00 83 e8 20 50 6a ..@$..y...... Pj\n 00535910: 32 6a 40 6a 40 8b 45 f0 8b 40 14 50 6a 00 6a 00 2j@j@.E..@.Pj.j.\n 00535920: 8b 45 f4 8b 48 14 b2 01 a1 d0 b5 55 00 e8 66 b3 .E..H......U..f.\n 00535930: 02 00 6a 10 6a 78 8b 45 f4 8b 40 24 83 e8 20 50 ..j.jx.E..@$.. P\n 00535940: 8b 45 f4 8b 40 28 2d 2c 01 00 00 50 8b 45 f0 8b .E..@(-,...P.E..\n 00535950: 40 1c 50 6a 00 a1 78 0b 57 00 8b 00 50 8b 45 f4 @.Pj..x.W...P.E.\n 00535960: 8b 48 14 b2 01 a1 9c b4 55 00 e8 41 c8 02 00 c6 .H......U..A....\n 00535970: 80 a1 00 00 00 01 6a 10 68 e0 00 00 00 8b 45 f4 ......j.h.....E.\n 00535980: 8b 40 24 83 e8 20 50 6a 64 8b 45 f0 8b 40 20 50 .@$.. Pjd.E..@ P\n 00535990: 6a 00 a1 6c 12 57 00 8b 00 50 8b 45 f4 8b 48 14 j..l.W...P.E..H.\n 005359a0: b2 01 a1 9c b4 55 00 e8 04 c8 02 00 c6 80 a1 00 .....U..........\n 005359b0: 00 00 01 8b 45 f4 8b 40 24 d1 f8 79 03 83 d0 00 ....E..@$..y....\n 005359c0: 83 e8 32 50 8b 45 f4 8b 40 28 83 e8 32 50 6a 64 ..2P.E..@(..2Pjd\n 005359d0: 6a 16 68 30 5a 53 00 68 8c bc 55 00 6a 00 6a 00 j.h0ZS.h..U.j.j.\n 005359e0: 8b 45 f4 8b 48 14 b2 01 a1 b8 b2 55 00 e8 96 75 .E..H......U...u\n","stderr":""}Let me find and decompile the function at 0x4ed5c2 (push 0x7d context) which likely handles CMD=125 receive/send.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\ndef va2off(va):\n return 0x400 +(va - 0x401000)\n\nwithopen('/sandbox/FFG.exe','rb') as f:\n # Find function startbefore 0x4ed5c2\n f.seek(va2off(0x4ed400))\n data= f.read(0x300)\n base= 0x4ed400\n starts = []\n for i in range(len(data)-2):\n if data[i] == 0x55 and data[i+1] == 0x8B and data[i+2] == 0xEC:\n starts.append(base +i)\nprint('Function starts:', [hex(a)for ain starts])\n\"\n"}
Tool result
{"exitCode":0,"stdout":"Function starts: ['0x4ed42c', '0x4ed6a8']\n","stderr":""}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_004ed42c"}
Tool result
{"result":"\n/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */\n\nvoid FUN_004ed42c(int param_1,undefined4 param_2,undefined4 param_3,char param_4)\n\n{\n int iVar1;\n int *piVar2;\n char local_d;\n \n DAT_0057aa2c = param_1;\n iVar1 = FUN_0055e99c(*(int *)PTR_DAT_00570fe0,0x217,0x136,1,(longlong *)&DAT_004ed638);\n FUN_0055accc(*(int *)PTR_DAT_00570ddc,(longlong *)\"drag_onmouseup.wav\",0);\n piVar2 = FUN_005619d0((int *)PTR_PTR_0055b668,'\\x01',*(int *)(iVar1 + 0x14),0xfa,0,0xa7d0d4,\n *(int *)(iVar1 + 0x28) + -0x26,*(int *)(iVar1 + 0x24) + -0x10,0x1e,8);\n piVar2[0xf] = (int)&LAB_004eb830;\n FUN_005621b0((int *)PTR_PTR_0055b49c,'\\x01',*(int *)(iVar1 + 0x14),0,'\\0',\n *(int *)(*(int *)(DAT_0057aa2c + 0x1c) + 0x28),0x4b,0x15e,0x91,0x82);\n FUN_0055cf88((int *)PTR_PTR_0055b2b8,'\\x01',*(int *)(iVar1 + 0x14),(longlong *)0x0,0,0x55bc8c,\n (longlong *)&DAT_004ed670,0x16,100,*(int *)(iVar1 + 0x28) + -0x3e,\n *(int *)(iVar1 + 0x24) + -0x78);\n if (param_4 == '\\0') {\n FUN_0055cf88((int *)PTR_PTR_0055b2b8,'\\x01',*(int *)(iVar1 + 0x14),(longlong *)0x0,0,0x4ed374,\n (longlong *)&DAT_004ed680,0x16,100,*(int *)(iVar1 + 0x28) + -0x3e,\n *(int *)(iVar1 + 0x24) + -0xe1);\n if (((*(char *)(*(int *)(param_1 + 0x1c) + 0x69) == '\\0') &&\n (local_d = '\\x01', 0 < *(int *)(*(int *)(param_1 + 0x1c) + 0x3c))) &&\n ((float10)*(float *)(param_1 + 0x30) <\n _DAT_004ed68c * (float10)*(int *)(*(int *)(param_1 + 0x1c) + 0x3c))) {\n local_d = '\\0';\n }\n if (*(int *)(*(int *)(param_1 + 0x1c) + 0x14) == 500) {\n if (local_d == '\\0') {\n FUN_0055cf88((int *)PTR_PTR_0055b2b8,'\\x01',*(int *)(iVar1 + 0x14),(longlong *)0x0,1,\n 0x4eb470,(longlong *)&DAT_004ed6a0,0x16,100,*(int *)(iVar1 + 0x28) + -0x3e,0x14\n );\n }\n else {\n FUN_0055cf88((int *)PTR_PTR_0055b2b8,'\\x01',*(int *)(iVar1 + 0x14),(longlong *)0x0,1,\n 0x4eb470,(longlong *)&DAT_004ed6a0,0x16,100,*(int *)(iVar1 + 0x28) + -0x3e,0x7d\n );\n }\n }\n }\n return;\n}\n\n"}Let me check the remaining CMD=0x7d push locations more systematically.
Call sandbox_execute
Arguments
{"command":"python3 -c \"\ndef va2off(va):\n return 0x400 + (va - 0x401000)\n\nwith open('/sandbox/FFG.exe','rb') as f:\n for va in [0x004d28c8,0x00543138, 0x00544de3, 0x00548828, 0x005490a1]:\nf.seek(va2off(va-20))\n d = f.read(48)\nh = ' '.join(f'{b:02x}' for b in d)\n a = ''.join(chr(b) if 32 <=b <127 else '.' for b in d)\n print(f'{va:08x}: {h}')\n print(f' {a}')\n print()\n\"\n"}
Tool result
{"exitCode":0,"stdout":"004d28c8: ff 84 c0 74 28 a1 10 13 57 00 8b 00 8b 40 34 99 52 50 6a 00 6a 7d e8 01 af f9 ff 50 c1 f8 1f 3b c2 58 74 05 e8 6f 17 f3 ff 8b f0 eb 05 be 7d 00\n ...t(...W....@4.RPj.j}.....P...;.Xt..o........}.\n\n00543138: 6a 00 8b 45 f8 8b 48 14 b2 01 a1 b8 b2 55 00 e8 50 9e 01 00 6a 7d 8b 45 f8 8b 40 28 83 e8 2d 50 6a 64 6a 16 68 9c 32 54 00 68 54 c7 53 00 6a 69\n j..E..H......U..P...j}.E..@(..-Pjdj.h.2T.hT.S.ji\n\n00544de3: 40 1c e8 ba 47 ec ff 83 bd 90 fe ff ff 00 0f 95 c0 5a 88 02 6a 7d a1 b8 e1 57 00 8b 40 28 83 e8 2d 50 6a 64 6a 16 68 30 50 54 00 68 bc 33 54 00\n @...G............Z..j}...W..@(..-Pjdj.h0PT.h.3T.\n\n00548828: 00 50 8b 45 f4 8b 48 14 b2 01 a1 5c b8 55 00 e8 3c 42 01 00 6a 7d 8b 45 f4 8b 40 28 83 e8 2f 50 6a 64 6a 16 68 6c 8c 54 00 68 7c 60 54 00 68 2c\n .P.E..H....\\.U..<B..j}.E..@(../Pjdj.hl.T.h|`T.h,\n\n005490a1: 01 a1 b8 b2 55 00 e8 f0 3e 01 00 8b 15 1c e2 57 00 89 50 68 6a 7d 8b 45 f4 8b 40 28 83 e8 2f 50 6a 64 6a 16 68 c8 91 54 00 68 9c 5f 54 00 6a 00\n ....U...>......W..Phj}.E..@(../Pjdj.h..T.h._T.j.\n\n","stderr":""}FUN_004e6464 is the server-side handler. I need to find the client-side packet dispatch. Let me search for the client's CMD=120 receive handler.
Call sandbox_execute
Arguments
{"command": "python3 -c \"\n# Search forclient-side dispatch that handlesCMD=0x78(120) and 0x7d (125)\n# Pattern: cmp [reg+0x14], 0x78 orsimilar\n# Or look for all functions that reference field names from CMD=120 response\n\ndef va2off(va):\n return 0x400 + (va -0x401000)\n\nwith open('/sandbox/FFG.exe','rb') as f:\n text_data = f.read()\n\ntext_start_va = 0x401000\ntext_raw_off = 0x400\ntext_size = 0x169800\n\ntext = text_data[text_raw_off:text_raw_off+ text_size]\n\n# Search forpattern: mov eax, [reg+0x14] and cmpeax, 0x78\n# Pattern: 8B4? 14 (mov [e/r]cx, [reg+0x14])followed by comparison\nhits = []\nfori in range(len(text)-10):\n # Looking for:mov reg,[reg+0x14]thencompare to0x78\n b =text[i:i+3]\n if b[0]== 0x8Band (b[1]&0x40) == 0x40 and (b[1]& 0x07) !=0x04 and b[2] ==0x14:\n # Foundmov reg,[something+0x14]\n #Check if followed by cmp to 0x78 withinnext 20 bytes\n following = text[i+3:i+25]\n forj inrange(len(following)-1):\n if following[j] == 0x83and (following[j+1] & 0xF8)== 0xF8 and following[j+2] == 0x78:\n hits.append(text_start_va + i)\n break\n if following[j] == 0x3Dand following[j+1]== 0x78 and following[j+2:j+5] == b'\\\\x00\\\\x00\\\\x00':\n hits.append(text_start_va + i)\n break\n\nprint('Potential CMD dispatch locations:', [hex(a)for a in hits[:20]])\n\"\n"}
Tool result
{"exitCode":1,"stdout":"","stderr":"Traceback (most recent call last):\n File \"<string>\", line 29, in <module>\n if following[j] == 0x83 and (following[j+1] & 0xF8) == 0xF8 and following[j+2] == 0x78:\n ~~~~~~~~~^^^^^\nIndexError: index out of range\n"}Call sandbox_execute
Arguments
{"command":"python3 << 'EOF'\ndef va2off(va):\n return0x400 + (va - 0x401000)\n\nwith open('/sandbox/FFG.exe','rb') as f:\n text_data = f.read()\n\ntext_raw_off= 0x400\ntext_size = 0x169800\ntext_start_va = 0x401000\ntext =text_data[text_raw_off:text_raw_off + text_size]\n\nhits =[]\nfor i in range(len(text)-25):\n b0, b1, b2 = text[i], text[i+1], text[i+2]\n # mov reg, [reg+0x14]\n if b0== 0x8B and (b1 & 0xC7) ==0x47and b2 == 0x14:\n following = text[i+3:i+23]\n for jin range(len(following)-2):\n if following[j] == 0x83 and following[j+2] == 0x78:\n hits.append(text_start_va + i)\n break\n\nprint('CMD dispatchlocations:', [hex(a) for a in hits[:20]])\n\n# Also search forthe string \"fishid=\" xrefto find the CLIENT receive handler\n# The client would parse fishid= from incoming CMD=120from server\n# \"fishid=\" is at 0x4e9f50\n# Let'sfind xrefs \ntarget_addr =0x4e9f50 # \"fishid=\" in CMD=120 builder\ntarget_bytes_le =target_addr.to_bytes(4, 'little')\npositions= []\nfor i in range(len(text)-3):\n if text[i:i+4] == target_bytes_le:\npositions.append(text_start_va + i)\n\nprint('Refs to 0x4e9f50 (fishid= in CMD=120builder):', [hex(p) for pin positions])\nEOF\n"}
Tool result
{"exitCode":0,"stdout":"CMD dispatch locations: []\nRefs to 0x4e9f50 (fishid= in CMD=120 builder): ['0x4e9e70']\n","stderr":""}Let me find the client-side CMD=125 handler by searching for references to "oid=" used in parsing.
Call ghidra_get_xrefs_to
Arguments
{"filepath": "/sandbox/FFG.exe", "address": "0x004e73cc"}
Tool result
{"result":["From 004e68cd in FUN_004e6464 [DATA]"]}Call ghidra_list_strings
Arguments
{"filepath": "/sandbox/FFG.exe", "filter": "oid="}
Tool result
{"result":["00534cd4: \"fishoid=\"","00536738: \"fishoid=\"","0053692c: \"fishoid=\"","00537530: \"fishoid=\""]}Let me trace back from FUN_0052162c to understand when CMD=120 is received client-side.
Call ghidra_get_function_xrefs
Arguments
{"filepath": "/sandbox/FFG.exe", "name":"FUN_0052162c"}
Tool result
{"result":["From 00518c6a in FUN_005170e4 [UNCONDITIONAL_CALL]"]}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_005170e4"}
Tool result
{"result":"Succeeded and the artifact is saved at /sandbox/ghidra/decompiled_0x5170e4.txt. Please find the table of contents below. \n[{'funcName': 'FUN_00405b24', 'lineNum': 134}, {'funcName': 'FUN_0052835c', 'lineNum': 142}, {'funcName': 'FUN_0053421c', 'lineNum': 149}, {'funcName': 'FUN_00569b08', 'lineNum': 158}, {'funcName': 'FUN_00569de0', 'lineNum': 160}, {'funcName': 'FUN_00569b08', 'lineNum': 161}, {'funcName': 'FUN_0041fa5c', 'lineNum': 163}, {'funcName': 'FUN_0041fa5c', 'lineNum': 164}, {'funcName': 'FUN_0041fb1c', 'lineNum': 167}, {'funcName': 'FUN_0041fb1c', 'lineNum': 169}, {'funcName': 'FUN_0041fb1c', 'lineNum': 171}, {'funcName': 'FUN_0041fb1c', 'lineNum': 175}, {'funcName': 'FUN_0041fb1c', 'lineNum': 178}, {'funcName': 'FUN_0041fb1c', 'lineNum': 181}, {'funcName': 'FUN_00478fe0', 'lineNum': 184}, {'funcName': 'FUN_00404184', 'lineNum': 187}, {'funcName': 'FUN_0055eb34', 'lineNum': 191}, {'funcName': 'FUN_004e2950', 'lineNum': 192}, {'funcName': 'FUN_00569708', 'lineNum': 194}, {'funcName': 'FUN_004053f8', 'lineNum': 197}, {'funcName': 'FUN_0055e264', 'lineNum': 198}, {'funcName': 'FUN_0055e264', 'lineNum': 199}, {'funcName': 'FUN_004d38d8', 'lineNum': 202}, {'funcName': 'FUN_0055eb34', 'lineNum': 207}, {'funcName': 'FUN_004e2950', 'lineNum': 208}, {'funcName': 'FUN_00569708', 'lineNum': 210}, {'funcName': 'FUN_004053f8', 'lineNum': 212}, {'funcName': 'FUN_0055e264', 'lineNum': 213}, {'funcName': 'FUN_0055e264', 'lineNum': 214}, {'funcName': 'FUN_004d38d8', 'lineNum': 217}, {'funcName': 'FUN_0055eb34', 'lineNum': 222}, {'funcName': 'FUN_004e2950', 'lineNum': 223}, {'funcName': 'FUN_0055e264', 'lineNum': 224}, {'funcName': 'FUN_004d38d8', 'lineNum': 228}, {'funcName': 'FUN_00569b08', 'lineNum': 233}, {'funcName': 'FUN_004099ec', 'lineNum': 234}, {'funcName': 'FUN_0040537c', 'lineNum': 235}, {'funcName': 'FUN_00469584', 'lineNum': 236}, {'funcName': 'FUN_00569a34', 'lineNum': 237}, {'funcName': 'FUN_00409dc4', 'lineNum': 238}, {'funcName': 'FUN_0040537c', 'lineNum': 239}, {'funcName': 'FUN_00469584', 'lineNum': 240}, {'funcName': 'FUN_00569b68', 'lineNum': 241}, {'funcName': 'FUN_00409ad8', 'lineNum': 242}, {'funcName': 'FUN_0040537c', 'lineNum': 243}, {'funcName': 'FUN_00469584', 'lineNum': 244}, {'funcName': 'FUN_00569da0', 'lineNum': 245}, {'funcName': 'FUN_004099ec', 'lineNum': 246}, {'funcName': 'FUN_0040537c', 'lineNum': 247}, {'funcName': 'FUN_00469584', 'lineNum': 248}, {'funcName': 'FUN_00569de0', 'lineNum': 249}, {'funcName': 'FUN_0040537c', 'lineNum': 250}, {'funcName': 'FUN_00469584', 'lineNum': 251}, {'funcName': 'FUN_00569de0', 'lineNum': 252}, {'funcName': 'FUN_0040537c', 'lineNum': 253}, {'funcName': 'FUN_00469584', 'lineNum': 254}, {'funcName': 'FUN_00569d14', 'lineNum': 255}, {'funcName': 'FUN_0040b75c', 'lineNum': 257}, {'funcName': 'FUN_0040537c', 'lineNum': 258}, {'funcName': 'FUN_00469584', 'lineNum': 259}, {'funcName': 'FUN_004d99d8', 'lineNum': 263}, {'funcName': 'FUN_004d81a4', 'lineNum': 267}, {'funcName': 'FUN_004ddaa0', 'lineNum': 271}, {'funcName': 'FUN_004dd144', 'lineNum': 275}, {'funcName': 'FUN_004dd504', 'lineNum': 279}, {'funcName': 'FUN_004dd9d0', 'lineNum': 283}, {'funcName': 'FUN_004dd77c', 'lineNum': 287}, {'funcName': 'FUN_004dd334', 'lineNum': 291}, {'funcName': 'FUN_004dd264', 'lineNum': 295}, {'funcName': 'FUN_004dd504', 'lineNum': 299}, {'funcName': 'FUN_004dcfa4', 'lineNum': 303}, {'funcName': 'FUN_004dde7c', 'lineNum': 307}, {'funcName': 'FUN_004d8e30', 'lineNum': 311}, {'funcName': 'FUN_004df2bc', 'lineNum': 315}, {'funcName': 'FUN_004df3e4', 'lineNum': 319}, {'funcName': 'FUN_00569708', 'lineNum': 325}, {'funcName': 'FUN_004c7ab0', 'lineNum': 326}, {'funcName': 'FUN_0055e264', 'lineNum': 327}, {'funcName': 'FUN_0055e264', 'lineNum': 328}, {'funcName': 'FUN_00569678', 'lineNum': 332}, {'funcName': 'FUN_0055fc34', 'lineNum': 334}, {'funcName': 'FUN_0055eb88', 'lineNum': 335}, {'funcName': 'FUN_004099ec', 'lineNum': 336}, {'funcName': 'FUN_0040537c', 'lineNum': 337}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 338}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 339}, {'funcName': 'FUN_004099ec', 'lineNum': 340}, {'funcName': 'FUN_0040537c', 'lineNum': 341}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 342}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 343}, {'funcName': 'FUN_0055e264', 'lineNum': 345}, {'funcName': 'FUN_00569678', 'lineNum': 348}, {'funcName': 'FUN_0055fc34', 'lineNum': 350}, {'funcName': 'FUN_0055e264', 'lineNum': 352}, {'funcName': 'FUN_0055fc34', 'lineNum': 358}, {'funcName': 'FUN_00569708', 'lineNum': 362}, {'funcName': 'FUN_00569708', 'lineNum': 365}, {'funcName': 'FUN_0040ac40', 'lineNum': 368}, {'funcName': 'FUN_0055e264', 'lineNum': 370}, {'funcName': 'FUN_00569678', 'lineNum': 375}, {'funcName': 'FUN_0054bbe8', 'lineNum': 377}, {'funcName': 'FUN_0055fc34', 'lineNum': 380}, {'funcName': 'FUN_0055e264', 'lineNum': 382}, {'funcName': 'FUN_004099ec', 'lineNum': 385}, {'funcName': 'FUN_0040537c', 'lineNum': 386}, {'funcName': 'FUN_00469584', 'lineNum': 387}, {'funcName': 'FUN_0054bff0', 'lineNum': 391}, {'funcName': 'FUN_0055fc34', 'lineNum': 395}, {'funcName': 'FUN_0055accc', 'lineNum': 396}, {'funcName': 'FUN_004f7998', 'lineNum': 397}, {'funcName': 'FUN_0055fc34', 'lineNum': 401}, {'funcName': 'FUN_004f7188', 'lineNum': 402}, {'funcName': 'FUN_0055fc34', 'lineNum': 406}, {'funcName': 'FUN_004f7998', 'lineNum': 407}, {'funcName': 'FUN_0054c26c', 'lineNum': 412}, {'funcName': 'FUN_0054cc50', 'lineNum': 416}, {'funcName': 'FUN_0053f8f8', 'lineNum': 420}, {'funcName': 'FUN_0055eb34', 'lineNum': 421}, {'funcName': 'FUN_00533cd0', 'lineNum': 422}, {'funcName': 'FUN_00569678', 'lineNum': 423}, {'funcName': 'FUN_0054d53c', 'lineNum': 424}, {'funcName': 'FUN_00569678', 'lineNum': 425}, {'funcName': 'FUN_0054d520', 'lineNum': 426}, {'funcName': 'FUN_005335d0', 'lineNum': 427}, {'funcName': 'FUN_00569708', 'lineNum': 428}, {'funcName': 'FUN_00533644', 'lineNum': 429}, {'funcName': 'FUN_0054fcb8', 'lineNum': 431}, {'funcName': '(ram, 0x4e2268, 8)', 'lineNum': 432}, {'funcName': '(ram, 0x4e2268, 8)', 'lineNum': 433}, {'funcName': 'FUN_004e28e4', 'lineNum': 434}, {'funcName': 'FUN_004e2950', 'lineNum': 436}, {'funcName': 'FUN_004e28c8', 'lineNum': 438}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 439}, {'funcName': 'FUN_0053f288', 'lineNum': 440}, {'funcName': 'FUN_00533df8', 'lineNum': 446}, {'funcName': 'FUN_0053421c', 'lineNum': 453}, {'funcName': 'FUN_0054ce4c', 'lineNum': 461}, {'funcName': 'FUN_00569678', 'lineNum': 470}, {'funcName': 'FUN_00569b08', 'lineNum': 477}, {'funcName': 'FUN_00569b08', 'lineNum': 479}, {'funcName': 'FUN_00569b08', 'lineNum': 481}, {'funcName': 'FUN_00569b08', 'lineNum': 483}, {'funcName': 'FUN_00569b08', 'lineNum': 485}, {'funcName': 'FUN_00569b08', 'lineNum': 487}, {'funcName': 'FUN_004e46cc', 'lineNum': 491}, {'funcName': 'FUN_004e4678', 'lineNum': 493}, {'funcName': 'FUN_004e4720', 'lineNum': 495}, {'funcName': 'FUN_0046984c', 'lineNum': 497}, {'funcName': 'FUN_0046984c', 'lineNum': 498}, {'funcName': 'FUN_004099ec', 'lineNum': 499}, {'funcName': 'FUN_0040537c', 'lineNum': 500}, {'funcName': 'FUN_0046984c', 'lineNum': 501}, {'funcName': 'FUN_004099ec', 'lineNum': 502}, {'funcName': 'FUN_0040537c', 'lineNum': 503}, {'funcName': 'FUN_0046984c', 'lineNum': 504}, {'funcName': 'FUN_004099ec', 'lineNum': 505}, {'funcName': 'FUN_0040537c', 'lineNum': 506}, {'funcName': 'FUN_0046984c', 'lineNum': 507}, {'funcName': 'FUN_004099ec', 'lineNum': 508}, {'funcName': 'FUN_0040537c', 'lineNum': 509}, {'funcName': 'FUN_0046984c', 'lineNum': 510}, {'funcName': 'FUN_004099ec', 'lineNum': 511}, {'funcName': 'FUN_0040537c', 'lineNum': 512}, {'funcName': 'FUN_0046984c', 'lineNum': 513}, {'funcName': 'FUN_00569b08', 'lineNum': 514}, {'funcName': 'FUN_00569b08', 'lineNum': 516}, {'funcName': 'FUN_00569b08', 'lineNum': 518}, {'funcName': 'FUN_00569b08', 'lineNum': 520}, {'funcName': 'FUN_00569b08', 'lineNum': 522}, {'funcName': 'FUN_00569b08', 'lineNum': 524}, {'funcName': 'FUN_0046984c', 'lineNum': 526}, {'funcName': 'FUN_004099ec', 'lineNum': 527}, {'funcName': 'FUN_0040537c', 'lineNum': 528}, {'funcName': 'FUN_0046984c', 'lineNum': 529}, {'funcName': 'FUN_004099ec', 'lineNum': 530}, {'funcName': 'FUN_0040537c', 'lineNum': 531}, {'funcName': 'FUN_0046984c', 'lineNum': 532}, {'funcName': 'FUN_004099ec', 'lineNum': 533}, {'funcName': 'FUN_0040537c', 'lineNum': 534}, {'funcName': 'FUN_0046984c', 'lineNum': 535}, {'funcName': 'FUN_004099ec', 'lineNum': 536}, {'funcName': 'FUN_0040537c', 'lineNum': 537}, {'funcName': 'FUN_0046984c', 'lineNum': 538}, {'funcName': 'FUN_004099ec', 'lineNum': 539}, {'funcName': 'FUN_0040537c', 'lineNum': 540}, {'funcName': 'FUN_0046984c', 'lineNum': 541}, {'funcName': 'FUN_005245f4', 'lineNum': 545}, {'funcName': 'FUN_00569b08', 'lineNum': 549}, {'funcName': 'FUN_00554bd4', 'lineNum': 555}, {'funcName': 'FUN_0054ca20', 'lineNum': 561}, {'funcName': 'FUN_0054c674', 'lineNum': 565}, {'funcName': 'FUN_0054b774', 'lineNum': 569}, {'funcName': 'FUN_0054b664', 'lineNum': 573}, {'funcName': 'FUN_00539f2c', 'lineNum': 577}, {'funcName': 'FUN_0055fc34', 'lineNum': 582}, {'funcName': 'FUN_00536200', 'lineNum': 583}, {'funcName': 'FUN_00536178', 'lineNum': 587}, {'funcName': 'FUN_005391e4', 'lineNum': 591}, {'funcName': 'FUN_004eb1d0', 'lineNum': 595}, {'funcName': 'FUN_0054d254', 'lineNum': 600}, {'funcName': 'FUN_0054cee0', 'lineNum': 605}, {'funcName': 'FUN_0054d07c', 'lineNum': 609}, {'funcName': 'FUN_004f1bac', 'lineNum': 616}, {'funcName': 'FUN_004f68c8', 'lineNum': 621}, {'funcName': 'FUN_00569678', 'lineNum': 625}, {'funcName': 'FUN_00565310', 'lineNum': 626}, {'funcName': 'FUN_005695e4', 'lineNum': 627}, {'funcName': 'FUN_00469584', 'lineNum': 629}, {'funcName': 'FUN_005695e4', 'lineNum': 632}, {'funcName': 'FUN_00569678', 'lineNum': 638}, {'funcName': 'FUN_0054b4f0', 'lineNum': 639}, {'funcName': 'FUN_00565214', 'lineNum': 640}, {'funcName': 'FUN_004f694c', 'lineNum': 646}, {'funcName': 'FUN_004f31e8', 'lineNum': 652}, {'funcName': 'FUN_004eaf08', 'lineNum': 656}, {'funcName': 'FUN_004ea3e4', 'lineNum': 662}, {'funcName': 'FUN_004fa38c', 'lineNum': 669}, {'funcName': 'FUN_004f2ef8', 'lineNum': 673}, {'funcName': 'FUN_00535a38', 'lineNum': 680}, {'funcName': 'FUN_004f999c', 'lineNum': 686}, {'funcName': 'FUN_004f81b8', 'lineNum': 690}, {'funcName': 'FUN_004f9e98', 'lineNum': 696}, {'funcName': 'FUN_004f2888', 'lineNum': 703}, {'funcName': 'FUN_00520b80', 'lineNum': 708}, {'funcName': 'FUN_004d38d8', 'lineNum': 714}, {'funcName': 'FUN_0055accc', 'lineNum': 715}, {'funcName': 'FUN_00525944', 'lineNum': 721}, {'funcName': 'FUN_0054b6f4', 'lineNum': 725}, {'funcName': 'FUN_00569578', 'lineNum': 731}, {'funcName': 'FUN_00569708', 'lineNum': 736}, {'funcName': 'FUN_0040bce0', 'lineNum': 738}, {'funcName': 'FUN_00478f88', 'lineNum': 740}, {'funcName': 'FUN_0040d268', 'lineNum': 742}, {'funcName': 'FUN_0055accc', 'lineNum': 745}, {'funcName': 'FUN_00525990', 'lineNum': 753}, {'funcName': 'FUN_00526fd0', 'lineNum': 758}, {'funcName': 'FUN_00525a28', 'lineNum': 763}, {'funcName': 'FUN_005259dc', 'lineNum': 768}, {'funcName': 'FUN_005207f8', 'lineNum': 778}, {'funcName': 'FUN_00520988', 'lineNum': 782}, {'funcName': 'FUN_00520cb8', 'lineNum': 788}, {'funcName': 'FUN_00520a50', 'lineNum': 795}, {'funcName': 'FUN_00520540', 'lineNum': 801}, {'funcName': 'FUN_005208c0', 'lineNum': 807}, {'funcName': 'FUN_00569708', 'lineNum': 814}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 815}, {'funcName': '(unique, 0x17200, 4)', 'lineNum': 816}, {'funcName': 'FUN_0055e264', 'lineNum': 818}, {'funcName': 'FUN_0055fc34', 'lineNum': 819}, {'funcName': 'FUN_00522278', 'lineNum': 825}, {'funcName': 'FUN_0051fc30', 'lineNum': 830}, {'funcName': 'FUN_00521294', 'lineNum': 834}, {'funcName': 'FUN_00520eac', 'lineNum': 838}, {'funcName': 'FUN_00520f78', 'lineNum': 844}, {'funcName': 'FUN_0052162c', 'lineNum': 850}, {'funcName': 'FUN_00521958', 'lineNum': 854}, {'funcName': 'FUN_00522b94', 'lineNum': 860}, {'funcName': 'FUN_0054c3c0', 'lineNum': 867}, {'funcName': 'FUN_0053b4bc', 'lineNum': 868}, {'funcName': 'FUN_0055fc34', 'lineNum': 872}, {'funcName': 'FUN_00521958', 'lineNum': 873}, {'funcName': 'FUN_00535e84', 'lineNum': 874}, {'funcName': 'FUN_0054ccd8', 'lineNum': 878}, {'funcName': 'FUN_00569708', 'lineNum': 879}, {'funcName': 'FUN_00569678', 'lineNum': 883}, {'funcName': 'FUN_00542eec', 'lineNum': 884}, {'funcName': 'FUN_0054c3c0', 'lineNum': 890}, {'funcName': 'FUN_00543664', 'lineNum': 896}, {'funcName': 'FUN_00543538', 'lineNum': 900}, {'funcName': 'FUN_005445cc', 'lineNum': 906}, {'funcName': 'FUN_0052fb84', 'lineNum': 913}, {'funcName': 'FUN_0055e264', 'lineNum': 919}, {'funcName': 'FUN_004d96e8', 'lineNum': 924}, {'funcName': 'FUN_0054c830', 'lineNum': 928}, {'funcName': 'FUN_00542cac', 'lineNum': 929}, {'funcName': 'FUN_00535e84', 'lineNum': 933}, {'funcName': 'FUN_0054c698', 'lineNum': 937}, {'funcName': 'FUN_005429a8', 'lineNum': 938}, {'funcName': 'FUN_00542448', 'lineNum': 944}, {'funcName': 'FUN_005410d0', 'lineNum': 950}, {'funcName': 'FUN_00549858', 'lineNum': 954}, {'funcName': 'FUN_004d38d8', 'lineNum': 960}, {'funcName': 'FUN_0052f8d4', 'lineNum': 967}, {'funcName': 'FUN_0055e264', 'lineNum': 972}, {'funcName': 'FUN_0052feb4', 'lineNum': 976}, {'funcName': 'FUN_0052fc5c', 'lineNum': 982}, {'funcName': 'FUN_0052f6ec', 'lineNum': 988}, {'funcName': 'FUN_00530290', 'lineNum': 994}, {'funcName': 'FUN_00547b0c', 'lineNum': 1001}, {'funcName': 'FUN_00530f28', 'lineNum': 1006}, {'funcName': 'FUN_0052faf8', 'lineNum': 1010}, {'funcName': 'FUN_00530eec', 'lineNum': 1014}, {'funcName': 'FUN_0052fc20', 'lineNum': 1020}, {'funcName': 'FUN_005303a8', 'lineNum': 1026}, {'funcName': 'FUN_0055e264', 'lineNum': 1030}, {'funcName': 'FUN_0055fc34', 'lineNum': 1032}, {'funcName': 'FUN_00548d70', 'lineNum': 1038}, {'funcName': 'FUN_00569578', 'lineNum': 1046}, {'funcName': 'FUN_004d8c28', 'lineNum': 1048}, {'funcName': 'FUN_004e1f94', 'lineNum': 1049}, {'funcName': 'FUN_0055accc', 'lineNum': 1050}, {'funcName': 'FUN_00569578', 'lineNum': 1053}, {'funcName': 'FUN_004d8c28', 'lineNum': 1055}, {'funcName': 'FUN_004e1f94', 'lineNum': 1056}, {'funcName': 'FUN_0055accc', 'lineNum': 1058}, {'funcName': 'FUN_00569578', 'lineNum': 1061}, {'funcName': 'FUN_004d8c28', 'lineNum': 1063}, {'funcName': 'FUN_004e1f94', 'lineNum': 1064}, {'funcName': 'FUN_0055accc', 'lineNum': 1066}, {'funcName': 'FUN_00569578', 'lineNum': 1069}, {'funcName': 'FUN_004d8c28', 'lineNum': 1071}, {'funcName': 'FUN_004e1f94', 'lineNum': 1072}, {'funcName': 'FUN_0055accc', 'lineNum': 1074}, {'funcName': 'FUN_00569578', 'lineNum': 1077}, {'funcName': 'FUN_004d8c28', 'lineNum': 1079}, {'funcName': 'FUN_004e1f94', 'lineNum': 1080}, {'funcName': 'FUN_00569578', 'lineNum': 1083}, {'funcName': 'FUN_004d8c28', 'lineNum': 1085}, {'funcName': 'FUN_004e1f94', 'lineNum': 1086}, {'funcName': 'FUN_0055accc', 'lineNum': 1088}, {'funcName': 'FUN_0054a5a4', 'lineNum': 1092}, {'funcName': 'FUN_0054850c', 'lineNum': 1097}, {'funcName': 'FUN_0040548c', 'lineNum': 1103}, {'funcName': 'FUN_0055e264', 'lineNum': 1108}, {'funcName': 'FUN_0040548c', 'lineNum': 1110}, {'funcName': 'FUN_0055e264', 'lineNum': 1115}, {'funcName': 'FUN_0040548c', 'lineNum': 1117}, {'funcName': 'FUN_004d8c28', 'lineNum': 1119}, {'funcName': 'FUN_004e1f94', 'lineNum': 1120}, {'funcName': 'FUN_0055fc34', 'lineNum': 1122}, {'funcName': 'FUN_00569578', 'lineNum': 1128}, {'funcName': 'FUN_0055e264', 'lineNum': 1131}, {'funcName': 'FUN_00569578', 'lineNum': 1133}, {'funcName': 'FUN_0055e264', 'lineNum': 1136}, {'funcName': 'FUN_0055fc34', 'lineNum': 1138}, {'funcName': 'FUN_00569578', 'lineNum': 1145}, {'funcName': 'FUN_00569708', 'lineNum': 1147}, {'funcName': 'FUN_004053f8', 'lineNum': 1149}, {'funcName': 'FUN_004d8c28', 'lineNum': 1150}, {'funcName': 'FUN_004e1f94', 'lineNum': 1151}, {'funcName': 'FUN_00569708', 'lineNum': 1154}, {'funcName': 'FUN_004053f8', 'lineNum': 1156}, {'funcName': 'FUN_004d8c28', 'lineNum': 1157}, {'funcName': 'FUN_004e1f94', 'lineNum': 1158}, {'funcName': 'FUN_0054a2cc', 'lineNum': 1163}, {'funcName': 'FUN_005491e4', 'lineNum': 1169}, {'funcName': 'FUN_00404184', 'lineNum': 1173}, {'funcName': 'FUN_00405088', 'lineNum': 1175}, {'funcName': 'FUN_00405088', 'lineNum': 1176}, {'funcName': 'FUN_00405c40', 'lineNum': 1177}, {'funcName': 'FUN_004065d0', 'lineNum': 1178}, {'funcName': 'FUN_00405bf4', 'lineNum': 1179}, {'funcName': 'FUN_00405064', 'lineNum': 1180}, {'funcName': 'FUN_00405064', 'lineNum': 1181}]"}FUN_005170e4 is the client-side packet handler (calls FUN_0052162c at line 850). Let me search that artifact for CMD=120/125.
Call ghidra_search_artifact
Arguments
{"artifact_path": "/sandbox/ghidra/decompiled_0x5170e4.txt", "regex": "0x78|0x7d|cmd.*120|cmd.*125"}
Tool result
{"result":" FUN_004f7998(param_1[0xd]);\n break;\n case 0x69:\n *(int *)PTR_DAT_0057086c = *(int *)PTR_DAT_0057086c + -1;\n puStack_14 = &stack0xfffffffc;\n FUN_0054c26c(*(int *)PTR_DAT_00570c9c,param_1[0xd]);\n break;\n case 0x6a:\n puStack_14 = &stack0xfffffffc;\n FUN_0054cc50(*(int *)PTR_DAT_00570c9c,(int)param_1);\n break;\n case 0x6e:\n puStack_14 = &stack0xfffffffc;\n FUN_0053f8f8();\n FUN_0055eb34(*(int *)PTR_DAT_00570fe0);\n FUN_00533cd0(*(int *)PTR_DAT_00570c08,0xfa);\n uVar7 = FUN_00569678((int)param_1,0x519800);\n FUN_0054d53c(*(int *)PTR_DAT_00570c9c,uVar7);\n uVar7 = FUN_00569678((int)param_1,0x519810);\n FUN_0054d520(*(int *)PTR_DAT_00570c9c,uVar7);\n FUN_005335d0(*(int *)PTR_DAT_00570c08,*(int *)(*(int *)PTR_DAT_00570c9c + 0x78));\n FUN_00569708((int)param_1,0x519820,&local_1fc);\n FUN_00533644(*(int *)PTR_DAT_00570c08,*(int *)(*(int *)PTR_DAT_00570c9c + 0x3c),local_1fc)\n ;\n FUN_0054fcb8(*(int *)PTR_DAT_00570c84);\n func_0x004e2268(*(undefined4 *)(*(int *)PTR_DAT_00570d28 + 0x28));\n func_0x004e2268(*(undefined4 *)(*(int *)PTR_DAT_00570d28 + 0x2c));\n iVar8 = FUN_004e28e4(*(int *)PTR_DAT_00570b24);\n if (iVar8 != 3) {\n FUN_004e2950(*(int *)PTR_DAT_00570b24,3,extraout_ECX_04);\n }\n puVar5 = (undefined4 *)FUN_004e28c8(*(int *)PTR_DAT_00570b24);\n (**(code **)*puVar5)();\n FUN_0053f288();\n break;\n case 0x6f:\n puStack_14 = &stack0xfffffffc;\n if (*(int *)(*(int *)(*(int *)PTR_DAT_00570c08 + 0x10) + 0x24) != 0) {\n puStack_14 = &stack0xfffffffc;\n FUN_00533df8(*(int *)(*(int *)(*(int *)PTR_DAT_00570c08 + 0x10) + 0x20),(int)param_1);\n...\n FUN_0046984c(*(int *)PTR_DAT_00570b54,(int *)0x0,local_240);\n FUN_004099ec(*(uint *)(*(int *)PTR_DAT_00571180 + 0x58),(int *)&local_24c);\n FUN_0040537c(&local_248,(longlong *)&DAT_0051989c,local_24c);\n FUN_0046984c(*(int *)PTR_DAT_00570b54,(int *)0x0,local_248);\n break;\n case 0x74:\n puStack_14 = &stack0xfffffffc;\n FUN_005245f4((int)param_1);\n break;\n case 0x77:\n puStack_14 = &stack0xfffffffc;\n uVar4 = FUN_00569b08((int)param_1);\n **(undefined1 **)(*(int *)PTR_DAT_00570c84 + uVar4 * 4) = 0;\n if ((((*(char *)(*(int *)(*(int *)PTR_DAT_00570c84 + uVar4 * 4) + 0x2e) != '\\0') &&\n (*(char *)(*(int *)(*(int *)PTR_DAT_00570c84 + uVar4 * 4) + 0x2d) != '\\0')) &&\n (*(char *)(*(int *)(*(int *)PTR_DAT_00570c84 + uVar4 * 4) + 0x30) == '\\0')) &&\n (*PTR_DAT_00570c90 == '\\0')) {\n FUN_00554bd4(*(int *)(*(int *)PTR_DAT_00570c84 + uVar4 * 4),(int)param_1);\n }\n break;\n case 0x78:\n *(int *)PTR_DAT_0057086c = *(int *)PTR_DAT_0057086c + -1;\n puStack_14 = &stack0xfffffffc;\n FUN_0054ca20(*(int *)PTR_DAT_00570c9c,(int)param_1);\n break;\n case 0x7a:\n puStack_14 = &stack0xfffffffc;\n FUN_0054c674(*(int *)PTR_DAT_00570c9c,(int)param_1);\n break;\n case 0x7d:\n puStack_14 = &stack0xfffffffc;\n FUN_0054b774(*(int *)PTR_DAT_00570c9c,(int)param_1);\n break;\n case 0x7e:\n puStack_14 = &stack0xfffffffc;\n FUN_0054b664(*(int *)PTR_DAT_00570c9c,(int)param_1);\n break;\n case 0x82:\n puStack_14 = &stack0xfffffffc;\n FUN_00539f2c(0);\n break;\n case 0x84:\n case 0x85:\n puStack_14 = &stack0xfffffffc;\n FUN_0055fc34(*(int *)PTR_DAT_00570fe0,0);\n FUN_00536200((int)param_1);\n break;\n case 0x86:\n puStack_14 = &stack0xfffffffc;\n...\n else {\n puStack_14 = &stack0xfffffffc;\n if (iVar8 == 0x4b2) {\n puStack_14 = &stack0xfffffffc;\n FUN_0052fc5c(*(undefined4 *)PTR_DAT_00570924,(int)param_1);\n }\n }\n }\n else if ((iVar8 == 0x4e2) || (iVar8 == 0x4e7)) {\n puStack_14 = &stack0xfffffffc;\n FUN_0052f6ec(*(int **)PTR_DAT_00570924,(int)param_1);\n }\n else {\n puStack_14 = &stack0xfffffffc;\n if (iVar8 == 0x4ec) {\n puStack_14 = &stack0xfffffffc;\n FUN_00530290(*(undefined4 *)PTR_DAT_00570924,(int)param_1);\n }\n }\n }\n else if (iVar8 < 0x7d2) {\n if (iVar8 == 0x7d1) {\n puStack_14 = &stack0xfffffffc;\n FUN_00547b0c(*(int *)PTR_DAT_00570ed0,(int)param_1);\n }\n else if (iVar8 < 0x506) {\n if (iVar8 == 0x505) {\n puStack_14 = &stack0xfffffffc;\n FUN_00530f28(*(undefined4 *)PTR_DAT_00570924,(int)param_1,extraout_ECX);\n }\n else if (iVar8 == 0x4f7) {\n puStack_14 = &stack0xfffffffc;\n FUN_0052faf8(*(int *)PTR_DAT_00570924,(int)param_1);\n }\n else if (iVar8 == 0x500) {\n puStack_14 = &stack0xfffffffc;\n FUN_00530eec(*(undefined4 *)PTR_DAT_00570924,(int)param_1);\n }\n else {\n puStack_14 = &stack0xfffffffc;\n if (iVar8 == 0x502) {\n...\n uStackY_40 = uStackY_40 & 0xffffff;\n }\n cVar2 = FUN_00569578((int)param_1,0x519d10);\n if (cVar2 != '\\0') {\n iVar8 = FUN_004d8c28((int *)PTR_DAT_004d7ae4,'\\x01',(longlong *)&DAT_00519d20);\n FUN_004e1f94(*(int *)(*(int *)PTR_DAT_00570d28 + 0x30),iVar8);\n uStackY_40 = uStackY_40 & 0xffffff;\n }\n cVar2 = FUN_00569578((int)param_1,0x519d4c);\n if (cVar2 != '\\0') {\n iVar8 = FUN_004d8c28((int *)PTR_DAT_004d7ae4,'\\x01',(longlong *)&DAT_00519d60);\n FUN_004e1f94(*(int *)(*(int *)PTR_DAT_00570d28 + 0x30),iVar8);\n in_stack_ffffffd8 = (int *)0x50;\n FUN_0055accc(*(int *)PTR_DAT_00570ddc,(longlong *)\"error.wav\",0);\n uStackY_40 = uStackY_40 & 0xffffff;\n }\n if (uStackY_40._3_1_ != '\\0') {\n FUN_0054a5a4(*(undefined4 *)PTR_DAT_00570ed0,(int)param_1);\n }\n }\n else if (iVar8 == 0x7da) {\n puStack_14 = &stack0xfffffffc;\n FUN_0054850c(*(int *)PTR_DAT_00570ed0,(int)param_1);\n }\n else {\n bVar9 = iVar8 == 0x7ee;\n if (bVar9) {\n puStack_14 = &stack0xfffffffc;\n FUN_0040548c((char *)param_1[0xd],\"artremove_ok\");\n uVar10 = 0;\n if (bVar9) {\n uVar10 = 1;\n in_stack_ffffffd8 = (int *)0x518fdb;\n FUN_0055e264(*(int *)PTR_DAT_00570fe0,0x519ae4,(longlong *)0x0,0,'\\x02');\n }\n FUN_0040548c((char *)param_1[0xd],\"artremove_noall\");\n uVar11 = 0;\n if ((bool)uVar10) {\n in_stack_ffffffd8 = (int *)0x0;\n uVar11 = 1;"}Found it! Client dispatches CMD=120 → FUN_0054ca20, CMD=125 → FUN_0054b774. Let me decompile both.
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_0054ca20"}
Tool result
{"result":"\nvoid FUN_0054ca20(int param_1,int param_2)\n\n{\n bool bVar1;\n char cVar2;\n uint uVar3;\n undefined4 uVar4;\n int iVar5;\n undefined4 extraout_ECX;\n undefined4 extraout_ECX_00;\n undefined4 extraout_ECX_01;\n undefined4 extraout_ECX_02;\n undefined1 *extraout_ECX_03;\n undefined4 extraout_ECX_04;\n undefined4 *in_FS_OFFSET;\n undefined4 uStack_34;\n undefined1 *puStack_30;\n undefined1 *puStack_2c;\n longlong *local_28;\n longlong *local_24;\n int local_20;\n int local_1c;\n int *local_18;\n int local_14;\n int local_10;\n int local_c;\n int local_8;\n \n puStack_2c = &stack0xfffffffc;\n local_28 = (longlong *)0x0;\n local_24 = (longlong *)0x0;\n puStack_30 = &LAB_0054cc43;\n uStack_34 = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_34;\n local_c = param_2;\n local_8 = param_1;\n local_18 = FUN_004201a0((int *)PTR_DAT_0041fdd8,'\\x01',0);\n do {\n bVar1 = FUN_00569818(local_c);\n if (bVar1) {\n FUN_004205a8(*(int *)(local_8 + 0x14),'\\0',extraout_ECX_03);\n iVar5 = FUN_004202b4((int)local_18);\n if (-1 < iVar5 + -1) {\n local_10 = 0;\n local_20 = iVar5;\n do {\n local_14 = FUN_00420460((int)local_18,local_10);\n FUN_0041ff48(*(int *)(local_8 + 0x14),local_14,extraout_ECX_04,*(int *)(local_14 + 8),0);\n local_10 = local_10 + 1;\n local_20 = local_20 + -1;\n } while (local_20 != 0);\n }\n FUN_00404184(local_18);\n cVar2 = FUN_005365d0();\n if (cVar2 != '\\0') {\n FUN_00539f2c(0);\n }\n *in_FS_OFFSET = uStack_34;\n puStack_2c = &LAB_0054cc4a;\n puStack_30 = (undefined1 *)0x54cc42;\n FUN_00405088((int *)&local_28,2);\n return;\n }\n local_1c = FUN_00569b68(local_c);\n local_14 = FUN_00420090(*(int *)(local_8 + 0x14),0,extraout_ECX,local_1c,0);\n uVar4 = extraout_ECX_00;\n if (local_14 == 0) {\n local_14 = FUN_00404154((int *)PTR_DAT_0054accc,'\\x01',extraout_ECX_00);\n *(int *)(local_14 + 8) = local_1c;\n uVar4 = extraout_ECX_01;\n }\n FUN_0041ff48((int)local_18,local_14,uVar4,*(int *)(local_14 + 8),0);\n if ((int)DAT_0057e22c < 0) {\n if ((int)DAT_0057e22c >> 0x1f < 0) goto LAB_0054caca;\n }\n else if (DAT_0057e22c < local_1c + 1U) {\nLAB_0054caca:\n DAT_0057e22c = local_1c + 1;\n }\n *(uint *)(local_14 + 4) = DAT_0057e22c;\n uVar3 = FUN_00569b08(local_c);\n *(uint *)(local_14 + 0xc) = uVar3;\n uVar4 = FUN_0054daac(*(int *)PTR_DAT_00570ee0,*(int *)(local_14 + 0xc),extraout_ECX_02);\n *(undefined4 *)(local_14 + 0x14) = uVar4;\n FUN_0054e53c(*(int *)(local_14 + 0x14));\n uVar3 = FUN_00569b08(local_c);\n *(uint *)(local_14 + 0x18) = uVar3;\n uVar4 = FUN_00569b68(local_c);\n *(undefined4 *)(local_14 + 0x20) = uVar4;\n FUN_00569b08(local_c);\n FUN_00569b08(local_c);\n FUN_00569b08(local_c);\n bVar1 = FUN_00569a34(local_c);\n *(bool *)(local_14 + 0x10) = bVar1;\n bVar1 = FUN_00569a34(local_c);\n *(bool *)(local_14 + 0x3e) = bVar1;\n bVar1 = FUN_00569a34(local_c);\n *(bool *)(local_14 + 0x3c) = bVar1;\n FUN_00569de0(local_c,(int *)&local_24);\n FUN_004050b8((int *)(local_14 + 0x30),local_24);\n uVar3 = FUN_00569b08(local_c);\n *(uint *)(local_14 + 0x34) = uVar3;\n FUN_00569de0(local_c,(int *)&local_28);\n FUN_004050b8((int *)(local_14 + 0x38),local_28);\n } while( true );\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath":"/sandbox/FFG.exe", "name_or_address": "FUN_0054b774"}
Tool result
{"result":"\nvoid FUN_0054b774(int param_1,int param_2)\n\n{\n char cVar1;\n int iVar2;\n int iVar3;\n int *piVar4;\n undefined4 extraout_ECX;\n undefined4 extraout_ECX_00;\n undefined4 extraout_ECX_01;\n undefined4 extraout_ECX_02;\n undefined4 extraout_ECX_03;\n int *in_FS_OFFSET;\n int local_90;\n undefined4 local_8c;\n undefined1 local_88;\n int local_84;\n undefined1 local_80;\n uint local_7c;\n undefined1 local_78;\n longlong *local_74;\n int local_70;\n int local_6c;\n undefined4 local_68;\n undefined1 local_64;\n undefined4 local_60;\n undefined1 local_5c;\n int local_58;\n undefined1 local_54;\n int *local_50;\n undefined1 local_4c;\n undefined4 local_48;\n undefined1 local_44;\n int local_40;\n longlong *local_3c;\n undefined4 local_38;\n int local_34;\n int *local_30;\n uint local_2c;\n uint local_28;\n uint local_24;\n undefined1 local_1e;\n undefined1 local_1d;\n int local_1c;\n uint local_18;\n undefined4 local_14;\n uint local_10;\n int local_c;\n int local_8;\n \n local_74 = (longlong *)0x0;\n local_90 = 0;\n local_70 = 0;\n local_6c = 0;\n local_38 = 0;\n local_3c = (longlong *)0x0;\n iVar3 = *in_FS_OFFSET;\n *in_FS_OFFSET = (int)&stack0xffffff60;\n local_c = param_2;\n local_8 = param_1;\n local_10 = FUN_00569b08(param_2);\n local_14 = FUN_00569b68(local_c);\n local_18 = FUN_00569b08(local_c);\n local_24 = FUN_00569b08(local_c);\n local_30 = (int *)FUN_00569b08(local_c);\n local_1d = FUN_00569a34(local_c);\n local_28 = FUN_00569b08(local_c);\n local_1e = FUN_00569a34(local_c);\n local_2c = FUN_00569b08(local_c);\n FUN_00569de0(local_c,(int *)&local_3c);\n local_40 = FUN_004202b4(*(int *)(local_8 + 0x14));\n local_1c = 0;\n do {\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n if (*(uint *)(iVar2 + 4) == local_10) {\n local_34 = FUN_0054daac(*(int *)PTR_DAT_00570ee0,local_24,extraout_ECX);\n if (local_34 != 0) {\n local_68 = *(undefined4 *)(local_34 + 0x20);\n local_64 = 0;\n local_60 = *(undefined4 *)(local_34 + 0x18);\n local_5c = 0xb;\n piVar4 = local_30;\n FUN_005685b8(&local_6c,(int)local_30 >> 0x1f,extraout_ECX_00,(int)local_30,\n (int)local_30 >> 0x1f);\n local_58 = local_6c;\n local_54 = 0xb;\n local_50 = local_30;\n local_4c = 0;\n iVar3 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n local_48 = *(undefined4 *)(iVar3 + 0x30);\n local_44 = 0xb;\n FUN_0040ac40((byte *)\" %d | %s | %s | %d | %s\",&local_68,4,piVar4);\n FUN_0040537c(&local_70,*(longlong **)PTR_DAT_00570e18,(longlong *)\"FishLog.txt\");\n (**(code **)PTR_DAT_00570f04)();\n local_8c = *(undefined4 *)(local_34 + 0x18);\n local_88 = 0xb;\n iVar3 = (int)local_30 >> 0x1f;\n piVar4 = local_30;\n FUN_005685b8(&local_90,iVar3,extraout_ECX_01,(int)local_30,iVar3);\n local_84 = local_90;\n local_80 = 0xb;\n local_7c = local_28;\n local_78 = 0;\n FUN_0040ac40(&LAB_0054bb40,&local_8c,2,piVar4);\n iVar2 = FUN_004d8c28((int *)PTR_DAT_004d7ae4,'\\x01',local_74);\n FUN_004e1f94(*(int *)(*(int *)PTR_DAT_00570d28 + 0x28),iVar2);\n }\n FUN_0054e53c(local_34);\n FUN_00420160(*(int *)(local_8 + 0x14),local_1c,extraout_ECX_02,local_14,0);\n cVar1 = (**(code **)(**(int **)PTR_DAT_00570bb0 + 0x10))\n (*(int **)PTR_DAT_00570bb0,\"Options\",\"opensadok\",1);\n if (cVar1 == '\\0') {\n piVar4 = (int *)FUN_005455c8((int *)PTR_PTR_005450e4,'\\x01',local_24);\n FUN_00545398(*(int *)PTR_DAT_00571030,piVar4,extraout_ECX_03);\n }\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(int *)(iVar2 + 0x14) = local_34;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(uint *)(iVar2 + 0xc) = local_24;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(int **)(iVar2 + 0x18) = local_30;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(undefined4 *)(iVar2 + 8) = local_14;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(uint *)(iVar2 + 0x20) = local_18;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(undefined1 *)(iVar2 + 0x10) = local_1d;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(undefined1 *)(iVar2 + 0x3d) = 0;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(undefined1 *)(iVar2 + 0x3c) = local_1e;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n *(uint *)(iVar2 + 0x34) = local_2c;\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n FUN_004050b8((int *)(iVar2 + 0x38),local_3c);\n iVar2 = FUN_00420460(*(int *)(local_8 + 0x14),local_1c);\n FUN_005346e0(*(int *)PTR_DAT_00570b6c,iVar2);\n break;\n }\n local_1c = local_1c + 1;\n local_40 = local_40 + -1;\n } while (local_40 != 0);\n *in_FS_OFFSET = iVar3;\n FUN_00405064(&local_90);\n FUN_00405088((int *)&local_74,3);\n FUN_00405088((int *)&local_3c,2);\n return;\n}\n\n"}The client uses stream readers FUN_00569b08/FUN_00569b68. Let me verify these functions to understand binary vs text parsing.
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569b08"}
Tool result
{"result":"\nuint FUN_00569b08(int param_1)\n\n{\n byte bVar1;\n byte bVar2;\n byte bVar3;\n byte bVar4;\n \n bVar1 = FUN_00569a60(param_1);\n bVar2 = FUN_00569a60(param_1);\n bVar3 = FUN_00569a60(param_1);\n bVar4 = FUN_00569a60(param_1);\n return (uint)bVar1 << 0x18 | (uint)bVar2 << 0x10 | (uint)bVar3 << 8 | (uint)bVar4;\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569b68"}
Tool result
{"result":"\nvoid FUN_00569b68(int param_1)\n\n{\n byte bVar1;\n undefined4 *in_FS_OFFSET;\n undefined4 uStack_30;\n undefined1 *puStack_2c;\n undefined1 *puStack_28;\n undefined4 local_24 [2];\n uint local_1c;\n uint local_18;\n uint local_14;\n uint local_10;\n int local_8;\n \n puStack_28 = &stack0xfffffffc;\n local_24[0] = 0;\n puStack_2c = &LAB_00569d03;\n uStack_30 = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_30;\n local_8 = param_1;\n bVar1 = FUN_00569a60(param_1);\n local_1c = (uint)bVar1;\n local_18 = 0;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n bVar1 = FUN_00569a60(local_8);\n local_18 = local_18 << 8 | local_1c >> 0x18;\n local_1c = local_1c << 8 | (uint)bVar1;\n *in_FS_OFFSET = uStack_30;\n puStack_28 = &LAB_00569d0a;\n puStack_2c = (undefined1 *)0x569d02;\n local_14 = local_1c;\n local_10 = local_18;\n FUN_004065d0(local_24,(int)PTR_DAT_0046cb7c);\n return;\n}\n\n"}The stream readers read raw bytes big-endian (binary format). Let me check FUN_00569a60 (single byte reader) and FUN_00569de0 (string reader).
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569a60"}
Tool result
{"result":"\nundefined1 FUN_00569a60(int param_1)\n\n{\n undefined1 local_9;\n int local_8;\n \n local_8 = param_1;\n FUN_0041955c(*(int **)(param_1 + 0x14),&local_9,1);\n return local_9;\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569de0"}
Tool result
{"result":"\nvoid FUN_00569de0(int param_1,int *param_2)\n\n{\n undefined1 uVar1;\n int iVar2;\n undefined4 *in_FS_OFFSET;\n undefined4 uStack_2c;\n undefined1 *puStack_28;\n undefined1 *puStack_24;\n int local_1c;\n int local_18;\n longlong *local_14;\n short local_e;\n int *local_c;\n int local_8;\n \n puStack_24 = &stack0xfffffffc;\n local_14 = (longlong *)0x0;\n puStack_28 = &LAB_00569e7d;\n uStack_2c = *in_FS_OFFSET;\n *in_FS_OFFSET = &uStack_2c;\n local_c = param_2;\n local_8 = param_1;\n local_e = FUN_00569da0(param_1);\n if (local_e < 1) {\n FUN_00405064(local_c);\n }\n else {\n FUN_00405784((int *)&local_14,(int)local_e);\n local_1c = (int)local_e;\n if (0 < local_1c) {\n local_18 = 1;\n do {\n uVar1 = FUN_00569a60(local_8);\n iVar2 = thunk_FUN_00405508((int *)&local_14);\n *(undefined1 *)(iVar2 + -1 + local_18) = uVar1;\n local_18 = local_18 + 1;\n local_1c = local_1c + -1;\n } while (local_1c != 0);\n }\n FUN_004050b8(local_c,local_14);\n }\n *in_FS_OFFSET = uStack_2c;\n puStack_24 = &LAB_00569e84;\n puStack_28 = (undefined1 *)0x569e7c;\n FUN_00405064((int *)&local_14);\n return;\n}\n\n"}Let me check FUN_00569818 (EOF check) and FUN_00569a34 (bool reader) and FUN_00569da0 (length prefix reader).
Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569818"}
Tool result
{"result":"\nbool FUN_00569818(int param_1)\n\n{\n uint uVar1;\n uint uVar2;\n int extraout_EDX;\n int extraout_EDX_00;\n bool bVar3;\n \n uVar1 = (**(code **)**(undefined4 **)(param_1 + 0x14))();\n uVar2 = FUN_00419330(*(int **)(param_1 + 0x14));\n if (extraout_EDX_00 == extraout_EDX) {\n bVar3 = uVar1 <= uVar2;\n }\n else {\n bVar3 = extraout_EDX <= extraout_EDX_00;\n }\n return bVar3;\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569a34"}
Tool result
{"result":"\nbool FUN_00569a34(int param_1)\n\n{\n char cVar1;\n \n cVar1 = FUN_00569a60(param_1);\n return cVar1 != '\\0';\n}\n\n"}Call ghidra_decompile_function
Arguments
{"filepath": "/sandbox/FFG.exe", "name_or_address": "FUN_00569da0"}
Tool result
{"result":"\nundefined2 FUN_00569da0(int param_1)\n\n{\n undefined1 uVar1;\n undefined1 uVar2;\n \n uVar1 = FUN_00569a60(param_1);\n uVar2 = FUN_00569a60(param_1);\n return CONCAT11(uVar1,uVar2);\n}\n\n"}Let me check where FUN_004e9e08 is called to verify it's actually for CMD=120.
Call ghidra_get_function_xrefs
Arguments
{"filepath": "/sandbox/FFG.exe","name": "FUN_004e9e08"}
Tool result
{"result":["From 004e8d2b in FUN_004e8acc [UNCONDITIONAL_CALL]","From 004e85cd in FUN_004e8580 [UNCONDITIONAL_CALL]"]}Call ghidra_get_function_xrefs
Arguments
{"filepath": "/sandbox/FFG.exe", "name": "FUN_004e8580"}
Tool result
{"result":["From 004e665b in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6b09 in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6ba9 in FUN_004e6464 [UNCONDITIONAL_CALL]","From 004e6c4a in FUN_004e6464 [UNCONDITIONAL_CALL]"]}Now I have a clear picture. Let me check the format string at 0x54bb40 and also verify the CMD=120 client→server text fields.
Call sandbox_execute
Arguments
Inference interrupted by user.
