Calling a function from another process - c++

I apologize in advance for my English :D
How can I call a function from a process, knowing the pointer to it?
I tried this:
Process.cpp:
DWORD pid;
HWND hwnd;
HANDLE phandle;
void Attach() {
hwnd = FindWindow(NULL, L"GTA:SA:MP");
if (!hwnd) {
cout << "Process is not found" << endl;
system("pause");
}
else if (hwnd) {
cout << "Process was successfully loaded" << endl;
GetWindowThreadProcessId(hwnd, &pid);
phandle = OpenProcess(PROCESS_VM_READ, 0, pid);
}
else
{
cout << "Error 0x01" << endl;
system("pause");
}
}
void GameText(const char* szText, int iTime, signed int iStyle)
{
typedef void(__stdcall* GameText_t)(const char*, int, signed int);
GameText_t pGameText = (GameText_t)((char*)phandle + 0x69F2B0);
return pGameText(szText, iTime, iStyle);
}
main.cpp:
int main()
{
std::cout << "Hello World!\n";
Attach();
GameText("~r~Test!", 1000, 5);
}
And I get the following exception:
An exception was thrown at the address 0x006EF7B6 in wh_mta.exe:
0xC0000005: access violation during execution at 0x006EF7B6.
Why is this happening? How can I call a function by its pointer through HANDLE?
P.S
Reading an integer through HANDLE works great.
int Read_Int(int address) {
int value;
ReadProcessMemory(phandle, (void*)address, &value, sizeof(value), 0);
return value;
}

Maybe 30 years ago that would have worked :D :D :D
Processes can't access each other's memory… Every process has their own image of the memory, so address 0xWHATEVER in a process does not contain the same data as 0xWHATEVER in another process!
You need to make a library or use some inter process communication (IPC).

What you are doing is adding the pointer to the HANDLE of the process. You need the address of the process in it's virtual address space. To do so, use EnumProcessModules andGetModuleFileNameEx to find the filename of the module with the function you want. (Could be an EXE or a DLL.) EnumProcessModules returns an array of HMODULES which are just addresses of module in the specified process's virtual address space. So loop through the array, then cast the HMODULE that you need to a PBYTE. Then, add the function pointer to it, then try to execute.
Also, according your code, you are going to execute the function in YOUR program. That's fine, just make sure that if it needs to run in the target program, you'll need to use CreateRemoteThread to run it there.

Related

Writing Memory to Process

I'm trying to write a float value into a video game emulator called Dolphin. I have a spread sheet of memory addresses for a specific game I'd like to be able to change the values at those address. Dolphin has a debug setting and i'm able to look at the games memory on the fly but whenever I try to run my program the value at the memory address does not change
#include <cstdlib>
#include <iostream>
#include <windows.h>
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
float newValue = 22;
HWND hWnd = FindWindow(0, "Dolphin 5.0-321");
if(hWnd == 0) {
cerr << "Cannot Find Window." << endl;
} else {
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if(!hProc) {
cerr << "Cannot Open Process." << endl;
} else {
int isSuccessful = WriteProcessMemory(hProc, (LPVOID)0x81118DF0, &newValue, (DWORD)sizeof(newValue), NULL);
if (isSuccessful) {
clog << "Process Memory Written." << endl;
} else {
cerr << "Cannot Write Process Memory." << endl;
}
CloseHandle(hProc);
}
}
return 0;
}
Dolphin in an emulator, if you're using it's debug function it may not be providing actual real memory addresses, but rather the addresses relative to the emulated system not your Windows operating system. Think of it kinda like a virtual machine, the dolphin emulator is running a guest operating system and you're writing to memory from the host Windows OS.
If you've located those addresses by reversing the game from the host OS then you can write to those addresses without much issue.
There is no guarantee that writing to the variables address will have the effect you're looking for, it's possible that it gets overwritten by some other code.
Lastly, if you have the correct address for the virtual memory of the dolphin process and you have tested that it changes correctly with a tool like Cheat Engine, the last problem that could arise is that you're not running your C++ project as administrator. Once doing so, it should work without issue.

