CreateRemoteThread - ERROR_ACCES_DENIED - c++

I think my code is finally working now. Only problem is that for some reason, even though I've opened the process with PROCESS_ALL_ACCESS, CreateRemoteThread throws back an error: ERROR_ACCESS_DENIED.
The error was retrieved with GetLastError and it spit out '5', which translates to ERROR_ACCESS_DENIED.
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
char* dllPath = "C:\\Users\\Kalist\\Desktop\\Projects\\DLL\\bin\\Debug\\DLL.dll";
char* ProcToInject = "calc.exe";
int main(){
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE procSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(procSnap == INVALID_HANDLE_VALUE){
std::cout << "Snapshot function failed" << std::endl;
}
DWORD procID = 0;
if(Process32First(procSnap, &pe32)){
do{
if(!strcmp(pe32.szExeFile, ProcToInject)){
procID = pe32.th32ProcessID;
break;
}
}while(Process32Next(procSnap, &pe32));
}
CloseHandle(procSnap);
if(procID != 0){
HANDLE procAccess = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
if(procAccess == NULL){
std::cout << "OpenProcess error: " << GetLastError() << std::endl;
}
LPVOID remoteString = (LPVOID)VirtualAllocEx(procAccess, NULL, strlen(dllPath)+1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if(remoteString == NULL){
std::cout << "VirtualAllocEx error: " << GetLastError() << std::endl;
}
bool memoryWritten = WriteProcessMemory(procAccess, (LPVOID)remoteString, dllPath, strlen(dllPath)+1, NULL);
if(memoryWritten == 0){
std::cout << "WriteProcessMemory error: " << GetLastError() << std::endl;
}
LPVOID getLibAdd = (LPVOID)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
if(getLibAdd == NULL){
std::cout << "GetProcAddress error: " << GetLastError() << std::endl;
}
HANDLE remoteThread = CreateRemoteThread(procAccess, NULL, 0, (LPTHREAD_START_ROUTINE)getLibAdd, (LPVOID)remoteString, 0, NULL);
if(remoteThread == NULL){
std::cout << "CreateRemoteThread error: " << GetLastError() << std::endl;
}
CloseHandle(procAccess);
}else{
std::cout << "Failed to retrieve procID" << std::endl;
}
}

You'll get this error when you attempt to call CreateRemoteThread from a 32 bit process, but where the target process is a 64 bit process. I'm betting that's what you are doing.
In order to inject into a 64 bit process, you need your injector process also to be 64 bit. And obviously, as I am sure you already know, the DLL that you inject must also be 64 bit.
For what it is worth, you don't need to ask for so much when you call OpenProcess. I believe that all you need is:
PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION
| PROCESS_VM_WRITE | PROCESS_VM_READ

The code, you have written, assumes that the process, the code is running on, the dll you are injecting, and the calc.exe are all the same bitness.
If this is not statisfied, the call to CreateRemoteThread will fail.
This is, due to a constraint of the lpStartAddress parameter.
The following Quote is from the CreateRemoteThread documentation
A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see ThreadProc.
The assumtion of the code is due, to the following:
The LoadLibraryA function is located at a different rva, when comparing x86 to x64, because a different Kernel32.dll file is loaded, when you have a x86 process vs a x64 process.
The different Kernel32.dll files are also loaded at a different base address, when comparing a x86 process to a x64 process.
The Address you get back, from GetProcAddr is rva + dll base address.
Currently I am programming an injector, which will be also capable of x86 to x64, and have verified, that all addresses, that are passed to CreateRemoteThread are in the scope, of the target process. Also I am opening the Process with PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_READ| PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION. But I still have this issue.
This is because, the pointer length, of x86 is 32-bit. The parameter lpStartAddress of CreateRemoteThread is a pointer though. This means, that you will never be able to call all functions of a x64 target, because the function pointer will be capped, to 32-bit.
That in turn means that you can call at most all function inside the x86 addressable region, from a x86 process, in a x64 target process.

Related

Executable "C:\Windows\System32\Fodhelper.exe" not found

I am trying to start the above builtin Windows executable from within a C++ program. Firstly I can confirm that the program does exist, at the path "C:\Windows\System32\fodhelper.exe"
I have tried 3 different methods for running this program:
System()
ShellExecuteW()
CreateProcessW()
None of these methods work. The error I receive is: The system cannot find the file specified.
Due to the fact that I can start this executable as my usual Windows account from the start menu, run box and from within Windows explorer, i believe that my user account does have the privileges to run the program. Also, I am not receiving an access denied error from my code. Regardless, I have run VS as an Administrator and I have still experienced the same problem.
I believe the code I am using to start the process is correct, as the same code will start cmd.exe without issue. See below:
#include <Windows.h>
#include <tchar.h>
#include <iostream>
void CreateProcessMethod(LPCWSTR programPath) {
HRESULT result;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
ZeroMemory(&processInformation, sizeof(processInformation));
result = CreateProcessW(programPath, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &startupInfo, &processInformation);
if (result == 0) {
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
/* Display error */
std::wcout << programPath << " not started: " << buf << std::endl;
}
else {
std::wcout << programPath << " started successfuly" << std::endl;
}
}
void ShellExecuteMethod(LPCWSTR programPath) {
SHELLEXECUTEINFOW shExecInfo = { 0 };
shExecInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
shExecInfo.fMask = SEE_MASK_FLAG_NO_UI;
shExecInfo.hwnd = nullptr;
shExecInfo.lpVerb = L"open";
shExecInfo.lpFile = programPath;
shExecInfo.lpParameters = L"\\C";
shExecInfo.nShow = SW_SHOWNORMAL;
if (ShellExecuteExW(&shExecInfo) == 0)
{
if (GetLastError() != ERROR_CANCELLED) // Operation canceled by the user
{
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
/* Display error */
std::wcout << programPath << " not started: " << buf << std::endl;
}
}
else {
std::wcout << programPath << " started successfuly" << std::endl;
}
}
int main(){
CreateProcessMethod(L"C:\\Windows\\System32\\cmd.exe");
CreateProcessMethod(L"C:\\Windows\\System32\\fodhelper.exe");
ShellExecuteMethod(L"C:\\Windows\\System32\\cmd.exe");
ShellExecuteMethod(L"C:\\Windows\\System32\\fodhelper.exe");
}
See output of the program below:
Does anyone have any insight into what exactly I am doing wrong here? I cannot find any information that relates to this issue. Is far as I can understand, the code attempting to run the program is correct, works with different executables. This also occurs with three different methods. Any help would greatly be appreciated.
32-bit applications running on WOW64 will be put under file system redirection. Therefore if your app is a 32-bit one, the path C:\Windows\System32\fodhelper.exe will be redirected to C:\Windows\SysWOW64\fodhelper.exe which doesn't exist. You have some solutions:
Use SysNative to access the real system32 folder, which means you need to use something like system(R"(C:\Windows\SysNative\fodhelper.exe)");
Turn off file system redirection explicitly (should be avoided in general)
Or better compiling your exe as a 64-bit app.

Rangechecks out of range access - C++

So I'm trying to inject a debug dll on my test process that just says "hello world" upon being successfully injected:
PS: I'm using C++/CLI to launch my C++ script from an interface.
hello.dll
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
if (reason == DLL_PROCESS_ATTACH)
MessageBox(NULL, L"HELLO WORLD", L"INFO", NULL);
return TRUE;
}
Below is the part of my code which takes this dll, allocates memory in the target process, writes the dll path to the latter allocated space. LoadLibraryA is then called to run the DLL from the path. However when I attach my vstudio debugger to the target process while injecting the DLL it crashes at the LoadLibraryA function with an error:
ntldll.dll rangechecks out of range access
PSS: the callstack just contains ntdll.dll functions
Injection code:
char* dll_path = "C:/some_path/hello.dll";
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, NULL, debug_app_id);
HANDLE allocatedMemory = VirtualAllocEx(h_process, 0, MAX_PATH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(h_process, allocatedMemory, dll_path, strlen(dll_path) + 1, nullptr);
HANDLE h_thread = CreateRemoteThread(h_process, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, allocatedMemory, 0, 0);//crashes here
cout << "Success!" << endl;
cout << endl;
cout << "Cleaning..." << endl;
CloseHandle(h_process);//dropping process handle
VirtualFreeEx(h_process, allocatedMemory, NULL, MEM_RELEASE);//release pointed to memory
Any ideas?
EDIT: when I try to allocate the memory I get System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt
Thanks in advance.

Windows C++: Whats the fastest way to write a large file on a remote machine?

In our application we have to write large files (100 MBytes up to some GBytes) on remote machines (in the same LAN segement) frequently. This is the bottleneck of our application. Remote machines may be native Windows but also Linux machines using SMB.
We found that creating files first locally and then copying them using the Windows API function CopyFile is MUCH faster than using CreateFile directly with a UNC Path (or drive letter) targeting the remote machine. But still we have to do 2 writes which seems far from optimum.
Inspired by the first comments on this question i implemented the usage of FILE_FLAG_OVERLAPPED for CreateFile as discussed here and here:
HANDLE hToken;
auto openResult = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
if (!openResult)
{
gConsoleAndLog << "OpenProcessToken failed with err " << GetLastError() << std::endl;
}
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 3;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[1].Attributes = SE_PRIVILEGE_ENABLED;
tp.Privileges[2].Attributes = SE_PRIVILEGE_ENABLED;
if(! LookupPrivilegeValue(NULL, SE_MANAGE_VOLUME_NAME, &tp.Privileges[0].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_MANAGE_VOLUME_NAME failed with err " << GetLastError() << std::endl;
if (! LookupPrivilegeValue(NULL, SE_INCREASE_QUOTA_NAME, &tp.Privileges[1].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_INCREASE_QUOTA_NAME failed with err " << GetLastError() << std::endl;
if (! LookupPrivilegeValue(NULL, SE_ASSIGNPRIMARYTOKEN_NAME, &tp.Privileges[2].Luid))
gConsoleAndLog << "LookupPrivilegeValue SE_ASSIGNPRIMARYTOKEN_NAME failed with err " << GetLastError() << std::endl;
auto adjustResult = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
if (!adjustResult || GetLastError() != ERROR_SUCCESS)
{
gConsoleAndLog << "AdjustTokenPrivileges failed with err " << GetLastError() << std::endl;
}
else gConsoleAndLog << "AdjustTokenPrivileges SUCCESS" << std::endl;
In difference to the second post i can not set the privilege "SE_ASSIGNPRIMARYTOKEN_NAME" even when starting as administrator. I dont know if that makes a difference.
After opening the file with FILE_FLAG_NO_BUFFERING | FILE_FLAG_OVERLAPPED, the calculated size is pre allocated:
auto setFileErr = SetFilePointerEx(hFile, endPosition, NULL, FILE_BEGIN);
if (setFileErr == INVALID_SET_FILE_POINTER)
{
CPrintWithOSError(NULL, 0, "SetFilePointerEx FAILED");
return 1;
}
if (!SetEndOfFile(hFile))
{
CPrintWithOSError(NULL, 0, "SetEndOfFile FAILED");
return 1;
}
if (!SetFileValidData(hFile, endPosition.QuadPart))
{
CPrintWithOSError(NULL, 0, "SetFileValidData FAILED");
return 1;
}
That works for local drives but SetFileValidData fails on remote drives.
The call fails with windows error
1314 a required privilege is not held by the client
How can this be fixed?
What are other ways to do this?
Is there a
way to increase file buffering for appending writes using the WinAPI?
If you have access to the tifflib source code, you should be able to solve this by buffering data to be written to the output file until the buffer is full or the file is closed. A simple FILE * will do this, using setvbuf to set the buffer size to 1MB or so.

Mapping a 32 bit image to a 32 bit process from a 64 bit application

I'm trying to figure out a way to map (either through loadlibrary or preferably manually) a 32bit image (dll) into a 32bit process from a 64bit running application. Any ideas?
Currently, injection/mapping everything looks like it's working, but when testing with an empty dll that just creates a message box, it doesn't actually create the messagebox. The injection works fine when coming from a 32bit application.
Here is how I've tested with LoadLibrary
EnsureElevation( ); // ensures that we're run as admin and that we have debug privs
// messy code because it's test code
LPVOID LoadLib = ( LPVOID )GetProcAddress( GetModuleHandleA( "kernel32.dll" ), "LoadLibraryA" );
HANDLE Proc = OpenProcess( PROCESS_ALL_ACCESS, false, GetProcessID( L"target.exe" ) );
std::cout << Proc << '\n';
std::cout << "Proc Error: 0x" << std::hex << GetLastError( ) << '\n'; // 0x0
LPVOID RemoteString = VirtualAllocEx( Proc, NULL, strlen( R"(C:\Users\Username\Desktop\MessageBox.dll)" ), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE );
std::cout << RemoteString << '\n';
std::cout << "String Error: 0x" << std::hex << GetLastError( ) << '\n'; // 0x0
std::cout << WriteProcessMemory( Proc, RemoteString, R"(C:\Users\Username\Desktop\MessageBox.dll)", strlen( R"(C:\Users\Username\Desktop\MessageBox.dll)" ), NULL ) << '\n';
std::cout << "Write Error: 0x" << std::hex << GetLastError( ) << '\n'; // 0x0
std::cout << CreateRemoteThread( Proc, NULL, NULL, ( LPTHREAD_START_ROUTINE )LoadLib, ( LPVOID )RemoteString, NULL, NULL ) << '\n';
std::cout << "Create Error: 0x" << std::hex << GetLastError( ) << '\n'; // 0x0
when thread created inside wow64 process it anyway begin execute in 64bit mode - from LdrInitializeThunk inside 64-bit ntdll.dll.
inside this, when process is wow64, the Run64IfContextIs64 function is called - system try determinate - are thread must execute in native or wow64 context. this is done by checking tread start address - if it is within a native dll (currently this is ntdll.dll, wow64.dll, wow64win.dll, wow64cpu.dll ) - system run it in native (64 bit mode). call graph is
and in debugger we can see next debug print:
<pid>:<tid> Found inside *.dll
<pid>:<tid> InitialPC <rip> is within a native dll. Running native context unchanged.
special case is InitialPC was inside 64-bit kernel32.dll or 64-bit user32.dll (look for DllsToRemap ) - inside Run64IfContextIs64 called MapContextAddress64TO32 system check address inside native dll. in some case (say for DebugBreak) system try redirect this to 32bit kernel32.dll DebugBreak and execute in wow64 mode, but.. here bug - crashed. in most case - system redirect address from 64-bit kernel32.dll (or user32.dll ) to Wow64pBreakPoint (not exported function) inside wow64.dll. this function executed in native (64-bit mode) - call int 3 (breakpoint) if debugger attached. after this simply terminate thread. in debug output we can view
<pid>:<tid> InitialPC <rip> found in the space reserved for 64-bit kernel32.dll
this is however exactly your case - you pass address of LoadLibraryA inside 64-bit kernel32.dll. which of course is error.
otherwise (if PC not inside 64-bit module) - system execute this thread in wow64 context, what we and need here
<pid>:<tid> ThunkStartupContent64TO32: Original InitialPC <rip>, StartupAddress <eip>, Arg1 <pv>
<pid>:<tid> ThunkStartupContext64TO32: Thunking RTL user thread start
after BTCpuSimulate thread go to the LdrInitializeThunk from 32-bit ntdll.dll and execute as usual in wow64 context.
so we need instead address of LoadLibraryA inside 64-bit kernel32.dll got address of LoadLibraryW inside 32-bit kernel32.dll. however this task is not simply if try use only documented win32 api. i use for this ntdll api (and some of this not documented). however as is:
PVOID getRVA(PVOID Base, ULONG_PTR BaseAddress, PCSTR Name)
{
if (PIMAGE_NT_HEADERS32 pinth = (PIMAGE_NT_HEADERS32)RtlImageNtHeader(Base))
{
BaseAddress -= pinth->OptionalHeader.AddressOfEntryPoint;
DWORD Size, exportRVA;
if (PIMAGE_EXPORT_DIRECTORY pied = (PIMAGE_EXPORT_DIRECTORY)
RtlImageDirectoryEntryToData(Base, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &Size))
{
exportRVA = RtlPointerToOffset(Base, pied);
DWORD NumberOfFunctions = pied->NumberOfFunctions;
DWORD NumberOfNames = pied->NumberOfNames;
if (0 < NumberOfNames && NumberOfNames <= NumberOfFunctions)
{
PDWORD AddressOfFunctions = (PDWORD)RtlOffsetToPointer(Base, pied->AddressOfFunctions);
PDWORD AddressOfNames = (PDWORD)RtlOffsetToPointer(Base, pied->AddressOfNames);
PWORD AddressOfNameOrdinals = (PWORD)RtlOffsetToPointer(Base, pied->AddressOfNameOrdinals);
DWORD a = 0, b = NumberOfNames, o;
do
{
o = (a + b) >> 1;
int i = strcmp(RtlOffsetToPointer(Base, AddressOfNames[o]), Name);
if (!i)
{
DWORD Rva = AddressOfFunctions[AddressOfNameOrdinals[o]];
return (ULONG_PTR)Rva - (ULONG_PTR)exportRVA < Size ? 0 : RtlOffsetToPointer(BaseAddress, Rva);
}
0 > i ? a = o + 1 : b = o;
} while (a < b);
}
}
}
return 0;
}
PVOID GetWowLoadLibraryW()
{
PVOID pv = 0;
STATIC_OBJECT_ATTRIBUTES(oa, "\\KnownDlls32\\kernel32.dll");
HANDLE hSection;
if (0 <= ZwOpenSection(&hSection, SECTION_QUERY|SECTION_MAP_READ, &oa))
{
SECTION_IMAGE_INFORMATION sii;
if (0 <= ZwQuerySection(hSection, SectionImageInformation, &sii, sizeof(sii), 0))
{
PVOID BaseAddress = 0;
SIZE_T ViewSize = 0;
if (0 <= ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 0, 0, &ViewSize, ViewUnmap, 0, PAGE_READONLY))
{
__try {
pv = getRVA(BaseAddress, (ULONG_PTR)sii.TransferAddress, "LoadLibraryW");
} __except( EXCEPTION_EXECUTE_HANDLER) {
}
ZwUnmapViewOfSection(NtCurrentProcess(), BaseAddress);
}
}
NtClose(hSection);
}
return pv;
}
after this task became trivial:
if (PVOID wowLoadLibraryW = GetWowLoadLibraryW())
{
//PCWSTR szLibPath = ...
SIZE_T s = (wcslen(szLibPath) + 1) * sizeof(WCHAR);
if (HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, <pid>))
{
if (PVOID pv = VirtualAllocEx(hProcess, 0, s, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE))
{
if (WriteProcessMemory(hProcess, pv, szLibPath, s, 0))
{
if (HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, (PTHREAD_START_ROUTINE)wowLoadLibraryW, pv, 0, 0))
{
CloseHandle(hThread);
}
}
}
CloseHandle(hProcess);
}
}

How can I get the name of any process having a visible window - WinAPI?

I'm trying to get the name of processes which have a visible window. For example, if I have Chrome opened, I would like to get the string "chrome.exe", but I only get the init value "unknown" using the code below.
I read around it could be an access rights problem, can you suggest me how to change them in order to get the name of processes?
DWORD idProc = 0; //pointer to the process which created the window
DWORD idThread = GetWindowThreadProcessId(Wnd->get_handle(), &idProc);
Wnd->set_pid(idThread); //Wnd is an object of a class i created, to collect processes info
// Get a handle to the process.
TCHAR szProcessName[DEFAULT_BUFLEN] = TEXT("<unknown>");
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, idProc);
if (hProcess!=NULL) {
HMODULE hMod;
DWORD cbNeeded;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod),
&cbNeeded))
{
GetModuleBaseName(hProcess, hMod, szProcessName,
sizeof(szProcessName) / sizeof(TCHAR));
}
}
Wnd->set_processname(szProcessName);
CloseHandle(hProcess);
It works fine for some processes, but it doesn't for many others like Chrome, as I said.
EDIT: I forgot to say, I've just filtered visible windows, so suppose handles are what I need yet.
this question how get process name/path by ID - is many time already answered here.
if you need name only (but not full path) - you can use CreateToolhelp32Snapshot / Process32First / Process32Next
compare PROCESSENTRY32.th32ProcessID with your idProc and use PROCESSENTRY32.szExeFile.
alternate and more effective way use ZwQuerySystemInformation with SystemProcessInformation info class.compare SYSTEM_PROCESS_INFORMATION.UniqueProcessId with your idProc and use SYSTEM_PROCESS_INFORMATION.ImageName. really first way is shell over this method.
if you need not only name, but full path :
if you have SE_DEBUG_PRIVILEGE - you need enable it, open process with PROCESS_QUERY_LIMITED_INFORMATION (vista+) or PROCESS_QUERY_INFORMATION (xp/2003) and use ZwQueryInformationProcess with ProcessImageFileName (return path in NT form) or GetProcessImageFileName (internally it call ZwQueryInformationProcess(,ProcessImageFileName,))
or begin from vista - you can use ProcessImageFileNameWin32 (return win32-path) or QueryFullProcessImageName (again only documented thin shell over this way)
also begin from vista - most effective way query process full path (in NT form) - use ZwQuerySystemInformation with SystemProcessIdInformation info class. this way not require any privileges and open process
use GetProcessImageNamr API instead:
#include <iostream>
using namespace std;
#include <windows.h>
#include <Psapi.h>
#pragma comment(lib, "Psapi.lib")
int main()
{
DWORD dwProcessId;
DWORD dwThreadId ;
while(1)
{
Sleep(2000);
HWND hForg = GetForegroundWindow(); // to get the foreground windows' handle window
dwThreadId = GetWindowThreadProcessId(hForg, &dwProcessId); // getting the window's process ID
DWORD dwDesiredAccess =
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
bool bInheritHandle = false;
HANDLE hProcess = OpenProcess(dwDesiredAccess,
bInheritHandle, dwProcessId);
if(INVALID_HANDLE_VALUE == hProcess)
cout << "Failed to open process!" << endl;
HINSTANCE hMod = (HINSTANCE)GetWindowLongPtr(hForg, GWLP_HINSTANCE);
if(!hMod)
cout << "Null Module!" << endl;
char szModFileName[MAX_PATH] = "";
// never use this cause it won't get you what you want
// GetModuleFileNameEx(hProcess, hMod, szModFileName, MAX_PATH);
// use this
GetProcessImageFileName(hProcess, szModFileName, MAX_PATH);
CloseHandle(hProcess);
char szWindowName[MAX_PATH] = "";
GetWindowText(hForg, szWindowName, MAX_PATH);
cout << "Window Name: " << szWindowName << endl;
cout << "Created by: " << szModFileName << endl << endl;
}
cout << endl << endl << endl;
return 0;
}
don't use GetModuleFileNameEx but use GetProcessImageFileName