   [ASM/Theoretic] Problem interpreting address from IDA
  Heya!In order to improve my knowledge in debuggin applications after compilation i decided to make a first step in finding the place where the score in Win7's Solitaire is stored. I found that it is a member of the class SolitaireGame which gets allocated dynamically so the address of it is not static. But ive found a static address like this:.data:01097074 ; class SolitaireGame * g_pSolitaireGame.data:01097074 ?g_pSolitaireGame@@3PAVSolitaireGame@@A dd ?.data:01097074 ; DATA XREF: ChangeAppearenceDialog::Show(void)+47r.data:01097074 ; ChangeAppearenceDialog::Show(void)+136r ...So i see 0x1097074 as the absolute address of g_pSolitaireGame. As i need the RVA for ReadProcessMemory ive looked for the imagebase and thats 0x1000000. That leads me to a RVA of 0x97074. Reading the value at that location gives me 0x30000. This address cannot be a pointer to SolitaireGame. From the name:.text:01006CC4 ; const SolitaireGame::`vftable'{for `CardSolver::ISolverGame'}I think SolitaireGame must have virtual functions. But [0x30000] gives me an address which is not within the accessible space of the process. So 0x30000 cannot be the pointer to SolitaireGame./Edit:Ok, i know now that it contains virtual functions, its no longer just a guess :P.text:0102EB08 ; public: virtual bool __thiscall SolitaireGame::SolverGameOnMoveComplete(class CardSolver::CTable *, struct CardSolver::SMove const &)What did i wrong?GreetingsPlerion[Edited by - Plerion on April 14, 2010 1:58:14 AM]
  Actually for ReadProcessMemory, you need to use the absolute address.  As far as I know, during runtime, you never have to do the RVA conversion.As for g_pSolitaireGame, it will probably go something like this:Code refers to some constant address (uninitialized static data section)Static memory either has uninitialized value or pointer to actual struct.Struct has pointer to vtable(s) along with other data.Vtable has array of function pointers, or zeros for pure virtuals.   ;  Yes, i was thinking of that to. I thought that 0x1097074 should be the absolute address of that, but reading at 0x1097074 returns an error with GetLastError set to:ERROR_PARTIAL_COPY299 (0x12B)Only part of a ReadProcessMemory or WriteProcessMemory request was completed.And dwBytesRead set to 0.   ;  Hm, I've never seen ERROR_PARTIAL_COPY before, and I've snooped a LOT of process memory...Try using VirtualQueryEx to see what the memory protection flags are on that block of memory (Virtual Memory comes in 4096-byte chunks which are 0x1000 aligned, so virtual query will return information about an entire range)You're only trying to read 4 bytes when reading that global, right?Unfortunately my memory reader app only works on 32-bit processes and I have the 64-bit version of Solitaire, so I can't try to find out what's up... :(   ;  You are actually using a debugger and not just static analysis, I hope. If you find the IDA one is a bit limiting (and it sometimes is) use ollydbg. Examine the memory layout of the program.Edit: If you're on a 64-bit machine then ollydbg won't work, use windbg instead.   ;  Yes, thats strange...MEMORY_BASIC_INFORMATION info;VirtualQueryEx(hProcess, (LPCVOID)OFS_CSOLITAIRE_GAME, &info, sizeof(info));std::cout << "Protection flags: " << std::hex << info.AllocationProtect << std::endl;DWORD g_SolitaireGame = 0;DWORD dwBytesRead = 0;if(FALSE == ReadProcessMemory(hProcess, (LPCVOID)OFS_CSOLITAIRE_GAME, &g_SolitaireGame, 4, &dwBytesRead)){std::cout << "Error reading memory at 0x" << std::hex << OFS_CSOLITAIRE_GAME << "! (" << GetLastError() << ")" << std::endl;std::cout << "Could read " << std::dec << dwBytesRead << " bytes!" << std::endl;std::cin.sync();std::cin.get();return 0;}I get PAGE_READONLY so that means that that page should be accessible for read, but ReadProcessMemory returns 0 with GetLastError() returnin 0x12B. And dwBytesRead is 0.   ;  oh, i forgot to start the debugger once in IDA to relocate the module base. Now its 0xC97074 and thats a working address! Learned something new :)   