So I am learning some dll injection stuff on a test executable. Once I have injected my dll, I try to get the module handle and with that I try to get the base address of the module(the main exe).
DWORD dwGetModuleBaseAddress(DWORD dwProcessIdentifier, WCHAR *lpszModuleName)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwProcessIdentifier);
DWORD dwModuleBaseAddress = 0;
if(hSnapshot != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 ModuleEntry32 = {0};
ModuleEntry32.dwSize = sizeof(MODULEENTRY32);
if(Module32First(hSnapshot, &ModuleEntry32))
{
do
{
if(wcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
{
dwModuleBaseAddress = (DWORD)ModuleEntry32.modBaseAddr;
break;
}
}
while(Module32Next(hSnapshot, &ModuleEntry32));
}
CloseHandle(hSnapshot);
}
return dwModuleBaseAddress;
}
That is how I try to do it. This is after my dll is injected, but it seems to return INVALID_HANDLE_VALUE for some reason. I found the function from one website and modified it a bit but it still doesn't seem to work. If you have a more cleaner method to get the base address I would be glad to know about it.
Edit the problem is now with this line:
if(wcscmp(ModuleEntry32.szModule, lpszModuleName) == 0)
It never is 0 but there is a module name I am looking for, I can see my exe in the debugger but this comparison doesn't somehow work.
This is how I call the function
HWND window = FindWindow(0, LPCWSTR("test"));
DWORD pID = 0;
GetWindowThreadProcessId(window, &pID);
base = dwGetModuleBaseAddress(pID, (WCHAR*)("test"));
You are using functions designed for wide character strings.
"test"
L"test"
The top line is a regular c string char array. The second line is using the L macro to define the string literal as a wide char c string.
Casting to WCHAR* will not solve the issue, you either have to define them using the L macro or switch your functions to use regular char arrays.
Here is a regular char array version of your function I use
char* GetModuleBaseAddress(const char* modName, DWORD procId)
{
char* modBaseAddr{ nullptr };
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procId);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry{};
modEntry.dwSize = sizeof(modEntry);
if (Module32First(hSnap, &modEntry))
{
do
{
if (!_stricmp(modEntry.szModule, modName))
{
modBaseAddr = (char*)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
Related
I'm writing a c++ program with visual studio and I have written this code
DWORD GetProcIDByName(const char* procName) {
HANDLE hSnap;
BOOL done;
PROCESSENTRY32 procEntry;
ZeroMemory(&procEntry, sizeof(PROCESSENTRY32));
procEntry.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
done = Process32First(hSnap, &procEntry);
do {
/* here */ char file_str[sizeof(procEntry.szExeFile)];
int wc_convert = WideCharToMultiByte(CP_ACP, 0, procEntry.szExeFile, sizeof(procEntry.szExeFile), file_str, sizeof(file_str), NULL, NULL);
if (_strnicmp(file_str, procName, sizeof(file_str)) == 0) {
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnap, &procEntry));
return 0;
}
in order to convert the value procEntry.szExeFile from a WCHAR* (wide unicode character array), to a standard char* to compare, I had to make a char* buffer for it. I wrote the line
char file_str[sizeof(procEntry.szExeFile)];
and realized later that I should use heap memory for this buffer that will change sizes depending on the process name, but I was surprised to see that my visual studio had no problem with this code and I was able to build it with no compiler errors. I haven't run it yet and I probably will not because I imagine if this runs there is a potential for buffer overflow and undefined behaviour
I don't have any issue, but I am curious about why I was able to write this code without getting a compiler error. If the process name is not known at compile time, how can I allocate this buffer on the stack?
The szExeFile field is not dynamic length. It is a fixed-length array of MAX_PATH characters, holding a null-terminated string.
Note that:
sizeof() reports a size in bytes
szExeFile is an array of wchar_t characters, in your case
wchar_t is 2 bytes in size on Windows.
So, when you declare your char[] array as char file_str[sizeof(procEntry.szExeFile)];, it will have a static compile-time size of MAX_PATH*2 chars. Which should be large enough to easily handle most conversions from wchar_t[] to char[] in this case.
BTW, your use of sizeof(procEntry.szExeFile) in the 4th parameter of WideCharToMultiByte() is wrong. That parameter expects a character count, not a byte count. Use lstrlenW(procEntry.szExeFile) or wcslen(procEntry.szExeFile) instead. Or just -1 to let WideCharToMultiByte() count the wide characters for you.
That being said, an easier solution is to use Process32FirstA()/Process32NextA() instead. Or, change your function to take a Unicode wchar_t string as input. Either way, then you won't have to convert the procEntry.szExeFile at all, just use it as-is.
Also, you are leaking the HANDLE from CreateToolhelp32Snapshot(), you need to call CloseHandle() when you are done using it.
Try this:
DWORD GetProcIDByName(const char* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32A procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstA(hSnap, &procEntry);
while (ok) {
if (_stricmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextA(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
Or this:
DWORD GetProcIDByName(const wchar_t* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32W procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstW(hSnap, &procEntry);
while (ok) {
if (_wcsicmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextW(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
edit: how can i get windows title using processname? for example get current title of chrome.exe
You can get title of specific windows using it's process ID.
If you know the name of executed file(ex: Chrome.exe), you can get Handle with FindWindowEX() or get PID "Chrome.exe" with CreateToolHelp32Snapshot.
Then use EnumWindows to get HWND using HANDLE.
struct param_enum
{
unsigned long ulPID;
HWND hWnd_out;
};
HWND find_specific_window(unsigned long process_id)
{
param_enum param_data;
param_data.ulPID = process_id;
param_data.hWnd_out = 0;
EnumWindows(enum_windows_callback, (LPARAM)¶m_data);
get_window_title(process_id, param_data.hWnd_out);
return param_data.hWnd_out;
}
BOOL CALLBACK enum_windows_callback(HWND handle, LPARAM lParam)
{
param_enum& param_data = *(param_enum*)lParam;
unsigned long process_id = 0;
GetWindowThreadProcessId(handle, &process_id);
if (param_data.ulPID != process_id)
{
return TRUE;
}
param_data.hWnd_out = handle;
return FALSE;
}
---------------------------Get Handle---------------------------
HANDLE GetHandleFromProcessPath(TCHAR* szExeName, DWORD& dwPID)
{
HANDLE hExeName = INVALID_HANDLE_VALUE;
HANDLE hSnap = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE != hSnap)
{
if (Process32First(hSnap, &pe32))
{
do
{
//!!! Attention pe32.szExeFile always return exe file name. not window title.
if (NULL != _tcsstr(pe32.szExeFile, szExeName))
{
hExeName = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pe32.th32ProcessID);
dwPID = pe32.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe32));
}
}
return hExeName;
}
Completing the answer of "G.Alexander" and and the comment of Skewjo
the get_window_title code is incomplete. So, worked for me, by removing it and calling find_specific_window like below:
wchar_t* caption = new wchar_t[MAX_PATH*2];
HWND h = find_specific_window(processID);
GetWindowTextW(h, caption, MAX_PATH*2);
I tried to convert wchar* to string. First I made it as wstring. This method is specified in stackoverflow when I search. But it doesn't work for my part. What's wrong with it?
GetProcessImageNameFromPID.cpp
BOOL GetProcessImageNameFromPID::getProcessNameFromProcessID(DWORD processId, WCHAR**processName)
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Take a snapshot of all processes in the system.
hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hProcessSnap == INVALID_HANDLE_VALUE)
{
printError(TEXT("CreateToolhelp32Snapshot (of processes)"));
return(FALSE);
}
// Set the size of the structure before using it.
pe32.dwSize = sizeof(PROCESSENTRY32);
// Retrieve information about the first process,
// and exit if unsuccessful
if (!Process32First(hProcessSnap, &pe32))
{
printError(TEXT("Process32First")); // show cause of failure
CloseHandle(hProcessSnap); // clean the snapshot object
return(FALSE);
}
// Now walk the snapshot of processes, and
// display information about each process in turn
int i = 0;
do
{
WCHAR*allprocessName = pe32.szExeFile;
//_tprintf( TEXT("\n%d)PROCESS NAME: %s"), i, allprocessName);
// Retrieve the priority class.
dwPriorityClass = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
if (hProcess == NULL)
printError(TEXT("OpenProcess"));
else
{
dwPriorityClass = GetPriorityClass(hProcess);
if (!dwPriorityClass)
printError(TEXT("GetPriorityClass"));
CloseHandle(hProcess);
}
DWORD pid = pe32.th32ProcessID;
//_tprintf( TEXT("\n Process ID = %d"), pid );
if (pid == processId)
{
*processName = allprocessName;
//_tprintf( TEXT("Inside Method:\n"));
_tprintf(TEXT("PROCESS NAME: %s\n\n"), *processName);
return TRUE;
}
i++;
} while (Process32Next(hProcessSnap, &pe32));
CloseHandle(hProcessSnap);
return(FALSE);
}
int _tmain(int argc, _TCHAR* argv[])
{
WCHAR**processName = (WCHAR**)malloc(sizeof(WCHAR));
GetProcessImageNameFromPID::getProcessNameFromProcessID(4, processName);
_tprintf(TEXT("PROCESS NAME: %s\n\n"), *processName); // correct
GetProcessImageNameFromPID::getProcessNameFromProcessID(executionProcessID, processName);
wstring ws(*processName);
string str(ws.begin(), ws.end());
processImageName = str;
cout << processImageName << endl; // some wrong characters are printed
}
There are various problems with your code, the last one is the most serious:
This looks strange:
WCHAR**processName = (WCHAR**)malloc(sizeof(WCHAR));
I suppose you want a pointer to WCHAR*, why dont you:
WCHAR* processName;
and then:
GetProcessImageNameFromPID::getProcessNameFromProcessID(4, &processName);
^~~~~ !!
What is the type of processImageName? What is the name of the process, if it contains non ASCII chars then your conversion code will give wrong characters.
Another is that code:
*processName = allprocessName;
is making *processName equal to pointer which is dangling pointer after your function ends, it points to WCHAR array in:
PROCESSENTRY32 pe32;
which is created on stack.
What you should do is make processName an array:
WCHAR processName[MAX_PATH];
and inside your function copy process name from pe32 to this array.
I'm trying to add my software to registry, I have found some pieces of the codes I can use but not full working code C/C++ is new to me and can't create it on my own. But here is the basic idea: Check if reg key set if not create it.
I was able to get my program location using this code:
TCHAR szPath[MAX_PATH];
GetModuleFileName(NULL,szPath,MAX_PATH);
And was able to create the key with: (Not sure if it's the right way)
HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER,"Software\\Microsoft\\Windows\\CurrentVersion\\Run",&newValue);
RegSetValueEx(newValue,"myprogram",0,REG_SZ,(LPBYTE)szPath,sizeof(szPath));
RegCloseKey(newValue);
return 0;
What is missing, A small check if the key isn't already there...
Thank you!
Here's some code that likely does what you want. Call RegisterProgram for your EXE to self-register itself for automatically being started when the user logs in. This function calls GetModuleFileName and then invokes another helper function called RegisterMyProgramForStartup that does the writing to the registry.
Call IsMyProgramRegisteredForStartup(L"My_Program") to detect if the registration actually exists and appears valid.
One quick note. The performance impact of checking to see if the key exists before actually writing it out again is negligible. You could just call RegisterProgram blindly and it will overwrite the key if it already exists. Detecting if the registration exists is useful for initializing your UI checkbox that enables or disables auto-start. (You are giving your users a choice, right? Because I hate apps that automatically install themselves to run automatically without giving me a choice.)
BOOL IsMyProgramRegisteredForStartup(PCWSTR pszAppName)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwRegType = REG_SZ;
wchar_t szPathToExe[MAX_PATH] = {};
DWORD dwSize = sizeof(szPathToExe);
lResult = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_READ, &hKey);
fSuccess = (lResult == 0);
if (fSuccess)
{
lResult = RegGetValueW(hKey, NULL, pszAppName, RRF_RT_REG_SZ, &dwRegType, szPathToExe, &dwSize);
fSuccess = (lResult == 0);
}
if (fSuccess)
{
fSuccess = (wcslen(szPathToExe) > 0) ? TRUE : FALSE;
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
BOOL RegisterMyProgramForStartup(PCWSTR pszAppName, PCWSTR pathToExe, PCWSTR args)
{
HKEY hKey = NULL;
LONG lResult = 0;
BOOL fSuccess = TRUE;
DWORD dwSize;
const size_t count = MAX_PATH*2;
wchar_t szValue[count] = {};
wcscpy_s(szValue, count, L"\"");
wcscat_s(szValue, count, pathToExe);
wcscat_s(szValue, count, L"\" ");
if (args != NULL)
{
// caller should make sure "args" is quoted if any single argument has a space
// e.g. (L"-name \"Mark Voidale\"");
wcscat_s(szValue, count, args);
}
lResult = RegCreateKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, NULL, 0, (KEY_WRITE | KEY_READ), NULL, &hKey, NULL);
fSuccess = (lResult == 0);
if (fSuccess)
{
dwSize = (wcslen(szValue)+1)*2;
lResult = RegSetValueExW(hKey, pszAppName, 0, REG_SZ, (BYTE*)szValue, dwSize);
fSuccess = (lResult == 0);
}
if (hKey != NULL)
{
RegCloseKey(hKey);
hKey = NULL;
}
return fSuccess;
}
void RegisterProgram()
{
wchar_t szPathToExe[MAX_PATH];
GetModuleFileNameW(NULL, szPathToExe, MAX_PATH);
RegisterMyProgramForStartup(L"My_Program", szPathToExe, L"-foobar");
}
int _tmain(int argc, _TCHAR* argv[])
{
RegisterProgram();
IsMyProgramRegisteredForStartup(L"My_Program");
return 0;
}
To check whether or not the value exists, call RegQueryValueEx.
LONG retval = RegQueryValueEx(hKey, "myprogram", NULL, NULL, NULL, NULL);
Note that what you called newValue is actually a key rather than a value. To avoid confusion you should name it such. I used the name hKey.
Then to check whether or not the value exists, compare retval against ERROR_SUCCESS as described in the documentation.
The other problem with your code is that there is absolutely no error checking. I'll leave that to you to address.
You forget to write an argument about security access
I have a C++ Custom Action Project. I have two functions, RegProductName and GetProductName.
I call RegProductName and it has three possible outcomes. I have these in an if statement that if it is outcome 1 or outcome 2 then i call my second function GetProductName but i can't seem to get it working. Can anyone give me an example of calling one function from another please?
extern "C" UINT __stdcall RegProductName(MSIHANDLE hInstall)
{
AssertSz(FALSE, "debug here");
DebugBreak();
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
char szProductName[MAX_PATH];
hr = WcaInitialize(hInstall, "RegProductName");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
strcpy(szProductName, Orc_Get_Product_Name());
if(szProductName == "ORCHESTRATOR")
{
GetProductName();
}
else if (szProductName == "CORAL")
{
GetProductName();
}
else
{
MsiSetProperty(hInstall, "PRODUCTNAME", szProductName);
}
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
The error is "Too few arguments in function call when i hover over GetProductName();
extern "C" UINT __stdcall GetProductName(MSIHANDLE hInstall)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
DWORD Ret;
CHAR *Section = "General";
CHAR szBuffer[MAX_PATH];
CHAR szProductIniFile[MAX_PATH];
char lpszString[MAX_PATH];
int lplValue;
hr = WcaInitialize(hInstall, "GetProductName");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
TCHAR* szValueBuf = NULL;
DWORD cchValueBuf = 0;
UINT uiStat = MsiGetProperty(hInstall, TEXT("TEMPFOLDER"), TEXT(""), &cchValueBuf);
if (ERROR_MORE_DATA == uiStat)
{
++cchValueBuf;
szValueBuf = new TCHAR[cchValueBuf];
if (szValueBuf)
{
uiStat = MsiGetProperty(hInstall, TEXT("TEMPFOLDER"), szValueBuf, &cchValueBuf);
}
}
if (ERROR_SUCCESS != uiStat)
{
if (szValueBuf != NULL)
delete[] szValueBuf;
return ERROR_INSTALL_FAILURE;
}
strcpy(szProductIniFile,szValueBuf);
Ret = strlen(szProductIniFile);
if(szProductIniFile[Ret-1] != '\\')
strcat(szProductIniFile,"\\");
strcat(szProductIniFile, "Product.ini");
Ret = GetPrivateProfileString(Section, // Section Title [General]
"PRODUCT_NAME", // Entry
"Orchestrator", // Default Value
szBuffer, // Address of buffer to read to
MAX_PATH, // Length of buffer
szProductIniFile); // .ini file name
if (strlen(szBuffer) == 0)
strcpy(szBuffer, "ORCHESTRATOR");
if (strlen(szBuffer) >= 3 && (stricmp(szBuffer+strlen(szBuffer)-3,"DEM") == 0))
lplValue = 1;
else
lplValue = 0;
MsiSetProperty(hInstall, "PRODUCTNAME", szBuffer);
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
Your GetProductName() function takes an argument MSIHANDLE hInstall. You'll need to provide that when calling it. For instance, if you just want to call it with the same handle as RegProductName() was called with:
GetProductName(hInstall);
This does not compare the string content:
if(szProductName == "ORCHESTRATOR")
either use strcmp() or use std::string and ==:
if(szProductName == std::string("ORCHESTRATOR"))
Your GetProductName looks like this:
extern "C" UINT __stdcall GetProductName(MSIHANDLE hInstall)
\________________/
The Argument
So it needs to take 1 argument, while you are calling it without argumanes at all:
getProductName( );
^
|
nothing is being passed here
hence the error you're getting. Based on your code you should probably pass your hInstall there:
getProductName( hInstall );
The GetProductName requires one argument of type MSIHANDLE whereas you are calling it without any parameter. Try instead
GetProductName(hInstall);
GetProductName is defined as GetProductName(MSIHANDLE hInstall), that means you MUST pass relevant MSIHANDLE as parameter. And that's exactly the error you're getting.
But you're doing szProductName == "ORCHESTRATOR" - this is not how you compare strings in C. You seem to lack basic knowledge about C. You should not be writing in C or C++.