Where inside injected DLL to loop? - c++

So I've got an application that starts another application with my DLL injected (with Detours). The entry point is DllMain. I can't do much from DllMain, and certainly cannot loop. So how do I call my DLL monitor functions every x seconds? I read you cannot create a thread from DllMain (at least until it returns) and its true because it crashed me. So I tried creating it in the attach thread event and it crashed me. So now what I'm trying to do is inject it again (incase Detours fails) so I can get the module handle. Then I get the address of an initializer function which creates my thread. I get the module handle fine, but I don't think I can get the function address. I made the function empty, and it still crashed me. So it doesn't even get as far as calling the function. Visual Studio said I have no read access.
So what am I suppose to do? What do you do to loop your DLL functions when you don't own the attached program (exe).
//Application.exe
STARTUPINFO si = {sizeof(STARTUPINFO)};
PROCESS_INFORMATION pi = {0};
DetourCreateProcessWithDll(filename, NULL, NULL, NULL, TRUE,
CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, path,
&si, &pi, detoured, hook, NULL);
processID = pi.dwProcessId;
hDll = InjectDLL(processID, hook);
if(hDll != NULL)
{
STARTER Starter = (STARTER)GetProcAddress(hDll, "Starter");
if(Starter != NULL)
Starter();
}
ResumeThread(pi.hThread);
The function Starter is extern C exported and looks fine inspected (it's ordinal 1).
I have no idea what could possibly be wrong, and merely hope someone out there has had experience with this topic and crashing.
Here's the DLL code:
//Hook.h
extern "C"
{
void __declspec(dllexport) Starter(void);
}
//Hook.cpp
void Starter(void)
{
}
Thanks

You can't do it that way because the DLL is injected into a different process and you're trying to execute the function in the address space of your hooking process.
What you'll have to do is call CreateRemoteThread, passing in the address that you get from GetProcAddress in the lpStartAddress parameter. This will create a new thread on the remote process, and execute the function in the address space of that process, in the context of the new thread.
BTW, technically you should be able to create a new thread in DllMain/DLL_PROCESS_ATTACH, as long as you're not doing any synchronizing with other threads, though it's not recommended. I'm not sure what issues might exist if doing this when the DLL is being injected though.

Related

Manual DLL injection

I am trying to learn some manual dll injection, but cant seem to get the execution of the dlls code to work. I am new to Windows C++ so any tips on improving my code is appreciated. I have also only posted the relevant code.
Injector program:
hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, getPID(TARGET_NAME));
DWORD gotDLL = GetFullPathName(DLL_NAME, MAX_PATH, dllPath, NULL);
hFile = CreateFile(dllPath, GENERIC_READ, NULL, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
dllFileSize = GetFileSize(hFile, NULL);
memAddrForDLL = VirtualAllocEx(hProcess, NULL, dllFileSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
loadedDLL = HeapAlloc(GetProcessHeap(), NULL, dllFileSize);
// Load dll into allocated memory in current process
ReadFile(hFile, loadedDLL, dllFileSize, &bytesRead, NULL))
// Find offset of dll entry point
IMAGE_NT_HEADERS* pOldNtHeader = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<BYTE*>(loadedDLL) + reinterpret_cast<IMAGE_DOS_HEADER*>(loadedDLL)->e_lfanew);
IMAGE_OPTIONAL_HEADER* pOldOptHeader = &pOldNtHeader->OptionalHeader;
entryPointOffset = pOldOptHeader->AddressOfEntryPoint;
// Load dll into allocated memory in target process
WriteProcessMemory(hProcess, memAddrForDLL, loadedDLL, bytesRead, NULL)
LPTHREAD_START_ROUTINE entryPoint = (LPTHREAD_START_ROUTINE)((unsigned __int64)memAddrForDLL + entryPointOffset);
CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)LoadLibrary, entryPoint, NULL, NULL)
DLL:
DWORD WINAPI OnDllAttach(LPVOID base){
typedef void func(void);
func* f = (func*)0x00007FF605EC5835;
f();
FreeLibraryAndExitThread(static_cast<HMODULE>(base),1);
}
BOOL WINAPI OnDllDetach(){
return TRUE;
}
BOOL WINAPI DllMain(_In_ HINSTANCE hinstDll,
_In_ DWORD fdwReason,
_In_opt_ LPVOID lpvReserved){
typedef void func(void);
func* f = (func*)0x00007FF605EC5835;
f();
switch(fdwReason) {
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDll);
CreateThread(nullptr, 0, OnDllAttach, hinstDll, 0, nullptr);
return TRUE;
case DLL_PROCESS_DETACH:
if(lpvReserved == nullptr)
return OnDllDetach();
return TRUE;
default:
return TRUE;
}
}
Target program contains this function:
void printer(){
cout << "test" << endl;
}
My injector produces the following output
1. Attempting to attatch to process target.exe
--- Got target.exe PID: 14640
--- Got target.exe Handle: 0x0000000000000084
2. Attempting to allocate memory
--- Found dll: D:\projects\injector\hack.dll
--- Got hack.dll Handle: 0x0000000000000088
--- Allocated memory in target.exe at 0x0000017BEB690000
3. Attempting to copy dll to target.exe
--- Allocated memory at 0x00000226A060FFE0
--- Loaded hack.dll in current process at 0x00000226A060FFE0
--- hack.dll is a valid DLL
--- Loaded hack.dll into target.exe at 0x0000017BEB690000
4. Attempting to execute dll
--- Offset from start of file to entrypoint: 0x3cf6
--- Began execution of hack.dll in target.exe at 0x0000017BEB693CF6
Using Ghidra I can confirm this is the correct offset for the dll entrypoint. But when running my injector nothing happens in the target process, I've also tried using cout to print a message from the dll but I get nothing(I dont think it would even work because nothing has been relocated)
I was using
CreateRemoteThread(hProcess, NULL, NULL, entryPoint, memAddrForDLL, NULL, NULL)
before as the 4th parameter is called lpStartAddress and I thought this should want the entry point but it was causing the target process to crash and every example I saw used the way I currently have it in my code.
In my dll I am calling the function in the target process by the address.
EDIT: I am testing this on my own console application.
The most basic form of DLL injection is:
Allocating Memory in target process using VirtualAllocEx()
Writing the path of the DLL to that memory location with WriteProcessMemory
Calling LoadLibrary() via CreateRemoteThread() in the target process
Passing the memory location where the DLL path is written to that call
You already have this but, your goal is to manually map the DLL and avoid using LoadLibrary(). The code you have provided is not going to work out, there are about 5 more steps. You need to emulate everything that LoadLibrary() normally does:
Load raw binary data
Map sections into target process
Inject loader shellcode
Do relocations
Fix imports
Execute TLS callbacks
Call DllMain
Cleanup
The benefits of manually mapping are that you will be hidden from ToolHelp32Snapshot(), walking the module linked list in the PEB and NtQueryVirtualMemory.
If you want to do it right, with decent error checking, it's about 350 lines of code and it gets complicated. It's all done by parsing the PE header.
Get the process id of the target
Read the DLL file
Allocate memory in target process the same size as ImageBase from the PE header
Loop through PE sections after parsing the PE header
Write the section to memory in the correct relative address
Write shellcode into target process
Call CreateRemoteThread and set your shellcode to execute
Your shellcode fixes imports and does relocations
Your Shellcode Execute TLS callbacks
The above 2 steps are done parsing the DataDirectory in the optional header
Call DllMain(), with DLL_PROCESS_ATTACH argument
Now your DLL is loaded and the DLL_PROCESS_ATTACH switch case is executing. Obivously it's more complicated than that, but that's the idea.
I wouldn't know anything about this without my friend Broihon teaching me it, so I want credit this answer to him. Good luck
A .DLL loaded in memory is not the same thing as a .DLL file on disk. The section layout is not the same and you need to deal with relocations, the import table and the PEB loaded module list. You basically have to re-implement NTDLL!Ldr*.
Calling CreateRemoteThread on LoadLibrary is a different technique and when you do this the thread parameter needs to point to the .DLLs path in the remote process, not the entrypoint.

GetProcAddress return NULL when the hModule and lpProcName is valid

I started a new project recently and my objectives is to inject bytecode into another process, and then start a remote thread executing my bytecode, however i have run into a very strange problem.
What it does is that it allocates and write to memory of a arbitrary process, it writes a struct containing pointers to functions in user32.dll and kernel32.dll for the remote process, it also writes a calling operation for the function pointers from the struct, it then creates a remotethread with a lpStartAddress of the "calling operation"
You can find the source code here :
http://pastie.org/9298306
GetPrivileges is being called on line 55 (method on line 185), it returns true meaning that OpenProcessToken, LookupPrivilegeValue and AdjustTokenPrivileges returned true.
Soon after that the following will be callled:
param->pMessageBox = (DWORD)GetProcAddress(user32, "MessageBoxA");
param->pSleep = (DWORD)GetProcAddress(kernel32, "Sleep");
Both user32 and kernel32 are valid handles, but param->pMessageBox will be set to NULL, whilst param->pSleep will get the actual pointer for the Sleep.
And the strange thing about this is when i replace the GetPrivileges with this snippet that i copied online it works fine and the param->pMessageBox will be set with the correct pointer address.
BOOL GetPrivileges()
{
HANDLE tokenHandle;
TOKEN_PRIVILEGES tokenPriv;
if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &tokenHandle) != 0)
{
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tokenPriv.Privileges[0].Luid);
tokenPriv.PrivilegeCount = 1;
tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(tokenHandle, 0, &tokenPriv, sizeof(tokenPriv), NULL, NULL);
}
else
{
TCHAR buffer[256];
wsprintf(buffer, TEXT("0x%x"), GetLastError());
MessageBox(NULL, buffer, TEXT("OpenProcessTokenError"), MB_ICONERROR);
return FALSE;
}
return true;
}
Continuing on with my debugging take note that the else statement in the copied GetPrivileges will not be called due to OpenProcessToken returning true as expected, and by removing:
TCHAR buffer[256];
wsprintf(buffer, TEXT("0x%x"), GetLastError());
param->pMessageBox will set to NULL, how can that be?
Regards a frustrated ogelami.
The module handles are in fact not valid. They are module handles for a remote process. Module handles are in fact implement as base addresses and so only have meaning with respect to the virtual address space of the executing process.
It looks like, by chance, the base address of the kernel32 module of the injecting process is the same as the base address of the kernel32 module in the remote process.
Realistically, your goals are going to be hard to achieve if you put so much code in the injecting process. You would be better off if you injected a DLL into the other process. Create a remote thread whose first act is to load this DLL. Then you will have code running in the other process, inside its address space, and so able to call directly functions like GetModuleHandle, GetProcAddress etc.

