Deprecated: The behavior of unparenthesized expressions containing both '.' and '+'/'-' will change in PHP 8: '+'/'-' will take a higher precedence in /home/iano/public_html/tpforums-vb5/forum/includes/class_core.php on line 5842

PHP Warning: Use of undefined constant MYSQL_NUM - assumed 'MYSQL_NUM' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_ASSOC - assumed 'MYSQL_ASSOC' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: Use of undefined constant MYSQL_BOTH - assumed 'MYSQL_BOTH' (this will throw an Error in a future version of PHP) in ..../includes/init.php on line 165

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 588

PHP Warning: "continue" targeting switch is equivalent to "break". Did you mean to use "continue 2"? in ..../includes/functions_navigation.php on line 612

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../global.php(29) : eval()'d code(6) : eval()'d code on line 1

PHP Warning: Use of undefined constant misc - assumed 'misc' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant index - assumed 'index' (this will throw an Error in a future version of PHP) in ..../includes/class_bootstrap.php(1422) : eval()'d code(4) : eval()'d code on line 1

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6

PHP Warning: Use of undefined constant onlinestatusphrase - assumed 'onlinestatusphrase' (this will throw an Error in a future version of PHP) in ..../includes/class_core.php(4684) : eval()'d code on line 6
Reading memory in C++
Results 1 to 9 of 9

