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 archive_postsperpage - assumed 'archive_postsperpage' (this will throw an Error in a future version of PHP) in ..../archive/index.php on line 456
Reading memory in C++ [Archive] - Forums

PDA

View Full Version : Reading memory in C++



XtrmJash
07-13-2013, 11:30 PM
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:


// 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

Sketchy
07-14-2013, 01:24 PM
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).

XtrmJash
07-15-2013, 10:53 PM
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

Sketchy
07-16-2013, 02:32 PM
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.

XtrmJash
07-16-2013, 02:55 PM
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 :p

panqnik
07-17-2013, 08:29 AM
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/UserMode/Structures/PEB_LDR_DATA.html)
mov eax, [eax + 0x14] ; eax contains ldr.list ( link to list entry structure http://www.nirsoft.net/kernel_struct/vista/LDR_DATA_TABLE_ENTRY.html)

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

Sketchy
07-17-2013, 12:25 PM
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.

XtrmJash
07-17-2013, 04:36 PM
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

Blequi
07-17-2013, 05:26 PM
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.,



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/source/browse/branches/tibiaapi-current/trunk/tibiaapi/Objects/Client.LoginHelper.cs#158