GetFullPathName wont get DLL Path - c++

I am trying to load a DLL from resource and use SetWindowsHook to inject DLL to all Process GetFullPathName doesnt Seem to Work in this case, Now i am asking what would I do to get the DLL Path in this case, My code looks like this. I am new to using This and hence i cannot seem to get the DLL Path
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include "resource.h"
void ExtractnRun()
{
char* name = getenv("USERNAME");
char info[1500];
char aNewFile[1500];
sprintf(info,"C:\\Users\\%s\\AppData\\Local\\MicroSoftX",name);
//_mkdir(info);
if (CreateDirectoryA(info, NULL))
{
MessageBoxA(NULL, "Directory Created", "", MB_OK);
}
// Extract From Resource
HRSRC hrsrc = FindResource(0, MAKEINTRESOURCE(IDR_DLL21),"DLL2");
DWORD size = SizeofResource(0, hrsrc);
PVOID buff = LockResource(LoadResource(0, hrsrc));
DWORD dwBytesToWrite = (DWORD)strlen((char*)buff);
DWORD dwBytesWritten = 0;
sprintf(aNewFile, "C:\\Users\\%s\\AppData\\Local\\MicroSoftX\\mshelp.dll", name);
HANDLE hFile = CreateFileA(aNewFile, GENERIC_WRITE, 0, NULL,CREATE_ALWAYS ,FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile)
{
MessageBoxA(NULL, "File Created!", "", MB_OK);
}
/*FILE* f = fopen(aNewFile, "wb");
fwrite(buff,1,size,f);
fclose(f);
*/
if (WriteFile(hFile, buff, size, &dwBytesWritten, NULL))
{
MessageBoxA(NULL, "Data Written to DLL", "", MB_OK);
}
/*STARTUPINFOA si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
*/
char dll[MAX_PATH];
GetFullPathName((LPCSTR)hFile, MAX_PATH, dll, NULL); // Shows Error here Cannot get Full Path of DLL
printf("%s\n",dll);
HMODULE MYdll = LoadLibrary(dll);
if (MYdll == NULL)
{
printf("dll cannot be found!\n");
getchar();
printf("DLL : %s", MYdll);
}
HOOKPROC addr = (HOOKPROC)GetProcAddress(MYdll, "SayHelloWorld");
if (addr == NULL)
{
printf("Cannot find Address!\n");
getchar();
}
HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, MYdll, 0);
if (handle == NULL)
{
printf("Hook Failed!\n");
getchar();
}
printf("Program Hooked!\n");
getchar();
UnhookWindowsHookEx(handle);
//printf("%s\n",dll);
system("PAUSE");
}
int main()
{
ExtractnRun();
return 0;
}
The Exception Error i get looks like this :
Exception thrown at 0x7764171A (ntdll.dll) in ResourceExample.exe:
0xC0000005: Access violation reading location 0x0000009C.
If there is a handler for this exception, the program may be safely
continued.
What am I not getting correctly?

You can not pass the file handler to the "GetFullPahtName". It should be file name to find full path.
GetFullPathName((LPCSTR)hFile, MAX_PATH, dll, NULL);
Please refer the below link for more details.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa364963(v=vs.85).aspx

Related

Dll Injector not detecting Dll