EnumProcessModules failed with error 299 on 32bit win7

My code is running on win7 32bit, but when I use EnumProcessModules, it returned false and getlasterror() return error code 299, which declare that the program is 32bit and this statement can not be running on 64bit system.
I wonder why this happens, and why the system thinks that I am running on a 64bit OS?
The code I use:
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
if (hProcess)
{
HMODULE hMod = NULL;
DWORD cbNeeded = 0;
if (EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
{
//do something here...
}
}
dwPid is the id of the process I want to manipulate.
PS.This error just happen on one of my test machine, others are fine. So This problem may be related to that specific machine or system configration?
Though It has been a while since you posted this question.But I thought of giving it a try .
Reason might be because You are using CreateProcessA in your code.. and suddenly calling EnumProcessModules.Thus windows is not able to create ModuleInfo by that time.And it returns error 299(Thinking its a 64 bit system.. as it fails to read the memory).
Actually I was stuck at this too and figured it out..after looking at your post.
Thanks
http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx
CreatProcess Remarks.. It ask to call WaitforInput Idle before proceeding.;-)
The calling thread can use the WaitForInputIdle function to wait until the new process has finished its initialization and is waiting for user input with no input pending. This can be useful for synchronization between parent and child processes, because CreateProcess returns without waiting for the new process to finish its initialization. For example, the creating process would use WaitForInputIdle before trying to find a window associated with the new process.