Thread: Reading memory in C++

  1. #1
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725

    Reading memory in C++

    Hi all,

    Don't currently have time for this as a video (may do tomorrow), but wanted to share it as I now have this knowledge, so what I've been working on lately is a C++ version of JAPI (hopefully), which I'm doing solely for the purpose of learning. I've never really used C++ that extensively, only to do some fundamental calculations and what not, but here is some code which may help some of you along:

    Code:
    // ConsoleApplication1.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <Windows.h>
    #include <string>
    #include <Psapi.h>
    
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv [])
    {
    	// First off we grab a handle to Tibia via FindWindow()
    	HWND hwnd = FindWindow(L"TibiaClient", NULL);
    	// Dump the handle to console
    	cout << "HWND: " << hwnd << endl;
    	// These variables are self explanitory except cbNeeded, which I still don't fully get... Ah well
    	DWORD cbNeeded;
    	DWORD processID;
    	DWORD address = 0x3BE1E0;
    	// This is the MODULES handle, for the Tibia.exe module in the Tibia process (long story, basically we get a window, find the process linked to it, find the modules in 
    	//the process, then we finally have the handle - which is also the base address!)
    	HMODULE hModule;
    	// Declare a wstring to hold the location of the Tibia client, bare in mind this won't always be the same, 32 bit will not have (x86)!
    	wstring fileName = L"C:\\Program Files (x86)\\Tibia\\Tibia.exe";
    	// A buffer to hold the value we read
    	int buffer;
    	// This gets the process ID of the process linked to the handle we obtained using FindWindow - Getting the ID from the window handle
    	GetWindowThreadProcessId(hwnd, &processID);
    	// Dump it to console
    	cout << "Process ID: " << processID << endl;
    	// This will get us a handle to the process itself, allowing us to enumerate it's modules!
    	HANDLE handle = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processID);
    	// Dump it to the console
    	cout << "Process Handle: " << handle << endl;
    	// Declare an array to store the modules in
    	HMODULE hMods[1024];
    	// Check the enumeration is legit (if the process doesn't exist or whatever, it will fail at this point!
    	if (EnumProcessModules(handle, hMods, sizeof(hMods), &cbNeeded))
    	{
    		// Inform the user that the enumeration worked fine, useful for debugging
    		cout << "Enumerated: " << "Success!" << endl;
    		// Cycle through the list of enumerations
    		for (int i = 0; i < (cbNeeded / sizeof(hwnd)); i++)
    		{
    			// Tell the user which cycle we are on, so we can monitor easily
    			cout << "Round " << i << ": ";
    			// Declare a TCHAR to hold the module name (szModName) of the required length
    			TCHAR szModName[MAX_PATH];
    			// If we can get the module file name, if the module denies us access it will fail here
    			if (GetModuleFileNameEx(handle, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
    			{
    				// Print the module name (stored as wstring, hence wcout instead of cout), and it's address from hMods
    				cout << "Module Name: ";
    				wcout << szModName;
    				cout << ". Entry Number: " << hMods[i];
    				// If the modules name is the same as the path we declared earlier then assign hModule to that module, and add the base address to the address to read.
    				if (szModName == fileName)
    				{
    					hModule = hMods[i];
    					address += (DWORD)hMods[i];
    				}
    
    			}
    			// Inform the user we finished the loop
    			cout << ". " << endl;
    		}
    		// Inform the user of the module handle (to confirm it is correct against the above list)
    		cout << "Module Handle: " << hModule << endl;
    	}
    	// Attempt to read memory, this will print 1 if success, 2 if failure
    	cout << "Read Success: " << ReadProcessMemory(handle, (void*)address, &buffer, sizeof(buffer), 0) << endl;
    	// Print the last error, incase of failure.
    	cout << "Last error: " << GetLastError() << endl;
    	// Print the data we read
    	cout << "Read: " << buffer << endl;
    	// Clean up a little
    	CloseHandle(handle);
    	// Inform the user that we've finished and wait for input.
    	cout << "End" << endl;
    	cin.get();
    	return 0;
    }
    Any comments or suggestions on how to make this easier are appreciated, I will make a tutorial about this tomorrow, explaining more as to why I took this route.

    Thanks

  2. #2
    Senior Member
    Join Date
    Sep 2007
    Posts
    230
    The cbNeeded parameter for EnumProcessModules is used to return the number of modules the function found, the actual value being the total number of bytes needed to store them all. So you can use this value to determine when the last module in your array is reached, as you did, and to determine whether your array was too small to contain all modules. You also shouldn't need to iterate through the array to find the main module, it should always be the first module in the array (at least based on reflection of the .NET Process.MainModule property which always returns the first module from EPM, so I assume it's pretty much guaranteed to be the case).

  3. #3
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Thanks mate, the main module is changed by teamviewer amongst some other desktop / env mods, so I keep searching for a way around that, I'm gonna implement this into a C# version soon though, to enum the modules and extract the correct one, then will probably implement to JAPI ��

    cheers, I really appreciate your help mate

  4. #4
    Senior Member
    Join Date
    Sep 2007
    Posts
    230
    Well just installed TeamViewer on a VM for some testing, didn't actually try a call to EPM but instead inspected the client's Process Environment Block from which EPM reads the modules list from and didn't see any changes made by TV itself. During an active session TV does inject a module into running processes, perhaps this is hooking EPM for some unknown reason. When it happens to you what is the first module anyway? And what version of Windows?

    Anyway if the PEB's modules list is left untouched you read it directly yourself with help from NtQueryProcessInformation to get its address. The PEB also includes an ImageBase field outside of the modules list which should point to the main module, calling GetModuleHandle with a NULL parameter actually returns this field. Speaking of GetModuleHandle you could also remote thread a call to it in the client process and get its return value from the thread's exit code, but this would of course have higher overhead.

    If for some reason the client executable isn't the main module and you have to enumerate them all I'd advise against verifying the file name, instead I would use information from the file version structure such as the product name or description. Alternatively you could verify both the client & version together by reading a version unique value from its memory, the version string used in the login screen about box is excellent for this and something I've used a number of times.

  5. #5
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Quote Originally Posted by Sketchy View Post
    Well just installed TeamViewer on a VM for some testing, didn't actually try a call to EPM but instead inspected the client's Process Environment Block from which EPM reads the modules list from and didn't see any changes made by TV itself. During an active session TV does inject a module into running processes, perhaps this is hooking EPM for some unknown reason. When it happens to you what is the first module anyway? And what version of Windows?

    Anyway if the PEB's modules list is left untouched you read it directly yourself with help from NtQueryProcessInformation to get its address. The PEB also includes an ImageBase field outside of the modules list which should point to the main module, calling GetModuleHandle with a NULL parameter actually returns this field. Speaking of GetModuleHandle you could also remote thread a call to it in the client process and get its return value from the thread's exit code, but this would of course have higher overhead.

    If for some reason the client executable isn't the main module and you have to enumerate them all I'd advise against verifying the file name, instead I would use information from the file version structure such as the product name or description. Alternatively you could verify both the client & version together by reading a version unique value from its memory, the version string used in the login screen about box is excellent for this and something I've used a number of times.
    So the exact issue I'm experiencing is when using SendMessage() to send shit to Tibia, it's not reacting. Something in TeamViewer is hooking user input and not forwarding it unless certain circumstances are met. I haven't invested the time with Spy++ to find out what the messages are or why they are being ignored, but basically what I'm currently doing is using Process.GetProcessesByName("Tibia")[0].MainModule.BaseAddress to get the base address, which is fine, and at first I thought maybe this was the issue, since TV injects, I thought it may direct all input at itself and take it upon itself to become the "main module"... I'll try get more info about this later, atm I'm working and busy as hell

  6. #6
    Member
    Join Date
    Feb 2009
    Posts
    76
    Quote Originally Posted by Sketchy View Post
    Well just installed TeamViewer on a VM for some testing, didn't actually try a call to EPM but instead inspected the client's Process Environment Block from which EPM reads the modules list from and didn't see any changes made by TV itself. During an active session TV does inject a module into running processes, perhaps this is hooking EPM for some unknown reason. When it happens to you what is the first module anyway? And what version of Windows?

    Anyway if the PEB's modules list is left untouched you read it directly yourself with help from NtQueryProcessInformation to get its address. The PEB also includes an ImageBase field outside of the modules list which should point to the main module, calling GetModuleHandle with a NULL parameter actually returns this field. Speaking of GetModuleHandle you could also remote thread a call to it in the client process and get its return value from the thread's exit code, but this would of course have higher overhead.

    If for some reason the client executable isn't the main module and you have to enumerate them all I'd advise against verifying the file name, instead I would use information from the file version structure such as the product name or description. Alternatively you could verify both the client & version together by reading a version unique value from its memory, the version string used in the login screen about box is excellent for this and something I've used a number of times.
    He can also do:

    mov eax, [fs:0x30] ; eax contains TEB.peb
    mov eax, [eax + 0xC] ; eax contains peb.ldr ( link to ldr structure http://undocumented.ntinternals.net/..._LDR_DATA.html)
    mov eax, [eax + 0x14] ; eax contains ldr.list ( link to list entry structure http://www.nirsoft.net/kernel_struct...BLE_ENTRY.html)

    now just loop by list and print it's modules / do whatever you want.

  7. #7
    Senior Member
    Join Date
    Sep 2007
    Posts
    230
    Yeah you can do that too, or you could also replace the last two instructions with mov eax, [eax + 0x8] to get the PEB.ImageBaseAddress field. This obviously needs to be executed within the client process though so it requires some form of injection, I'd only use it if you are completely injecting your program otherwise I'd stick with NtQueryProcessInformation which will work for processes created in suspension.

  8. #8
    Senior Member
    Join Date
    Jan 2008
    Location
    Cambridge, England
    Posts
    725
    Did some spy++Ing today to discover the lParam I was sending was invalid, fixed that and it appears to work either way now. Does anyone have a better understanding of what the lParam?

    thanks again

  9. #9
    Senior Member
    Join Date
    Jan 2012
    Posts
    417
    if you are talking about SendMessage, wparam and lparam depend on the message being sent. It seems a bitwise combination of some flags for the desired msg.

    Windows often makes it clear in the message description (just type its name in google and look in the windows link. ex: WM_CHAR, WM_KEYDOWN, WM_LBUTTONUP,...) with LOW, HIGH words in which you use the MakeParam function, i.e.,

    Code:
    IntPtr MakeParam(int low, int high)
    {
        return new IntPtr((low & 0xFFFF) | (high << 16));
    }
    reading Windows description and spying with Spy++ to see what is being sent (those especific flags), you can form the exact message.

    TibiaApi (farsa, maybe) made it in the http://code.google.com/p/tibiaapi/so...nHelper.cs#158

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •