Injecting a DLL from LoadImageNotifyRoutine, hangs on ZwMapViewOfSection - wdk

So I'm making a crackme and one of the parts is to hook a certain function and wait for a certain combination a params to happen, then the challenge is done.
For that, I'm creating a driver to inject a DLL into processes that have a specific DLL and hook a certain function.
I'm doing it by
Getting a handle for the DLL to inject
ZwCreateFile(
&DeviceExtension->HookDllHandle,
GENERIC_ALL,
&Attributes,
&StatusBlock,
NULL,
0,
0,
FILE_OPEN,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0
)
Then, registering a LoadImageNotifyRoutine inside driver main
PsSetLoadImageNotifyRoutine(ImageCBK);
What's supposed to happen:
I check the if the needed DLL (that will export my function) is loaded.
By being inside the context of the process that invoked the callback, I create a section with ZwCreateSection, then map the dll into that section and call the DLL's entry point by creating a new thread.
After that, the hooking should be no problem.
Even though the IRQL for ZwCreateSection and ZwMapViewOfSection allows their use inside a notify routine, still ZwMapViewOfSection hangs every time I try to use it.
I've been using some code from Beholder
status = ObOpenObjectByPointer(PsGetCurrentProcess(), OBJ_KERNEL_HANDLE, NULL, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ProcessHandle);
if (!NT_SUCCESS(status))
{
DbgPrint("Unable to get process handle\n");
return STATUS_SEVERITY_ERROR;
}
// Create a new section for DLL mapping
InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateSection(&DllSectionHandle, SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_QUERY, &Attributes, NULL, PAGE_EXECUTE_READ, SEC_IMAGE, DeviceExtension->HookDllHandle);
if (!NT_SUCCESS(status))
{
ZwClose(ProcessHandle);
DbgPrint("Section creation failed %08X\n", status);
return status;
}
DbgPrint("Section created %08X\n", DllSectionHandle);
// Map DLL on the section
status = ZwMapViewOfSection(DllSectionHandle, ProcessHandle, &DllBaseAddress, 0, 0, NULL, &DllViewSize, ViewUnmap, 0, PAGE_EXECUTE_READ);
if (!NT_SUCCESS(status))
{
ZwClose(ProcessHandle);
ZwClose(DllSectionHandle);
DbgPrint("Unable to map section %08X\n", status);
return status;
}
DbgPrint("Mapped DLL: %08X\n", DllBaseAddress);
Sadly, it never shows the last DbgPrint with the DllBaseAddress

simply read documentation
The operating system calls the driver's load-image notify routine at
PASSIVE_LEVEL inside a critical region with normal kernel APCs always
disabled
and
To avoid deadlocks, load-image notify routines must not call system
routines that map, allocate, query, free, or perform other operations
on user-space virtual memory.
you ignore this and call routine ZwMapViewOfSection that map. and got deadlock
solution is simply and elegant - insert normal kernel mode APC to current thread inside ImageCBK. because this APC is disabled here - it executed already after you return from ImageCBK -just system exit from critical region and enable APC. at this point your apc KernelRoutine/NormalRoutine will be called. and exactly inside NormalRoutine you must map

Related

MmProbeAndLockPages() failed while coding windows driver

I am coding a windows driver.
I try to probes a Virtual Memory Page using MmProbeAndLockPages() https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-mmprobeandlockpages
First I allocate the MDL using IoAllocateMdl(). Then I probes the virtual memory page. The code is like :
PMDL pMdl = IoAllocateMdl(Dest, (ULONG)Size, FALSE, FALSE, NULL);
if (pMdl) {
__try {
MmProbeAndLockPages(pMdl, KernelMode, IoModifyAccess);
MmUnlockPages(pMdl);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
status = GetExceptionCode();
}
IoFreeMdl(pMdl);
}
I also tried to attach to the process using KeStackAttachProcess() but it has no effect.
The Dest variable is a PVOID to a userland process' address. The address is valid because I can read from it.
Do you have an idea why MmProbeAndLockPages() failed and my code goes into the except branch?
The exception code is 0xC0000005 (which is an access violation) but I specified IoModifyAccess/IoWriteAccess and I should be able to write to a userland process from kernelland, right?
Even when I unset the WP bit of cr0, it doesn't work ... hum something weird is happening
I am using a windows 10.0.19044
Thanks
regards
I have to change IoModifyAccess to IoReadAccess.
Then to call MmProtectMdlSystemAddress() with PAGE_READWRITE.