Windows program entry point using EnumProcessModules returns unexpected value

I am running a simple app and trying to read a specific offset within it's memory using Window's PSAPI.
when I run my debugger, I get the real value of the memory address, and the relative one to my ".exe" entry point.
yet, when I run the following code, the base module I get as an entry point together with my offset yields a different address(it's wrong, and off by a few (hexa)demical points).
what might be the problem?
ReadMemory is a template for ReadProcessMemory
HWND WINDOW_HANDLE;
HANDLE PROC_HANDLE;
DWORD PROC_ID;
DWORD address;
SIZE_T bytesRead;
int InitReadMemory(const char* windowClass,const char* caption, DWORD addressOffset)
{
DWORD cbNeeded;
DWORD dwdResult;
HMODULE mainModule;
BOOL enumResult;
//Get the window handle
WINDOW_HANDLE = FindWindow(windowClass, NULL);
if(WINDOW_HANDLE == NULL)
{
//Window was not foud
return 10;
}
//Get the process ID
dwdResult = GetWindowThreadProcessId(WINDOW_HANDLE, &PROC_ID);
if(dwdResult==0)
{
//Getting Process ID failed
return 20;
}
//Open the process
PROC_HANDLE = OpenProcess(PROCESS_ALL_ACCESS, false, PROC_ID);
if(PROC_HANDLE==NULL)
{
//Process failed to open
return 30;
}
/*
*Get the Main Module-
*first entry in the returned HMODULE array from
*EnumProcessModules
*/
enumResult = EnumProcessModules(PROC_HANDLE, &mainModule, sizeof(HMODULE), &cbNeeded);
if(enumResult != 0)
{
//Failed enumerating process modules
return 40;
}
//offset the requested memory address from the application's base address
address = (DWORD)((UINT_PTR)mainModule + addressOffset);
#ifdef DEBUG
using namespace std;
char filenameBuffer[64]="";
string number;
stringstream stristream;
stristream << address;
stristream >> number;
cout << number << "\r\n" << endl;
GetModuleFileNameEx(PROC_HANDLE, mainModule , filenameBuffer, 256);
cout << (byte)ReadMemory<byte>() << "\r\n" << number << "\r\n" << filenameBuffer << endl;
system("PAUSE");
#endif
return 1;}
thank you in advance :)
P.S. I'm mostly just looking for pointers ...
bah dum tsss
Update:
apparently, checking for GetLastError value, EnumProcessModules prompts a 299 error code after it is done. and debugging shows that mainModule holds nothing... yet EnumProcessModules returns 0 as in "no errors".
yesterday, I managed to get it AND get GetModuleFileName to work propery(same code, only added GetLastError).
Apparently, my problem was that I was running the tests with the snippet
enumResult = EnumProcessModules(PROC_HANDLE, &mainModule, sizeof(HMODULE), &cbNeeded)
if(enumResult != 0)
{
//Failed enumerating process modules
return 40;
}
and a successful run of EnumProcessModules yields a nonzero result! (thus causing me some confusion and faulted my whole debugging process)
after I figured this detail out, I ran some old tests again and found out that my target process is 64 bit, while I was running a 32 bit application.
changed to 64bit and now it works like a charm

Crashing When Creating a Process

