There is a code that, for some reason which is incomprehensible to me, cannot find the necessary addresses.

bool CompareMask(const BYTE* pData, const BYTE* bMask, const char* szMask) { for(; *szMask; ++szMask, ++pData, ++bMask) if(*szMask == 'x' && *pData != *bMask) return NULL; return (*szMask) == NULL; } DWORD FindPattern(DWORD dwAddress, BYTE* bMask, char* szMask) { for(DWORD i = 0; i < 2048; i++) if(CompareMask((BYTE*)(dwAddress + i), bMask, szMask)) return (DWORD)(dwAddress + i); return NULL; } void ToolboxThread() { AllocConsole(); freopen("CONOUT$", "w", stdout); MEMORY_BASIC_INFORMATION mMemInfo; for(DWORD dwAddress = 0; dwAddress < 0x7FFFFFFF; dwAddress += 2048) { DWORD dwVirtualQuery = VirtualQuery((void*)dwAddress, &mMemInfo, 2048); if(dwVirtualQuery == ERROR_INVALID_PARAMETER || dwVirtualQuery == NULL) break; if(mMemInfo.Type == MEM_MAPPED) continue; if(!mMemInfo.Protect & (PAGE_GUARD | PAGE_NOCACHE | PAGE_NOACCESS)) { if(mMemInfo.Protect == PAGE_READONLY) { Offsets.Health = FindPattern(dwAddress, (PBYTE)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8C\x01\x00\x00\x00\x36\x65", "??????????????xxx???xx"); Offsets.Mana = FindPattern(dwAddress, (PBYTE)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8C\x02\x00\x00\x00\x37\x65", "??????????????xxx???xx"); Offsets.Vigor = FindPattern(dwAddress, (PBYTE)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8C\x04\x00\x00\x00\x39\x65", "??????????????xxx???xx"); } } } std::cout << Offsets.Health << std::endl << Offsets.Mana << std::endl << Offsets.Vigor << std::endl; } 

The address masks are correct. They were tested through OllyDbg. Interested in such a moment, why it does not work. Maybe I missed some important detail, because There are not enough resources on this topic in the network.

  • This is not a "cheat" forum! Here, as far as I know, you cannot discuss such things as modifications of the original client of the application (game), but if I am mistaken and can be, then I will tell you your mistake, it is obvious! - Duracell
  • @Duracell I am one of the developers of the game itself (namely, the only active server, because the game is 19 years old), you can find it here: github.com/OpenMeridian105/Meridian59 . We need an application for the implementation of streams, or rather to get HP, MP, VG from the game, but it is not necessary to write the SDK specifically for this purpose. - Purixi
  • Then I have a question, are these addresses exactly in the game client, inside the game module? Or is it necessary to look for dynamic memory? If dynamic - then the memory pages starting from 0x0 are not advisable, if the application is x86 architecture, it makes sense to start with 0x400000, then the step of iterating through virtual pages has a size of 0x2048 - it cannot be permanently 0x2048, they have a different size! Therefore, it happens to you as I believe the application crashes when searching for addresses. - Duracell
  • @Duracell, I did not quite understand about the modules, but the address itself is in the executable file of the game (meridian.exe). I also tried to look for 0x4096. This did not give any results, either crash or zeros. - Purixi
  • Start by dumping the data you are looking for into a file. Then look at the availability of the desired data in the file. Then put bryaku when searching at this address. And somewhere in this place you will be able to see what is really happening there. - Vladimir Martyanov

1 answer 1

This code should work 100% (provided that the mask and signature are 100% correct !!!).

 #include <Psapi.h> #pragma comment( lib, "Psapi.lib" ) bool bCompare(const BYTE* pData, const BYTE* bMask, const char* szMask) { for (; *szMask; ++szMask, ++pData, ++bMask) { if (*szMask == 'x' && *pData != *bMask) { return false; } } return (*szMask) == NULL; } DWORD findPattern(const BYTE* bMask, const char* szMask) { MODULEINFO moduleInf{}; if (GetModuleInformation(GetCurrentProcess(), GetModuleHandle(0), &moduleInf, sizeof(MODULEINFO)) == NULL) { return 0; } if ((DWORD)moduleInf.lpBaseOfDll == 0) { return 0; }; DWORD start = (DWORD)moduleInf.lpBaseOfDll; DWORD size = moduleInf.SizeOfImage; for (DWORD i = 0; i < size; i++) { if (bCompare((BYTE*)(start + i), bMask, szMask)) { return start + i; } } return 0; } 

I categorically do not advise to do with the help of plug-ins ollie and go signatures !!! Personally, I always do it manually, evaluating each instruction in the disassembler.

Use it like this:

DWORD healthAddress = findPattern((PBYTE)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8C\x01\x00\x00\x00\x36\x65", "??????????????xxx???xx");

UPD:

 DWORD findPattern(const TCHAR * moduleName, const BYTE * bMask, const char * szMask) { MODULEINFO moduleInf{}; if (GetModuleInformation(GetCurrentProcess(), GetModuleHandle(moduleName), &moduleInf, sizeof(MODULEINFO)) == NULL) { return 0; } if ((DWORD)moduleInf.lpBaseOfDll == 0) { return 0; }; DWORD start = (DWORD)moduleInf.lpBaseOfDll; DWORD size = moduleInf.SizeOfImage; for (DWORD i = 0; i < size; i++) { if (bCompare((BYTE*)(start + i), bMask, szMask)) { return (start + i); } } return 0; } 

Use it like this:

DWORD healthAddress = findPattern(_T("meridian.exe"), (PBYTE)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8C\x01\x00\x00\x00\x36\x65", "??????????????xxx???xx");

  • The signature was made by hand. I'll check now, thank you in advance. - Purixi 7:14 pm
  • Unhandled exception at 0x778f15ee in meridian.exe: 0xC0000005: Access violation reading location 0x01578000. - Purixi 7:27 pm
  • @Purixi - means the signature is not correct, as I understand the function goes beyond the limits of the game module and gets into the memory that is protected and it crashes with an error to the memory access - Duracell
  • The injector loads the module normally. It looks like the GetModuleInformation() function cannot access something: moduleInf {lpBaseOfDll=0xfffffefc SizeOfImage=3904910335 EntryPoint=0xfff58c34 } _MODULEINFO . This is what the debugger is connecting to the process. After that, the execution stops. - Purixi
  • @Purixi - of course, the address of the entry point of the dll and the size of its module are determined - this is not true, updated the code, try another search function, it sets exactly that module you need. - Duracell