Remote thread is failing on call to LoadLibrary with error 87

I am tring to create a Remote thread that will load a DLL I wrote, and run a function from it.
The DLL is working fine (Checked) but from some reason, the Remote thread fails and the proccess in which it was created stop responding.
I used ollyDebug to try and see what is going wrong and I noticed two things...
My strings (dll name and function name) are passed to the remote thread correctly
The thread fails on LoadLibrary with lasterror code 87 "ERROR_INVALID_PARAMETER"
My best guess is that somehow, The remote thread can't find LoadLibrary (Is this because the linker is done with repspect to my proccess???, Just a guess...)
What am I doing wrong?
This is the code to the remote function:
static DWORD WINAPI SetRemoteHook (DATA *data)
{
HINSTANCE dll;
HHOOK WINAPI hook;
HOOK_PROC hookAdress;
dll = LoadLibrary(data->dll);
hookAdress = (HOOK_PROC) GetProcAddress(dll,data->func);
if (hookAdress != NULL)
{
(hookAdress)();
}
return 1;
}
Edit:
This is the part in which I allocate the memory to the remote proccess:
typedef struct
{
char* dll;
char* func;
} DATA;
char* dllName = "C:\\Windows\\System32\\cptnhook.dll";
char* funcName = "SetHook";
char* targetPrgm = "mspaint.exe";
Data lData;
lData.dll = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(dllName), MEM_COMMIT, PAGE_READWRITE );
lData.func = (char*) VirtualAllocEx( explorer, 0, sizeof(char)*strlen(funcName), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, lData.func, funcName, sizeof(char)*strlen(funcName), &v );
WriteProcessMemory( explorer, lData.dll, dllName, sizeof(char)*strlen(dllName), &v );
rDataP = (DATA*) VirtualAllocEx( explorer, 0, sizeof(DATA), MEM_COMMIT, PAGE_READWRITE );
WriteProcessMemory( explorer, rDataP, &lData, sizeof(DATA), NULL );
Edit:
It looks like the problem is that the remote thread is calling a "garbage" address
instead of LoadLibrary base address. Is there a possibily Visual studio linked
the remote proccess LoadLibrary address wrong?
Edit:
when I try to run the same exact code as a local thread (I use a handle to the current procces in CreateRemoteThread) the entire thing works just fine. What can cause this?
Should I add the calling function code? It seems to be doing its job as
the code is being executed in the remote thread with the correct parameters...
The code is compiled under VS2010.
data is a simple struct with char* 's to the names. (As explicetly writing the strings in code would lead to pointers to my original proccess).
What am I doing wrong?
Failing with ERROR_INVALID_PARAMETER indicates that there is a problem with the parameters passed.
So one should look at data->dll which represents the only parameter in question.
It is initialised here:
lData.dll = VirtualAllocEx(explorer, 0, sizeof(char) * (strlen(dllName) + 1), MEM_COMMIT, PAGE_READWRITE);
So let's add a check whether the allocation of the memory which's reference should be store into lData.dll really succeded.
if (!lData.dll) {
// do some error logging/handling/whatsoever
}
Having done so, you might have detected that the call as implemented failed because (verbatim from MSDN for VirtualAllocEx()):
The function fails if you attempt to commit a page that has not been
reserved. The resulting error code is ERROR_INVALID_ADDRESS.
So you might like to modifiy the fourth parameter of the call in question as recommended (again verbatim from MSDN):
To reserve and commit pages in one step, call VirtualAllocEx with
MEM_COMMIT | MEM_RESERVE.
PS: Repeat this exercise for the call to allocate lData.func. ;-)
It's possible that LoadLibrary is actually aliasing LoadLibraryW (depending on project settings), which is the Unicode version. Whenever you use the Windows API with "char" strings instead of "TCHAR", you should explicitly use ANSI version names. This will prevent debugging hassles when the code is written, and also in the future for you or somebody else in case the project ever flips to Unicode.
So, in addition to fixing that horrible unterminated string problem, make sure to use:
LoadLibraryA(data->dll);

