public static ReadString ( System.Int64 address, uint length = 32, int handle = -1 ) : string | ||
address | System.Int64 | |
length | uint | |
handle | int | |
return | string |
public static void ReadMemoryInternal(Process process, ReadMemoryResults results) { int currentAddress = process.MainModule.BaseAddress.ToInt32(); IntPtr ptr = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_WM_READ, false, process.Id); if (ptr == null) { return; } int processHandle = ptr.ToInt32(); currentAddress += (int)MemoryReader.TabsBaseAddress; currentAddress = MemoryReader.ReadInt32(currentAddress, processHandle); currentAddress = MemoryReader.ReadInt32(currentAddress + 0x24, processHandle); currentAddress = MemoryReader.ReadInt32(currentAddress + 0x10, processHandle); currentAddress = MemoryReader.ReadInt32(currentAddress + 0x10, processHandle); int tabsAddress = MemoryReader.ReadInt32(currentAddress + 0x30, processHandle); //first tab node address is tabsAddress + 0x24 int tabNodeAddress = MemoryReader.ReadInt32(tabsAddress + 0x24, processHandle); int tabCount = 0; //repeat until tab node address = 0x0 while (tabNodeAddress != 0x0) { tabCount++; //use 0x30 for longer name (possibly upto 30 bytes) //0x2C will use '...' for names longer than 15 chars int tabNamePointer = MemoryReader.ReadInt32(tabNodeAddress + 0x2C, processHandle); string tabName = MemoryReader.ReadString(tabNamePointer, 16, processHandle); int tabMessagesDataStructure = MemoryReader.ReadInt32(tabNodeAddress + 0x24, processHandle); bool serverLog = tabName == "Server Log"; // only read log messages from the server log; only read chat messages from other tabs IEnumerable <string> tabMessages = ReadTabMessages(processHandle, tabMessagesDataStructure); SearchChunk(tabMessages, results, !serverLog, serverLog); //next tab node pointer is current tab node address + 0x10 tabNodeAddress = MemoryReader.ReadInt32(tabNodeAddress + 0x10, processHandle); } }
// SPECIAL THANKS TO tony902304 FOR MAKING THIS POSSIBLE // // For the C client: Read the server log messages from the internal Tab Messages structure, rather than scanning the entire process memory // This results in significantly faster performance and eliminates duplicate message issues in Tibia's memory // The only pitfall is that the base address has to be updated whenever Tibia is updated // We leave the old "scan everything" option as a setting for when Tibia gets updated and the base address has not been found yet public static IEnumerable <string> ReadTabMessages(int processHandle, int tabMessagesDataStructure) { int tabMessageNodeAddress = MemoryReader.ReadInt32(tabMessagesDataStructure + 0x10, processHandle); int messageCount = 0; while (tabMessageNodeAddress != 0x0) { messageCount++; int tabMessageAddress = MemoryReader.ReadInt32(tabMessageNodeAddress + 0x4C, processHandle); //max message input is 255 characters, but the Advertising channel has 400+ character initial message string tabMessage = MemoryReader.ReadString(tabMessageAddress, 255, processHandle); if (tabMessage != null && tabMessage.Length > 5 && tabMessage[0].isDigit() && tabMessage[1].isDigit() && tabMessage[2] == ':' && tabMessage[3].isDigit() && tabMessage[4].isDigit()) { yield return(tabMessage); } //next tab messages node pointer is current tab messages node address + 0x5C tabMessageNodeAddress = MemoryReader.ReadInt32(tabMessageNodeAddress + 0x5C, processHandle); } yield break; }