I've created a GUI DLL injector in QT Creator using the MinGW 32bit compiler and keep getting this reoccurring issue where I'll click inject and it won't inject the DLL but it will however scramble my DLL path.
Example: Example Screenshot
The first path is the DLL after converting it the correct type
Last DLL is the DLL after the process
The address is the address where the DLL is located in the target process
0 is GetLastError()
The code DLL path conversion:
QString fileInput = ui->filesCmb->currentText(); //gets dll
dllPath = fileInput.toStdString().c_str(); //converts dll to string
qDebug() << dllPath << "\n";
The injection Process code:
QString methodChosen = ui->methodCmb->currentText();
QString targetProcess = ui->processTxt->text();
const wchar_t* tgtProc = (const wchar_t*)targetProcess.utf16();
if (methodChosen == "Manual Map") {
ui->statusTxt->setPlainText("Method not added[" + methodChosen + "]");
} else if (methodChosen == "LdrLoadDLL") {
ui->statusTxt->setPlainText("Method not added[" + methodChosen + "]");
} else {
ui->statusTxt->setPlainText("File input: " + fileInput + "\n" + "Method: " + methodChosen + "\n" + "Target Process: " + targetProcess + "\n" + "Dll path: " + dllPath + "\n");
DWORD pid = getPid(tgtProc);
dwordToQstring = QString::number(pid);
HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, NULL, pid);
if (!pHandle || pHandle == INVALID_HANDLE_VALUE) {
ui->statusTxt->setPlainText("Couldn't get handle[" + dwordToQstring + "]");
}
LPVOID pDllPath = VirtualAllocEx(pHandle, 0, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE); // allocate memeory within our target process to fit our dll
if (pDllPath != nullptr) {
WriteProcessMemory(pHandle, pDllPath, (LPVOID)dllPath, strlen(dllPath) + 1, 0); //writes our dll to the allocated memory
HANDLE hLoad = CreateRemoteThread(pHandle, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("Kernel32.dll"), "LoadLibraryA"), pDllPath, 0, 0); //creates a thread in the target process to allow out code to run
if (hLoad != nullptr) {
WaitForSingleObject(hLoad, INFINITE); //maybe waits for our dll code to execute?
ui->statusTxt->setPlainText("File input: " + fileInput + "\n" + "Method: " + methodChosen + "\n" + "Target Process: " + targetProcess + "\n" + "PID: " + dwordToQstring + "\n" + "INJECTED");
qDebug() << "LastDLL=>" << dllPath << "\n";
qDebug() << &pDllPath;
qDebug() << GetLastError();
VirtualFreeEx(pHandle, pDllPath, strlen(dllPath) + 1, MEM_RELEASE); // free the memory allocated for out dll
}
}
}
I haven't tried a lot of solutions only a few different conversion techniques, but they didn't change anything, any idea on what is causing this weird output?.
Thanks in advance.
EDIT: Thought I had fixed it but it seems to occur completely randomly sometimes it works sometimes it doesn't really confused.
Related
I am trying to inject a simple dll that creates a MessageBox in the target process. Using a injector from the www works without any issues. However using my own code to inject does not do anything at all (I am using it on notepad.exe)
I compiled both dll and this code as x64 debug in VS2017. Injector is created as Win32 console project.
All the stages in the code passes. I get a handle to the process and also the thread handle is valid. However the GetExitCode returns 0 so it fails all the time but I do not know why?
HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
if (process == NULL)
{
std::cout << "Error opening process." << std::endl;
return false;
}
const char * dllString = "C:\\test.dll";
// load memory for dll
int bytes = sizeof(dllString);
PVOID mem = VirtualAllocEx(process, NULL, sizeof(dllString) + 1, MEM_COMMIT, PAGE_READWRITE);
if (mem == NULL)
{
std::cout << "Unable to allocate mem." << std::endl;
CloseHandle(process);
return false;
}
// write dll path to that location
SIZE_T bytesWritten;
BOOL status = WriteProcessMemory(process, mem, dllString, sizeof(dllString) + 1, &bytesWritten);
if (!status)
{
std::cout << "Writing dll path failed." << std::endl;
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
return false;
}
FARPROC loadLibrary = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
HANDLE thread = CreateRemoteThread(process, NULL, NULL, reinterpret_cast<LPTHREAD_START_ROUTINE>(loadLibrary), mem, NULL, NULL);
if (thread == INVALID_HANDLE_VALUE)
{
std::cout << "Unable to create thread in remote process. " << std::endl;
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
}
WaitForSingleObject(thread, INFINITE);
DWORD exitCode = 0;
GetExitCodeThread(thread, &exitCode);
if (exitCode != 0)
std::cout << "DLL loaded successfully." << std::endl;
else
std::cout << "DLL loading failed." << std::endl;
CloseHandle(thread);
VirtualFreeEx(process, mem, sizeof(dllString) + 1, MEM_RELEASE);
CloseHandle(process);
return true;
Just solved it myself. Actually a noob issue. sizeof in fact is returning the size of the pointer with is 64bits for x64 and not the length of the string for the memory I needed to allocate. So after changing it to strlen it worked.
my problem is the following:
I have a UI created in Visual Studio with C++/CLI.
Now I have a button event that creates a process which runs a C++ Console Application with Parameters.
This works fine, the console application gets executed with parameters with no errors and im also seeing the console window with the right output.
But I still get an exception:
StandardOut has not been redirected or the process hasn't started yet.
I think this has something to do with the Streamreader and some DataReceivedEvents but I have no clue.
This is my code:
try {
String^ parameters = tbLoadXML->Text + " " + tbNumberAnts->Text + " " + tbIteration->Text + " " + tbReduction->Text + " " + tbPheromoneDeposit->Text + " " + tbPheromoneReduction->Text + " " + tbAlpha->Text + " " + tbBeta->Text + " " + reduce.ToString() + " " + algorithm.ToString() + " " + probabilityalgorithm.ToString() + " " + numbercities.ToString();
Process^ process = gcnew Process();
process->StartInfo->UseShellExecute = false;
process->StartInfo->CreateNoWindow = true;
process->StartInfo->RedirectStandardOutput = true;
process->Start("TSPACO.exe", parameters);
StreamReader^ reader = process->StandardOutput;
String^ output = reader->ReadToEnd();
textBox1->Text += output;
process->WaitForExit();
process->Close();
}
catch (Exception^ ex) {
MessageBox::Show(ex->Message);
}
I also tried a while-loop:
while (!process->StandardOutput->EndOfStream)
{
textBox1->Text += process->StandardOutput->ReadLine();
}
But nothing really works - I have no idea why.
So I figured out a solution for my problem - I have no clue why this works but I think the trick is to create a ProcessStartInfo-Object with all the needed properties and then just use the default method of Process::Start without any parameters:
ProcessStartInfo^ startInfo = gcnew ProcessStartInfo();
startInfo->FileName = "TSPACO.exe";
startInfo->Arguments = parameters;
startInfo->UseShellExecute = false;
startInfo->CreateNoWindow = true;
startInfo->RedirectStandardOutput = true;
Process^ process = gcnew Process();
process->StartInfo = startInfo;
process->Start();
StreamReader^ reader = process->StandardOutput;
String^ output = reader->ReadToEnd();
textBox1->Text += output;
process->WaitForExit();
process->Close();
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;
I am able to create a shared memory object, as well as open it using the guide from MSDN.
The first process creates it and keeps it open.
The second process inputs a string.
Then the first process will attempt to recover that string and display it, however I can't seem to get anything. It's always empty although it seems like the writing part is set up correctly.
I write a string to memory like this:
int MemoryMapper::Write(const std::string& data) {
m_pBuffer = (LPCTSTR)MapViewOfFile(m_OpenHandle, FILE_MAP_ALL_ACCESS, 0, 0, m_BufferSize);
if (m_pBuffer == NULL)
{
std::cerr << m_DebugErrorTitle << "Write(): " << MM_ERROR_MAPPING_FAILED << " {" << GetLastError() << "}" << std::endl;
Close();
return 0;
}
const char* cdata = _CharFromString(data);
int size = (lstrlen(cdata) * sizeof(const char*));
CopyMemory((PVOID)m_pBuffer, cdata, size);
m_WrittenSize += size;
if (m_Debug > 1) { std::cout << m_DebugTitle << "Wrote " << size << " bytes." << std::endl; }
return size;
}
Then I read it like so:
int MemoryMapper::Read(std::string& data) {
m_pBuffer = (LPCTSTR) MapViewOfFile(m_OpenHandle, FILE_MAP_ALL_ACCESS, 0, 0, m_BufferSize);
if (m_pBuffer == NULL)
{
std::cerr << m_DebugErrorTitle << "Read(" << m_MemoryName << "): " << MM_ERROR_MAPPING_FAILED << " {" << GetLastError() << "}" << std::endl;
Close();
return 0;
}
MessageBox(NULL, m_pBuffer, TEXT("TEST MESSAGE"), MB_OK);
int size = (lstrlen(m_pBuffer) * sizeof(const char*));
UnmapViewOfFile(m_pBuffer);
return size;
}
m_pBuffer is a LPCTSTR and m_BufferSize is 1024.
The name speficied for the object is the same on both ends. I've already made sure the creation and opening/closing part works.
The second process writes '8312.000000,8312.000000', a total of 92 bytes according to the code.
The reader's buffer is empty.
What am I doing wrong?
I've tried various data types, char, const char, string, tchar - same result.
8312.000000,8312.000000 is 23 characters in length.
std::string::c_str() returns a null-terminated char* pointer. lstrlen() returns the number of characters up to but not including the null terminator.
Write() is multiplying the string length by sizeof(const char*), which is 4 in a 32-bit process (8 in a 64-bit process). Write() is exceeding the bounds of data and attempting to copy 23 * 4 = 92 bytes into m_pBuffer. cdata is guaranteed to point at a buffer containing 24 bytes max (23 characters + 1 null terminator), so Write() is reaching into surrounding memory. That is undefined behavior, and anything could happen. In your case, you probably just ended up copying extra garbage into m_pBuffer. Write() could have easily crashed instead.
In fact, if data has more than 256 characters, Write() WOULD crash, because it would be trying to copy 257+ * 4 > 1024 bytes into m_pBuffer - more than MapViewOfFile() mapped access for.
You should be multiplying the string length by sizeof(std::string::value_type) instead, which is sizeof(char), which is always 1 (so you could just omit the multiplication).
Read() has the same sizeof() mistake, but it is also making the assumption that m_pBuffer is always null-terminated when calling lstrlen() and MessageBox(), but Write() does not guarantee that a null terminator is always present.
With that said, try something more like this instead:
int MemoryMapper::Write(const std::string& data)
{
// include the null terminator if there is room...
DWORD size = std::min(data.size() + 1, m_BufferSize);
char *pBuffer = (char*) MapViewOfFile(m_OpenHandle, FILE_MAP_WRITE, 0, 0, size);
if (!pBuffer)
{
DWORD errCode = GetLastError();
std::cerr << m_DebugErrorTitle << "Write(): " << MM_ERROR_MAPPING_FAILED << " {" << errCode << "}" << std::endl;
Close();
return 0;
}
CopyMemory(pBuffer, data.c_str(), size);
UnmapViewOfFile(pBuffer);
m_WrittenSize += size;
if (m_Debug > 1) {
std::cout << m_DebugTitle << "Wrote " << size << " bytes." << std::endl;
}
return size;
}
int MemoryMapper::Read(std::string& data)
{
char *pBuffer = (char*) MapViewOfFile(m_OpenHandle, FILE_MAP_READ, 0, 0, m_BufferSize);
if (!pBuffer)
{
DWORD errCode = GetLastError();
std::cerr << m_DebugErrorTitle << "Read(" << m_MemoryName << "): " << MM_ERROR_MAPPING_FAILED << " {" << errCode << "}" << std::endl;
Close();
return 0;
}
// check for a null terminator, but don't exceed the buffer...
char *terminator = std::find(pBuffer, pBuffer + m_BufferSize, '\0');
std::size_t len = std::distance(pBuffer, terminator);
data.assign(pBuffer, len);
UnmapViewOfFile(pBuffer);
MessageBoxA(NULL, data.c_str(), "TEST MESSAGE", MB_OK);
// include the null terminator if it was read...
return std::min(len + 1, m_BufferSize);
}
Well, i want to learn about hooking, but it seems that the tutorials found on the internet won't run.
What i want to do is a jump hook, in C++.
Here's the code :
void DoHook(DWORD* Address, DWORD* Hook, DWORD pid){
HANDLE Server = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ , false, pid );
Address = (DWORD*)Address + 0x18;
DWORD OldProt;
DWORD HookOffset = (DWORD*)Hook-(DWORD*)Address-5;
std::wcout << "Hook on address" << std::hex << Address<< std::endl;
std::wcout << "Hook offset is " << std::hex << HookOffset << std::endl;
if ( ! VirtualProtectEx(Server, (LPVOID) Address, 40,PAGE_EXECUTE_READWRITE, &OldProt) ) {
ErrorExit(L"VirtualProtectEx");
};
char* CharPointer = (char*) Address;
BYTE newdata[5]={0xE9};
BYTE x;
int i = 1;
while ( HookOffset > 0 ) {
x = HookOffset & 0xff;
newdata[5-i] = x;
i++;
HookOffset >>= 8;
}
std::wcout << "Bytes " <<newdata[0] << " " << newdata[1] << " " << newdata[2] << " " << newdata[3] << " " << newdata[4] << std::endl;
DWORD newdatasize = sizeof(newdata);
if ( ! WriteProcessMemory(Server,Address,(LPCVOID*)newdata,newdatasize,NULL) ) {
ErrorExit(L"WriteProcessMemory");
}
// VirtualProtect((void*) Address, 40, 0x40, &OldProt);
return;
}
Here's some output text :
Process ID is 2764 // PID of the app that's being hooked
Function address is 00A81190 // this is the function i'm doing the jump to
Entry point is 00080000 // for the app that's being hooked
Hook on address 00080060 // for the app that's being hooked
Hook offset is 28048e // HookAddress - FunctionAddress - 5
Bytes e9 0 28 4 8e // this is the jump i'm planning to do
Press any key to continue . . .
However, the application doesn't update.
You must run your program as administrator to have correct permissions to write to process memory. Here is my x86 detour function which I have tested and used many times
bool Detour32(char* src, char* dst, const intptr_t len)
{
if (len < 5) return false;
DWORD curProtection;
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);
intptr_t relativeAddress = (intptr_t)(dst - (intptr_t)src) - 5;
*src = (char)'\xE9';
*(intptr_t*)((intptr_t)src + 1) = relativeAddress;
VirtualProtect(src, len, curProtection, &curProtection);
return true;
}
src is the address you want to place the hook, dst is the address where you want to jump to. len is the number of bytes you are going to destroy with your jmp. The jmp is 5 bytes so if you're destroying instructions which are more than 5 bytes, you need copy more than 5 of the "stolen bytes" into your destination to ensure they get executed.