Been stuck for a few hours making a (simple) dll injector that takes a .dll file and a process as arguments and then injects said .dll into the process, and I'm about to start tearing my hair out.
It doesn't function properly, and for no obvious reason either. The dll simply won't load into the process, but without any error messages being displayed. I did the exact same thing but with ANSI functions instead of Unicode and it worked like a charm, which after some testing is leading me to believe it's PROBABLY a problem with the file path not being loaded properly but I have no idea why.
I've attached my entire source code below and added some comments to hopefully clarify somewhat. And like I said, if I'm right, then the important part should start somewhere around:
//Get the full path of our dll and store it in a variable
Help a bro out.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
int main()
{
HANDLE hSnapshot, hProc = NULL;
PROCESSENTRY32 PE32;
PE32.dwSize = sizeof(PROCESSENTRY32);
WCHAR injProcName[100] = {NULL}, injDllName[100] = {NULL};
//Let user input options
cout << "Dll injector started!" << endl << "Please enter the name of the dll you would like to inject: ";
wcin >> injDllName;
cout << "Enter the name of the target process: ";
wcin >> injProcName;
//Create snapshot
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
Process32First(hSnapshot, &PE32);
//Load the first process into PE32 and loop to see if target process is running
do {
if(wcscmp(PE32.szExeFile, injProcName) == 0) {
wcout << PE32.szExeFile << " found!" << endl;
wcout << "Attempting to open " << injProcName << ".." << endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PE32.th32ProcessID);
if(!hProc)
{
cout << "Failed to open process!" << endl;
return 1;
}
break;
}
}
while(Process32Next(hSnapshot, &PE32));
if(!hProc) {
cout << "Unable to locate process!" << endl;
return 1;
}
cout << "Process successfully opened!" << endl;
//Get the full path of our dll and store it in a variable
WCHAR DllPath[MAX_PATH] = {NULL};
GetFullPathName(injDllName, MAX_PATH, DllPath, NULL);
wcout << DllPath << endl;
//Allocate memory in target process
cout << "Allocating memory.." << endl;
LPVOID DllMemAddr = VirtualAllocEx(hProc,
NULL,
wcslen(DllPath),
MEM_COMMIT|MEM_RESERVE,
PAGE_READWRITE);
//Write our path into target process memory
wcout << "Writing dll to target process.." << endl;
WriteProcessMemory(hProc,
DllMemAddr,
DllPath,
wcslen(DllPath),
NULL);
//Get the memory address of LoadLibraryW
LPVOID LoadAddr = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
//Finally, start a new thread with the address of LoadLibraryW and our dll path as argument
cout << "Executing dll in remote process.." << endl;
CreateRemoteThread(hProc,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)LoadAddr,
DllMemAddr,
NULL,
NULL);
cout << "Dll sucessfully injected!" << endl;
cin.get();
return 0;
}
wcslen returns length in wchar_t units. But VirtualAllocEx and WriteProcessMemory receive a length in byte units. So you only write half the string, because wchar_t is two bytes wide. And you did not write the null terminator.
You need to pass (wcslen(DllPath)+1)*sizeof(wchar_t).
Incidentally, your ANSI code was probably broken too because, presumably, it also missed the null terminator. But you probably got away with it by chance.
A little error checking would not go amis, while we are in the business of looking at your code. And initialising DllPath is a little pointless when you follow it with the call to GetFullPathName.
Related
I tried the code below. It requests ejection when the device name contains "San", because I have plugged in a SanDisk USB drive. However it fails, and the reason seems to be PNP_VetoIllegalDeviceRequest. I looked up the reason, and this page says it is
The device does not support the specified operation.
But I can manually eject the SanDisk using Windows' menu, so the reason seems absurd. Did I call the function correctly? Do I need to call something else before calling CM_Request_Device_Eject?
The output was
....
SanDisk Ultra USB Device
Removing Sandisk
rejected.
type:8
name:USBSTOR\Disk&Ven_SanDisk&Prod_Ultra&Rev_1.00\....
The code was (the value of Devinst was 3)
if (wcsstr(buffer, L"San") != 0)
{
wcout << "Removing Sandisk" << endl;
PNP_VETO_TYPE vType;
WCHAR vName[MAX_PATH];
result = CM_Request_Device_Eject(Devinst, &vType, vName, MAX_PATH, NULL);
if (result == CR_SUCCESS)
{
cout << "ejected" << endl;
}
else
{
wcout << "rejected." << endl;
wcout << "type:"<< vType << endl;
wcout << "name:" << vName << endl;
}
}
After searching the web, I have found this page: https://www.winvistatips.com/threads/removal-of-usb-disk.179677/
The questioner had the exact same error, and there was a reply that said that he needs to call that function to the parent node, not the USB disk node. So, I modified the code like below, and it worked.
DEVINST parent;
CM_Get_Parent(&parent, Devinst, NULL);
PNP_VETO_TYPE vType;
WCHAR vName[MAX_PATH];
result = CM_Request_Device_Eject(parent, &vType, vName, MAX_PATH, NULL);
I found Get DLL path at runtime but I'm not sure what to use for the localFunc variable. I tried the filename of the DLL, I tried null and some other things, but the status returned was always 'File Not Found'.
From the MSDN:
lpModuleName [in, optional]
The name of the loaded module (either a .dll or .exe file), or an address in the module (if dwFlags is GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS).
So I assume they just mean the plain file name eg, "MyControl.dll" and not the path to file, since I do not know the path.
Edit: added the actual code:
char localFunc[MAX_PATH]
sprintf_s(localFunc, 52, "MyActiveXComponent.dll");
if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR) &localFunc, &hm))
{
int ret = GetLastError();
OutFile << L"GetModuleHandle returned " << ret << std::endl;
} else {
GetModuleFileNameA(hm, path, sizeof(path));
OutFile << L"Path of dll is:" << path << L"<" << std::endl;
}
Here's what I ended up with (performed both ways)
LPCWSTR anotherFunc = L"MyActiveXComponents.dll";
HMODULE hm2 = GetModuleHandle(anotherFunc); // get the handle to the module
LPWSTR anotherPath = new WCHAR[MAX_PATH];
GetModuleFileName(hm2, anotherPath, MAX_PATH); // get the full path
OutFile << L"Path of dll is:" << anotherPath << L"<" << std::endl;
Here's the other way.
char path[MAX_PATH];
HMODULE hm = NULL;
char localFunc[MAX_PATH] = {"MyActiveXComponents.dll"};
if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, LPCSTR) &localFunc, &hm))
{
int ret = GetLastError();
OutFile << L"GetModuleHandle returned " << ret << std::endl;
} else {
GetModuleFileNameA(hm, path, sizeof(path));
OutFile << L"Path of dll is:" << path << L"<" << std::endl;
}
Thanks. I'm sure it is simple question.
Call GetModuleHandle() with the raw name like user32.dll or whatever the name of the DLL is. After you have the handle, call GetModuleFileName() to get the fully qualified name including path.
So, i'm injecting a code in the memory of another process like this:
void RemoteInj::ExecuteFunction(DWORD Start, DWORD End, DWORD Entry, RemoteArgs* Args)
{
unsigned long Id;
int size = End - Start;
cout << size << endl;
void* Func = VirtualAllocEx(hProcess, NULL, size+10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
void* ep = (void*)(Entry-Start+(DWORD)(Func));
WriteProcessMemory(hProcess, Func, (void*)Start, size, NULL);
void* Data = VirtualAllocEx(hProcess, NULL, sizeof(RemoteArgs)+1, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(hProcess, Data, (void*)Args, sizeof(RemoteArgs), NULL);
cout << hex << Func << endl;
cout << "Function: 0x" << hex << Start << endl << "End: 0x" << hex << End << endl;
system("PAUSE");
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)ep, Data, NULL, NULL);
CloseHandle(hProcess);
}
My problem is: If i use calls in that thread, for example:
void F(RemoteArgs* arg)
{
while (true)
{
arg->pSleep(50); //Works
Sleep(50); //doesnt work
}
return;
}
No need to explain why it doesn't work, i know, it's another process....My question is: Is there a way to make function like this(Sleep()) work, i could try importing to the process also the IAT with the proper distance, do you have a better idea?Thanks!
As you suspect, the reason this doesn't work right off the bat is that the call to Sleep in your process actually goes to a location in your import address table (IAT) which has a jump to the real Sleep implementation in kernel32.dll. Even though the other process also imports kernel32.dll (all processes do), it obviously does not have an identical IAT.
There are ways, but none that I know of are trivial.
GetLastError tells me I'm getting the "The program issued a command but the command length is incorrect." error when calling Process32First() (see code below). I found one post that looked helpful (http://social.msdn.microsoft.com/Forums/is/vcgeneral/thread/6f43716f-fdd3-4c92-bfba-6a23178c32bf), but I'm not sure if this is my problem.
I've tried building a program that includes only "stdafx.h", <iostream>, <Windows.h> and <TlHelp32.h> to test __alignof(PROCESSENTRY32), but I still get a value of 4. Not sure if that's correct or not.
Here is the code that's failing:
HANDLE hProcess;
PROCESSENTRY32 pe32;
cout << "Size of PROCESSENTRY32 is: " << sizeof(PROCESSENTRY32) << "\r\n"; // 556
cout << "Align of PROCESSENTRY32 is: " << __alignof(PROCESSENTRY32) << "\r\n"; // 4
if ( !(hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)) ) {
cout << "CreateToolhelp32Snapshot() failed: " << GetLastError() << "\r\n";
return (HANDLE)NULL;
} else {
cout << "CreateToolhelp32Snapshot() succeeded.\r\n";
}
if (Process32First(hProcess, &pe32)) {
do {
cout << pe32.th32ModuleID;
} while (Process32Next(hProcess, &pe32));
} else {
cout << "Process32First() failed: " << GetLastError() << "\r\n";
}
From the docs on Process32First:
The calling application must set the dwSize member of PROCESSENTRY32 to the size, in bytes, of the structure.
I don't see you doing that in your code, and I suspect it's the problem. Fix it:
pe32.dwSize = sizeof pe32;
if (Process32First(...))
The reasoning behind this mandatory action for many of the winapi structures is for the flexibility to add more onto the structure later on, but let functions know which version is being used by checking against known sizes of previous versions.
I am trying to do some dll injection. I think I tried everything I could but cound not solve the problem unfortunately. I always get ERROR CODE 127 which means ERROR_PROC_NOT_FOUND. I am using Windows 7 64 bit.
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
char FileToInject[] = "theDll.dll";
char ProcessName[] = "calc.exe";
typedef HINSTANCE (*fpLoadLibrary)(char*);
bool InjectDLL(DWORD processId);
int main() {
DWORD processId = NULL;
PROCESSENTRY32 pre32 = {sizeof(PROCESSENTRY32)};
HANDLE hProcSnap;
cout << "BEFORECreateToolhelo32Snapshot:" << GetLastError() <<endl;
while(!processId) {
system("CLS");
cout << "Searching..." << endl;
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
cout << "CreateToolhelo32Snapshot:" << GetLastError() <<endl;
if(Process32First(hProcSnap, &pre32)) {
do {
if(!(strcmp(pre32.szExeFile, ProcessName))) {
processId = pre32.th32ProcessID;
break;
}
}
while(Process32Next(hProcSnap, &pre32));
}
Sleep(1000);
}
cout << GetLastError() <<endl;
while(!InjectDLL(processId)) {
cout << "DLL Injection failed" << endl;
Sleep(1000);
}
cout << "DLL Injected successfully" << endl;
getchar();
CloseHandle(hProcSnap);
return 0;
}
bool InjectDLL(DWORD processId) {
HANDLE hProc;
LPVOID paramAddr;
cout << "START:" << GetLastError() <<endl;
HINSTANCE hDll = LoadLibrary("KERNEL32");
cout << "LoadLibrary:" << GetLastError() <<endl;
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
cout << "LoadLibraryArr:" << GetLastError() <<endl;
hProc = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
cout << "OpenProcess:" << GetLastError() <<endl;
char DllPath[250] = "C:\\Hacks\test.dll";
paramAddr = VirtualAllocEx(hProc, 0, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
cout << "VirtualAlloxEx:" <<GetLastError() <<endl;
bool MemoryWritten = WriteProcessMemory(hProc, paramAddr, DllPath, strlen(DllPath) + 1, NULL);
cout << "WriteProcessMemory:" << GetLastError() <<endl;
CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)LoadLibraryAddr, paramAddr, 0, 0);
cout << "CreateRemoteThread:" <<GetLastError() <<endl;
CloseHandle(hProc);
return MemoryWritten;
}
The output is the following:
Searching...
CreateToolhelp32Snapshot: 18 ERROR_NO_MORE_FILES
LoadLibrary:18 ERROR_NO_MORE_FILES
LoadLibraryArr:127 ERROR_PROC_NOT_FOUND
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
CreateRemoteThread:5 ACCESS DENIED
DLL Injected successfully
The program finds the calc.exe as a process with no problem, but after that something goes wrong. Could someone please help me with this?
Thank you,
Tamas
This is one problem:
char DllPath[250] = "C:\\Hacks\test.dll";
The last backslash is not escaped. Change to:
char DllPath[250] = "C:\\Hacks\\test.dll";
The function is called LoadLibraryA(), not LibraryLoadA():
fpLoadLibrary LoadLibraryAddr =
(fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
A few other suggestions:
Only check GetLastError() if the previous WINAPI function failed.
Only continue processing if the previous WINAPI code (or other code) succeeded.
In
fpLoadLibrary LoadLibraryAddr = (fpLoadLibrary)GetProcAddress(hDll, "LibraryLoadA");
you should rather resolve the string LoadLibraryA. The
OpenProcess:127 ERROR_PROC_NOT_FOUND
VirtualAlloxEx:127 ERROR_PROC_NOT_FOUND (<-- sic)
WriteProcessMemory:127 ERROR_PROC_NOT_FOUND
errors are caused because you're using GetLastError even though these functions maybe didn't even fail. So before calling GetLastError, make sure that these functions yield an error return value (NULL or the like).