I am trying to use msdn function (CreateProcess) in C++ in order to run an application. I don't get any errors but when I run it, it crashes. What I did also notice it that it created a process, but it didn't run the text file it was supposed to.
My code:
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
void createPro ();
int main()
{
createPro();
}
void createPro () {
LPCTSTR lpApplicationName = "C:/Users/Andyy/Desktop/hello.txt";
LPSTARTUPINFO lpStartupInfo;
LPPROCESS_INFORMATION lpProcessInfo;
memset(&lpStartupInfo, 0, sizeof(lpStartupInfo));
memset(&lpProcessInfo, 0, sizeof(lpProcessInfo));
if (!CreateProcess(lpApplicationName,
NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
lpStartupInfo,
lpProcessInfo
)
) {
cout << "Failed to create process" << lpApplicationName << endl;
}
cout << "Program exec: " << lpApplicationName << endl;
}
It creates the process but it fails to run the text file and no errors showed in compilers. Thanks in advance.
Return error: Process returned -1073741819 (0xC0000005)
CreateProcess is used to create process objects from executable files. You are passing a text file which is not an executable file. Presumably you are actually trying to show the text file in the default text editor. Use ShellExecuteEx to do that.
Beyond that, you don't allocate the two structs that are needed in your call to CreateProcess. Instead you declare pointers to structs, and leave the pointer uninitialized. I expect that this is the cause of the access violation error 0xC0000005. For future reference, you would allocate and initialise these structs like so:
STARTUPINFO StartupInfo = { sizeof StartupInfo };
PROCESS_INFORMATION ProcessInfo = { 0 };
Then pass &StartupInfo and &ProcessInfo to CreateProcess. Of course, I'm just adding this advice for completeness. You'll be throwing away all the code relating to CreateProcess and calling ShellExecuteEx instead.

Inside exception handler, MessageBox() successfully returns IDOK but never shows

I'm using a self written exception class called windows_error that inherits from std::runtime_error, which I use to, well, properly handle unexpected errors from Windows API functions.
All the way on the bottom of the callstack, at the end of my WinMain function, I catch all windows_error exceptions that haven't been dealt with yet. I intend to handle them by display an error message right before the program terminates, like so:
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int winshow)
{
// Initialize result to EXIT_FAILURE in case the program terminates due to
// an exception.
int result = EXIT_FAILURE;
try {
result = sIRC()();
}
catch (windows_error &e) {
e.basicHandler();
}
return result;
}
The basicHandler member function looks like this:
void windows_error::basicHandler() const
{
std::wostringstream ss;
ss << L"An unexpected error has occurred in a Windows function.\n\n" \
L"Function " << m_api << L" was called by " << m_caller << L" in " << m_srcFile << L" at line " << m_srcLine << L". " \
L"It returned error " << m_error << L":\n\n" << m_errorMessage;
#ifdef _CONSOLE
std::wcout << L"\n" << ss.str();
#else
auto result = MessageBox(HWND_DESKTOP, ss.str().c_str(), L"Windows error!", MB_ICONERROR);
result = result; // I added this line so I can put a breakpoint in the debugger
#endif // _CONSOLE
}
When I started out with the program I'm working on, this worked beautifully. But now the program is starting to grow. While trying out new code I noticed the program seemed to terminate unexpectedly. By running it in the Visual C++ 2010 debugger, I noticed a windows_error exception being thrown. By stepping through the basicHandler function, I could see that the MessageBox function returns 1 (IDOK) without actually showing the message box...
What could cause this behavior?
I know my description is a little vague, but I have no idea what else to add... I couldn't find anything on MSDN that would suggest this behavior is even possible. There is no parent window handle I could pass to MessageBox, since they're all being destroyed during stack unwinding. I'm also positive that the stack is not unwound through a window procedure or any other Windows callback.
Any hint at all would be appreciated.
Raymond provided the hint I needed in his comment to my question. During stack unwinding the destructor of my user_interface class calls DestroyWindow on the window handle because it is still valid at that point. What I didn't know was that MessageBox interprets the resulting WM_QUIT message to close itself. I thought a message box had its own internal message queue?
I was able to fix my issue by modifying the destructor of my user_interface class.
It was:
if (_wnd)
DestroyWindow(_wnd);
I changed it to:
if (_wnd) {
DestroyWindow(_wnd);
MSG msg = MSG();
while (msg.message != WM_QUIT) {
GetMessage(&msg, 0, 0, 0);
}
}
This works, but seems a little ugly. Any suggestions to improve this?