How can I delete a file and send it to the recycle bin in Vista/7 using IFileOperation?

According to the documentation for IFileOperation::SetOperationFlags, the FOFX_RECYCLEONDELETE flag was introduced in Windows 8.
I would like to delete files and send them to the recycle bin. How is it possible to do that using IFileOperation in Vista and Windows 7?
I know that SHFileOperation supports that functionality, but I don't want to use SHFileOperation as Microsoft are telling us to use IFileOperation in its place. Is this possible using IFileOperation, and if so, how is it to be done?
The documentation for SetOperationFlags says:
This member can be a combination of the following flags. FOF flags are defined in Shellapi.h and FOFX flags are defined in Shobjidl.h.
So you can use the exact same flag, FOF_ALLOWUNDO, that you use with SHFileOperation to direct a delete action to move to the recycle bin.
 FOFX_RECYCLEONDELETE flag was introduced in Win 8 - will it work in Vista/7?
Since FOFX_RECYCLEONDELETE was introduced in Windows 8, then it did not exist in Vista/7, so no, it will not work in those versions.
There's always SHFileOperation but I'd rather use a more up-to-date Win32 API method. Anything else to know? Any alternate ways of recycling files/folders?
SHFileOperation() is the only documented way to recycle files/folders:
When used to delete a file, SHFileOperation permanently deletes the file unless you set the FOF_ALLOWUNDO flag in the fFlags member of the SHFILEOPSTRUCT structure pointed to by lpFileOp. Setting that flag sends the file to the Recycle Bin. If you want to simply delete a file and guarantee that it is not placed in the Recycle Bin, use DeleteFile.
That same flag is available in IFileOperation, but its documented behavior is different:
Preserve undo information, if possible.
Prior to Windows Vista, operations could be undone only from the same process that performed the original operation.
In Windows Vista and later systems, the scope of the undo is a user session. Any process running in the user session can undo another operation. The undo state is held in the Explorer.exe process, and as long as that process is running, it can coordinate the undo functions.
That is why FOFX_RECYCLEONDELETE had to be introduced - to re-add the old Recycle Bin behavior that had been lost when IFileOperation was first introduced.
I have verified David Heffernan's assessment of the FOF_ALLOWUNDO flag's use with IFileOperation to send items to the recycle bin. Here's the code. Apparently SHCreateItemFromParsingName is MS's way of saying create an item from a string. This code is catered to C++ with Qt. You'll have to initialize COM first of course.
void Worker::deleteItem(QString item)
{
HRESULT hr;
IFileOperation *pfo;
wchar_t *itemWChar = new wchar_t[item.length()+1];
item.toWCharArray(itemWChar);
itemWChar[item.length()] = 0;
PCWSTR itemPCWSTR = itemWChar;
hr = CoCreateInstance(CLSID_FileOperation,
NULL,
CLSCTX_ALL,
//IID_IFileOperation,
IID_PPV_ARGS(&pfo));
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->SetOperationFlags(FOF_ALLOWUNDO | FOF_NOCONFIRMATION);
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
IShellItem *deleteItem = NULL;
hr = SHCreateItemFromParsingName(itemPCWSTR,
NULL,
IID_PPV_ARGS(&deleteItem));
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->DeleteItem(deleteItem,NULL);
if (deleteItem != NULL)
{
deleteItem->Release();
}
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
hr = pfo->PerformOperations();
if (!SUCCEEDED(hr))
{
//error handling here
return;
}
pfo->Release();
delete[] itemWChar;
}

how to pass a process thread handle to another process

I need to pass a thread handle for APC to another process in order to be able to call QueueUserAPC into the src thread :
HANDLE SMconsumerThread;
if (!DuplicateHandle(GetCurrentProcess(),// src server thread
GetCurrentThread(),
GetCurrentProcess(),// target is any client
(HANDLE*)&SMconsumerThread,
THREAD_SET_CONTEXT, // only permission required by QueueUserAPC
FALSE, // not inheritable
0)) // no options
{
printf("cannot server thread handle");
}
how is it done, because GetCurrentProcess/GetCurrentThread return the pseudo handle -1 within the caller process, I found this explanation for passing sockets among processes: http://tangentsoft.net/wskfaq/articles/passing-sockets.html
are there any examples or explanations how to duplicate a thread handle ?

Boost interprocess message_queue and COM

