Im looking for a method/function that i can use to get base address of "program.exe"+03262C08 -> B4895A0. This address is from Cheat Engine and base address has been found with Pointer scanner. In pointer scanner i can press show module list and there is address of program.exe starting at address 00400000 program.exe. Pointer scanner was scanned for address 09c3000(The address which i want to reach after base address+many offsets[the final address]). This address is base for certain object but i cant reach the address. I'm able to get only base address of exe file at 00400000. I'm trying to add offsets from pointer 03262C08(and the others) but i cant still reach the address. I cant use function FindWindow(). Becouse a name of the program will be changing and it will be redundant to stick with it. I'm using OpenProcess(), EnumProcessModulesEx(), GetModuleFileNameEx() functions. I have tried others as well like GetModuleInformation(),... with the same result. GetModuleHandle() ended with result 0x126 [ERROR_MOD_NOT_FOUND]. I'm using 64 bit OS and I'm trying to get base address of another process.
I can see all processes on local machine and modules of "program" process.
if (!K32EnumProcesses(aProcesses, sizeof(aProcesses), &cbNeeded)) {
return 1;
}
cProcesses = cbNeeded / sizeof(DWORD);
cout << setw(15) << left << "Process ID" << setw(10) << left << "Modules";
cout << setw(30) << left << "Process Name" << endl;
for (i = 0; i < cProcesses; i++) {
if (aProcesses[i] != 0) {
ProcessView::GetProccesses(aProcesses[i], modules, sizeModules, &cModules, &hCurrProcess);
if (hCurrProcess != NULL) {
cout << endl << setw(15) << left << aProcesses[i] << setw(10) << left << cModules;
ProcessView::PrintModuleName(hCurrProcess, modules);
CloseHandle(hCurrProcess);
}
}
}
ProcessView::GetProccesses(cProcesses, modules, sizeModules, &cModules, &hCurrProcess);
system("cls");
ProcessView::PrintModuleNameAll(hCurrProcess, modules, cModules);
I added here definition of function in example from ProcessView.h file that i have created.
static void GetProccesses(_In_ DWORD processID, _Inout_ HMODULE ahModules[], _In_ int sizeModules, _Out_ DWORD* cModules, _Out_ HANDLE* hProcess);
static void PrintModuleName(_In_ HANDLE processID, _In_ HMODULE* modules);
static void PrintModuleNameAll(_In_ HANDLE hProcess, _In_ HMODULE * modules, _In_ DWORD cModules);
Windows has been using Address Space Layout Randomization for about a decade now, but the module base in EXE's is far older than that. Simply ignore it, it's now meaningless.
And don't forget: each process has its own address space. A pointer in one process is meaningless in the other.
To use ReadProcessMemory or WriteProcessMemory on an address which is found via pointer chain on a process and dynamically get the module base address at runtime you need to accomplish these steps:
Find the Process with ToolHelp32Snapshot
Find the Module with ToolHelp32Snapsho
Get a handle to the process with correct permissions
Walk the pointer chain, de-referencing and adding offsets
Then you can Call ReadProcessMemory or WriteProcessMemory
You must run as administrator
For this example I will use a simple assault cube cheat I've made
#include <iostream>
#include <vector>
#include <Windows.h>
#include "proc.h"
int main()
{
//Get ProcId of the target process
DWORD procId = GetProcId(L"ac_client.exe");
//Getmodulebaseaddress
uintptr_t moduleBase = GetModuleBaseAddress(procId, L"ac_client.exe");
//Get Handle to Process
HANDLE hProcess = 0;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, procId);
//Resolve base address of the pointer chain
uintptr_t dynamicPtrBaseAddr = moduleBase + 0x10f4f4;
std::cout << "DynamicPtrBaseAddr = " << "0x" << std::hex << dynamicPtrBaseAddr << std::endl;
//Resolve our ammo pointer chain
std::vector<unsigned int> ammoOffsets = { 0x374, 0x14, 0x0 };
uintptr_t ammoAddr = FindDMAAddy(hProcess, dynamicPtrBaseAddr, ammoOffsets);
std::cout << "ammoAddr = " << "0x" << std::hex << ammoAddr << std::endl;
//Read Ammo value
int ammoValue = 0;
ReadProcessMemory(hProcess, (BYTE*)ammoAddr, &ammoValue, sizeof(ammoValue), nullptr);
std::cout << "Curent ammo = " << std::dec << ammoValue << std::endl;
//Write to it
int newAmmo = 1337;
WriteProcessMemory(hProcess, (BYTE*)ammoAddr, &newAmmo, sizeof(newAmmo), nullptr);
//Read out again
ReadProcessMemory(hProcess, (BYTE*)ammoAddr, &ammoValue, sizeof(ammoValue), nullptr);
std::cout << "New ammo = " << std::dec << ammoValue << std::endl;
getchar();
return 0;
}
The header file proc.cpp:
DWORD GetProcId(const wchar_t* procName)
{
DWORD procId = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 procEntry;
procEntry.dwSize = sizeof(procEntry);
if (Process32First(hSnap, &procEntry))
{
do
{
if (!_wcsicmp(procEntry.szExeFile, procName))
{
procId = procEntry.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &procEntry));
}
}
CloseHandle(hSnap);
return procId;
}
uintptr_t GetModuleBaseAddress(DWORD procId, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
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 (!_wcsicmp(modEntry.szModule, modName))
{
modBaseAddr = (uintptr_t)modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
uintptr_t FindDMAAddy(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}
Related
I've successfully injected a .dll into an .exe and need to access a value through multi level pointers.
This is a working example that's getting the correct value:
#include <Windows.h>
#include <iostream>
#include <vector>
#include <TlHelp32.h>
#include <tchar.h>
using namespace std;
DWORD dwGetModuleBaseAddress(TCHAR *lpszModuleName, DWORD pID)
{
DWORD dwBaseAddress = 0;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pID);
MODULEENTRY32 moduleEntry32 = { 0 };
moduleEntry32.dwSize = sizeof(MODULEENTRY32);
if (Module32First(hSnapshot, &moduleEntry32))
{
do {
if (_tcscmp(moduleEntry32.szModule, lpszModuleName) == 0)
{
dwBaseAddress = (DWORD)moduleEntry32.modBaseAddr;
break;
}
} while (Module32Next(hSnapshot, &moduleEntry32));
}
CloseHandle(hSnapshot);
return dwBaseAddress;
}
int main()
{
DWORD pID;
DWORD off1, off2, off3, off4, off5;
DWORD baseAddress;
DWORD xAddress;
int newX;
int currentX;
char moduleName[] = "TibiaInjected2.exe";
HWND hGameWindow;
HANDLE pHandle;
// Getting handles
hGameWindow = FindWindowA(NULL, "Tibia - 127.0.0.1:7171");
GetWindowThreadProcessId(hGameWindow, &pID);
pHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
// Getting base address
DWORD clientBase = dwGetModuleBaseAddress(_T(moduleName), pID);
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x0031D0CC), &baseAddress, sizeof(baseAddress), NULL);
cout << "Base address: " << hex << baseAddress << endl;
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x4), &off1, sizeof(off1), NULL);
cout << "Offset 1: " << hex << off1 << endl;
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x4), &off2, sizeof(off2), NULL);
cout << "Offset 2: " << hex << off2 << endl;
ReadProcessMemory(pHandle, (LPCVOID)(off2 + 0xA0), &off3, sizeof(off3), NULL);
cout << "Offset 3: " << hex << off3 << endl;
ReadProcessMemory(pHandle, (LPCVOID)(off3 + 0x100), &off4, sizeof(off4), NULL);
cout << "Offset 4: " << hex << off4 << endl;
ReadProcessMemory(pHandle, (LPCVOID)(off4 + 0x14), &off5, sizeof(off5), NULL);
cout << "Offset 5: " << hex << off5 << endl;
cin.get();
}
I'd rather use my statically injected DLL and from what I've heard I can replace the whole dwGetModuleBaseAddress with GetModuleHandle(NULL) since it's from within the injected DLL. I also don't need to open any process. But if I don't do all that, what to replace the ReadProcessMemory with?
ReadProcessMemory(pHandle, (LPCVOID)(clientBase + 0x0031D0CC), &baseAddress, sizeof(baseAddress), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(baseAddress + 0x4), &off1, sizeof(off1), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off1 + 0x4), &off2, sizeof(off2), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off2 + 0xA0), &off3, sizeof(off3), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off3 + 0x100), &off4, sizeof(off4), NULL);
ReadProcessMemory(pHandle, (LPCVOID)(off4 + 0x14), &off5, sizeof(off5), NULL);
I've managed to access value from static addresses directly by doing:
int* exampleValue = *(int*)0x12345678;
But can't figure out how to do the same with pointers and offset.
Yes you can use GetModuleHandle(NULL); to get the handle to the main .exe module or replace NULL with a string that matches the DLL name.
You can use this function that loops through the offsets, de-referencing and adding offsets at each level:
uintptr_t FindDMAAddy(uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size() ; ++i)
{
addr = *(uintptr_t*)addr;
addr += offsets[i];
}
return addr;
}
uintptr_t ammoAddr = FindDMAAddy(dynamicPtrBaseAddr, { 0x374, 0x14, 0x0 });
//or
int * ammoAddr = (int*)FindDMAAddy(dynamicPtrBaseAddr, { 0x374, 0x14, 0x0 });
You could also do some crazy thing like:
int * ammo = (int*)((*(uintptr_t*)((*(uintptr_t*)(dynamicPtrBaseAddr)) +0x374)) + 0x14);
But it's more confusing and annoying than it's worth.
This worked for me (could be put in a loop like the other answer did):
DWORD base = *(DWORD*)(clientBase + 0x0031D0CC);
DWORD offsets[] = { 0x4, 0x4, 0xA0, 0x100, 0x14 };
DWORD off1 = *(DWORD*)(base + offsets[0]);
DWORD off2 = *(DWORD*)(off1 + offsets[1]);
DWORD off3 = *(DWORD*)(off2 + offsets[2]);
DWORD off4 = *(DWORD*)(off3 + offsets[3]);
DWORD off5 = *(DWORD*)(off4 + offsets[4]);
cout << "Value: " << off5 << endl;
So I'm trying to read Memory out of a running exe with ReadProcessMemory() as you can see in the code provided below.
The only problem I constantly run into is that I receive the Error 3E6 / 998 which seems to be NOACCESS but I cant find a solution to fix this.
And yes I tried to run the exe in Admin Mode without success...
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
using namespace std;
int id = NULL;
HANDLE hProcess = NULL;
int getPID(const string name);
bool setHandle(int id, HANDLE &out);
DWORD64 GetModule(const string name);
int main()
{
bool success = false;
id = getPID("sample.exe");
string name = "SAMPLE";
cout << "Process Name: " << name << endl;
cout << "Process ID: " << id << endl;
success = setHandle(id, hProcess);
if (success)
{
cout << "Handle set..." << endl;
}
else if (!success)
{
cout << "You need to have SOMETHING opened..." << endl;
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
success = false;
DWORD64 baseAddress = GetModule("sample.exe");
DWORD64 ammo = 0x24ED13273A8;
DWORD64 addr = baseAddress + ammo;
cout << "Base Address: " << hex << uppercase << "0x" << baseAddress << endl;
cout << "Ammo Address: " << hex << uppercase << "0x" << ammo << endl;
cout << "Complete Address: " << hex << uppercase << "0x" << addr << endl;
int buffer = 0;
success = ReadProcessMemory(hProcess, (LPCVOID)addr, (LPVOID)&buffer, sizeof(&buffer), NULL);
if (success)
{
cout << "ReadProccess succeeded..." << endl;
system("pause");
return 0;
}
else if (!success)
{
cout << "ERROR CODE: " << GetLastError() << endl;
system("pause");
return 1;
}
system("pause");
return 0;
}
bool setHandle(int id, HANDLE &out)
{
out = OpenProcess(PROCESS_ALL_ACCESS, FALSE, id);
if (!out) return false;
return true;
}
int getPID(const string name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(const string name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
string modName = szModName;
if (modName.find(name) != string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
I'm kinda new to c++... so sry? :)
There are actually two basic mistakes in your code, both of which, unfortunately for you, me and the rest of the civilised world, generate the same error code. Was it ever thus. There is also a logic error, but you are lucky enough to be getting away with it (just about). I commented the fix in the code I posted below.
There are also a number of 'good practise' shortcomings in your code, specifically:
NULL should not be used to represent integer zero
All error conditions should be checked for and (sensibly!) reported
You use the same string literal in two different places (so if you ever change it, you would need to change it in both places, and you might forget). So don't do that.
using namespace std; is widely frowned upon (because it causes such a lot of namespace pollution)
Why are id and hProcess global variables? This is just plain unnecessary.
You should give your functions more descriptive names, setHandle being the one I particularly have in mind. I got rid of that one completely.
When passing a std::string as a read-only function parameter, it is usually best to pass it as const ref, then it doesn't need to be copied.
Only use std::endl when you actually want to flush the buffer. It is inefficient.
Clean up after you (in this case, close any open handles). I know this is just a throwaway program but it's a good habit to get into.
OK, so here's some code that works (I have posted my own because I cleaned up all of the above). The substantive changes are:
To read the memory of another process, you need to give your user token the SE_DEBUG_NAME privilege. This in turn means you need to run your program as Administrator (aka elevated).
You cannot (obviously) read from a nonsense address in the target process so I just quietly fixed that.
Like I say, both of these generate the same error code. Huh!
OK, here you go. Enjoy:
#include <Windows.h>
#include <iostream>
#include <string>
#include <tlhelp32.h>
#include <Psapi.h>
#include <tchar.h>
int getPID(const std::string& name);
DWORD64 GetModule(HANDLE hProcess, const std::string& name);
// Stolen from: https://learn.microsoft.com/en-gb/windows/desktop/SecAuthZ/enabling-and-disabling-privileges-in-c--
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if ( !LookupPrivilegeValue(
NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid ) ) // receives LUID of privilege
{
printf("LookupPrivilegeValue error: %u\n", GetLastError() );
return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
if ( !AdjustTokenPrivileges(
hToken,
FALSE,
&tp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL) )
{
printf("AdjustTokenPrivileges error: %u\n", GetLastError() );
return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{
printf("The token does not have the specified privilege. \n");
return FALSE;
}
return TRUE;
}
constexpr const char* theProcess = "notepad.exe";
int main()
{
HANDLE hToken;
BOOL ok = OpenProcessToken (GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken);
if (!ok)
{
std::cout << "OpenProcessToken failed, error " << GetLastError() << "\n";
return 255;
}
ok = SetPrivilege (hToken, SE_DEBUG_NAME, TRUE);
if (!ok)
{
CloseHandle (hToken);
return 1;
}
int pid = getPID (theProcess);
HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL)
{
std::cout << "OpenProcess failed, error " << GetLastError() << "\n";
CloseHandle (hToken);
return 1;
}
DWORD64 baseAddress = GetModule(hProcess, theProcess);
std::cout << "Base Address: " << std::hex << std::uppercase << "0x" << baseAddress << "\n";
int buffer = 0; // Note: sizeof (buffer) below, not sizeof (&buffer)
ok = ReadProcessMemory(hProcess, (LPCVOID)baseAddress, (LPVOID)&buffer, sizeof(buffer), NULL);
CloseHandle (hProcess);
CloseHandle (hToken);
if (ok)
{
std::cout << "ReadProcessMemory succeeded, buffer = " << buffer << "\n";
system("pause");
return 0;
}
std::cout << "ReadProcessMemory failed, error " << GetLastError() << "\n";
system("pause");
return 1;
}
int getPID(const std::string& name)
{
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (!Process32First(snapshot, &entry)) return NULL;
do
{
if (strcmp(entry.szExeFile, name.c_str()) == 0)
{
CloseHandle(snapshot);
return entry.th32ProcessID;
}
} while (Process32Next(snapshot, &entry));
CloseHandle(snapshot);
return NULL;
}
DWORD64 GetModule(HANDLE hProcess, const std::string& name)
{
HMODULE hMods[1024];
DWORD cbNeeded;
if (EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for (int i = 0; i < (cbNeeded / sizeof(HMODULE)); i++)
{
TCHAR szModName[MAX_PATH];
if (GetModuleFileNameEx(hProcess, hMods[i], szModName, sizeof(szModName) / sizeof(TCHAR)))
{
std::string modName = szModName;
if (modName.find(name) != std::string::npos)
{
return (DWORD64)hMods[i];
}
}
}
}
return NULL;
}
Output (when run as Administrator):
Base Address: 0x7FF6D8470000
ReadProcessMemory succeeded, buffer = 905A4D
Output (when run as a normal user):
The token does not have the specified privilege.
You can also grab some code over at GitHub.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
There are probably several post that explain my problem in several ways... But I have been searching in google and stackoverflow searchbox and I didn't found anything. So here I go.
I want to Write in a Process Memory a String Changing it in c++, but I don't even know clearly how it work so..
I have this pointer:
Image of the pointer
Please, can someone help me doing it?
I've tried it but it's not working..
#include <windows.h>
#include <iostream>
int main() {
HWND hWnd = FindWindow(0, "WindowName");
if (hWnd == 0) {
std::cout << "Cannot find window." << std::endl;
}
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
DWORD baseAddress = 0x009B03D0;
DWORD offset = 0xA7;
DWORD ptrAddress;
char *newString = "newvalue";
ReadProcessMemory(hProc, (void*)baseAddress, &ptrAddress, sizeof(DWORD), 0);
WriteProcessMemory(hProc, (void*)(ptrAddress + offset), newString, strlen(newString), 0);
std::cout << "Done. " << &ptrAddress << std::endl;
std::getchar();
}
I should get the pointer and jumpt to the last one because I only have one offset.. But I'm not getting the correct one..
Edit:
Here is my new code, it works until the WriteProcessMemory function.. What can be wrong?
CODE THAT ACTUALLY WORKS:
int main()
{
unsigned long Pointer; /* to hold the final value */
unsigned long temp; /* hold the temp values */
unsigned long address = 0x009B03D0;
unsigned long offset = 0xA7;
unsigned long newString = 0;
DWORD pid;
HWND hwnd;
hwnd = FindWindow(0, TEXT("NewWindow"));
if (!hwnd)
{
cout << "No!\n";
cin.get();
}
else
{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (!phandle)
{
cout << "None!\n";
cin.get();
}
else
{
while (1)
{
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(address), &temp, sizeof(temp), 0);
Pointer = temp + offset;
//Good
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(Pointer), &newString, 16, 0);
cout << reinterpret_cast<LPVOID>(Pointer) << " en " << newString;
Sleep(1000);
}
return 0;
}
}
}
CODE THAT NOT WORK:
int main()
{
unsigned int Pointer; /* to hold the final value */
unsigned int temp; /* hold the temp values */
unsigned int address = 0x009B03D0;
unsigned int offset = 0xA7;
unsigned int newString = 1768060259;
DWORD pid;
HWND hwnd;
hwnd = FindWindow(0, TEXT("NewWindow"));
if (!hwnd)
{
cout << "NO\n";
cin.get();
}
else
{
GetWindowThreadProcessId(hwnd, &pid);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (!phandle)
{
cout << "NONE\n";
cin.get();
}
else
{
while (1)
{
ReadProcessMemory(phandle, reinterpret_cast<LPVOID>(address), &temp, sizeof(temp), 0);
Pointer = temp + offset;
//Good
if (!WriteProcessMemory(phandle, reinterpret_cast<LPVOID>(Pointer), &newString, sizeof(newString), 0))
std::cerr << "Couldn't write process memory:" << GetLastError() << std::endl;
cout << reinterpret_cast<LPVOID>(Pointer) << " en " << newString;
Sleep(1000);
}
return 0;
}
}
}
Each process has its own memory and address space. So ReadProcessMemory() and WriteProcessMemory() use an intermediary buffer to do their job of accessing memory of another process.
Unfortunately, there are issues with your ReadProcessMemory() call:
you don't initialise ptrAddress to point to a buffer
you pass the address of ptrAddress and not its value that should point to a valid buffer
you pass 0 (i.e. a nullptr) instead of passing the address of the zie variable that should contain the number of bytes that could be read.
Note also that you manage the address in the target process using a DWORD for a LPCVOID. The first is always 32 bits, while the latter depend on your compiling options (32 bit code or 64 bit code).
You should also verify the error code in case of failure. It is almost certain taht special priviledges are required to read/write in distinct processes.
Here an adjusted code, with some diagnosis messages to help you further.
HWND hWnd = FindWindow(0, TEXT("WindowName") );
if (hWnd == 0) {
std::cerr << "Cannot find window." << std::endl;
}
else {
DWORD pId;
GetWindowThreadProcessId(hWnd, &pId);
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
if (hProc) {
char *newString = "newvalue";
size_t sz = strlen(newString) + 1;
LPVOID baseAddress = (LPVOID)0x009B03D0;
DWORD offset = 0xA7;
LPVOID ptrAddress = new char[sz];
SIZE_T bytes_read = 0, bytes_written=0;
if (ReadProcessMemory(hProc, baseAddress, ptrAddress, sz, &bytes_read) || GetLastError()== ERROR_PARTIAL_COPY) {
if (bytes_read == 0)
std::cerr << "Houston, we have a problem..." << std::endl;
if(!WriteProcessMemory(hProc, baseAddress, (LPCVOID)newString, sz, &bytes_written))
std::cerr << "Couldn't write process memory:" << GetLastError() << std::endl;
std::cout << "Done. " << bytes_read <<" bytes read and "<<bytes_written<<" bytes written"<< std::endl;
}
else {
std::cerr<< "Couldn't read process memory:" << GetLastError() << std::endl;
}
delete[] ptrAddress;
}
else {
std::cerr << "Couldn't open process " << pId << ": " << GetLastError() << std::endl;
}
}
std::getchar();
I have written DLL injector, to inject i use NtCreateThread to create remote thread into remote process
I work on 64 bit OS - Windows 7
To comiple i use
32 bit - g++ (tdm-2) 4.8.1
64 bit - g++ (tdm64-1) 5.1.0
Problem concerns 64 bit verion of my injector
I have 2 problems
1)
OK. My injector sometimes work and sometimes not work.
I dont know what is reason.
This is problematic line
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, (LPVOID)ntbuffer );
When i call function NtCreateThreadEx and in last argument is pointer to NtCreateThreadExBuffer, it not work.
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, **ntbuffer** );
When i give in last parametr NULL it works and I DONT KNOW WHY.
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, **NULL** );
Any idea?
2)
I use NtCreateThreadEx because i want inject code to SYSTEM PROCESS (like csrss.exe) because i like BSoD :).
Unfortunately, my injector can inject code ONLY to process in this same session.
Reason is ?Session Separation? (implemented on Vista and every later OS)
It is rise why i cannot use CreateRemoteThread
I have thought when i use NtCreateThreadEx separation of sessions is not a problem.
I try inject DLL to process in sesion 0.
I tried reduce the privileges
I replaced:
HProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
on
HProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, PID);
etc. but it not work.
Can you tell me why NtCreateThreadEx() works in admin mode, but not in standard mode ?
Maby i should use other undocumented functions (like NtCreateThreadEx) for example NtOpenProcess to get handle to process with all access?
I need any idea what i should doing. Please help me.
#include <iostream>
#include <string>
#include <windows.h>
struct NtCreateThreadExBuffer;
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress, LPVOID lpSpace);
BOOL EnableDebugPrivilege();
int main()
{
int PIDOfProcess = 0;
std::string pathToDLL = "dll64.dll\0"; ///find DLL in local directory
DWORD PID = (DWORD)PIDOfProcess; ///PID
HANDLE HProcess = NULL; ///Handle to process
LPVOID LibAddr = NULL; ///Address of procedure 'LoadLibraryA'
LPVOID DllAdr = NULL; ///Address of memory in other process
HANDLE hThread = NULL; ///Handle to remote thread
int WirteStatus = 0; ///Status of writing to memory of other process
std::cout << "Get PID of process" << std::endl;
std::cin >> PIDOfProcess;
PID = (DWORD)PIDOfProcess;
if(EnableDebugPrivilege() == true)
{
std::cout << "Debug privilege was enabled with status: "<< GetLastError() << " [OK]" << std::endl;
}else std::cout << "Debug privilege was not enabled: "<< GetLastError() << " [FAILED]" << std::endl;
/*
NtOpenProcess(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK AccessMask,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN PCLIENT_ID ClientId );*/
/// NtOpenProcess();
HProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, FALSE, PID);
if(HProcess == NULL)
{
std::cout << "Could not find process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "Process opened: [OK]" << std::endl;
DllAdr = (LPVOID)VirtualAllocEx(HProcess, NULL, pathToDLL.size() +1, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(DllAdr == NULL)
{
std::cout << "Cannot allocate memory in remote process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "Region of memory in remote process allocated: [OK]" << std::endl;
WirteStatus = WriteProcessMemory(HProcess, (LPVOID)DllAdr, pathToDLL.c_str() ,pathToDLL.size()+1, NULL);
if(WirteStatus == 0)
{
std::cout << "Could not write to process's address space: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "A memory has written name of DLL: [OK]" << std::endl;
LibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(LibAddr == NULL)
{
std::cout << "Unable to locate LoadLibraryA: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
} std::cout << "A address of procedure LoadLibraryA has found [OK]" << std::endl;
hThread = NtCreateThreadEx(HProcess,LibAddr,DllAdr);
if(hThread == NULL)
{
std::cout << "Could not create remote thread on process: "<< GetLastError() << " [FAILED]" << std::endl;
system("pause");
return GetLastError();
}
system("pause");
}
struct NtCreateThreadExBuffer///This information is derived based on reverse engineering work.
{
ULONG Size;
ULONG Unknown1;
ULONG Unknown2;
PULONG Unknown3;
ULONG Unknown4;
ULONG Unknown5;
ULONG Unknown6;
PULONG Unknown7;
ULONG Unknown8;
};
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpSpace)
{
///The prototype of NtCreateThreadEx from undocumented.ntinternals.com
///typ_zwracanej_wartości (__konwencja_wywolania*nazwa_wskaźnika)(typ1 argument1, typ2 argument2);
/* 2OOO, 11 November http://undocumented.ntinternals.net/
NTSYSAPI NTSTATUS NTAPI NtCreateThread(
OUT PHANDLE ThreadHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN HANDLE ProcessHandle,
OUT PCLIENT_ID ClientId,
IN PCONTEXT ThreadContext,
IN PINITIAL_TEB InitialTeb,
IN BOOLEAN CreateSuspended );*/
typedef LONG64 (WINAPI * functypeNtCreateThreadEx)(
PHANDLE ThreadHandle, ///Handle to thread which will be created /// OUT
ACCESS_MASK DesiredAccess, ///possible: GENERIC_WRITE GENERIC_READ GENERIC_EXECUTE GENERIC_ALL//// IN
LPVOID ObjectAttributes, /// IN,OPTIONAL
HANDLE ProcessHandle, ///Handle to our process /// IN
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
/*DWORD*/LONG64 dwStackSize,
LONG64 SizeOfStackCommit,
LONG64 SizeOfStackReserve,
LPVOID lpBytesBuffer ///pointer to initialized object of NtCreateThreadExBuffer
);
NtCreateThreadExBuffer * ntbuffer = NULL;
HANDLE hRemoteThread = NULL;
HMODULE hNtDllModule = NULL;
functypeNtCreateThreadEx funcNtCreateThreadEx = NULL;
ntbuffer = new NtCreateThreadExBuffer;
memset (ntbuffer,0,sizeof(NtCreateThreadExBuffer));///fill buffer zeros
DWORD temp1 = 0;
DWORD temp2 = 0;
ntbuffer->Size = sizeof(NtCreateThreadExBuffer);
ntbuffer->Unknown1 = 0x10003;
ntbuffer->Unknown2 = 0x8;
ntbuffer->Unknown3 = &temp2;
ntbuffer->Unknown4 = 0;
ntbuffer->Unknown5 = 0x10004;
ntbuffer->Unknown6 = 4;
ntbuffer->Unknown7 = &temp1;
ntbuffer->Unknown8 = 0;
//Get handle for ntdll which contains NtCreateThreadEx
hNtDllModule = GetModuleHandle( "ntdll.dll" );
if ( hNtDllModule == NULL )
{
std::cout << "Cannot get module ntdll.dll error: " << GetLastError() << std::endl;
return NULL;
} std::cout << "A 'ntdll.dll' module has got: "<< GetLastError() << " [OK]" << std::endl;
funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress( hNtDllModule, "NtCreateThreadEx" );
if ( !funcNtCreateThreadEx )
{
std::cout << "Cannot get procedure address error: " << GetLastError() << std::endl;
return NULL;
} std::cout << "'NtCreateThreadEx' has executed: "<< GetLastError() << " [OK]" << std::endl;
///Here is problem - when in last argument i replace NULL
funcNtCreateThreadEx( &hRemoteThread,GENERIC_EXECUTE /*GENERIC_ALL 0x1FFFFF/*Może tu jest błąd*/, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, ntbuffer );
std::cout << "_______________________________________ " << std::endl;
std::cout << "NtCreateThreadEx' has status: " << GetLastError() << std::endl;
std::cout << "hRemoteThread: " << hRemoteThread << std::endl;
std::cout << "State of handle to DLL: " << hNtDllModule << std::endl;
std::cout << "Addres of prcoedure NtCreateThreadEx: " << funcNtCreateThreadEx << std::endl;
return hRemoteThread;
}
BOOL EnableDebugPrivilege()
{
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken ))
{
return FALSE;
}
if(!LookupPrivilegeValue( NULL, SE_DEBUG_NAME, &luid ))
{
return FALSE;
}
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = luid;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges( hToken, false, &tkp, sizeof( tkp ), NULL, NULL ))
{
return FALSE;
}
if(!CloseHandle( hToken ))
{
return FALSE;
}
return TRUE;
}
try: zwcreatethreatex function.
typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx");
if (NULL == ZwCreateThreadEx)
{
ShowError("GetProcAddress_ZwCreateThread");
return FALSE;
}
I have written DLL injector. I used CreateRemoteThread to inject my DLL to process and all was good.
Now i am trying inject DLL to process by undocumented function - NtCreateThreadEx. I have written injector but he is not working.
When i use 32 bit injector to inject 32 bit DLL to 32 bit process
all working good.
Problem is when i use 64 bit injector to inject 64 bit DLL to 64 bit process.
My DLL code:
#include <windows.h>
///Compilation with option -m64
extern "C" BOOL __stdcall DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
MessageBox( NULL, "MESSAGE FROM 64 BIT DLL", "Lorem ipsum", MB_ICONINFORMATION | MB_OKCANCEL );
return 0;
}
My TestApp code
#include <iostream>
#include <windows.h>
int main()
{
std::cout << " Lorem IPSUM" << std::endl;
//HMODULE HDLL = LoadLibraryA("dll64.dll");
//std::cout << "Error: " << GetLastError() << std::endl;
while(1)
{
std::cout << "petla" << std::endl;
Sleep(5000);
}
return 0;
}
My injector code:
#include <iostream>
#include <string>
#include <windows.h>
/// 64 bit OS - Windows 7
///=====================
///* In this same user context ("User")
///TYPE OF(32/64 bits)
///INJECTOR===DLL===PROCESS===RESULT
/// 32 32 32 -SUCESS
/// 64 64 64 -FALIED (error: 1300)
//Handle to process,Address of'LoadLibraryA',see DllAdr
///TO DO
///* Inject DLL to process from normal user context ("User") to higher user context (Zarzadca)
///* Inject DLL to process from normal user context ("User") to other normal user context (User1)
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress, LPVOID lpSpace);
int privileges();
int main()
{
int PIDOfProcess = 0;
std::string pathToDLL = "dll64.dll\0"; ///find DLL in local directory
DWORD PID = (DWORD)PIDOfProcess; ///PID
HANDLE HProcess = NULL; ///Handle to process
LPVOID LibAddr = NULL; ///Address of procedure 'LoadLibraryA'
LPVOID DllAdr = NULL; ///Address of memory in other process
HANDLE hThread = NULL; ///Handle to remote thread
int WirteStatus = 0; ///Status of writing to memory of other process
std::cout << "ptr size = " << sizeof(void *) << std::endl;
std::cout << "Get PID of process" << std::endl;
std::cin >> PIDOfProcess;
PID = (DWORD)PIDOfProcess;
///std::cout << "Get path to DLL" << std::endl;
///std::cin >> pathToDLL;
if( privileges() != 0 )
{
std::cout << "Cannot get the right privileges" << std::endl;
}
HProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if(HProcess == NULL)
{
std::cout << "Could not find process" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
DllAdr = (LPVOID)VirtualAllocEx(HProcess, NULL, pathToDLL.size() +1, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if(DllAdr == NULL)
{
std::cout <<"Can not allocate memory." << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
WirteStatus = WriteProcessMemory(HProcess, (LPVOID)DllAdr, pathToDLL.c_str() ,pathToDLL.size()+1, NULL);
if(WirteStatus == 0)
{
std::cout << "Could not write to process's address space" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
LibAddr = (LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
if(LibAddr == NULL)
{
std::cout << "Unable to locate LoadLibraryA" << std::endl;
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
hThread = NtCreateThreadEx(HProcess,LibAddr,DllAdr);
///DWORD threadId = 0;
///hThread = CreateRemoteThread(HProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LibAddr, DllAdr, 0, &threadId);
if(hThread == NULL)
{
std::cout << "Error: ";
std::cout << GetLastError() << std::endl;
system("pause");
return GetLastError();
}
system("pause");
}
HANDLE NtCreateThreadEx(HANDLE hProcess,LPVOID lpBaseAddress,LPVOID lpSpace)
{
///The prototype of NtCreateThreadEx from undocumented.ntinternals.com
typedef DWORD (WINAPI * functypeNtCreateThreadEx)(
PHANDLE ThreadHandle,
ACCESS_MASK DesiredAccess,
LPVOID ObjectAttributes,
HANDLE ProcessHandle,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
BOOL CreateSuspended,
DWORD dwStackSize,
DWORD Unknown1,
DWORD Unknown2,
LPVOID Unknown3
);
HANDLE hRemoteThread = NULL;
HMODULE hNtDllModule = NULL;
functypeNtCreateThreadEx funcNtCreateThreadEx = NULL;
//Get handle for ntdll which contains NtCreateThreadEx
hNtDllModule = GetModuleHandle( "ntdll.dll" );
if ( hNtDllModule == NULL )
{
std::cout << "Cannot get module ntdll.dll error: " << GetLastError() << std::endl;
return NULL;
}
funcNtCreateThreadEx = (functypeNtCreateThreadEx)GetProcAddress( hNtDllModule, "NtCreateThreadEx" );
if ( !funcNtCreateThreadEx )
{
std::cout << "Cannot get procedure address error: " << GetLastError() << std::endl;
return NULL;
}
funcNtCreateThreadEx( &hRemoteThread, /*GENERIC_ALL*/0x1FFFFF, NULL, hProcess, (LPTHREAD_START_ROUTINE)lpBaseAddress, lpSpace, FALSE, NULL, NULL, NULL, NULL );
std::cout << "Status NtCreateThreadEx " << GetLastError() << std::endl;
std::cout << "hRemoteThread: " << hRemoteThread << std::endl;
std::cout << "hNtDllModule: " << hNtDllModule << std::endl;
std::cout << "funcNtCreateThreadEx: " << funcNtCreateThreadEx << std::endl;
return hRemoteThread;
}
int privileges()
{
HANDLE Token;
TOKEN_PRIVILEGES tp;
if(OpenProcessToken( GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,&Token)) ///It opens the access token associated with a process.
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);///Function retrieves the locally unique identifier (LUID)
tp.PrivilegeCount = 1;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(Token, false, &tp, sizeof(tp), NULL, NULL) != 0)///Function enables or disables privileges in the specified access token.
{
return 0; //OK
}
}
return 1;
}
When i use 64 bit injector to inject 64 bit DLL to 64 bit process, function NtCreateThreadEx return code of error 1300 and my DLL doesn't execute.
I use to compile on 64 bit architecture: g++ (tdm64-1) 5.1.0
I am working on Virus Windows 7 64 bit as normal user. Run as administrator doesn't help.
I dont know why it doesn't work, what i doing wrong.
PS: When i use 32 bit injector to inject 32 bit DLL to 32 bit process, function NtCreateThreadEx return code of error 1300 but my DLL execute.
In 32 bit version TestApp GetLastError return code 1114.
I use to compile on 32 bit architecture: g++ (tdm-2) 4.8.1
I include image
I based on:
http://www.p-programowanie.pl/cpp/dll-injection/ - Dll Injection (polish)
====
http://www.codeproject.com/Questions/369890/Ask-about-NtCreateThreadEx-in-Window-x
- Ask about NtCreateThreadEx in Window 7 x64!
=====
http://www.rohitab.com/discuss/topic/39535-code-injections-beginner-and-advanced/ Code Injections [beginner and advanced]
=====
http://securityxploded.com/ntcreatethreadex.php Remote Thread Execution in System Process using NtCreateThreadEx for Vista & Windows7
=====
http://cpp0x.pl/dokumentacja/WinAPI/Systemowe-kody-bledow-1300-1699/1470 Systemowe kody błędów (1300-1699) (polish)
Link to my topic on other forum (polish): http://forum.4programmers.net/C_i_C++/267735-dll_injection_w_windows_za_pomoca_nieudokumentowanej_funkcji_w_winapi?p=1234215#id1234215
My injector is working when i use him to inject DLL to other process in my user space (i am working as normal user)
but it is not working when
i am injecting to csrss.exe (or other system's process).
I get code of error 5 - Access Denied, when i run injector as Administrator i get code of error 0 (SUCCESS?) but my DLL not aborting process
( abort() - i try do BSoD).
I read about Session Separation and i think it is reason of my problem so i have one question: How i can hacking Windows :)
If it is imposibble can i inject DLL as normal user to proces in Administrator context (or other normal user's process) ?