Listing Windows Processes and Modules - c++

So I've been messing around with Windows API lately, and I've encountered an issue that I need a little assistance with. Actually, to be precise, there are two issues.
I will first show the code and then explain the difficulties that I am experiencing:
#pragma once
#pragma comment(lib, "Psapi.lib")
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
void ProcessError(DWORD error);
int main() {
FILE* file = fopen("C:\\Users\\Administrator\\Desktop\\processes.txt", "w");
DWORD count, i, modulesCount;
WCHAR buffer[128] = {0};
HMODULE modules[128] = {0};
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
PROCESSENTRY32 pEntry;
pEntry.dwSize = sizeof(PROCESSENTRY32);
count = 0;
if(snapshot != INVALID_HANDLE_VALUE) {
if(!Process32First(snapshot, &pEntry)) {
ProcessError(GetLastError());
CloseHandle(snapshot);
ExitProcess(EXIT_FAILURE);
}
do {
HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pEntry.th32ProcessID);
GetModuleFileNameEx(hProc, NULL, (LPWSTR)memset(buffer, 0, 128), 128);
fwprintf(file, L"-------------------------------------------------------\n");
fwprintf(file, L"%s\t pid: %d\n", pEntry.szExeFile, pEntry.th32ProcessID);
fwprintf(file, L"%s\n", buffer);
if(hProc != INVALID_HANDLE_VALUE) {
if(EnumProcessModules(hProc, (HMODULE*)memset(modules, 0, 128), 128, &modulesCount)) {
modulesCount = modulesCount <= 128 ? modulesCount : 128;
for(i = 0; i < modulesCount; ++i) {
GetModuleFileName(modules[i], (LPWSTR)memset(buffer, 0, 128), 128);
if(wcslen(buffer) > 0) {
fwprintf(file, L"\t\t0x%X Module: %s\n", modules[i], buffer);
}
}
}
else {
ProcessError(GetLastError());
}
CloseHandle(hProc);
}
else {
ProcessError(GetLastError());
}
count++;
} while(Process32Next(snapshot, &pEntry));
fwprintf(file, L"Process count: %d\n", count);
}
else {
ProcessError(GetLastError());
CloseHandle(snapshot);
ExitProcess(EXIT_FAILURE);
}
fclose(file);
CloseHandle(snapshot);
ExitProcess(EXIT_SUCCESS);
}
void ProcessError(DWORD error) {
printf("Error in thread 0x%X, code: 0x%X\n", GetThreadId(GetCurrentThread()), error);
}
So, the first issue has to do with the following:
if(EnumProcessModules(hProc, (HMODULE*)memset(modules, 0, 128), 128, &modulesCount))
Sometimes I get an INVALID_HANDLE error, and I don't really know why. The Process handle is not invalid, nor is any other parameter passed to the function. If somebody could explain to me or at least point me in some direction (which is more preferred solution, since I am more interested to learn :D) it would do me good.
Second is that for some reason, when I enumerate process' modules and GetModuleFileName() it also includes the location of the current process.
I would get the following when I write to the file:
TuneUpUtilitiesApp32.exe pid: 2744
D:\Program Files\TuneUp Utilities 2012\TuneUpUtilitiesApp32.exe
0x76F60000 Module: C:\Windows\SYSTEM32\ntdll.dll
0x75FE0000 Module: C:\Windows\system32\kernel32.dll
0x75370000 Module: C:\Windows\system32\KERNELBASE.dll
0x761A0000 Module: C:\Windows\system32\USER32.dll
0x770D0000 Module: C:\Windows\system32\GDI32.dll
0x77130000 Module: C:\Windows\system32\LPK.dll
0x76EC0000 Module: C:\Windows\system32\USP10.dll
0x75F20000 Module: C:\Windows\system32\msvcrt.dll
0x755D0000 Module: C:\Windows\system32\ADVAPI32.dll
0x75590000 Module: C:\Windows\SYSTEM32\sechost.dll
0x757D0000 Module: C:\Windows\system32\RPCRT4.dll
0x77120000 Module: C:\Windows\system32\PSAPI.DLL
0x755B0000 Module: C:\Windows\system32\IMM32.DLL
0x75670000 Module: C:\Windows\system32\MSCTF.dll
0x10000000 Module: C:\Windows\system32\guard32.dll
0x750D0000 Module: C:\Windows\system32\VERSION.dll
0x750C0000 Module: C:\Windows\system32\fltlib.dll
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
0x0 Module: C:\Users\Administrator\documents\visual studio 2010\Projects\FunWithWindowsAPI\Release\FunWithWindowsAPI.exe
It literally does that for every process that I can extract modules from. Any help would be much appreciated!