I'm using boost::interprocess::message_queue for communication between processes. In one of them i use
::CoInitializeEx( 0, COINIT_MULTITHREADED );
to set up for COM calls. I cannot access any queues created after this call from the other process, or for that matter the same process but before the CoInit call.
I'm not terribly famililar with COM and their threading model, the CoInit call was added by a co-worker. What can I do to resolve this?
Here is a short snippet to illustrate:
boost::interprocess::message_queue m_queue1( boost::interprocess::open_or_create, "testqueue", 256, sizeof(int) );
::CoInitializeEx( 0, COINIT_MULTITHREADED );
boost::interprocess::message_queue m_queue2( boost::interprocess::open_only, "testqueue" );
In this example the second queue's constructor will throw an exception because it thinks the queue doesn't exist. If I remove the CoInit call it works fine.
EDIT:
Boost version is 1.46.1. The call to CoInit in the snippet above returns S_OK.

How do I automatically destroy child processes in Windows?

In C++ Windows app, I launch several long running child processes (currently I use CreateProcess(...) to do this.
I want the child processes to be automatically closed if my main processes crashes or is closed.
Because of the requirement that this needs to work for a crash of the "parent", I believe this would need to be done using some API/feature of the operating system. So that all the "child" processes are cleaned up.
How do I do this?
The Windows API supports objects called "Job Objects". The following code will create a "job" that is configured to shut down all processes when the main application ends (when its handles are cleaned up). This code should only be run once.:
HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };
// Configure all child processes associated with the job to terminate when the
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
{
::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
}
}
Then when each child process is created, execute the following code to launch each child each process and add it to the job object:
STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
if(ghJob)
{
if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
{
::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
}
}
// Can we free handles now? Not sure about this.
//CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
VISTA NOTE: See AssignProcessToJobObject always return "access denied" on Vista if you encounter access-denied issues with AssignProcessToObject() on vista.
One somewhat hackish solution would be for the parent process to attach to each child as a debugger (use DebugActiveProcess). When a debugger terminates all its debuggee processes are terminated as well.
A better solution (assuming you wrote the child processes as well) would be to have the child processes monitor the parent and exit if it goes away.
Windows Job Objects sounds like a good place to start. The name of the Job Object would have to be well-known, or passed to the children (or inherit the handle). The children would need to be notice when the parent dies, either through a failed IPC "heartbeat" or just WFMO/WFSO on the parent's process handle. At that point any child process could TermianteJobObject to bring down the whole group.
You can keep a separate watchdog process running. Its only task is watching the current process space to spot situations like you describe. It could even re-launch the original application after a crash or provide different options to the user, collect debug information, etc. Just try to keep it simple enough so that you don't need a second watchdog to watch the first one.
You can assign a job to the parent process before creating processes:
static HANDLE hjob_kill_on_job_close=INVALID_HANDLE_VALUE;
void init(){
hjob_kill_on_job_close = CreateJobObject(NULL, NULL);
if (hjob_kill_on_job_close){
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobli = { 0 };
jobli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
SetInformationJobObject(hjob_kill_on_job_close,
JobObjectExtendedLimitInformation,
&jobli, sizeof(jobli));
AssignProcessToJobObject(hjob_kill_on_job_close, GetCurrentProcess());
}
}
void deinit(){
if (hjob_kill_on_job_close) {
CloseHandle(hjob_kill_on_job_close);
}
}
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE causes all processes associated with the job to terminate when the last handle to the job is closed. By default, all child processes will be assigned to the job automatically, unless you passed CREATE_BREAKAWAY_FROM_JOB when calling CreateProcess. See https://learn.microsoft.com/en-us/windows/win32/procthread/process-creation-flags for more information about CREATE_BREAKAWAY_FROM_JOB.
You can use process explorer from Sysinternals to make sure all processes are assigned to the job. Just like this:
You'd probably have to keep a list of the processes you start, and kill them off one by one when you exit your program. I'm not sure of the specifics of doing this in C++ but it shouldn't be hard. The difficult part would probably be ensuring that child processes are shutdown in the case of an application crash. .Net has the ability to add a function that get's called when an unhandled exception occurs. I'm not sure if C++ offers the same capabilities.
You could encapsulate each process in a C++ object and keep a list of them in global scope. The destructors can shut down each process. That will work fine if the program exits normally but it it crashes, all bets are off.
Here is a rough example:
class myprocess
{
public:
myprocess(HANDLE hProcess)
: _hProcess(hProcess)
{ }
~myprocess()
{
TerminateProcess(_hProcess, 0);
}
private:
HANDLE _hProcess;
};
std::list<myprocess> allprocesses;
Then whenever you launch one, call allprocessess.push_back(hProcess);

Resources