So I'm trying to inject a debug dll on my test process that just says "hello world" upon being successfully injected:
PS: I'm using C++/CLI to launch my C++ script from an interface.
hello.dll
// dllmain.cpp : Defines the entry point for the DLL application.
#include "pch.h"
#include <windows.h>
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD reason,
LPVOID lpReserved
)
{
if (reason == DLL_PROCESS_ATTACH)
MessageBox(NULL, L"HELLO WORLD", L"INFO", NULL);
return TRUE;
}
Below is the part of my code which takes this dll, allocates memory in the target process, writes the dll path to the latter allocated space. LoadLibraryA is then called to run the DLL from the path. However when I attach my vstudio debugger to the target process while injecting the DLL it crashes at the LoadLibraryA function with an error:
ntldll.dll rangechecks out of range access
PSS: the callstack just contains ntdll.dll functions
Injection code:
char* dll_path = "C:/some_path/hello.dll";
HANDLE h_process = OpenProcess(PROCESS_ALL_ACCESS, NULL, debug_app_id);
HANDLE allocatedMemory = VirtualAllocEx(h_process, 0, MAX_PATH, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(h_process, allocatedMemory, dll_path, strlen(dll_path) + 1, nullptr);
HANDLE h_thread = CreateRemoteThread(h_process, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, allocatedMemory, 0, 0);//crashes here
cout << "Success!" << endl;
cout << endl;
cout << "Cleaning..." << endl;
CloseHandle(h_process);//dropping process handle
VirtualFreeEx(h_process, allocatedMemory, NULL, MEM_RELEASE);//release pointed to memory
Any ideas?
EDIT: when I try to allocate the memory I get System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt
Thanks in advance.
Related
I have two files, the file which I'll use to load the Dll into the process is the following:
#include <Windows.h>
int main()
{
// path to our dll
LPCSTR DllPath = any_path;
// Open a handle to target process
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 26188);
// Allocate memory for the dllpath in the target process
// length of the path string + null terminator
LPVOID pDllPath = VirtualAllocEx(hProcess, 0, strlen(DllPath) + 1,
MEM_COMMIT, PAGE_READWRITE);
// Write the path to the address of the memory we just allocated
// in the target process
WriteProcessMemory(hProcess, pDllPath, (LPVOID)DllPath,
strlen(DllPath) + 1, 0);
// Create a Remote Thread in the target process which
// calls LoadLibraryA as our dllpath as an argument -> program loads our dll
HANDLE hLoadThread = CreateRemoteThread(hProcess, 0, 0,
(LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("Kernel32.dll"),
"LoadLibraryA"), pDllPath, 0, 0);
// Wait for the execution of our loader thread to finish
WaitForSingleObject(hLoadThread, INFINITE);
// Free the memory allocated for our dll path
VirtualFreeEx(hProcess, pDllPath, strlen(DllPath) + 1, MEM_RELEASE);
return 0;
}
So far, it's working properly and loading the Dll into the file, however, the Dll doesn't seem to be working:
#include "pch.h"
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
DWORD WINAPI HackThread(HMODULE hModule)
{
//Create Console
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
std::cout << "ttt" << std::endl;
std::cin.get();
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)HackThread, hModule, 0, nullptr);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
I know the Dll is loading properly because the process is hitting the 'DLL_PROCESS_ATTACH' case and when I tested it with a message box instead of the CreateThread, it showed up, however, I can't seem to make the console show up. What would be the problem?
One issue I see is that your thread is re-mapping only stdout to the new console, but it is not re-mapping stdin as well. So it is quite likely (use a debugger to verify this) that std::cin.get() is failing and thus not blocking the thread from closing the console immediately after creating it.
I need to develop a .exe file that will launch a runnable .jar file which is stored on a subfolder called core. I built the C++ .exe application with sublime text and mingw and it's working fine but there is a small problem that I need to solve. When you execute the .exe file, during a minimum portion of time you can see a black window on screen which is disappearing in some milliseconds and after it the Java .jar application opens. This only happens if I use this .exe. If I double click in the runnable jar the black window doesn't appear.
How can I avoid that black window which dissapears in some milliseconds?
This is the code:
#include <windows.h>
int main()
{
ShellExecute(0, "open", "core.jar", NULL, "core", SW_SHOW);
return 0;
}
I tried also with this code and same result:
ShellExecute(0, "open", "cmd.exe", "/C .\\core\\core.jar", 0, SW_HIDE);
I'm aware there are other similar questions but none of them works for this problem and none of them seems to be applicable to Sublime and gcc.
The problem isn't your call to ShellExecute. Your code is for a console application. Console applications, as one might guess, run in a console (that black window; same as you'd get if you ran cmd.exe).
You can just replace main with WinMain, and simply call ShellExecute in there to launch the jar, and there should be no resulting console window (assuming the jar itself isn't creating one).
See 14 B for how to make a 'windows' app with MingW.
Use CreateProcess() or ShellExecuteEx() which will return you handle to the created process, and with that handle you can kill the process.
Here is an example showing how this works including error handeling.
#include <windows.h>
#include <string>
#include <iostream>
void DisplayError(LPCTSTR errorDesc, DWORD errorCode)
{
TCHAR errorMessage[1024] = TEXT("");
DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_MAX_WIDTH_MASK;
FormatMessage(flags,
NULL,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
errorMessage,
sizeof(errorMessage) / sizeof(TCHAR),
NULL);
std::cerr << "Error : " << errorDesc << "\n";
std::cerr << "Code = " << errorCode << "\n";
std::cerr << "Message = " << errorMessage << "\n";
}
int main()
{
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processInfo;
ZeroMemory(&info, sizeof(info));
info.cb = sizeof(info);
ZeroMemory(&processInfo, sizeof(processInfo));
std::string path = "D:\\Java\\jdk1.6.0_26\\bin\\java.exe";
std::string cmdArgs = "java.exe -jar D:\\temp\\sample.jar";
// Start the child process.
if (CreateProcess(path.c_str(), const_cast<char *>(cmdArgs.c_str()), NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
// Wait until child process exits.
WaitForSingleObject(processInfo.hProcess, INFINITE);
// Close process and thread handles.
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
else
{
DWORD errorCode = GetLastError();
DisplayError(TEXT("Unable to execute."), errorCode);
}
//system("pause");
}
Finally I discovered that is enough with adding -mwindows to the gcc compile command:
gcc -o launcher launcher.cpp -mwindows
I've been trying to figure out what's wrong for so long.
I've seen some people assign:
GetProcAddress(GetModuleHandle("KERNEL32.dll"), "LoadLibraryA")
And I wonder if that's what I have to do, but I just don't understand what that line of code does exactly. It has nothing to do with MY dll function, so why load it?
Main (console application A.K.A injector):
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
char* dllPath = "C:\\Users\\Kalist\\Desktop\\Projects\\DLL\\bin\\Debug\\DLL.dll";
typedef DWORD (WINAPI *pThreadFunc)();
char* ProcToInject = "calc.exe";
int main(){
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE procSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
DWORD procID;
if(procSnap){
if(Process32First(procSnap, &pe32)){
do{
if(!strcmp(pe32.szExeFile, ProcToInject)){
procID = pe32.th32ProcessID;
break;
}
}while(Process32Next(procSnap, &pe32));
}
CloseHandle(procSnap);
}
HANDLE procAccess = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
void* memSpace = VirtualAllocEx(procAccess, NULL, strlen(dllPath)+1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(procAccess, memSpace, dllPath, strlen(dllPath)+1, NULL);
HINSTANCE getLibadd = LoadLibrary(dllPath);
pThreadFunc pThreadFuncVar = (pThreadFunc)GetProcAddress(getLibadd, "threadFunc");
CreateRemoteThread(procAccess, NULL, 0, (LPTHREAD_START_ROUTINE)pThreadFuncVar, memSpace, 0, NULL);
CloseHandle(procAccess);
}
DLL remote process:
#include <iostream>
#include <windows.h>
extern "C" DWORD WINAPI threadFunc(){
MessageBox(0, "Injection worked!", "Injection message", MB_OK);
return 0;
}
The problem with your code is that pThreadFuncVar contains the address of threadFunc in your injector process. However, your Dll.dll is not even loaded in the target process. Even if your dll were loaded, it would likely not be loaded at the same address, so the pThreadFuncVar address would still be meaningless in the target process.
Only a few essentials modules, like KERNEL32, are loaded at the same address in every process. So, if you use the address of LoadLibraryA for CreateRemoteThread, it will load the dll from the path which you copied into the target process's memory. This will in turn call the dll attach procedure of your dll, which is where you want to put the MessageBox call.
I think my code is finally working now. Only problem is that for some reason, even though I've opened the process with PROCESS_ALL_ACCESS, CreateRemoteThread throws back an error: ERROR_ACCESS_DENIED.
The error was retrieved with GetLastError and it spit out '5', which translates to ERROR_ACCESS_DENIED.
#include <iostream>
#include <windows.h>
#include <TlHelp32.h>
char* dllPath = "C:\\Users\\Kalist\\Desktop\\Projects\\DLL\\bin\\Debug\\DLL.dll";
char* ProcToInject = "calc.exe";
int main(){
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
HANDLE procSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(procSnap == INVALID_HANDLE_VALUE){
std::cout << "Snapshot function failed" << std::endl;
}
DWORD procID = 0;
if(Process32First(procSnap, &pe32)){
do{
if(!strcmp(pe32.szExeFile, ProcToInject)){
procID = pe32.th32ProcessID;
break;
}
}while(Process32Next(procSnap, &pe32));
}
CloseHandle(procSnap);
if(procID != 0){
HANDLE procAccess = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
if(procAccess == NULL){
std::cout << "OpenProcess error: " << GetLastError() << std::endl;
}
LPVOID remoteString = (LPVOID)VirtualAllocEx(procAccess, NULL, strlen(dllPath)+1, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if(remoteString == NULL){
std::cout << "VirtualAllocEx error: " << GetLastError() << std::endl;
}
bool memoryWritten = WriteProcessMemory(procAccess, (LPVOID)remoteString, dllPath, strlen(dllPath)+1, NULL);
if(memoryWritten == 0){
std::cout << "WriteProcessMemory error: " << GetLastError() << std::endl;
}
LPVOID getLibAdd = (LPVOID)GetProcAddress(GetModuleHandle("Kernel32.dll"), "LoadLibraryA");
if(getLibAdd == NULL){
std::cout << "GetProcAddress error: " << GetLastError() << std::endl;
}
HANDLE remoteThread = CreateRemoteThread(procAccess, NULL, 0, (LPTHREAD_START_ROUTINE)getLibAdd, (LPVOID)remoteString, 0, NULL);
if(remoteThread == NULL){
std::cout << "CreateRemoteThread error: " << GetLastError() << std::endl;
}
CloseHandle(procAccess);
}else{
std::cout << "Failed to retrieve procID" << std::endl;
}
}
You'll get this error when you attempt to call CreateRemoteThread from a 32 bit process, but where the target process is a 64 bit process. I'm betting that's what you are doing.
In order to inject into a 64 bit process, you need your injector process also to be 64 bit. And obviously, as I am sure you already know, the DLL that you inject must also be 64 bit.
For what it is worth, you don't need to ask for so much when you call OpenProcess. I believe that all you need is:
PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION
| PROCESS_VM_WRITE | PROCESS_VM_READ
The code, you have written, assumes that the process, the code is running on, the dll you are injecting, and the calc.exe are all the same bitness.
If this is not statisfied, the call to CreateRemoteThread will fail.
This is, due to a constraint of the lpStartAddress parameter.
The following Quote is from the CreateRemoteThread documentation
A pointer to the application-defined function of type LPTHREAD_START_ROUTINE to be executed by the thread and represents the starting address of the thread in the remote process. The function must exist in the remote process. For more information, see ThreadProc.
The assumtion of the code is due, to the following:
The LoadLibraryA function is located at a different rva, when comparing x86 to x64, because a different Kernel32.dll file is loaded, when you have a x86 process vs a x64 process.
The different Kernel32.dll files are also loaded at a different base address, when comparing a x86 process to a x64 process.
The Address you get back, from GetProcAddr is rva + dll base address.
Currently I am programming an injector, which will be also capable of x86 to x64, and have verified, that all addresses, that are passed to CreateRemoteThread are in the scope, of the target process. Also I am opening the Process with PROCESS_CREATE_THREAD | PROCESS_VM_WRITE | PROCESS_VM_READ| PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION. But I still have this issue.
This is because, the pointer length, of x86 is 32-bit. The parameter lpStartAddress of CreateRemoteThread is a pointer though. This means, that you will never be able to call all functions of a x64 target, because the function pointer will be capped, to 32-bit.
That in turn means that you can call at most all function inside the x86 addressable region, from a x86 process, in a x64 target process.
I`m trying to inject a DLL in a process and call a exported function in my DLL.
The DLL is injected alright with that code:
HANDLE Proc;
char buf[50] = { 0 };
LPVOID RemoteString, LoadLibAddy;
if (!pID)
return false;
Proc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID);
if (!Proc)
{
sprintf_s(buf, "OpenProcess() failed: %d", GetLastError());
printf(buf);
return false;
}
LoadLibAddy = (LPVOID)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryA");
// Allocate space in the process for our DLL
RemoteString = (LPVOID)VirtualAllocEx(Proc, NULL, strlen(DLL_NAME), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
// Write the string name of our DLL in the memory allocated
WriteProcessMemory(Proc, (LPVOID)RemoteString, DLL_NAME, strlen(DLL_NAME), NULL);
// Load our DLL
HANDLE hThread = CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddy, (LPVOID)RemoteString, NULL, NULL);
The module of my DLL is created OK, like you see in that image of Process Hacker (BootstrapDLL.exe):
My exported functions is ok too, like you see in the list of functions exported on Process Hacker (ImplantDotNetAssembly):
The problems, I think, happens on the offset calculation to get the address of the "ImplantDotNetAssembly", because everything above is alright and when I do the calculation I get the address of the "ImplantDotNetAssembly", but when I call CreateRemoteThread again to call it, the window "Has stopped working..." of the windows is showed and the process stoped. What`s happening?
Here is the code of the calculation of the offset:
DWORD_PTR hBootstrap = GetRemoteModuleHandle(ProcId, L"BootstrapDLL.exe");
DWORD_PTR offset = GetFunctionOffset(L"C:\\Users\\Acaz\\Documents\\Visual Studio 2013\\Projects\\Contoso\\Debug\\BootstrapDLL.exe", "ImplantDotNetAssembly");
DWORD_PTR fnImplant = hBootstrap + offset;
HANDLE hThread2 = CreateRemoteThread(Proc, NULL, 0, (LPTHREAD_START_ROUTINE)fnImplant, NULL, 0, NULL);
Here are the functions GetRemoteModuleHandle and GetFunctionOffset:
DWORD_PTR GetFunctionOffset(const wstring& library, const char* functionName)
{
// load library into this process
HMODULE hLoaded = LoadLibrary(library.c_str());
// get address of function to invoke
void* lpInject = GetProcAddress(hLoaded, functionName);
// compute the distance between the base address and the function to invoke
DWORD_PTR offset = (DWORD_PTR)lpInject - (DWORD_PTR)hLoaded;
// unload library from this process
FreeLibrary(hLoaded);
// return the offset to the function
return offset;
}
DWORD_PTR GetRemoteModuleHandle(const int processId, const wchar_t* moduleName)
{
MODULEENTRY32 me32;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;
// get snapshot of all modules in the remote process
me32.dwSize = sizeof(MODULEENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processId);
// can we start looking?
if (!Module32First(hSnapshot, &me32))
{
CloseHandle(hSnapshot);
return 0;
}
// enumerate all modules till we find the one we are looking for or until every one of them is checked
while (wcscmp(me32.szModule, moduleName) != 0 && Module32Next(hSnapshot, &me32));
// close the handle
CloseHandle(hSnapshot);
// check if module handle was found and return it
if (wcscmp(me32.szModule, moduleName) == 0)
return (DWORD_PTR)me32.modBaseAddr;
return 0;
}
If someone know what is happening, I'll be very grateful!
I cant`t even debug the "has stopped work.." error. When I clik in the DEBUG button on the window, the error throw again and everything stop.
Thank you.
NEVER inject managed assemblies. If for some reason you must inject code into another process, use native code with either NO C library or a STATIC C library.