I have a code that inject dlls via Manual Map and works fine ( reading all bytes of file in disk ), now i want read all these bytes directly from a resource, i already tried with the following adaptation, but withou sucess until now.
Here is how is reading file from disk directly:
bool MapRemoteModule(unsigned long pId, char *module)
{
IMAGE_DOS_HEADER *dosHd;
IMAGE_NT_HEADERS *ntHd;
HANDLE hFile = CreateFile(module,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if(hFile == INVALID_HANDLE_VALUE)
return false;
unsigned int fSize;
if(GetFileAttributes(module) & FILE_ATTRIBUTE_COMPRESSED)
fSize = GetCompressedFileSize(module, NULL);
else
fSize = GetFileSize(hFile, NULL);
unsigned char *dllBin = new unsigned char[fSize];
unsigned int nBytes;
ReadFile(hFile, dllBin, fSize, (LPDWORD)&nBytes, FALSE);
CloseHandle(hFile);
...
and here is my try of adapt to work read these bytes from resource:
// Mapping.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "resource.h"
#include <windows.h>
#include <tlhelp32.h>
#include <shlwapi.h>
#include <string>
using namespace std;
#pragma comment(lib, "shlwapi.lib")
#define ID_LOADER_DLL MAKEINTRESOURCE(IDR_DLL1)
#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD_PTR)(ptr) + (DWORD_PTR)(addValue))
#define MakeDelta(cast, x, y) (cast) ( (DWORD_PTR)(x) - (DWORD_PTR)(y))
bool MapRemoteModule(unsigned long pId, LPCSTR ResName);
unsigned long GetProcessIdByName(char *);
HMODULE GetRemoteModuleHandle(unsigned long, char *);
FARPROC GetRemoteProcAddress(unsigned long, char *, char *);
bool FixImports(unsigned long, void *, IMAGE_NT_HEADERS *, IMAGE_IMPORT_DESCRIPTOR *);
bool FixRelocs(void *, void *, IMAGE_NT_HEADERS *, IMAGE_BASE_RELOCATION *, unsigned int);
bool MapSections(HANDLE, void *, void *, IMAGE_NT_HEADERS *);
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD, PIMAGE_NT_HEADERS);
LPVOID GetPtrFromRVA(DWORD, PIMAGE_NT_HEADERS, PBYTE);
__declspec(naked) void DllCall_stub(HMODULE hMod)
{
_asm
{
push 0
push 1
push [esp+0Ch]
mov eax, 0xDEADBEEF
call eax
ret
}
}
__declspec(naked) void DC_stubend(void) { }
bool MapRemoteModule(unsigned long pId, LPCSTR ResName)
{
IMAGE_DOS_HEADER *dosHd;
IMAGE_NT_HEADERS *ntHd;
HRSRC hResource;
HGLOBAL hResourceLoaded;
LPBYTE lpBuffer;
hResource = FindResource(NULL, ResName, RT_RCDATA);
if (NULL != hResource)
{
hResourceLoaded = LoadResource(NULL, hResource);
if (NULL != hResourceLoaded)
{
lpBuffer = (LPBYTE) LockResource(hResourceLoaded);
if (NULL != lpBuffer)
{
unsigned int fSize = 0;
fSize = SizeofResource(NULL, hResource);
if (fSize > 0)
{
unsigned char *dllBin = lpBuffer;
unsigned int nBytes = fSize;
dosHd = MakePtr(IMAGE_DOS_HEADER *, dllBin, 0);
if(dosHd->e_magic != IMAGE_DOS_SIGNATURE)
{
delete dllBin;
return false;
}
ntHd = MakePtr(IMAGE_NT_HEADERS *, dllBin, dosHd->e_lfanew);
if(ntHd->Signature != IMAGE_NT_SIGNATURE)
{
delete dllBin;
return false;
}
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if(!hProcess)
return false;
void *moduleBase = VirtualAllocEx(hProcess,
NULL,
ntHd->OptionalHeader.SizeOfImage,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(!moduleBase)
return false;
void *stubBase = VirtualAllocEx(hProcess,
NULL,
MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE);
if(!stubBase)
return false;
IMAGE_IMPORT_DESCRIPTOR *impDesc = (IMAGE_IMPORT_DESCRIPTOR *)GetPtrFromRVA(
(DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress),
ntHd,
(PBYTE)dllBin);
if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
{
if(!FixImports(pId,
(unsigned char *)dllBin,
ntHd,
impDesc)) return FALSE;
};
IMAGE_BASE_RELOCATION *reloc = (IMAGE_BASE_RELOCATION *)GetPtrFromRVA(
(DWORD)(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress),
ntHd,
(PBYTE)dllBin);
if(ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
{
FixRelocs(dllBin,
moduleBase,
ntHd,
reloc,
ntHd->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
}
else
{
return false;
};
WriteProcessMemory(hProcess,
moduleBase,
dllBin,
ntHd->FileHeader.SizeOfOptionalHeader + sizeof(ntHd->FileHeader) + sizeof(ntHd->Signature),
(SIZE_T *)&nBytes);
MapSections(hProcess, moduleBase, dllBin, ntHd);
VirtualProtect((LPVOID)DllCall_stub,
MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
PAGE_EXECUTE_READWRITE,
(DWORD *)&nBytes);
*MakePtr(unsigned long *, DllCall_stub, 9) =
MakePtr(unsigned long, moduleBase, ntHd->OptionalHeader.AddressOfEntryPoint);
WriteProcessMemory(hProcess,
stubBase,
(LPVOID)DllCall_stub,
MakeDelta(SIZE_T, DC_stubend, DllCall_stub),
(SIZE_T *)&nBytes);
CreateRemoteThread(hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)stubBase,
moduleBase,
0,
NULL);
delete dllBin;
return true;
}
}
}
}
return false;
}
bool MapSections(HANDLE hProcess, void *moduleBase, void *dllBin, IMAGE_NT_HEADERS *ntHd)
{
IMAGE_SECTION_HEADER *header = IMAGE_FIRST_SECTION(ntHd);
unsigned int nBytes = 0;
unsigned int virtualSize = 0;
unsigned int n = 0;
for(unsigned int i = 0; ntHd->FileHeader.NumberOfSections; i++)
{
if(nBytes >= ntHd->OptionalHeader.SizeOfImage)
break;
WriteProcessMemory(hProcess,
MakePtr(LPVOID, moduleBase, header->VirtualAddress),
MakePtr(LPCVOID, dllBin, header->PointerToRawData),
header->SizeOfRawData,
(LPDWORD)&n);
virtualSize = header->VirtualAddress;
header++;
virtualSize = header->VirtualAddress - virtualSize;
nBytes += virtualSize;
VirtualProtectEx(hProcess,
MakePtr(LPVOID, moduleBase, header->VirtualAddress),
virtualSize,
header->Characteristics & 0x00FFFFFF,
NULL);
}
return true;
}
bool FixImports(unsigned long pId, void *base, IMAGE_NT_HEADERS *ntHd, IMAGE_IMPORT_DESCRIPTOR *impDesc)
{
char *module;
bool retfix=1;
char tempstr[MAX_PATH]="";
while((module = (char *)GetPtrFromRVA((DWORD)(impDesc->Name), ntHd, (PBYTE)base)))
{
if(!GetRemoteModuleHandle(pId, module))
{
retfix=0;
break;
};
IMAGE_THUNK_DATA *itd =
(IMAGE_THUNK_DATA *)GetPtrFromRVA((DWORD)(impDesc->FirstThunk), ntHd, (PBYTE)base);
while(itd->u1.AddressOfData)
{
IMAGE_IMPORT_BY_NAME *iibn;
iibn = (IMAGE_IMPORT_BY_NAME *)GetPtrFromRVA((DWORD)(itd->u1.AddressOfData), ntHd, (PBYTE)base);
itd->u1.Function = MakePtr(DWORD, GetRemoteProcAddress(pId,
module,
(char *)iibn->Name), 0);
itd++;
}
impDesc++;
}
return retfix;
}
bool FixRelocs(void *base, void *rBase, IMAGE_NT_HEADERS *ntHd, IMAGE_BASE_RELOCATION *reloc, unsigned int size)
{
unsigned long ImageBase = ntHd->OptionalHeader.ImageBase;
unsigned int nBytes = 0;
unsigned long delta = MakeDelta(unsigned long, rBase, ImageBase);
while(1)
{
unsigned long *locBase =
(unsigned long *)GetPtrFromRVA((DWORD)(reloc->VirtualAddress), ntHd, (PBYTE)base);
unsigned int numRelocs = (reloc->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
if(nBytes >= size) break;
unsigned short *locData = MakePtr(unsigned short *, reloc, sizeof(IMAGE_BASE_RELOCATION));
for(unsigned int i = 0; i < numRelocs; i++)
{
if(((*locData >> 12) & IMAGE_REL_BASED_HIGHLOW))
*MakePtr(unsigned long *, locBase, (*locData & 0x0FFF)) += delta;
locData++;
}
nBytes += reloc->SizeOfBlock;
reloc = (IMAGE_BASE_RELOCATION *)locData;
}
return true;
}
FARPROC GetRemoteProcAddress(unsigned long pId, char *module, char *func)
{
HMODULE remoteMod = GetRemoteModuleHandle(pId, module);
HMODULE localMod = GetModuleHandle(module);
unsigned long delta = MakeDelta(unsigned long, remoteMod, localMod);
return MakePtr(FARPROC, GetProcAddress(localMod, func), delta);
}
HMODULE GetRemoteModuleHandle(unsigned long pId, char *module)
{
MODULEENTRY32 modEntry;
HANDLE tlh = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pId);
modEntry.dwSize = sizeof(MODULEENTRY32);
Module32First(tlh, &modEntry);
do
{
if(!_stricmp(modEntry.szModule, module))
return modEntry.hModule;
modEntry.dwSize = sizeof(MODULEENTRY32);
}
while(Module32Next(tlh, &modEntry));
return NULL;
}
PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva, PIMAGE_NT_HEADERS pNTHeader)
{
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
unsigned int i;
for ( i = 0; i < pNTHeader->FileHeader.NumberOfSections; i++, section++ )
{
DWORD size = section->Misc.VirtualSize;
if ( 0 == size )
size = section->SizeOfRawData;
if ( (rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + size)))
return section;
}
return 0;
}
LPVOID GetPtrFromRVA( DWORD rva, IMAGE_NT_HEADERS *pNTHeader, PBYTE imageBase )
{
PIMAGE_SECTION_HEADER pSectionHdr;
INT delta;
pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );
if ( !pSectionHdr )
return 0;
delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
return (PVOID) ( imageBase + rva - delta );
}
int _tmain(int argc, _TCHAR* argv[])
{
ULONG rc;
STARTUPINFO StartupInfo;
PROCESS_INFORMATION ProcessInfo;
memset(&StartupInfo, 0, sizeof(StartupInfo));
StartupInfo.cb = sizeof(STARTUPINFO);
StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow = SW_HIDE;
if (!CreateProcess( NULL, "c:\\windows\\system32\\notepad.exe", NULL, NULL, FALSE,
CREATE_NEW_CONSOLE,
NULL,
NULL,
&StartupInfo,
&ProcessInfo))
{
return 0;
}
WaitForSingleObject(ProcessInfo.hProcess, 5000);
if(!GetExitCodeProcess(ProcessInfo.hProcess, &rc))
rc = 0;
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
MapRemoteModule(ProcessInfo.dwProcessId, ID_LOADER_DLL);
return 0;
}
Someone could help to solve?
Related
I am trying to get the data of a registry key value, but then I encountered this error,
[bcc64 Error] AAP.h(210): invalid operands to binary expression ('const wchar_t *' and 'const wchar_t *') (also on this screenshot)
I'm pretty sure I did something wrong, or didn't do properly, (I'm new to c++)
HKEY currentKey;
TCHAR name[256];
String loly;
void fivenum()
{
DWORD dwSize = 1024;
DWORD dwIdx = 0;
long result = 0;
long fivenumberresult = 0;
result = RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft"), 0, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE | KEY_SET_VALUE, ¤tKey);
if(result != ERROR_SUCCESS)
{
// fail
}
else
{
DWORD indexs = 0;
fivenumberresult = RegEnumKeyEx(currentKey, indexs, name, &dwSize, NULL, NULL, NULL, NULL);
if(!fivenumberresult)
{
std::wstringstream box_message;
loly = box_message.str().c_str();
}
}
}
String awit;
void reg4()
{
HKEY hKey = 0;
wchar_t buf[255];
DWORD dwBufSize = sizeof(buf);
awit = _D("");
const wchar_t* xds = loly.w_str();
const wchar_t* xd = L"Software\\Microsoft\\" + xds;
if( RegOpenKeyExW(HKEY_CURRENT_USER,xd,0,KEY_QUERY_VALUE,&hKey) == ERROR_SUCCESS)
{
if(RegQueryValueExW(hKey,L"14770",0, 0, (BYTE*)buf, &dwBufSize) == ERROR_SUCCESS)
{
std::wstringstream box_messagess;
for(DWORD i = 0; i < dwBufSize; ++i)
{
box_messagess << IntToHex(static_cast<int>(buf[i]), 2).c_str() << _D(",");
}
awit = box_messagess.str().c_str();
}
}
}
As you know there is some difference between a process name and it's description, for example the dwm.exe process's description is Desktop Window Manager
I can check the name of the processes with this code:
#include <windows.h>
#include <TlHelp32.h>
#include <Winternl.h>
typedef NTSTATUS (NTAPI *NTQUERYINFORMATIONPROCESS)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
int main()
{
PEB Peb = {0};
DWORD dwSize = 0;
DWORD dwPID = 0;
HANDLE hProcess = NULL;
HANDLE hProcessSnap = NULL;
WCHAR PsPath[MAX_PATH] = {0};
WCHAR wszProcName[20] = L"dwm.exe"; //Desktop Window Manager
PROCESSENTRY32 PsEntry32 = {0};
PROCESS_BASIC_INFORMATION PsBasicInfo = {0};
RTL_USER_PROCESS_PARAMETERS RtlUserPsParams = {0};
NTQUERYINFORMATIONPROCESS NtFunction = NULL;
if((hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) != INVALID_HANDLE_VALUE)
{
PsEntry32.dwSize = sizeof(PROCESSENTRY32);
if(!Process32First(hProcessSnap, &PsEntry32))
{
CloseHandle(hProcessSnap);
return FALSE;
}
do
{
if(lstrcmpiW(PsEntry32.szExeFile, wszProcName) == 0)
{
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PsEntry32.th32ProcessID);
if(hProcess != INVALID_HANDLE_VALUE)
{
NtFunction = (NTQUERYINFORMATIONPROCESS)GetProcAddress(LoadLibraryW(L"ntdll.dll"), "NtQueryInformationProcess");
if(NtFunction)
{
if(NtFunction(hProcess, ProcessBasicInformation, &PsBasicInfo, sizeof(PROCESS_BASIC_INFORMATION), &dwSize) == ERROR_SUCCESS)
{
ReadProcessMemory(hProcess, PsBasicInfo.PebBaseAddress, &Peb, sizeof(PEB), (SIZE_T*)&dwSize);
ReadProcessMemory(hProcess, Peb.ProcessParameters, &RtlUserPsParams, sizeof(RTL_USER_PROCESS_PARAMETERS), (SIZE_T*)&dwSize);
ReadProcessMemory(hProcess, RtlUserPsParams.ImagePathName.Buffer, PsPath, RtlUserPsParams.ImagePathName.Length, (SIZE_T*)&dwSize);
dwPID = PsEntry32.th32ProcessID;
}
}
CloseHandle(hProcess);
}
}
}while(Process32Next(hProcessSnap, &PsEntry32));
CloseHandle(hProcessSnap);
}
return 0;
}
now I want to check the processes description
Is it possible to get all processes description one by one and check them?
I use ToolHelp32Snapshot() to get the module path instead of your PEB method, following that I:
GetFileVersionInfoSizeA() to get the size of the version structure
GetFileVersionInfoA() to pull the data from that structure into a local char array.
VerQueryValue() with "\VarFileInfo\Translation" to get the language code pages
Then I loop through the different language code pages to create the subblock string required for the next query.
Then I use VerQueryValue() with the correct language code page inserted inside the sub block and store the result into another char array.
Then we print this string to console.
#include <iostream>
#include <string>
#include <Windows.h>
#include <TlHelp32.h>
#include <strsafe.h>
#pragma comment(lib,"Version.lib")
std::string GetModulePath(std::string moduleName, DWORD procId)
{
std::string path;
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, moduleName.c_str()))
{
path = modEntry.szExePath;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return path;
}
std::string GetFilePath(std::string procName)
{
std::string path;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (Process32First(hSnap, &procEntry))
{
do
{
if (!_stricmp(procEntry.szExeFile, procName.c_str()))
{
path = GetModulePath(procName, procEntry.th32ProcessID);
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return path;
}
struct LANGANDCODEPAGE {
WORD wLanguage;
WORD wCodePage;
};
int main()
{
std::string path = GetFilePath("notepad++.exe");
DWORD verSize = GetFileVersionInfoSizeA(path.c_str(), 0);
char* data = new char[verSize]{ 0 };
GetFileVersionInfoA(path.c_str(), 0, verSize, data);
UINT length;
LANGANDCODEPAGE* lpTranslate;
VerQueryValue(data, "\\VarFileInfo\\Translation", (LPVOID*)&lpTranslate, &length);
char SubBlock[50]{ 0 };
for (unsigned int i = 0; i < (length / sizeof(struct LANGANDCODEPAGE)); i++)
{
HRESULT result = StringCchPrintf(SubBlock, 50,
TEXT("\\StringFileInfo\\%04x%04x\\FileDescription"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage);
char* description = new char[0x100]{ 0 };
UINT length2;
VerQueryValue(data, SubBlock, (LPVOID*)&description, &length2);
std::cout << description << "\n";
}
getchar();
return 0;
}
Must run as administrator, and only tested on x86.
I have this code in C++/VS2013/Win7x64, the app is compiled in 64-bit
CString strKey=_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\SharedDLLs");
CRegKeyEx reg;
// Count entries
if (reg.Open(HKEY_LOCAL_MACHINE, strKey, KEY_ALL_ACCESS) != ERROR_SUCCESS)
return;
if (reg.QueryInfo() != ERROR_SUCCESS) return;
dwCountEntries = reg.GetValuesCount();
This is the CRegKeyEx class
ifndef __REGKEYEX_H__INCLUDED__
#define __REGKEYEX_H__INCLUDED__
#include <atlbase.h>
//
// Enhanced version of ATL's CRegKey class
// After you open/attach the key, you should call QueryInfo in order
// to initialize some members which this class use.
//
class CRegKeyEx : public CRegKey
{
public:
// Retreives information about the key
LONG QueryInfo();
// Number of subkeys
DWORD GetSubKeysCount() { return m_cSubKeys; }
// Number of values
DWORD GetValuesCount() { return m_cValues; }
// Enumerate values of arbitrary type
// allocate space in ppBuff (you have to free() it)
LONG EnumValue(DWORD dwIndex, CString& strName,
LPBYTE* ppBuff, DWORD* pBuffSize, DWORD* pType);
// Enum value as String
// *pType will be REG_SZ or REG_EXPAND_SZ
LONG EnumValue(DWORD dwIndex, CString& strName, CString& strValue, DWORD* pType);
// EnumKey with CString output
LONG EnumKey(DWORD dwIndex, CString& strName);
protected:
DWORD m_cSubKeys;
DWORD m_cMaxSubKeyLen;
DWORD m_cValues;
DWORD m_cMaxValueNameLen;
DWORD m_cMaxValueLen; // this is in bytes (can be any kind of data)
};
// ---- implementation ----
// Retreives information about the key
inline LONG CRegKeyEx::QueryInfo()
{
LONG ret;
m_cSubKeys = 0;
m_cMaxSubKeyLen = 0;
m_cValues = 0;
m_cMaxValueNameLen = 0;
m_cMaxValueLen = 0;
ret = ::RegQueryInfoKey(m_hKey,
NULL, NULL, NULL,
&m_cSubKeys, &m_cMaxSubKeyLen,
NULL,
&m_cValues, &m_cMaxValueNameLen, &m_cMaxValueLen,
NULL, NULL);
// include the terminating NULL character(s)
m_cMaxSubKeyLen++;
m_cMaxValueNameLen++;
return ret;
}
// Enumerate values of arbitrary type
// allocate space in ppBuff (you have to free() it)
inline LONG CRegKeyEx::EnumValue(DWORD dwIndex,
CString& strName,
LPBYTE* ppBuff,
DWORD* pBuffSize,
DWORD* pType)
{
TCHAR *pName;
DWORD cName;
LPBYTE pBuff = NULL;
DWORD dwBuffSize = 0;
DWORD dwType;
LONG ret;
// Allocate space for buffers
pName = (TCHAR*)malloc(m_cMaxValueNameLen * sizeof(TCHAR));
cName = m_cMaxValueNameLen;
if (ppBuff != NULL) // data may not be required
{
pBuff = (LPBYTE)malloc(m_cMaxValueLen);
dwBuffSize = m_cMaxValueLen;
}
// Retreive name and data
ret = ::RegEnumValue(m_hKey, dwIndex,
pName, &cName,
NULL, &dwType,
pBuff, pBuff ? &dwBuffSize : NULL);
if (ret != ERROR_SUCCESS)
{
free(pName);
free(pBuff);
return ret;
}
// Resize the buffers
pName = (TCHAR*)realloc(pName, (cName + 1) * sizeof(TCHAR));
if (pBuff)
pBuff = (LPBYTE)realloc(pBuff, dwBuffSize);
if (ppBuff)
*ppBuff = pBuff;
if (pBuffSize)
*pBuffSize = dwBuffSize;
if (pType)
*pType = dwType;
strName = pName;
free(pName);
return ERROR_SUCCESS;
}
// Enum value as String
// *pType will be REG_SZ or REG_EXPAND_SZ
inline LONG CRegKeyEx::EnumValue(DWORD dwIndex,
CString& strName,
CString& strValue,
DWORD* pType)
{
DWORD dwType;
LPBYTE pBuff;
LONG ret;
ret = EnumValue(dwIndex, strName, &pBuff, NULL, &dwType);
if (ret != ERROR_SUCCESS)
return ret;
if (pType)
*pType = dwType;
if (dwType == REG_SZ || dwType == REG_EXPAND_SZ)
{
strValue = (TCHAR*)pBuff;
free(pBuff);
}
else
{
free(pBuff);
return ERROR_INVALID_DATATYPE;
}
return ERROR_SUCCESS;
}
// EnumKey with CString output
inline LONG CRegKeyEx::EnumKey(DWORD dwIndex, CString& strName)
{
TCHAR *pName;
DWORD dwLen;
LONG ret;
// Allocate space for buffers
dwLen = m_cMaxSubKeyLen;
pName = (TCHAR*)malloc(dwLen * sizeof(TCHAR));
memset(pName, 0, dwLen * sizeof(TCHAR));
ret = CRegKey::EnumKey(dwIndex, pName, &dwLen, NULL);
strName = pName;
free(pName);
return ret;
}
#endif __REGKEYEX_H__INCLUDED__
The registry key have 1725 values and GetValuesCount returns only 762 !
I'd like to have a function that allows me to read the memory of another process.
I was thinking about something like this (pseudo code):
staticAddress = 0x026E0DC4
processId = GetProcessIdByName(processName)
processHandle = GetProcessHandle(processId)
processBaseAddress = GetBaseAddress(processHandle)
addressToRead = processBaseAddress+staticAddress
readValueAsInt = ReadMemoryInt(processHandle, addressToRead)
readValueAsFloat = ReadMemoryFloat(processHandle, addressToRead)
readValueAsString = ReadMemoryString(processHandle, addressToRead)
Would that even be possible?
Here is what I got so far:
#include <Windows.h>
#include <conio.h>
#include <tlhelp32.h>
#include <string>
#include <psapi.h>
#pragma comment( lib, "psapi" )
int GetProcessId(char* ProcName) {
PROCESSENTRY32 pe32;
HANDLE hSnapshot = NULL;
pe32.dwSize = sizeof( PROCESSENTRY32 );
hSnapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( Process32First( hSnapshot, &pe32 ) ) {
do {
if( strcmp( pe32.szExeFile, ProcName ) == 0 )
break;
} while( Process32Next( hSnapshot, &pe32 ) );
}
if( hSnapshot != INVALID_HANDLE_VALUE )
CloseHandle( hSnapshot );
return pe32.th32ProcessID;
}
int GetModuleBase(HANDLE processHandle, string &sModuleName)
{
HMODULE *hModules;
char szBuf[50];
DWORD cModules;
DWORD dwBase = -1;
//------
EnumProcessModules(processHandle, hModules, 0, &cModules);
hModules = new HMODULE[cModules/sizeof(HMODULE)];
if(EnumProcessModules(processHandle, hModules, cModules/sizeof(HMODULE), &cModules)) {
for(int i = 0; i < cModules/sizeof(HMODULE); i++) {
if(GetModuleBaseName(processHandle, hModules[i], szBuf, sizeof(szBuf))) {
if(sModuleName.compare(szBuf) == 0) {
dwBase = (DWORD)hModules[i];
break;
}
}
}
}
delete[] hModules;
return dwBase;
}
int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 4; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int ReadMemoryFloat(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 8; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int ReadMemoryString(HANDLE processHandle, LPCVOID address) {
//LPVOID buffer = ??;
//SIZE_T size = ??;
SIZE_T NumberOfBytesToRead = 999; //??
ReadProcessMemory(processHandle, address, buffer, size, NumberOfBytesToRead)
return buffer; //??
}
int main()
{
//read an integer from "Program.exe"+0x05D8A3C4
int address = 0x05D8A3C4;
char* processName = "Program.exe";
int processId = GetProcessId(processName);
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
int processBaseAddress = GetModuleBase(processHandle, (string)"Program.exe";
LPCVOID actualAddress = processBaseAddress+address;
int readValue = ReadMemory(processHandle, actualAddress);
std::cout << readValue << std::endl;
CloseHandle(processHandle);
return 0;
}
As you can see form the question marks in the code I'm really unsure about the "buffer" and "size" parameters of ReadProcessMemory. I'd really appreciate it if someone could help me figuring this out.
https://github.com/T-vK/Memory-Hacking-Class
Is a pretty simple class to do all that and even more.
Here is a list with all the methods it supports:
GetProcessId()
GetModuleBase()
SetPrivilege()
GetDebugPrivileges()
ReadInt()
GetPointerAddress()
ReadPointerInt()
ReadFloat()
ReadPointerFloat()
ReadText()
ReadPointerText()
Example usage:
#include "Memory.hpp"
using std::string;
int main() {
char* TARGET_PROCESS_NAME = "League of Legends.exe";
int GAME_VERSION_MODULE_OFFSET = 0x2A1D738; // [Base address of 'League of Legends.exe']+0x2A1D738 (address of a string containing a version number)
Memory Memory;
Memory.GetDebugPrivileges();
int processId = Memory.GetProcessId(TARGET_PROCESS_NAME);
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
int baseAddress = Memory.GetModuleBase(processHandle, (string)TARGET_PROCESS_NAME);
int gameVersionAddress = baseAddress + GAME_VERSION_MODULE_OFFSET;
string gameVersion = Memory.ReadText(processHandle, gameVersionAddress);
std::cout << "Game version: " << gameVersionAddress << std::endl;
cin.get();
return 0;
}
In case you were wondering, yes, I'm the author.
Here is an example for your ReadMemoryInt() function:
int ReadMemoryInt(HANDLE processHandle, LPCVOID address) {
int buffer = 0;
SIZE_T NumberOfBytesToRead = sizeof(buffer); //this is equal to 4
SIZE_T NumberOfBytesActuallyRead;
BOOL err = ReadProcessMemory(processHandle, address, &buffer, NumberOfBytesToRead, &NumberOfBytesActuallyRead);
if (err || NumberOfBytesActuallyRead != NumberOfBytesToRead)
/*an error occured*/ ;
return buffer;
}
The & mean that the address of the variable is passed instead its value.
And in ReadMemoryString() you cannot know the actual size you need to read, you could either read a big block (size 999) or read many little blocks till you get one containing \0.
And if you want to know if it works, you can start it in a debugger and look if the values you expect are returned.
I have a foreign process (exe-file DllProj.exe is running), that has SampleDll.dll linked to it (implicit linking). I can find the base address of the linked dll with the help of my function imageBase(), but not the base address of the process itself! What is the difference and why it's not working as is?
I mean, this code returns pBase with correct DOS/NT-headers:
LPVOID pBase = imageBase("DllProj.exe", "SampleDll.dll");
if (!pBase)
return false;
PIMAGE_DOS_HEADER pDosHeader = PIMAGE_DOS_HEADER((HMODULE)pBase);
if (::IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ||
IMAGE_DOS_SIGNATURE != pDosHeader->e_magic)
return false;
but this code return is FALSE:
LPVOID pBase = imageBase("DllProj.exe", "DllProj.exe");
//and so on...
Here is my procedure:
LPVOID imageBase(LPSTR szVictimProcess, LPSTR szVictim)
{
//находим процесс szVictimProcess
DWORD aProcesses[1024], cbNeeded, nProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return NULL;
nProcesses = cbNeeded / sizeof(DWORD);
HANDLE ProcHandle = 0;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
for (i = 0; i < nProcesses; i++)
{
ProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
if (NULL != ProcHandle)
{
HMODULE hMod[1024];
if ( EnumProcessModules(ProcHandle, hMod, sizeof(hMod), &cbNeeded) )
{
GetModuleBaseName(ProcHandle, hMod[0], szProcessName, sizeof(szProcessName)/sizeof(TCHAR)); // Get the process name
if (0 == lstrcmpiA(szVictimProcess, szProcessName))
{
//находим модуль szVictim
DWORD nModules = cbNeeded / sizeof(HMODULE);
char szModName[MAX_PATH];
for (unsigned int j = 0; j < nModules; j++)
{
if (GetModuleFileNameEx(ProcHandle, hMod[j], szModName, sizeof(szModName))) // Get the module name
{
shortName(szModName);
if (0 == lstrcmpiA(szModName, szVictim))
{
MODULEINFO info;
GetModuleInformation(ProcHandle, hMod[j], &info, sizeof(info));
return info.lpBaseOfDll;
//Equal To:
//return hMod[j];
//Debug:
//LPSTR string = new char[256];
//wsprintf(string,"\t%s (0x%08X)\n", szModName, hMod[j]);
}
}
}
break;
}
}
}
CloseHandle(ProcHandle);
}
return NULL;
}
P.S.: My next goal is to get import-table of DllProj.exe (where Sample.dll is) and hiijack dll's function call
What about using this:
#pragma comment( lib, "psapi" )
DWORD GetModuleBase(HANDLE hProc, string &sModuleName)
{
HMODULE *hModules;
char szBuf[50];
DWORD cModules;
DWORD dwBase = -1;
//------
EnumProcessModules(hProc, hModules, 0, &cModules);
hModules = new HMODULE[cModules/sizeof(HMODULE)];
if(EnumProcessModules(hProc, hModules, cModules/sizeof(HMODULE), &cModules)) {
for(int i = 0; i < cModules/sizeof(HMODULE); i++) {
if(GetModuleBaseName(hProc, hModules[i], szBuf, sizeof(szBuf))) {
if(sModuleName.compare(szBuf) == 0) {
dwBase = (DWORD)hModules[i];
break;
}
}
}
}
delete[] hModules;
return dwBase;
}
Credit to answer here
There is nothing wrong with your code, I compiled your code and it works fine and outputs the correct address to console. Make sure you run as administrator. This is the project using your code which I tested working:
#include <windows.h>
#include <iostream>
#include <psapi.h>
#include <string>
void shortName(LPSTR strToChange)
{
std::string path(strToChange);
std::string filename;
size_t pos = path.find_last_of("\\");
if (pos != std::string::npos)
filename.assign(path.begin() + pos + 1, path.end());
else
filename = path;
lstrcpy(strToChange, filename.data());
}
LPVOID imageBase(LPSTR szVictimProcess, LPSTR szVictim)
{
DWORD aProcesses[1024], cbNeeded, nProcesses;
unsigned int i;
if (!EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded))
return NULL;
nProcesses = cbNeeded / sizeof(DWORD);
HANDLE ProcHandle = 0;
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
for (i = 0; i < nProcesses; i++)
{
ProcHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, aProcesses[i]);
if (NULL != ProcHandle)
{
HMODULE hMod[1024];
if (EnumProcessModules(ProcHandle, hMod, sizeof(hMod), &cbNeeded))
{
GetModuleBaseName(ProcHandle, hMod[0], szProcessName, sizeof(szProcessName) / sizeof(TCHAR)); // Get the process name
if (0 == lstrcmpiA(szVictimProcess, szProcessName))
{
DWORD nModules = cbNeeded / sizeof(HMODULE);
char szModName[MAX_PATH];
for (unsigned int j = 0; j < nModules; j++)
{
if (GetModuleFileNameEx(ProcHandle, hMod[j], szModName, sizeof(szModName))) // Get the module name
{
shortName(szModName);
if (0 == lstrcmpiA(szModName, szVictim))
{
MODULEINFO info;
GetModuleInformation(ProcHandle, hMod[j], &info, sizeof(info));
return info.lpBaseOfDll;
}
}
}
break;
}
}
}
CloseHandle(ProcHandle);
}
return NULL;
}
int main(void)
{
void* base = imageBase((char*)"ac_client.exe", (char*)"ac_client.exe");
std::cout << "0x" << std::hex << base;
}