You are not using the returned "modulesCount" correctly. It is not the number of modules, it is the size of the array in bytes. You'll need to divide by sizeof(HMODULE) to get the number of modules.
The second problem is that you hope that the pEntry.th32ProcessID is still valid when you start iterating the process entries. That's idle hope, a process can terminate while you are iterating. You don't check for this, you don't verify if OpenProcess() returns a valid handle. It may also fail because you don't have enough permissions to access the process.
Focus on what CreateToolhelp32Snapshot() can do, it also supports Module32First/Next(). It will be more reliable because of the function's ability to create a snapshot.

Related

dll library not being injected even though there are no errors

I'm trying to inject my .dll in a target process. I will give the script a command line argument to launch a certain process then inject the .dll in it. The problem is that the code runs without errors but the .dll is not being injected. The reasons which I believe the .dll is not being injected are that I can delete the .dll when the target process is running. I don't see my .dll when printing the modules used by the target process, and the code in the .dll only writes the word "hello" to a file (other than that there is nothing in the DllMain()) but I don't see that file. I have read tons of posts about dll injection on stackoverflow and I couldn't find a solution to my problem.
My code:
if (!CreateProcessW(NULL, // No module name (use command line)
wtext, // Command line arguments to launch the target process
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
CREATE_SUSPENDED,
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi) // Pointer to PROCESS_INFORMATION structure
)
{
printf("CreateProcess failed (%d).\n", GetLastError());
return 1;
}
wstring dllPath = wstring(selfdir) + TEXT("\\HookEngine.dll"); // full path to the .dll
LPCWSTR PathToDll = dllPath.c_str();
size_t nLength = (wcslen(PathToDll)+1) * sizeof(LPCWSTR);
LPVOID lpRemoteString = VirtualAllocEx(pi.hProcess, NULL, nLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (lpRemoteString == NULL) {
printf("Failed to allocate memory in the target process, error number (%d).\n", GetLastError());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
if (!WriteProcessMemory(pi.hProcess, lpRemoteString, PathToDll, nLength, NULL)) {
printf("Failed to write memory to the target process, error number (%d).\n", GetLastError());
VirtualFreeEx(pi.hProcess, lpRemoteString, 0, MEM_RELEASE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
LPVOID lpLoadLibraryW = NULL;
lpLoadLibraryW = GetProcAddress(GetModuleHandle(L"KERNEL32.DLL"), "LoadLibraryW");
if (!lpLoadLibraryW) {
printf("Load library failed, error number (%d).\n", GetLastError());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
HANDLE hThread = CreateRemoteThread(pi.hProcess,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)lpLoadLibraryW,
lpRemoteString,
NULL,
NULL
);
if (!hThread) {
printf("Creating thread failed, error number (%d).\n", GetLastError());
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 1;
}
else {
WaitForSingleObject(hThread, 10000);
HMODULE arr[1024]; // the next few line are for checking which dlls are being used by the target process
DWORD bneeded = 0;
wchar_t arr2[1024];
EnumProcessModulesEx(pi.hProcess, arr, sizeof(arr), &bneeded, LIST_MODULES_ALL);
for (int i = 0; i < bneeded/sizeof(HMODULE); i++) {
int len = GetModuleFileNameEx(pi.hProcess, arr[i], arr2, 1024);
for (int j = 0; j < len; j++) {
wcout << arr2[j];
}
cout << endl;
}
ResumeThread(pi.hThread);
}
WaitForSingleObject(pi.hProcess, INFINITE);
VirtualFreeEx(pi.hProcess, lpRemoteString, 0, MEM_RELEASE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
I don't have any idea why this is not working. No errors are happening so I think it should work.
The script and the dll are in the same folder and I give it the command line argument "python myscript.py". The code in the python script only prints some number on a text file and I can see that file when I run the python script from my code so CreateProcess() is succeeding and the process is being resumed. So, when I run my script it only creates a process and nothing else happens. It is like the code between CreateProcess and ResumeThread() doesn't do anything. What should I do?

How can a program read its own image from memory via ReadProcessMemory?

I am trying to make an executable which can read itself from memory using ReadProcessMemory api of windows.
Then, I will use this to calculate the checksum of executable.
This is my code :
#define PSAPI_VERSION 1
#include <string>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <psapi.h>
#include <Wincrypt.h>
#define BUFSIZE 1024
#define MD5LEN 16
// To ensure correct resolution of symbols, add Psapi.lib to TARGETLIBS
#pragma comment(lib, "psapi.lib")
int main(void)
{
HWND hMyProcess = (HWND)(GetCurrentProcess());
HMODULE hModule = (HMODULE)GetModuleHandle(NULL);
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
MODULEINFO moduleInfo;
if(hModule != NULL && hMyProcess != NULL){
// if (GetModuleInformation())
GetModuleBaseName(hMyProcess, hModule, szProcessName, MAX_PATH);
printf("%s\n", szProcessName);
if (GetModuleInformation(hMyProcess, hModule, &moduleInfo, sizeof(moduleInfo))){
printf("lpBaseOfDLL : %x\n", moduleInfo.lpBaseOfDll);
printf("Entry Point : %x\n", moduleInfo.EntryPoint);
printf("SizeOfImage : %x\n", moduleInfo.SizeOfImage);
}
}
// Till here working fine, problem lies below
// read process memory
TCHAR *hexEXE;
SIZE_T *lpNumberOfBytesRead;
if(ReadProcessMemory(hMyProcess, moduleInfo.lpBaseOfDll,
hexEXE, moduleInfo.SizeOfImage, 0)){
//printf("%s\n", hexEXE);
printf("Read memory\n");
printf("%d \n",strlen(hexEXE));
}
// will be implemented later, taken from --> https://msdn.microsoft.com/en-us/library/aa382380(VS.85).aspx
DWORD dwStatus = 0;
BOOL bResult = FALSE;
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
/*if (!CryptAcquireContext(&hProv,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT)){
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
//CloseHandle(hFile);
return dwStatus;
}
if (!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash)){
dwStatus = GetLastError();
printf("CryptAcquireContext failed: %d\n", dwStatus);
//CloseHandle(hFile);
CryptReleaseContext(hProv, 0);
return dwStatus;
}*/
return 0;
}
Problem :
I am not able to read the my own process's memory, it's the first time I'm using WinAPI, so perhaps I am using the function in some wrong way.
The program just hangs and it shows "Windows has encountered some problem..."
Possible Reasons of Error :
I think the handle to the process ( hMyProcess ) I'm getting earlier isn't with the required privileges ( PROCESS_VM_READ ), how do I verify it and if it isn't then how do I get the correct privileges.
TCHAR *hexEXE;
SIZE_T *lpNumberOfBytesRead;
hexEXE = malloc (moduleInfo.SizeOfImage);
if(ReadProcessMemory(hMyProcess, moduleInfo.lpBaseOfDll,
hexEXE, moduleInfo.SizeOfImage, 0)){
//printf("%s\n", hexEXE);
printf("Read memory\n");
//hexEXE is not a string. Don't use it in strlen.
//printf("%d \n",strlen(hexEXE));
print("%d \n", moduleInfo.SizeOfImage);
}
The ReadProcessMemory need a memory to store the image. So, the "hexEXE" need be assign to a memory buffer.
Sorry for the extended discussion, but I got it running by changing the code to instead of using ReadProcessMemory directly iterating over the memory through a for loop like this :
long *baseAddress = (long *)moduleInfo.lpBaseOfDll;
printf("%d %x\n",baseAddress, baseAddress);
for (int i = 0; i < moduleInfo.SizeOfImage; ++i){
long *addressToRead = baseAddress+i;
printf("%x : %x\n", addressToRead, *addressToRead);
}
Here's the output :
Further thoughts
However, I don't understand why am I not able to get it using ReadProcessMemory.

OpenProcess Failure (SeDebugPrivilege?)

I'm trying to use OpenProcess, for some reason it keeps failing.
HANDLE GetProcessPid()
{
DWORD pid = 0;
wchar_t ProcessName[] = L"notepad.exe";
// Create toolhelp snapshot.
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
// Walkthrough all processes.
if (Process32First(snapshot, &process))
{
do
{
if (wcscmp(process.szExeFile, ProcessName) == 0)
{
pid = process.th32ProcessID;
break;
}
} while (Process32Next(snapshot, &process));
}
CloseHandle(snapshot);
if (pid != 0)
{
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
}
return NULL;
}
This always returns 0xcccccccccccccccc or 0x0000000000000020 even when I've set the pid manually when calling OpenProcess.
I've tried running as admin outside of debugging inside visual studio and get the same results, after searching, I think I need to enable debug priviledges (SeDebugPrivilege), how do I do this in visual studio 2013?
Your code is fine, you just need to run your executable as administrator and it works, I just tested it.

Writing Performance Data to a Log File

I'm trying to use one of the windows examples to have some CPU data. When I try to debug the below code I receive the message "The command line must include a valid log file name" I am using MS Visual studio 2013 and I am intrested in Total Processor time%.
Pls advise.
More details about the code:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa373228(v=vs.85).aspx
The Code:
#include <windows.h>
#include <stdio.h>
#include <pdh.h>
#include <pdhmsg.h>
#pragma comment(lib, "pdh.lib")
CONST PWSTR COUNTER_PATH = L"\\Processor(0)\\% Processor Time";
CONST ULONG SAMPLE_INTERVAL_MS = 1000;
void DisplayCommandLineHelp(void)
{
wprintf(L"The command line must include a valid log file name.\n");
}
void wmain(int argc, WCHAR **argv)
{
HQUERY hQuery = NULL;
HLOG hLog = NULL;
PDH_STATUS pdhStatus;
DWORD dwLogType = PDH_LOG_TYPE_CSV;
HCOUNTER hCounter;
DWORD dwCount;
if (argc != 2)
{
DisplayCommandLineHelp();
goto cleanup;
}
// Open a query object.
pdhStatus = PdhOpenQuery(NULL, 0, &hQuery);
if (pdhStatus != ERROR_SUCCESS)
{
wprintf(L"PdhOpenQuery failed with 0x%x\n", pdhStatus);
goto cleanup;
}
// Add one counter that will provide the data.
pdhStatus = PdhAddCounter(hQuery,
COUNTER_PATH,
0,
&hCounter);
if (pdhStatus != ERROR_SUCCESS)
{
wprintf(L"PdhAddCounter failed with 0x%x\n", pdhStatus);
goto cleanup;
}
// Open the log file for write access.
pdhStatus = PdhOpenLog(argv[1],
PDH_LOG_WRITE_ACCESS | PDH_LOG_CREATE_ALWAYS,
&dwLogType,
hQuery,
0,
NULL,
&hLog);
if (pdhStatus != ERROR_SUCCESS)
{
wprintf(L"PdhOpenLog failed with 0x%x\n", pdhStatus);
goto cleanup;
}
// Write 10 records to the log file.
for (dwCount = 0; dwCount < 10; dwCount++)
{
wprintf(L"Writing record %d\n", dwCount);
pdhStatus = PdhUpdateLog(hLog, NULL);
if (ERROR_SUCCESS != pdhStatus)
{
wprintf(L"PdhUpdateLog failed with 0x%x\n", pdhStatus);
goto cleanup;
}
// Wait one second between samples for a counter update.
Sleep(SAMPLE_INTERVAL_MS);
}
cleanup:
// Close the log file.
if (hLog)
PdhCloseLog(hLog, 0);
// Close the query object.
if (hQuery)
PdhCloseQuery(hQuery);
}
if (argc != 2)
{
DisplayCommandLineHelp();
goto cleanup;
}
This is your answer right here. You need to set your project up to pass a filename to the program when it runs.
argc counts how many command-line arguments your program has received. It always gets at least one, the name of the program itself. But this program needs a second one, the name of the logfile to write to.

How to get the process name in C++

How do I get the process name from a PID using C++ in Windows?
I guess the OpenProcess function should help, given that your process possesses the necessary rights. Once you obtain a handle to the process, you can use the GetModuleFileNameEx function to obtain full path (path to the .exe file) of the process.
#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
#include "stdio.h"
#include "psapi.h"
// Important: Must include psapi.lib in additional dependencies section
// In VS2005... Project > Project Properties > Configuration Properties > Linker > Input > Additional Dependencies
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE Handle = OpenProcess(
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE,
8036 /* This is the PID, you can find one from windows task manager */
);
if (Handle)
{
TCHAR Buffer[MAX_PATH];
if (GetModuleFileNameEx(Handle, 0, Buffer, MAX_PATH))
{
// At this point, buffer contains the full path to the executable
}
else
{
// You better call GetLastError() here
}
CloseHandle(Handle);
}
return 0;
}
You can obtain the process name by using the WIN32 API GetModuleBaseName after having the process handle. You can get the process handle by using OpenProcess.
To get the executable name you can also use GetProcessImageFileName.
All the above methods require psapi.dll to be loaded (Read the remarks section) and iterating through process snapshot is an option one should not even consider for getting a name of the executable file from an efficiency standpoint.
The best approach, even according to MSDN recommendation, is to use QueryFullProcessImageName.
std::string ProcessIdToName(DWORD processId)
{
std::string ret;
HANDLE handle = OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION,
FALSE,
processId /* This is the PID, you can find one from windows task manager */
);
if (handle)
{
DWORD buffSize = 1024;
CHAR buffer[1024];
if (QueryFullProcessImageNameA(handle, 0, buffer, &buffSize))
{
ret = buffer;
}
else
{
printf("Error GetModuleBaseNameA : %lu", GetLastError());
}
CloseHandle(handle);
}
else
{
printf("Error OpenProcess : %lu", GetLastError());
}
return ret;
}
If you are trying to get the executable image name of a given process, take a look at GetModuleFileName.
Check out the enumprocess functions in the tool help library:
http://msdn.microsoft.com/en-us/library/ms682629(v=vs.85).aspx
Good example # http://msdn.microsoft.com/en-us/library/ms682623(v=vs.85).aspx
Try this function :
std::wstring GetProcName(DWORD aPid)
{
PROCESSENTRY32 processInfo;
processInfo.dwSize = sizeof(processInfo);
HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (processesSnapshot == INVALID_HANDLE_VALUE)
{
std::wcout << "can't get a process snapshot ";
return 0;
}
for(BOOL bok =Process32First(processesSnapshot, &processInfo);bok; bok = Process32Next(processesSnapshot, &processInfo))
{
if( aPid == processInfo.th32ProcessID)
{
std::wcout << "found running process: " << processInfo.szExeFile;
CloseHandle(processesSnapshot);
return processInfo.szExeFile;
}
}
std::wcout << "no process with given pid" << aPid;
CloseHandle(processesSnapshot);
return std::wstring();
}