Createprocess and 0xc0000142 error

i have the following test code:
#define CMDLINE ".\\dummyFolder\\dummyProc.exe op1 op2 op3"
int main(int argc, char **argv) {
STARTUPINFO info;
info.cb = sizeof(STARTUPINFO);
info.lpReserved = NULL;
info.cbReserved2 = 0;
info.lpReserved2 = NULL;
PROCESS_INFORMATION processInfo;
SECURITY_ATTRIBUTES procAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
SECURITY_ATTRIBUTES threadAttr;
procAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
procAttr.lpSecurityDescriptor = NULL;
procAttr.bInheritHandle = false;
bool handlersInheritable = true;
char cmdLine2[sizeof(CMDLINE)];
strcpy(cmdLine2, CMDLINE);
char AppName[sizeof(".\\dummyFolder\\dummyProc.exe")];
strcpy(AppName, ".\\dummyFolder\\dummyProc.exe");
if (CreateProcess(AppName, cmdLine2, &procAttr, &threadAttr,
handlersInheritable, 0, NULL, NULL, &info, &processInfo)) {
//::WaitForMultipleObjects(procQty, handlers, waitForAll, waitInterval);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
CloseHandle(info.hStdError);
CloseHandle(info.hStdInput);
CloseHandle(info.hStdOutput);
} else {
std::cout << "Returned: " << GetLastError() << std::endl;
}
std::cout << "Exiting main process" << std::endl;
return 0;
}
This is just a test code for creating processes in windows. The problem is that when i launch "dummyProc.exe" i get a 0xc0000142 error.
The process dummyProc.exe runs fine from the command line, but not from within the code.
Here's the dummyProc code if it helps:
int main(int argc, char **argv) {
std::cout << "Working!!!!" << std::endl << "Receivedi: " << std::endl;
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return 0;
}
So, any ideas?
The most obvious thing that char cmdLine2[sizeof(CMDLINE)]; declares a string of length equal to your machine's pointer size. You need to use strlen(CMDLINE)+1 instead. Likewise for appName.
Note that the first parameter to CreateProcess does not need to be writeable. Just pass the string literal directly to it. No need for appName variable.
As for lpCommandLine which does need to be writeable it's easiest to do it like this:
char cmdline[] = "op1 op2 op3";
That gives you a writeable buffer. Note that you do not need to repeat the executable file name.
Another problem is that you have not initialized all the parameters to CreateProcess. For example the STARTUPINFO struct has 19 fields and you initialize only 3. You should initialize all your structs to 0 and then fill out any fields you need to be non-zero. Like this:
STARTUPINFO info = { 0 };
Do this for all the structs you pass.
You can, and should, pass NULL for the lpProcessAttributes and lpThreadAttributes parameters.
This answer is to relate another cause for 0xc0000142 - placed here (even though another answer was accepted for this question) because there is very little useful information on the intertubes about this error - and a shocking lack of any useful information on the subject from Microsoft - and so someone's internet search may get them here. (Well, mine did.)
So: You can get The application was unable to start correctly (0xc0000142) on starting a process written in C++ where you access though a null pointer in a constructor of a static object. (In my case it was in an initializer of a constructor of a static object.)
Your hint to this will be an event in the application log (event id 1000 source "Application Error") which has lines similar to the following:
Faulting module name: unknown, version: 0.0.0.0, time stamp: 0x00000000
Exception code: 0xc0000005
Fault offset: 0x0000000000000000
0xc0000005 is access violation, of course, and the offset of 0 (actually anything less than 0x10000 is a reference through a null pointer.
Anyway, the surprising thing (to me) is that evaluating statics happens before the debugger can attach (!!) so launching it with ImageFileExecutionOptions set or even directly within Visual Studio doesn't let you debug this thing!!
(And then of course you won't find 0xc0000142 in any Microsoft documentation whatsoever. Well done, NT team!)