I recently coded an injector where as long as the dll is in the same directory as the exe injector it will inject but even when the dLL is in the same path it still returns with the error file not found.
Very new to c++ so not exactly sure how to fix it, only this I know that the problem must lie in the dll_name
The c++ code is listed here
#include <Windows.h>
#include <string>
#include <thread>
#include <libloaderapi.h>
using namespace std;
void get_proc_id(const char* window_title, DWORD &process_id)
{
GetWindowThreadProcessId(FindWindow(NULL, window_title), &process_id); // Find Process ID by using title of window
}
void error(const char* error_title, const char* error_message)
{
MessageBox(NULL, error_message, error_title, NULL);
exit(-1);
//if error occurs output false
}
bool file_exists(string file_name) // Makes sure file exists
{
struct stat buffer;
return (stat(file_name.c_str(), &buffer) == 0);
//Information goes through buffer if = 0 , it worked
//Creates random buffer of stat sturc doesnt matter what goes in - making sure function is successful, gets info about file and checks if it workeed
}
int main()
{
DWORD proc_id = NULL;
char dll_path[MAX_PATH];
const char* dll_name = "TestDll2.dll"; //Name of Dll
const char* window_title = "Untitled - Paint"; //Must Match Title Name
if (!file_exists(dll_name));
{
error("file_exists", "File does not exist");
}
if (!GetFullPathName(dll_name, MAX_PATH, dll_path, nullptr))
{
error("GetFullPathName", "Failed to get full file path");
}
get_proc_id(window_title, proc_id);
if (proc_id == NULL)
{
error("get_proc_id", "Failed to get process ID");
}
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, NULL, proc_id);
if (!h_process)
{
error("OpenProcess", "Failed to open handle to process");
}
void* allocated_memory = VirtualAllocEx(h_process, nullptr, MAX_PATH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); //Calling Virutal Allocation, passing handle to process - reserving memory by going thru reserve and need to commit to it so we can write
if (!allocated_memory)
{
error("VirtualAllocEx", "Failed to allocate memory");
}
if (!WriteProcessMemory(h_process, allocated_memory, dll_path, MAX_PATH, nullptr)) // Write DLL path into the target program
{
error("WriteProcessMemory", "Failed to write process memory");
}
//If above works we call loadlibarya which is where the dll is stored
HANDLE h_thread = CreateRemoteThread(h_process, nullptr, NULL, LPTHREAD_START_ROUTINE(LoadLibraryA), allocated_memory, NULL, nullptr);
if (!h_thread)
{
error("CreateRemoteThread", "Failed to create remote thread");
}
CloseHandle(h_process);
VirtualFreeEx(h_process, allocated_memory, NULL, MEM_RELEASE);
MessageBox(0, "Successfully Injected!", "Sucess", 0);
} ```
Try to use C++ STL function or Windows native API:
#include <string>
#include <filesystem>
#include <Shlwapi.h>
#pragma comment(lib, "Shlwapi.lib")
bool IsExists(const std::string &FilePathName)
{
return std::filesystem::exists(FilePathName);
}
bool IsExists(const std::string &FilePathName)
{
return PathFileExistsA(FilePathName.c_str());
}
The file is being searched in the current directory, not in the directory of the exe file. These might not be the same. You have to find the path to the exe file in order to search for files in its directory. On Windows you could do something like this:
#include <psapi.h>
// ....
HANDLE Handle = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, GetCurrentProcessId() );
if ( Handle ) {
TCHAR buffer[MAX_PATH];
if ( GetModuleFileNameEx( Handle, 0, buffer, MAX_PATH ) ) {
std::filesystem::path exePath( buffer ); // TODO this might need encoding conversion
auto exeDir = exePath.parent_path();
auto dllPath = exeDir / "TestDll2.dll";
if ( std::filesystem::exists( dllPath ) ) {
// ...
}
}
}
You can also try GetProcessImageFileName if GetModuleFileNameEx does not work. Apparently it does not work in 32-bit applications on a 64-bit system (see comments in this answer).

Hook and unhook one file DLL

I try hook file DLL into console app. This code
#include "pch.h"
#include <vector>
#include <string>
#include <windows.h>
#include <Tlhelp32.h>
using std::vector;
using std::string;
int main(void)
{
while (true)
{
vector<string>processNames;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE hTool32 = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
BOOL bProcess = Process32First(hTool32, &pe32);
if (bProcess == TRUE)
{
while ((Process32Next(hTool32, &pe32)) == TRUE)
{
processNames.push_back(pe32.szExeFile);
if (strcmp(pe32.szExeFile, "ConsoleApplication4.exe") == 0)
{
char* DirPath = new char[MAX_PATH];
char* FullPath = new char[MAX_PATH];
GetCurrentDirectory(MAX_PATH, DirPath);
sprintf_s(FullPath, MAX_PATH, "%s\\..\\ConsoleApplication1\\ConsoleApplication1.dll", DirPath);
FILE *pFile;
if (fopen_s(&pFile, FullPath, "r") || !pFile)
{
OutputDebugString("[Hook] File name or file does not exist");
OutputDebugString(FullPath);
return -1;
}
fclose(pFile);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (!hProcess)
{
OutputDebugString("[Hook] Open process fail");
return -1;
}
//attach
LPVOID LoadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if (!LoadLibraryAddr)
{
OutputDebugString("[Hook] Load LoadLibraryA fail");
return -1;
}
LPVOID LLParam = (LPVOID)VirtualAllocEx(hProcess, NULL, strlen(FullPath), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!WriteProcessMemory(hProcess, LLParam, FullPath, strlen(FullPath), NULL))
{
OutputDebugString("[Hook] Write process fail");
return -1;
}
HANDLE hHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, LLParam, NULL, NULL);
if (!hHandle)
{
OutputDebugString("[Hook] Hooked fail");
return -1;
}
system("pause");
//detach
LoadLibraryAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "FreeLibrary");
if (!LoadLibraryAddr)
{
OutputDebugString("[Hook] Load FreeLibrary fail");
return -1;
}
hHandle = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, LLParam, NULL, NULL);
if (!hHandle)
{
OutputDebugString("[Hook] detach fail");
return -1;
}
CloseHandle(hProcess);
delete[] DirPath;
delete[] FullPath;
system("pause");
return 0;
}
}
}
CloseHandle(hTool32);
}
return 0;
}
I have some question for this:
- Why this code can not detach file dll ?
- Why I change LoadLibraryA -> LoadLibrary : load LoadLibrary fail ?
- Why I change LoadLibraryA -> LoadLibraryW : file dll no attach ?
- Code in Mutibyte run is good, but convert to Unicode, file dll no attach ?
Thanks,
The reason this works in multibyte but won't compile with unicode character set is because you're passing a regular c string which is a regular char array. When you set your build type to use multibyte LoadLibrary() resolves to the ansi version which is LoadLibraryA(). If you want to use Unicode in your project properties it will resolve to LoadLibraryW() and you will need to pass a unicode char array, typically wchar_t[].
Even while compiling in unicode mode, you can still call LoadLibraryA() and pass a c string but you must specifically call the A (ansi) version of the function rather than rely on the #ifdef preprocessor statements which resolve them for you.

CreateRemoteThread MessageBoxA causes remote process to crash

I made a simple program that calculates the RVA of the function MessaegBoxA in user32.dll and then adds that offset to the base loading address of the dll in the remote process's memory to get the address of the function MessageBoxA. I made a dummy program that outputs the address of the function in its memory using GetProcAddress and then implement my own function in my program to display the address it calculated for the same function in the remote process. They always match so I'm certain my function for finding the address of MessageBoxA in remote process's is not the problem.
I made a struct that contains all the necessary information and parameters needed for ThreadProc to execute MessageBoxA in the remote process once I load it using WriteProcessMemory.
typedef struct
{
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
_MessageBoxA MessageBoxA;
//These are the four parameters passed to MessageBoxA
HWND hwnd;
LPCSTR msg;
LPCSTR caption;
UINT mb;
}MB_DATA, *PMB_DATA;
When I try this on my own dummy program, the message box shows up but with weird text contrary to the strings I specified in the msg and caption members of MB_DATA. It says the following for the caption asic_string::erase and for the message it says u). And when I try to do this in any other process than my dummy process it crashes the remote process. I made a function to iterate through the modules that have been loaded in the process with tlhelp32 functions to make sure user32.dll is present and it is and my function for finding the address of the function in the process doesn't return NULL like it would if the dll were not present.
Here all relevant functions and my main function:
dependencies.hpp
#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>
#include <iostream>
using namespace std;
typedef struct
{
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
_MessageBoxA MessageBoxA;
HWND hwnd;
LPCSTR msg;
LPCSTR caption;
UINT mb;
}MB_DATA, *PMB_DATA;
//Map the dll into memory
void* GetFileImage(char path[])
{
HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: %d", (int)GetLastError());return NULL;}
HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap");
if(file_map == INVALID_HANDLE_VALUE){printf("Error mapping file: %d", (int)GetLastError());return NULL;}
LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0);
if(file_image == 0){printf("Error getting mapped view: %d", (int)GetLastError());return NULL;}
return file_image;
}
//Get to the function export directory and find the offset for the specified function from the
//address in memory the dll was loaded at
DWORD_PTR RVAddress(char* image, const char* proc_name)
{
PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)image;
PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)(image+pDos_hdr->e_lfanew);
IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader;
IMAGE_DATA_DIRECTORY exp_entry = opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)(image+exp_entry.VirtualAddress);
DWORD* func_table = (DWORD*)(image+pExp_dir->AddressOfFunctions);
WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals);
DWORD* name_table = (DWORD*)(image+pExp_dir->AddressOfNames);
for(u_int i=0;i<pExp_dir->NumberOfNames;i++)
{
char* name = (char*)(image+name_table[i]);
if(strcmp(proc_name, name) == 0)
{
return (DWORD_PTR)func_table[ord_table[i]];
}
}
return (DWORD_PTR)0;
}
//Add the RVA returned from RVAddress to the address of the dll to find the function in the
//process memory
LPVOID GetProcAddressEx(DWORD dwPid, char* mod_path, char* function_name, char* mod_name)
{
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
me32.dwSize = sizeof(MODULEENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE|TH32CS_SNAPMODULE32, dwPid);
if(hSnapshot == INVALID_HANDLE_VALUE){printf("Snapshot failed");return 0;}
if(!(Module32First(hSnapshot, &me32)))
{
printf("Mod32First failed");
return 0;
}
BOOL found = FALSE;
while(Module32Next(hSnapshot, &me32))
{
if(stricmp(me32.szModule, mod_name) == 0)
{
CloseHandle(hSnapshot);
found = TRUE;
break;
}
}
if(found == FALSE){return 0;}
DWORD_PTR RVA = (DWORD_PTR)RVAddress((char*)GetFileImage(mod_path), function_name);
LPVOID func_addr = me32.modBaseAddr+RVA;
return func_addr;
}
main.cpp
#include "dependencies.hpp"
#define FUNC_SIZE 1024
typedef int (WINAPI* _MessageBoxA)(HWND, LPCSTR, LPCSTR, UINT);
int main()
{
MB_DATA mb_data;
mb_data.hwnd = NULL;
mb_data.msg = "Hey";
mb_data.caption = "Yo";
mb_data.mb = MB_OK;
SIZE_T nBytes = 0;
char proc_path[MAX_PATH];
char kernel_path[MAX_PATH];
char user32_path[MAX_PATH];
//get full path to the current process and store it in proc_path
GetModuleFileName(GetModuleHandle(NULL), proc_path, MAX_PATH);
//get full path to kernel32.dll and store it in kernel_path
GetModuleFileName(GetModuleHandle("kernel32.dll"), kernel_path, MAX_PATH);
//get full path to user3.dll and store it in user32_path
GetModuleFileName(GetModuleHandle("user32.dll"), user32_path, MAX_PATH);
//show all processes running and their PID's
system("tasklist");
DWORD dwPid = 0;
printf("PID: ");
scanf("%lu", &dwPid);
//if dwPid is 0 assign it the pid of the current process
if(dwPid == 0)
{
dwPid = GetCurrentProcessId();
}
//Get a handle to the process with all access rights
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
//make sure the handle is valid
if(hProc == NULL){printf("Error obtaining handle to process: %lu", GetLastError());return 1;}
//Get the address of the function in the remote process
LPVOID _MessageBoxA1 = GetProcAddressEx(dwPid, user32_path, (char*)"MessageBoxA", (char*)"user32.dll");
//assign the pointer to the address to the member MessageBoxA of the MB_DATA structure
mb_data.MessageBoxA = (_MessageBoxA)_MessageBoxA1;
//allocate 2mb for our the ThreadProc callback function and the MB_DATA structure
LPVOID lpBase = VirtualAllocEx(hProc, NULL, 2048, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
//did the allocation work
if(lpBase == NULL){printf("Error allocating space: %lu", GetLastError());return 1;}
//so I can check what was written with CheatEngine
cout << "Base address of memory allocated in remote process: " << lpBase << endl;
//Write the function into memory
if(WriteProcessMemory(hProc, lpBase, (LPVOID)ThreadProc, FUNC_SIZE, &nBytes) == 0)
{
printf("Error writing function to process");
return 1;
}
//the address the space left after having written ThreadProc into memory
LPVOID lpBuffer = lpBase+FUNC_SIZE;
//Write the MB_DATA structure into the memory of the remote process
if(WriteProcessMemory(hProc, lpBuffer, &mb_data, sizeof(MB_DATA), &nBytes) == 0)
{
printf("Error writing buffer to process");
}
//Run the ThreadProc function passing the MB_DATA structure to it as its lpParam parameter
if(CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)lpBase, lpBuffer, 0, NULL) == NULL)
{
printf("Error creating remote thread: %lu", GetLastError());
return 1;
}
//print a list of all the dll's being used by the process
EnumerateModules(dwPid);
system("pause");
return 0;
}
Any help would be greatly appreciated. Thank you very much! :)
mb_data.msg and mb_data.caption point to what in the another process ?? this is already enough for crash error. what is in ThreadProc not visible, but i not sure that it have no relocs. really ThreadProc must be member function of MB_DATA and access only it members. from you post obviously that you not debug remote process at injection time. also obviously that task is over your current level

Writing binary data to a file in Visual Studio

I have to admit that I am new to C++ and even new to Visual studio. I have to use Visual studio since the rest of the code is in visual studio and want to open a file and then save binary data to it. I have found some help from Visual Studio and found a program which can send strings to a file but I want to send binary data.For this purpose I have amended the program. But the problem is that it is not performing as per expectations and sending some symbols. I know that there are quite a lot of experts on Stack Overflow. Will any body help me in resolving my issue?
#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <strsafe.h>
#include<conio.h>
void DisplayError(LPTSTR lpszFunction);
void __cdecl _tmain(int argc, TCHAR *argv[])
//void __cdecl _tmain()
{
HANDLE hFile;
int DataBuffer[5] = { 1, 2, 3, 4, 5 };
DWORD dwBytesToWrite = 5;
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
printf("\n");
if (argc != 2)
{
printf("Usage Error:\tIncorrect number of arguments\n\n");
_tprintf(TEXT("%s <file_name>\n"), argv[0]);
return;
}
hFile = CreateFile(argv[1], // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_NEW, // create new file only
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
DisplayError(TEXT("CreateFile"));
_tprintf(TEXT("Terminal failure: Unable to open file \"%s\" for write.\n"), argv[1]);
return;
}
_tprintf(TEXT("Writing %d bytes to %s.\n"), dwBytesToWrite, argv[1]);
bErrorFlag = WriteFile(
hFile, // open file handle
DataBuffer, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
if (FALSE == bErrorFlag)
{
DisplayError(TEXT("WriteFile"));
printf("Terminal failure: Unable to write to file.\n");
}
else
{
if (dwBytesWritten != dwBytesToWrite)
{
// This is an error because a synchronous write that results in
// success (WriteFile returns TRUE) should write all data as
// requested. This would not necessarily be the case for
// asynchronous writes.
printf("Error: dwBytesWritten != dwBytesToWrite\n");
}
else
{
_tprintf(TEXT("Wrote %d bytes to %s successfully.\n"), dwBytesWritten, argv[1]);
}
}
CloseHandle(hFile);
}
void DisplayError(LPTSTR lpszFunction)
{
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0,
NULL);
lpDisplayBuf =
(LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf)
+ lstrlen((LPCTSTR)lpszFunction)
+ 40) // account for format string
* sizeof(TCHAR));
if (FAILED(StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error code %d as follows:\n%s"),
lpszFunction,
dw,
lpMsgBuf)))
{
printf("FATAL ERROR: Unable to output error code.\n");
}
_tprintf(TEXT("ERROR: %s\n"), (LPCTSTR)lpDisplayBuf);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
}

How to get the specific windows service executable file path from Visual C++

How can i get the executable file path of a running Windows service from another program when i only know the service name?
Use QueryServiceConfig(). The QUERY_SERVICE_CONFIG::lpBinaryPathName field will report the full command line that is used to run the service.
For example:
struct SCHandle
{
private:
SC_HANDLE hValue;
public:
SCHandle(SC_HANDLE Value) : hValue(Value) {}
~SCHandle() { if (hValue != NULL) CloseServiceHandle(hValue); }
operator SC_HANDLE() { return hValue; }
bool operator!() const { return (hValue == NULL); }
};
std::wstring GetServiceBinaryName(const std::wstring &ServiceName)
{
SCHandle hSCManager(OpenSCManagerW(NULL, NULL, SC_MANAGER_CONNECT));
if (!hSCManager)
return L"";
SCHandle hService(OpenServiceW(hSCManager, ServiceName.c_str(), SERVICE_QUERY_CONFIG));
if (!hService)
return L"";
std::vector<BYTE> buffer;
DWORD dwBytesNeeded = sizeof(QUERY_SERVICE_CONFIGW);
LPQUERY_SERVICE_CONFIGW pConfig;
do
{
buffer.resize(dwBytesNeeded);
pConfig = (LPQUERY_SERVICE_CONFIGW) &buffer[0];
if (QueryServiceConfigW(hService, pConfig, buffer.size(), &dwBytesNeeded))
return pConfig->lpBinaryPathName;
}
while (GetLastError() == ERROR_INSUFFICIENT_BUFFER);
return L"";
}
#include <Psapi.h>
#include <windows.h>
#pragma comment(lib, "psapi.lib")
int wmain()
{
//insert your service PID here instead of 404
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, 404);
if (!hProcess)
return(0);
wchar_t szBuffer[MAX_PATH];
ZeroMemory(szBuffer, sizeof(szBuffer));
DWORD dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]) - 1;
QueryFullProcessImageName(hProcess, 0, szBuffer, &dwSize);
return(0);
}
You have to start your code with the elevated rights to access system service information. Otherwise OpenProcess will return NULL and GetLastError will return ERROR_ACCESS_DENIED code.
Also you could use:
GetProcessImageFileName to get path in the system native
format;
GetModuleFileNameEx with the NULL module handle.
Update: If you have only service name, then you have to use a different approach:
int wmain()
{
LPQUERY_SERVICE_CONFIG lpsc;
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, GENERIC_READ);
if (!hSCManager)
return(0);
SC_HANDLE hService = OpenService(hSCManager, L"Browser", SERVICE_QUERY_CONFIG);
if (!hService)
{
CloseServiceHandle(hSCManager);
return(0);
}
DWORD dwBytesNeeded = 0, dwBufSize;
if (!QueryServiceConfig(hService, NULL, 0, &dwBytesNeeded))
{
DWORD dwError = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER == dwError)
{
dwBufSize = dwBytesNeeded;
lpsc = (LPQUERY_SERVICE_CONFIG)HeapAlloc(GetProcessHeap(), 0, dwBufSize);
}
else
{
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return(0);
}
}
if (QueryServiceConfig(hService, lpsc, dwBufSize, &dwBytesNeeded))
{
//lpsc->lpBinaryPathName contains exe path
}
HeapFree(GetProcessHeap(), 0, lpsc);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
return(0);
}