WriteProcessMemory to SYSTEM process with SeDebugPrivilege enabled. (C, Vista)

I'm interested in injecting DLLs into SYSTEM owned processes on my Vista machine. I'm going about this using the traditional method of VirtualAllocEx, WriteProcessMemory and CreateRemoteThread. However, because this will be operating on SYSTEM processes, I enable SeDebugPivilege on the injecting process before opening the target process.
int EnableDebugPriv(LPCTSTR name) {
HANDLE hToken;
LUID luid;
TOKEN_PRIVILEGES tkp;
if(!OpenProcessToken(GetCurrentProcess(),
/*TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY*/
TOKEN_ALL_ACCESS,
&hToken))
return 0;
if(!LookupPrivilegeValue(NULL,name,&luid))
return 0;
tkp.PrivilegeCount=1;
tkp.Privileges[0].Luid=luid;
tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
if(!AdjustTokenPrivileges(hToken,false,&tkp,sizeof(tkp),NULL,NULL))
{
printf("!AdjustTokenPrivileges - %d\n",GetLastError());
return 0;
}
if(GetLastError()==ERROR_NOT_ALL_ASSIGNED)
{
return 0;
}
CloseHandle(hToken);
return 1;
}
Where the SE_DEBUG_NAME constant is passed as name.
After enabling SeDebugPrivilege, I go through the process of opening the target process, locating LoadLibrary, allocating space, writing the DLL path to memory, and creating the thread (checking all return values along the way):
if(NULL==(p=OpenProcess(PROCESS_ALL_ACCESS,FALSE,(DWORD)pid)))
...
if(NULL==(loadLib=(LPVOID)GetProcAddress(GetModuleHandle("kernel32.dll"),
"LoadLibraryA")))
...
if(NULL==(dllBuff=(LPVOID)VirtualAllocEx(p,
NULL,
strlen(dllPath)+1,
MEM_RESERVE|MEM_COMMIT,
PAGE_READWRITE)))
...
if(NULL==WriteProcessMemory(p,
(LPVOID)dllBuff,
dllPath,
strlen(dllPath),
&written))
...
if(!CreateRemoteThread(p,
NULL,
NULL,
(LPTHREAD_START_ROUTINE)loadLib,
(LPVOID)dllBuff,
NULL,
NULL))
...
dllPath is a char* of the DLL's path (obviously), and pid is the PID of the target process. Both of these values are taken in through the command line and validated before being used.
The problem I'm having is that nothing is returning errors until CreateRemoteThread, which is returning an 8 ("Not enough storage"). HOWEVER, WriteProcessMemory is NOT writing any bytes to the process. After the call the written variable is always 0. No bytes are being written, but the function is not failing. I'm not sure why this is happening. I looked into other privileges, like the SeRestorePrivilege which promises write access to all processes, but nothing works.
I'm executing this program with Administrator rights.
Note: this WriteProcessMemory and CreateRemoteThread problem only happen when I run this program against higher privileged users (SYSTEM, LOCAL SERVICE, etc...). It works perfectly against a program owned by me (same privileges).
Edit: Here's a link to the whole source. http://pastebin.com/m77110d8e There's not much else there besides basic error checking, but maybe it will help?
This has to do with session isolation in Vista or higher versions of Windows. Check out the source or disassembly for password dumping tools like Cain and Abel that purport Vista functionality. Essentially the process is the same but you'll be calling a different function for CreateRemoteThread (sorry, I don't think the function is exported, you just have to find it, so disassembly of working software is probably the best bet).
You could try using RtlCreateUserThread, instead of CreateRemoteThread. This routine doesn't care what session the target process lives in. Just remember to have the thread call RtlExitUserThread before it ends. These threads don't clean up after themselves, like the CreateThread/CreateRemoteThread ones do.
The reactos code can give you a good look at what these routines are doing.