Hi,
Here I am really taking advantage of my summer vacations and back again with a second part of the Windows thread scheduling articles. In the previous blog post I discussed the internals of quantum end context switching (a flowchart). However, the routine responsible for context switching itself wasn't discussed in detail and that's why I'm here today.
Here are some notes that'll help us through this post :
1 - The routine which contains code that does context switching is SwapContext and it's called internally by KiSwapContext. There are some routines that prefer to call SwapContext directly and do the housekeeping that KiSwapContext does themselves.
2 - The routines above (KiSwapContext and SwapContext) are implemented in ALL context switches that are performed no matter what is the reason of the context switch (preemption,wait state,termination...).
3 - SwapContext is originally written in assembly and it doesn't have any prologue or epilogue that are normally seen in ordinary conventions, imagine it like a naked function.
4 - Neither SwapContext or KiSwapContext is responsible for setting the CurrentThread and NextThread fields of the current KPRCB. It is the responsibility of the caller to store the new thread's KTHREAD pointer into pPrcb->CurrentThread and queue the current thread (we're still running in its context) in the ready queue before calling KiSwapContext or SwapContext which will actually perform the context-switch.
Usually before calling KiSwapContext, the old irql (before raising it to DISPATCH_LEVEL) is stored in CurrentThread->WaitIrql , but there's an exception discussed later in this article.
So buckle up and let's get started :
Before digging through SwapContext let's first start by examining what its callers supply to it as arguments.
SwapContext expects the following arguments:
- ESI : (PKTHREAD) A pointer to the New Thread's structure.
- EDI : (PKTHREAD) A pointer to the old thread's structure.
- EBX : (PKPCR) A pointer to PCR (Processor control region) structure of the current processor.
- ECX : (KIRQL) The IRQL in which the thread was running before raising it to DISPATCH_LEVEL.
By callers, I mean the KiSwapContext routine and some routines that call SwapContext directly (ex : KiDispatchInterrupt).
Let's start by seeing what's happening inside KiSwapContext :
This routine expects 2 arguments the Current thread and New thread KTHREAD pointers in ECX and EDX respectively (__fastcall).
Before storing both argument in EDI and ESI, It first proceeds to save these and other registers in the current thread's (old thread soon) stack:
EBP : The stack frame base pointer (SwapContext only updates ESP).
EDI : The caller might be using EDI for something else ,save it.
ESI : The caller might be using ESI for something else ,save it too.
EBX : The caller might be using EBX for something else ,save it too.
Note that these registers will be popped from this same thread's stack when the context will be switched from another thread to this thread again at a later time (when it will be rescheduled to run).
After pushing the registers, KiSwapContext stores the self pointer to the PCR in EBX (fs:[1Ch]).Then it stores the CurrentThread->WaitIrql value in ECX, now that everything is set up KiSwapContext is ready to call SwapContext.
Again, before going through SwapContext let me talk about routines that actually call SwapContext directly and exactly the KiDispatchInterrupt routine that was referenced in my previous post.
Why doesn't KiDispatchInterrupt call KiSwapContext ?
Simply because it just needs to push EBP,EDI and ESI onto the current thread's stack as it already uses EBX as a pointer to PCR.
Here, we can see a really great advantage of software context switching where we just save the registers that we really need to save, not all registers.
Now , we can get to SwapContext and explain what it does in detail.
The return type of SwapContext is a boolean value that tells the caller (in the new thread's stack) whether the new thread has any APCs to deliver or not.
Let's see what SwapContext does in these 15 steps:
1 - The first thing that SwapContext does is verify that the new thread isn't actually running , this is only right when dealing with a multiprocessor system where another processor might be actually running the thread.If the new thread is running SwapContext just loops until the thread stops running. The boolean value checked is NewThread->Running and after getting out of the loop, the Running boolean is immediately set to TRUE.
2 - The next thing SwapContext does is pushing the IRQL value supplied in ECX. To spoil a bit of what's coming in the next steps (step 13) SwapContext itself pops ECX later, but after the context switch. As a result we'll be popping the new thread's pushed IRQL value (stack switched).
3 - Interrupts are disabled, and PRCB cycle time fields are updated with the value of the time-stamp counter. After the update, Interrupts are enabled again.
4 - increment the count of context switches in the PCR (Pcr->ContextSwitches++;) , and push Pcr->Used_ExceptionList which is the first element of PCR (fs:[0]). fs:[0] is actually a pointer to the last registered exception handling frame which contains a pointer to the next frame and also a pointer to the handling routine (similar to usermode), a singly linked list simply. Saving the exception list is important as each thread has its own stack and thus its own exception handling list.
5 - OldThread->NpxState is tested, if it's non-NULL, SwapContext proceeds to saving the floating-points registers and FPU related data using fxsave instruction. The location where this data is saved is in the initial stack,and exactly at (Initial stack pointer - 528 bytes) The fxsave output is 512 bytes long , so it's like pushing 512 bytes onto the initial stack , the other 16 bytes are for stack-alignment I suppose.The Initial stack is discussed later during step 8.
6 - Stack Swapping : Save the stack pointer in OldThread->KernelStack and load NewThread->KernelStack into ESP. We're now running in the new thread's stack, from now on every value that we'll pop was previously pushed the last time when the new thread was preparing for a context-switch.
7 - Virtual Address Space Swapping : The old thread process is compared with the new thread's process if they're different CR3 register (Page directory pointer table register) is updated with the value of : NewThread->ApcState.Process->DirectoryTableBase. As a result, the new thread will have access to a valid virtual address space. If the process is the same, CR3 is kept unchanged. The local descriptor table is also changed if the threads' processes are different.
8 - TSS Esp0 Switching : Even-though I'll dedicate a future post to discuss TSS (task state segment) in detail under Windows , a brief explanation is needed here. Windows only uses one TSS per processor and uses only (another field is also used but it is out of the scope of this article) ESP0 and SS0 fields which stand for the kernel stack pointer and the kernel stack segment respectively. When a usermode to kernelmode transition must be done as a result of an interrupt,exception or system service call... as part of the transition ESP must be changed to point to the kernel stack, this kernel stack pointer is taken from TSS's ESP0 field. Logically speaking, ESP0 field of the TSS must be changed on every context-switch to the kernel stack pointer of the new thread. In order to do so, SwapContext takes the kernel stack pointer at NewThread->InitialStack (InitialStack = StackBase - 0x30) ,it substrats the space that it has used to save the floating-point registers using fxsave instruction and another additional 16 bytes for stack alignment, then it stores the resulted stack pointer in the TSS's Esp0 field : pPcr->TssCopy.Esp0 (TSS can be also accessed using the TR segment register).
9 - We've completed the context-switch now and the old thread can be finally marked as "stopped running" by setting the previously discussed boolean value "Running" to FALSE. OldThread->Running = FALSE.
10 - If fxsave was previously executed by the new thread (the last time its context was switched), the data (floating-point registers...) saved by it is loaded again using xrstor instruction.
11 - Next the TEB (Thread environment block) pointer is updated in the PCR :
pPcr->Used_Self = NewThread->Teb . So the Used_Self field of the PCR points always to the current thread's TEB.
12 - The New thread's context switches count is incremented (NewThread->ContextSwitches++).
13 - It's finally the time to pop the 2 values that SwapContext pushed , the pointer to the exception list and the IRQL from the new thread's stack. the saved IRQL value is restored in ECX and the exception list pointer is popped into its field in the PCR.
14 - A check is done to see if the context-switch was performed from a DPC routine (Entering a wait state for example) which is prohibited. If pPrcb->DpcRoutineActive boolean is TRUE this means that the current processor is currently executing a DPC routine and SwapContext will immediately call KeBugCheck which will show a BSOD : ATTEMPTED_SWITCH_FROM_DPC.
15 - This is the step where the IRQL (NewThread->WaitIrql) value stored in ECX comes to use. As mentionned earlier SwapContext returns a boolean value telling the caller if it has to deliver any pending APCs. During this step SwapContext will check the new thread's ApcState to see if there are any kernel APCs pending. If there are : a second check is performed to see if special kernel APCs are disabled , if they're not disabled ECX is tested to see if it's PASSIVE_LEVEL, if it is above PASSIVE_LEVEL an APC_LEVEL software interrupt is requested and the function returns FALSE. Actually the only case that SwapContext returns TRUE is if ECX is equal to PASSIVE_LEVEL so the caller will proceed to lowering IRQL to APC_LEVEL first to call KiDeliverApc and then lower it to PASSIVE_LEVEL afterwards.
Special Case :
This special case is actually about the IRQL value supplied to SwapContext in ECX. The nature of this value depends on the caller in such way that if the caller will lower the IRQL immediately upon returning from SwapContext or not.
Let's take 2 examples : KiQuantumEnd and KiExitDispatcher routines. (KiQuantumEnd is the special case)
If you disassemble KiExitDispatcher you'll notice that before calling KiSwapContext it stores the OldIrql (before it was raised to DISPATCH_LEVEL) in the WaitIrql of the old thread so when the thread gains execution again at a later time SwapContext will decide whether there any APCs to deliver or not. KiExitDispatcher makes use of the return value of KiSwapContext (KiSwapContext returns the same value returned by SwapContext) to lower the IRQL. (see step 15 last sentence).
However, by disassembling KiQuantumEnd you'll see that it's storing APC_LEVEL at the old thread's WaitIrql without even caring about in which IRQL the thread was running before. If you refer back to my flowchart in the previous article you'll see that KiQuantumEnd always insures that SwapContext returns FALSE , first of all because KiQuantumEnd was called as a result of calling KiDispatchInterrupt which is meant to be called when a DISPATCH_LEVEL software interrupt was requested.Thus, KiDispatchInterrupt was called by HalpDispatchSoftwareInterrupt which is normally called by HalpCheckForSoftwareInterrupt. HalpDispatchSoftwareInterrupt is the function responsible for raising the IRQL to the software interrupt level (APC_LEVEL or DISPATCH_LEVEL) and upon returning from it HalpCheckForSoftwareInterrupt recovers back the IRQL to its original value (OldIrql). So the reason why KiQuantumEnd doesn't care about KiSwapContext return value because it won't proceed to lowering the IRQL (not its responsibility) nor to deliver any APCs that's why it's supplying APC_LEVEL as an old IRQL value to SwapContext so that it will return FALSE. However, a software interrupt might be requested by SwapContext if there are any pending APCs.
KiDispatchInterrupt which calls SwapContext directly uses the same approach as KiQuantumEnd, instead of storing the value at OldThread->WaitIrql it just moves it into ECX.
Post notes :
- Based on Windows 7 32 bit :>
- For any questions or suggestions feel free to leave a comment below or send me an email : souhail.hammou@outlook.com
See you again soon :)
-Souhail
Friday, September 5, 2014
Saturday, August 30, 2014
Windows Internals - Quantum end context switching
Hello,
Lately I decided to start sharing the notes I gather , almost daily , while reverse engineering and studying Windows. As I focused in the last couple of days on studying context switching , I was able to decompile the most involved functions and study them alongside with noting the important stuff. The result of this whole process was a flowchart.
Before getting to the flowchart let's start by putting ourselves in the main plot :
As you might know, each thread runs for a period of time before another thread is scheduled to run, excluding the cases where the thread is preempted ,entering a wait state or terminated. This time period is called a quantum. Everytime a clock interval ends (mostly 15 ms) the system clock issues an interrupt.While dispatching the interrupt, the thread current cycle count is verified against its cycle count target (quantum target) to see if it has reached or exceeded its quantum so the context would be switched the next thread scheduled to run.
Note that a context-switch in Windows doesn't happen only when a thread has exceeded its quantum, it also happens when a thread enters a wait state or when a higher priority thread is ready to run and thus preempts the current thread.
As it will take some time to organize my detailed notes and share them here as an article (maybe for later),consider the previous explanation as a small introduction into the topic. However ,the flowchart goes through the details involved in quantum end context switching.
Please consider downloading the pdf to be able to zoom as much as you like under your PDF reader because GoogleDocs doesn't provide enough zooming functionality to read the chart.
Preview (unreadable) :
PDF full size Download : GoogleDocs Link
P.S :
- As always , this article is based is on : Windows 7 32-bit
- Note that details concerning the routine that does the context switching (SwapContext) aren't included in the chart and are left it for a next post.
See you again soon.
-Souhail.
Lately I decided to start sharing the notes I gather , almost daily , while reverse engineering and studying Windows. As I focused in the last couple of days on studying context switching , I was able to decompile the most involved functions and study them alongside with noting the important stuff. The result of this whole process was a flowchart.
Before getting to the flowchart let's start by putting ourselves in the main plot :
As you might know, each thread runs for a period of time before another thread is scheduled to run, excluding the cases where the thread is preempted ,entering a wait state or terminated. This time period is called a quantum. Everytime a clock interval ends (mostly 15 ms) the system clock issues an interrupt.While dispatching the interrupt, the thread current cycle count is verified against its cycle count target (quantum target) to see if it has reached or exceeded its quantum so the context would be switched the next thread scheduled to run.
Note that a context-switch in Windows doesn't happen only when a thread has exceeded its quantum, it also happens when a thread enters a wait state or when a higher priority thread is ready to run and thus preempts the current thread.
As it will take some time to organize my detailed notes and share them here as an article (maybe for later),consider the previous explanation as a small introduction into the topic. However ,the flowchart goes through the details involved in quantum end context switching.
Please consider downloading the pdf to be able to zoom as much as you like under your PDF reader because GoogleDocs doesn't provide enough zooming functionality to read the chart.
Preview (unreadable) :
PDF full size Download : GoogleDocs Link
P.S :
- As always , this article is based is on : Windows 7 32-bit
- Note that details concerning the routine that does the context switching (SwapContext) aren't included in the chart and are left it for a next post.
See you again soon.
-Souhail.
Wednesday, July 9, 2014
OkayToCloseProcedure callback kernel hook
Hi ,
During the last few weeks I was busy exploring the internal working of Handles under Windows , by disassembling and decompiling certain kernel (ntoskrnl.exe) functions under my Windows 7 32-bit machine.In the current time I am preparing a paper to describe and explain what I learned about Handles. But today I’m here to discuss an interesting function pointer hook that I found while decompiling and exploring the ObpCloseHandleEntry function. (Source codes below).
A function pointer hook consists of overwriting a callback function pointer so when a kernel routine will call the callback function, the hook function will be called instead . The function pointer that we will be hooking in this article is the OkayToCloseProcedure callback that exists in the _OBJECT_TYPE_INITIALIZER structure which is an element of the OBJECT_TYPE struct.
Every object in Windows has an OBJECT_TYPE structure which specifies the object type name , number of opened handles to this object type ...etc OBJECT_TYPE also stores a type info structure (_OBJECT_TYPE_INITIALIZER) that has a group of callback functions (OpenProcedure ,CloseProcedure…) . All OBJECT_TYPE structures pointers are stored in the unexported ObTypeIndexTable array.
As I said earlier , the OkayToCloseProcedure is called inside ObpCloseHandleEntry function.In general this function (if the supplied handle is not protected from being closed) frees the handle table entry , decrements the object’s handle count and reference count.
Another case when the handle will not be closed is if the OkayToCloseProcedure returned 0 , in this case the ObpCloseHandleTableEntry returns STATUS_HANDLE_NOT_CLOSABLE.
I will discuss handles in more details in my future blog posts.
So how the OkayToCloseProcedure is called ?
ObpCloseHandleTableEntry function actually gets the Object (which the handle is opened to) header (_OBJECT_HEADER). A pointer to the object type structure (_OBJECT_TYPE) is then obtained by accessing the ObTypeIndexTable array using the Object Type Index from the object header (ObTypeIndexTable[ObjectHeader->TypeIndex]).
The function will access the OkayToCloseProcedure field and check if it’s NULL , if that’s true the function will proceed to other checks (check if the handle is protected from being closed). If the OkayToCloseProcedure field isn’t NULL , the function will proceed to call the callback function. If the callback function returns 0 the handle cannot be closed and ObpCloseHandleTableEntry will return STATUS_HANDLE_NOT_CLOSABLE. If it returns a value other than 0 we will proceed to the other checks as it happens when the OkayToCloseProcedure is NULL.
An additional point is that the OkayToCloseProcedure must always run within the context of the process that opened the handle in the first place (a call to KeStackAttachProcess). I don’t think that this would be a problem if ObpCloseHandleTableEntry is called as a result of calling ZwClose from usermode because we’ll be running in the context of the process that opened the handle.However, if ZwClose was called from kernel land and was supplied a kernel handle KeStackAttachProcess will attach the thread to the system process. The reason behind that is that we always want to access the right handle table (each process has a different handle table, and for the kernel we have the system handle table).
So if ObpCloseHandleTableEntry is called from another process context and is trying to close another process’s handle, the OkayToCloseProcedure must run in that process context. That’s why ObpCloseHandleTableEntry takes a pointer to the process object (owner of the handle) as a parameter.
Applying the hook :
Now after we had a quick overview of what’s happening , let’s try and apply the hook on the OBJECT_TYPE_INITIALIZER’s OkayToCloseProcedure field.
I applied the hook on the Process object type , we can obtain a pointer to the process object type by taking advantage of the exported PsProcessType , it’s actually a pointer to a pointer to the process’s object type.
Here’s a list containing the exported object types :
POBJECT_TYPE *ExEventObjectType;
POBJECT_TYPE *ExSemaphoreObjectType;
POBJECT_TYPE *IoFileObjectType;
POBJECT_TYPE *PsThreadType;
POBJECT_TYPE *SeTokenObjectType;
POBJECT_TYPE *PsProcessType;
POBJECT_TYPE *TmEnlistmentObjectType;
POBJECT_TYPE *TmResourceManagerObjectType;
POBJECT_TYPE *TmTransactionManagerObjectType;
POBJECT_TYPE *TmTransactionObjectType;
A second way to get an object’s type is by getting an existing object’s pointer and then pass it to the exported kernel function ObGetObjectType which will return a pointer to the object’s type.
A third way is to get a pointer to the ObTypeIndexTable array, it’s unexported by the kernel but there are multiple functions using it including the exported ObGetObjectType function.So the address can be extracted from the function's opcodes , but that will introduce another compatibility problem. After getting the pointer to the ObTypeIndexTable you'll have to walk through the whole table and preform a string comparison to the target's object type name ("Process","Thread" ...etc) against the Name field in each _OBJECT_TYPE structure.
In my case I hooked the Process object type , and I introduced in my code the 1st and the 2nd methods (second one commented).
My hook isn’t executing any malicious code !! it’s just telling us (using DbgPrint) that an attempt to close an open handle to a process was made.
“An attempt” means that we’re not sure "yet" if the handle will be closed or not because other checks are made after a successful call to the callback.And by a successful call , I mean that the callback must return a value different than 0 that’s why the hook function is returning 1. I said earlier that the ObpCloseHandleTableEntry will proceed to check if the handle is protected from being closed (after returning from the callback) if the OkayToCloseProcedure is null or if it exists and returns 1 , that's why it’s crucial that our hook returns 1.One more thing , I’ve done a small check to see if the object type’s OkayToCloseProcedure is already NULL before hooking it (avoiding issues).
Example :
For example when closing a handle to a process opened by OpenProcess a debug message will display the handle value and the process who opened the handle.
As you can see "TestOpenProcess.exe" just closed a handle "0x1c" to a process that it opened using OpenProcess().
P.S : The hook is version specific.
Source codes :
Decompiled ObpCloseHandleTableEntry : http://pastebin.com/QL0uaCtJ
Driver Source Code : http://pastebin.com/Z2zucYGZ
Your comments are welcome.
Souhail Hammou.
@Dark_Puzzle
During the last few weeks I was busy exploring the internal working of Handles under Windows , by disassembling and decompiling certain kernel (ntoskrnl.exe) functions under my Windows 7 32-bit machine.In the current time I am preparing a paper to describe and explain what I learned about Handles. But today I’m here to discuss an interesting function pointer hook that I found while decompiling and exploring the ObpCloseHandleEntry function. (Source codes below).
A function pointer hook consists of overwriting a callback function pointer so when a kernel routine will call the callback function, the hook function will be called instead . The function pointer that we will be hooking in this article is the OkayToCloseProcedure callback that exists in the _OBJECT_TYPE_INITIALIZER structure which is an element of the OBJECT_TYPE struct.
Every object in Windows has an OBJECT_TYPE structure which specifies the object type name , number of opened handles to this object type ...etc OBJECT_TYPE also stores a type info structure (_OBJECT_TYPE_INITIALIZER) that has a group of callback functions (OpenProcedure ,CloseProcedure…) . All OBJECT_TYPE structures pointers are stored in the unexported ObTypeIndexTable array.
As I said earlier , the OkayToCloseProcedure is called inside ObpCloseHandleEntry function.In general this function (if the supplied handle is not protected from being closed) frees the handle table entry , decrements the object’s handle count and reference count.
Another case when the handle will not be closed is if the OkayToCloseProcedure returned 0 , in this case the ObpCloseHandleTableEntry returns STATUS_HANDLE_NOT_CLOSABLE.
I will discuss handles in more details in my future blog posts.
So how the OkayToCloseProcedure is called ?
ObpCloseHandleTableEntry function actually gets the Object (which the handle is opened to) header (_OBJECT_HEADER). A pointer to the object type structure (_OBJECT_TYPE) is then obtained by accessing the ObTypeIndexTable array using the Object Type Index from the object header (ObTypeIndexTable[ObjectHeader->TypeIndex]).
The function will access the OkayToCloseProcedure field and check if it’s NULL , if that’s true the function will proceed to other checks (check if the handle is protected from being closed). If the OkayToCloseProcedure field isn’t NULL , the function will proceed to call the callback function. If the callback function returns 0 the handle cannot be closed and ObpCloseHandleTableEntry will return STATUS_HANDLE_NOT_CLOSABLE. If it returns a value other than 0 we will proceed to the other checks as it happens when the OkayToCloseProcedure is NULL.
An additional point is that the OkayToCloseProcedure must always run within the context of the process that opened the handle in the first place (a call to KeStackAttachProcess). I don’t think that this would be a problem if ObpCloseHandleTableEntry is called as a result of calling ZwClose from usermode because we’ll be running in the context of the process that opened the handle.However, if ZwClose was called from kernel land and was supplied a kernel handle KeStackAttachProcess will attach the thread to the system process. The reason behind that is that we always want to access the right handle table (each process has a different handle table, and for the kernel we have the system handle table).
So if ObpCloseHandleTableEntry is called from another process context and is trying to close another process’s handle, the OkayToCloseProcedure must run in that process context. That’s why ObpCloseHandleTableEntry takes a pointer to the process object (owner of the handle) as a parameter.
Applying the hook :
Now after we had a quick overview of what’s happening , let’s try and apply the hook on the OBJECT_TYPE_INITIALIZER’s OkayToCloseProcedure field.
I applied the hook on the Process object type , we can obtain a pointer to the process object type by taking advantage of the exported PsProcessType , it’s actually a pointer to a pointer to the process’s object type.
Here’s a list containing the exported object types :
POBJECT_TYPE *ExEventObjectType;
POBJECT_TYPE *ExSemaphoreObjectType;
POBJECT_TYPE *IoFileObjectType;
POBJECT_TYPE *PsThreadType;
POBJECT_TYPE *SeTokenObjectType;
POBJECT_TYPE *PsProcessType;
POBJECT_TYPE *TmEnlistmentObjectType;
POBJECT_TYPE *TmResourceManagerObjectType;
POBJECT_TYPE *TmTransactionManagerObjectType;
POBJECT_TYPE *TmTransactionObjectType;
A second way to get an object’s type is by getting an existing object’s pointer and then pass it to the exported kernel function ObGetObjectType which will return a pointer to the object’s type.
A third way is to get a pointer to the ObTypeIndexTable array, it’s unexported by the kernel but there are multiple functions using it including the exported ObGetObjectType function.So the address can be extracted from the function's opcodes , but that will introduce another compatibility problem. After getting the pointer to the ObTypeIndexTable you'll have to walk through the whole table and preform a string comparison to the target's object type name ("Process","Thread" ...etc) against the Name field in each _OBJECT_TYPE structure.
In my case I hooked the Process object type , and I introduced in my code the 1st and the 2nd methods (second one commented).
My hook isn’t executing any malicious code !! it’s just telling us (using DbgPrint) that an attempt to close an open handle to a process was made.
“An attempt” means that we’re not sure "yet" if the handle will be closed or not because other checks are made after a successful call to the callback.And by a successful call , I mean that the callback must return a value different than 0 that’s why the hook function is returning 1. I said earlier that the ObpCloseHandleTableEntry will proceed to check if the handle is protected from being closed (after returning from the callback) if the OkayToCloseProcedure is null or if it exists and returns 1 , that's why it’s crucial that our hook returns 1.One more thing , I’ve done a small check to see if the object type’s OkayToCloseProcedure is already NULL before hooking it (avoiding issues).
Example :
For example when closing a handle to a process opened by OpenProcess a debug message will display the handle value and the process who opened the handle.
As you can see "TestOpenProcess.exe" just closed a handle "0x1c" to a process that it opened using OpenProcess().
P.S : The hook is version specific.
Source codes :
Decompiled ObpCloseHandleTableEntry : http://pastebin.com/QL0uaCtJ
Driver Source Code : http://pastebin.com/Z2zucYGZ
Your comments are welcome.
Souhail Hammou.
@Dark_Puzzle
Sunday, May 4, 2014
Windows Heap Overflow Exploitation
Hi ,
In this article I will be talking about exploiting a heap overflow in a custom heap. A custom heap is a huge chunk of memory allocated by a usermode application and managed by it.In other words, the application manage 'heap' block allocations and frees (in the allocated chunk) in a custom way while completely ignoring the Windows's heap manager. This method gives the software much more control over its custom heap, but can result in critical security flaws.
The vulnerability that we'll be exploiting together is a heap overflow vulnerability occurring in a custom heap built by the application. The vulnerable software is : ZipItFast 3.0 and our is to gain code execution under Windows 7. ASLR , DEP , SafeSEH aren't enabled by default in the application which makes it even more reliable to us. However, there are still some painful surprises waiting for us ...
Let's start :
The Exploit :
I've actually got the POC from exploit-db , you can check it right here :
http://www.exploit-db.com/exploits/17512/
Oh , and there's also a full exploit here :
http://www.exploit-db.com/exploits/19776/
Unfortunately , you won't learn much from the full exploitation since it will work only on Windows XP SP1. Why ? simply because it's using a technique that consists on overwriting the vectored exception handler node that exists in a static address under windows XP SP1. Briefly , all you have to do is find a pointer to your shellcode (buffer) in the stack. Then take the stack address which points to your pointer and after that substract 0x8 from that address and then perform the overwrite. When an exception is raised , the vectored exception handlers will be dispatched before any handler from the SEH chain, and your shellcode will be called using a CALL DWORD PTR DS: [ESI + 0x8] (ESI = stack pointer to the pointer to your buffer - 0x8). You can google the _VECTORED_EXCEPTION_NODE and check its elements.
And why wouldn't this work under later versions of Windows ? Simply because Microsoft got aware of the use of this technique and now EncodePointer is used to encode the pointer to the handler whenever a new handler is created by the application, and then DecodePointer is called to decode the pointer before the handler is invoked.
Okay, let's start building our exploit now from scratch. The POC creates a ZIP file with the largest possible file name , let's try it :
N.B : If you want to do some tests , execute the software from command line as follows :
Cmd :> C:\blabla\ZipItFast\ZipItFast.exe C:\blabla\exploit.zip
Then click on the Test button under the program.
Let's try executing the POC now :
An access violation happens at 0x00401C76 trying to access an invalid pointer (0x41414141) in our case. Let's see the registers :
Basically the FreeList used in this software is a circular doubly linked lists similar to Windows's . The circular doubly linked list head is in the .bss section at address 0x00560478 and its flink and blink pointers are pointing to the head (self pointers) when the custom heap manager is initialized by the software.
I also didn't check the full implementation of the FreeList and the free/allocate operations in this software to see if they're similar to Windows's (bitmap , block coalescing ...etc).
It's crucial also to know that in our case , the block is being unlinked from the FreeList because the manager had a 'request' to allocate a new block , and it was chosen as best block for the allocation.
Let's get back to analysing the crash :
- First I would like to mention that we'll be calling the pointer to the Freelist Entry struct : "entry".
Registers State at 0x00401C76 :
EAX = entry->Flink
EDX = entry->Blink
[EAX] = entry->Flink->Flink
[EAX+4] = entry->Flink->Blink (Next Block's Previous block)
[EDX] = entry->Blink->Flink (Previous Block's Next Block)
[EDX+4] =entry->Blink->Blink
Logically speaking : Next Block's Previous Block and Previous Block's Next Block are nothing but the current block.
So the 2 instructions that do the block unlinking from the FreeList just :
- Set the previous freelist entry's flink to the block entry's flink.
- Set the next freelist entry's blink to the block entry's blink.
By doing so , the block doesn't belong to the freelist anymore and the function simply returns after that. So it'll be easy to guess what's happening here , the software allocates a static 'heap' block to store the name of the file and it would have best to allocate the block based on the filename length from the ZIP header (this could be a fix for the bug , but heap overflows might be found elsewhere , I'll propose a better method to fix ,but not fully, this bug later in this article).
Now , we know that we're writing past our heap block and thus overwriting the custom metadata of the next heap block (flink and blink pointers). So, We'll need to find a reliable way to exploit this bug , as the 2 unlinking instructions are the only available to us and we control both EAX and EDX. (if it's not possible in another case you can see if there are other close instructions that might help), you can think of overwriting the return address or the pointer to the structured exception handler as we have a stack that won't be rebased after reboot.
This might be a working solution in another case where your buffer is stored in a static memory location.
But Under Windows 7 , it's not the case , VirtualAlloc allocates a chunk of memory with a different base in each program run. In addition , even if the address was static , the location of the freed block that we overwrite varies. So in both cases we'll need to find a pointer to our buffer.
The best place to look is the stack , remember that the software is trying to unlink (allocate) the block that follows the block where we've written the name , so likely all near pointers in the stack (current and previous stack frame) are poiting to the newly allocated block (pointer to metadata) . That's what we don't want because flink and blink pointers that we might set might not be valid opcodes and might cause exceptions , so all we need to do is try to find a pointer to the first character of the name and then figure out how to use this pointer to gain code execution , this pointer might be in previous stack frames.
And here is a pointer pointing to the beginning of our buffer : 3 stack frames away

Remember that 0x01FB2464 will certainly be something else when restarting the program , but the pointer 0x0018F554 is always static , even when restarting the machine.
So when I was at this stage , I started thinking and thinking about a way that will help me redirect execution to my shellcode which is for sure at the address pointed by 0x0018F554 , and by using only what's available to me :
- Controlled registers : EAX and EDX.
- Stack pointer to a dynamic buffer pointer.
- 2 unlinking instructions.
- No stack rebase.
Exploiting the vulnerability and gaining code execution:
And Then I thought , why wouldn't I corrupt the SEH chain and create a Fake frame ? Because when trying to corrupt an SEH chain there are 3 things that you must know :
- SafeSEH and SEHOP are absent.
- Have a pointer to an exisiting SEH frame.
- Have a pointer to a pointer to the shellcode.
The pointer to the shellcode will be treated as the handler,and the value pointed by
((ptr to ptr to shellcode)-0x4) will be treated as the pointer to the next SEH frame.
Let's illustrate the act of corrupting the chain : (with a silly illustration , sorry)
Let me explain :
we need to achieve our goal by using these 2 instructions , right ? :
MOV [EDX],EAX
MOV [EAX+4], EDX
We'll need 2 pointers and we control 2 registers , but which pointer give to which register ? This must not be a random choice because you might overwrite the pointer to the shellcode if you chose EAX as a pointer to your fake SEH frame.
So we'll need to do the reverse , but with precaution of overwriting anything critical.
In addition we actually don't care about the value of "next SEH frame" of our fake frame.
So our main goal is to overwrite the "next SEH frame" pointer of an exisiting frame , to do so we need to have a pointer to our fake frame in one of the 2 registers. As [EAX+4] will overwrite the pointer to the buffer if used as a pointer to the fake SEH frame , we will use EDX instead. We must not also overwrite the original handler pointer because it will be first executed to try to handle the exception , if it fails , then our fake handler (shellcode) will be invoked then.
So : EDX = &(pointer to shellcode) - 0x4 = Pointer to Fake "Next SEH frame" element.
EDX must reside in the next frame field of the original frame which is : [EAX+4].
And EAX = SEH Frame - 0x4.
Original Frame after overwite :
Pointer to next SEH : Fake Frame
Exception Handler : Valid Handler
Fake Frame :
Pointer to next SEH : (Original Frame) - 0x4 (we just don't care about this one)
Exception Handler : Pointer to shellcode
The SEH frame I chose is at : 0x0018F4B4
So : EAX = 0x0018F4B4 - 0x4 = 0x0018F4B0 and EDX =0x0018F554 - 0x4 = 0x0018F550
When the overwrite is done the function will return normally to its caller , and all we have to do now is wait for an exception to occur . An exception will occur after a dozen of instructions as the metadata is badly corrupted. The original handler will be executed but it will fail to handle the access violation and then our fake handler will be called which is the shellcode .
Making the exploit work :
Now all we need to do is calculate the length between the 1st character of the name and the flink and blink pointers , and then insert our pointers in the POC.
Inserting the shellcode :
The space between the starting address of the buffer and the heap overwritten metadata is not so large , so it's best to put an unconditional jump at the start of our buffer to jump past the overwritten flink and blink pointers and then put the shellcode just after the pointers. As we can calculate the length , this won't cause any problem.
Final exploit here : http://pastebin.com/pKyQJicy
I chose a bind shellcode , which opens a connection to (0.0.0.0:4444). Let's try opening the ZIP file using ZipItFast and then check "netstat -an | find "4444" :
The method I stated before which consists on allocating the block based on the filename length from the ZIP headers can be valid only to fix the vulnerability in this case , but what if the attackers were also able to cause an overflow elsewhere in the software ?
The best way to fix the bug is that : when a block is about to be allocated and it's about to be unlinked from the Freelist the first thing that must be done is checking the validity of the doubly linked list , to do so : safe unlinking must be performed and which was introduced in later versions of Windows.
Safe unlinking is done the following way :
if ( entry->flink->blink != entry->blink->flink || entry->blink->flink != entry){
//Fail , Freelist corrupted , exit process
}
else {
//Unlink then return the block to the caller
}
Let's see how safe unlinking is implemented under Windows 7 :
The function is that we'll look at is : RtlAllocateHeap exported by ntdll
Even if this method looks secure , there is some research published online that provides weaknesses of this technique and how can it be bypassed. I also made sure to implement this technique in my custom heap manager (Line 86) , link above.
I hope that you've enjoyed reading this paper .
See you again soon ,
Souhail Hammou.
In this article I will be talking about exploiting a heap overflow in a custom heap. A custom heap is a huge chunk of memory allocated by a usermode application and managed by it.In other words, the application manage 'heap' block allocations and frees (in the allocated chunk) in a custom way while completely ignoring the Windows's heap manager. This method gives the software much more control over its custom heap, but can result in critical security flaws.
The vulnerability that we'll be exploiting together is a heap overflow vulnerability occurring in a custom heap built by the application. The vulnerable software is : ZipItFast 3.0 and our is to gain code execution under Windows 7. ASLR , DEP , SafeSEH aren't enabled by default in the application which makes it even more reliable to us. However, there are still some painful surprises waiting for us ...
Let's start :
The Exploit :
I've actually got the POC from exploit-db , you can check it right here :
http://www.exploit-db.com/exploits/17512/
Oh , and there's also a full exploit here :
http://www.exploit-db.com/exploits/19776/
Unfortunately , you won't learn much from the full exploitation since it will work only on Windows XP SP1. Why ? simply because it's using a technique that consists on overwriting the vectored exception handler node that exists in a static address under windows XP SP1. Briefly , all you have to do is find a pointer to your shellcode (buffer) in the stack. Then take the stack address which points to your pointer and after that substract 0x8 from that address and then perform the overwrite. When an exception is raised , the vectored exception handlers will be dispatched before any handler from the SEH chain, and your shellcode will be called using a CALL DWORD PTR DS: [ESI + 0x8] (ESI = stack pointer to the pointer to your buffer - 0x8). You can google the _VECTORED_EXCEPTION_NODE and check its elements.
And why wouldn't this work under later versions of Windows ? Simply because Microsoft got aware of the use of this technique and now EncodePointer is used to encode the pointer to the handler whenever a new handler is created by the application, and then DecodePointer is called to decode the pointer before the handler is invoked.
Okay, let's start building our exploit now from scratch. The POC creates a ZIP file with the largest possible file name , let's try it :
N.B : If you want to do some tests , execute the software from command line as follows :
Cmd :> C:\blabla\ZipItFast\ZipItFast.exe C:\blabla\exploit.zip
Then click on the Test button under the program.
Let's try executing the POC now :
An access violation happens at 0x00401C76 trying to access an invalid pointer (0x41414141) in our case. Let's see the registers :
Basically the FreeList used in this software is a circular doubly linked lists similar to Windows's . The circular doubly linked list head is in the .bss section at address 0x00560478 and its flink and blink pointers are pointing to the head (self pointers) when the custom heap manager is initialized by the software.
I also didn't check the full implementation of the FreeList and the free/allocate operations in this software to see if they're similar to Windows's (bitmap , block coalescing ...etc).
It's crucial also to know that in our case , the block is being unlinked from the FreeList because the manager had a 'request' to allocate a new block , and it was chosen as best block for the allocation.
Let's get back to analysing the crash :
- First I would like to mention that we'll be calling the pointer to the Freelist Entry struct : "entry".
Registers State at 0x00401C76 :
EAX = entry->Flink
EDX = entry->Blink
[EAX] = entry->Flink->Flink
[EAX+4] = entry->Flink->Blink (Next Block's Previous block)
[EDX] = entry->Blink->Flink (Previous Block's Next Block)
[EDX+4] =entry->Blink->Blink
Logically speaking : Next Block's Previous Block and Previous Block's Next Block are nothing but the current block.
So the 2 instructions that do the block unlinking from the FreeList just :
- Set the previous freelist entry's flink to the block entry's flink.
- Set the next freelist entry's blink to the block entry's blink.
By doing so , the block doesn't belong to the freelist anymore and the function simply returns after that. So it'll be easy to guess what's happening here , the software allocates a static 'heap' block to store the name of the file and it would have best to allocate the block based on the filename length from the ZIP header (this could be a fix for the bug , but heap overflows might be found elsewhere , I'll propose a better method to fix ,but not fully, this bug later in this article).
Now , we know that we're writing past our heap block and thus overwriting the custom metadata of the next heap block (flink and blink pointers). So, We'll need to find a reliable way to exploit this bug , as the 2 unlinking instructions are the only available to us and we control both EAX and EDX. (if it's not possible in another case you can see if there are other close instructions that might help), you can think of overwriting the return address or the pointer to the structured exception handler as we have a stack that won't be rebased after reboot.
This might be a working solution in another case where your buffer is stored in a static memory location.
But Under Windows 7 , it's not the case , VirtualAlloc allocates a chunk of memory with a different base in each program run. In addition , even if the address was static , the location of the freed block that we overwrite varies. So in both cases we'll need to find a pointer to our buffer.
The best place to look is the stack , remember that the software is trying to unlink (allocate) the block that follows the block where we've written the name , so likely all near pointers in the stack (current and previous stack frame) are poiting to the newly allocated block (pointer to metadata) . That's what we don't want because flink and blink pointers that we might set might not be valid opcodes and might cause exceptions , so all we need to do is try to find a pointer to the first character of the name and then figure out how to use this pointer to gain code execution , this pointer might be in previous stack frames.
And here is a pointer pointing to the beginning of our buffer : 3 stack frames away

Remember that 0x01FB2464 will certainly be something else when restarting the program , but the pointer 0x0018F554 is always static , even when restarting the machine.
So when I was at this stage , I started thinking and thinking about a way that will help me redirect execution to my shellcode which is for sure at the address pointed by 0x0018F554 , and by using only what's available to me :
- Controlled registers : EAX and EDX.
- Stack pointer to a dynamic buffer pointer.
- 2 unlinking instructions.
- No stack rebase.
Exploiting the vulnerability and gaining code execution:
And Then I thought , why wouldn't I corrupt the SEH chain and create a Fake frame ? Because when trying to corrupt an SEH chain there are 3 things that you must know :
- SafeSEH and SEHOP are absent.
- Have a pointer to an exisiting SEH frame.
- Have a pointer to a pointer to the shellcode.
The pointer to the shellcode will be treated as the handler,and the value pointed by
((ptr to ptr to shellcode)-0x4) will be treated as the pointer to the next SEH frame.
Let's illustrate the act of corrupting the chain : (with a silly illustration , sorry)
Let me explain :
we need to achieve our goal by using these 2 instructions , right ? :
MOV [EDX],EAX
MOV [EAX+4], EDX
We'll need 2 pointers and we control 2 registers , but which pointer give to which register ? This must not be a random choice because you might overwrite the pointer to the shellcode if you chose EAX as a pointer to your fake SEH frame.
So we'll need to do the reverse , but with precaution of overwriting anything critical.
In addition we actually don't care about the value of "next SEH frame" of our fake frame.
So our main goal is to overwrite the "next SEH frame" pointer of an exisiting frame , to do so we need to have a pointer to our fake frame in one of the 2 registers. As [EAX+4] will overwrite the pointer to the buffer if used as a pointer to the fake SEH frame , we will use EDX instead. We must not also overwrite the original handler pointer because it will be first executed to try to handle the exception , if it fails , then our fake handler (shellcode) will be invoked then.
So : EDX = &(pointer to shellcode) - 0x4 = Pointer to Fake "Next SEH frame" element.
EDX must reside in the next frame field of the original frame which is : [EAX+4].
And EAX = SEH Frame - 0x4.
Original Frame after overwite :
Pointer to next SEH : Fake Frame
Exception Handler : Valid Handler
Fake Frame :
Pointer to next SEH : (Original Frame) - 0x4 (we just don't care about this one)
Exception Handler : Pointer to shellcode
The SEH frame I chose is at : 0x0018F4B4
So : EAX = 0x0018F4B4 - 0x4 = 0x0018F4B0 and EDX =0x0018F554 - 0x4 = 0x0018F550
When the overwrite is done the function will return normally to its caller , and all we have to do now is wait for an exception to occur . An exception will occur after a dozen of instructions as the metadata is badly corrupted. The original handler will be executed but it will fail to handle the access violation and then our fake handler will be called which is the shellcode .
Making the exploit work :
Now all we need to do is calculate the length between the 1st character of the name and the flink and blink pointers , and then insert our pointers in the POC.
Inserting the shellcode :
The space between the starting address of the buffer and the heap overwritten metadata is not so large , so it's best to put an unconditional jump at the start of our buffer to jump past the overwritten flink and blink pointers and then put the shellcode just after the pointers. As we can calculate the length , this won't cause any problem.
Final exploit here : http://pastebin.com/pKyQJicy
I chose a bind shellcode , which opens a connection to (0.0.0.0:4444). Let's try opening the ZIP file using ZipItFast and then check "netstat -an | find "4444" :
Bingo !
A Fix for this vulnerability ??
The method I stated before which consists on allocating the block based on the filename length from the ZIP headers can be valid only to fix the vulnerability in this case , but what if the attackers were also able to cause an overflow elsewhere in the software ?
The best way to fix the bug is that : when a block is about to be allocated and it's about to be unlinked from the Freelist the first thing that must be done is checking the validity of the doubly linked list , to do so : safe unlinking must be performed and which was introduced in later versions of Windows.
Safe unlinking is done the following way :
if ( entry->flink->blink != entry->blink->flink || entry->blink->flink != entry){
//Fail , Freelist corrupted , exit process
}
else {
//Unlink then return the block to the caller
}
Let's see how safe unlinking is implemented under Windows 7 :
The function is that we'll look at is : RtlAllocateHeap exported by ntdll
Even if this method looks secure , there is some research published online that provides weaknesses of this technique and how can it be bypassed. I also made sure to implement this technique in my custom heap manager (Line 86) , link above.
I hope that you've enjoyed reading this paper .
See you again soon ,
Souhail Hammou.
Sunday, April 6, 2014
Retrieving an exported function address within a loaded module
Hi,
Today I came with a shellcode friendly blogpost , I didn't have time to write the code in ASM but I'll do it as soon as I have some time.
The goal of this small blogpost is retrieving a pointer to an exported function of choice within a loaded module and certainly without the use of any API calls.
This method can be really effective against ASLR, the only condition that needs to be met is that the function must be exported by the loaded module.
The process of applying this technique consists of retrieving the base address of the loaded module by walking through a doubly linked list. The linked list head pointer can be found using : &(PEB->Ldr.InMemoryOrderModuleList)
To walk the linked list we'll be just interested in the Flink pointer. Besides being a pointer to another list entry it's also a pointer to a _LDR_DATA_TABLE_ENTRY structure which contains ,among other elements, the Module name and the Module Base.
After running the search : if the Base Address was successfully found , we must get the address of the Export directory within the loaded module . In order to do that we perform some basic PE parsing to find the DataDirectory Array.
The first element of this array "DataDirectory[0]" contains the RVA to the export directory within the module , so all we have to do is add the RVA to the base to get the address.
The key elements of the Export directory that we'll need are the following :
AddressOfNames : This is an array of RVAs to ASCII strings which we'll use to search for the target function's RVA to name.
AddressOfNameOrdinals : This is an array of exported functions ordinals used as indexes to the AddressOfFunctions array.We will use the index found from AddressOfNames to retrieve the ordinal.
AddressOfFunctions : This is an array of function's RVAs , we will access this array using the ordinal that we retrieved previously in order to get the RVA to the exported function.
Finally All we have to do is Add the base address to the RVA and we'll get a valid pointer to the exported function.
Here's an example of getting a pointer to LoadLibraryA :
Today I came with a shellcode friendly blogpost , I didn't have time to write the code in ASM but I'll do it as soon as I have some time.
The goal of this small blogpost is retrieving a pointer to an exported function of choice within a loaded module and certainly without the use of any API calls.
This method can be really effective against ASLR, the only condition that needs to be met is that the function must be exported by the loaded module.
The process of applying this technique consists of retrieving the base address of the loaded module by walking through a doubly linked list. The linked list head pointer can be found using : &(PEB->Ldr.InMemoryOrderModuleList)
To walk the linked list we'll be just interested in the Flink pointer. Besides being a pointer to another list entry it's also a pointer to a _LDR_DATA_TABLE_ENTRY structure which contains ,among other elements, the Module name and the Module Base.
After running the search : if the Base Address was successfully found , we must get the address of the Export directory within the loaded module . In order to do that we perform some basic PE parsing to find the DataDirectory Array.
The first element of this array "DataDirectory[0]" contains the RVA to the export directory within the module , so all we have to do is add the RVA to the base to get the address.
The key elements of the Export directory that we'll need are the following :
AddressOfNames : This is an array of RVAs to ASCII strings which we'll use to search for the target function's RVA to name.
AddressOfNameOrdinals : This is an array of exported functions ordinals used as indexes to the AddressOfFunctions array.We will use the index found from AddressOfNames to retrieve the ordinal.
AddressOfFunctions : This is an array of function's RVAs , we will access this array using the ordinal that we retrieved previously in order to get the RVA to the exported function.
Finally All we have to do is Add the base address to the RVA and we'll get a valid pointer to the exported function.
Here's an example of getting a pointer to LoadLibraryA :
Source code : http://pastebin.com/ZhmD0M8X
See you soon ;
Souhail.
Tuesday, March 4, 2014
DEFKTHON CTF 2014 - Reversing 300 WriteUp
Hi Again,
The CTF just ended (less than 15 min) and here's the write-up , actually I prepared it yesterday.
Yesterday was a hard day at university , but I was happy to see that a CTF was taking place that night and there were some reversing tasks.
The CTF was DEFKTHON 2014 CTF , I was able to solve Reverse300 , and the challenge was quite cool.
They offered 'me' a 32-bit executable (300.exe) which will display "Password!!" when opening it
(I figured later that you can provide a command line argument and hope to get the flag if you have the right key : D which is really hard to predict btw).
The first step I took was to figure out where exactly the process will write to the console and I figured that it will create a child process that will do the job. Before that , and while stepping I saw that the parent will create a temporary folder under %temp% in which multiple "dll"s and "pyd" files will be stored (python27.dll for example) that folder name looks like _MEIxxxx where "x"s are random numbers . This gave me a clear idea about what this challenge is for, the executable was actually generated from a Py2Exe software and sooner or later the python source code will be in memory or in disk.
Now that I knew that the child process is the one that will execute the interpreted code, I tried to debug that child process. It is actually possible to do this under WinDbg (if you know a way to do it under Olly/Immunity please leave a comment below).
To switch the debugger to the Child Process whenever it's created all you have to do is type this command " .childdbg 1 " this will enable child process debugging for the current session.
eax=00000000 ebx=00000000 ecx=a1240000 edx=0009e138 esi=fffffffe edi=00000000
eip=776e103b esp=0036f9f8 ebp=0036fa24 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrVerifyImageMatchesChecksum+0x96c:
776e103b cc int 3
1:001> |
0 id: 2fa8 create name: image01340000
1 id: 1e30 child name: image01340000
(After Calling CreateProcess by the parent here we are breaking before executing the child proc)
Now all I had to do is determine what API is used to write to the console , so I've put a breakpoint on kernel32!WriteFile and kernel32!WriteConsole (there are high odds that would be one of these two), And It was WriteFile which writes the message to the console.
Now I'm at WriteFile and I need to go to the call from the child process right ? So I have kept returning from a function to its caller until reaching the original call from the ChildProcess.
Stack Trace :
============
0036d89c 729699ad kernel32!WriteFile
0036f3a8 72969d37 MSVCR90!lseeki64+0x56b
0036f3ec 7292f4c6 MSVCR90!write+0x9f
0036f410 729313ff MSVCR90!flsbuf+0x143
0036f438 729314ac MSVCR90!fwrite_nolock+0x11b
0036f47c 1e0b1ad8 MSVCR90!fwrite+0x61
0036f4a8 1e0abd64 python27!PyString_InsertThousandsGrouping+0x2c8
0036f4c8 1e0abdb6 python27!PyTrash_thread_destroy_chain+0x144
0036f4dc 1e094a55 python27!PyObject_Print+0x16
[...]
[...]
0036f638 0134352c python27!PyRun_SimpleString+0xc
00000000 00000000 image01340000+0x352c
And here's the call to the function from python27.dll (in the folder under %temp%)
01343525 53 push ebx
01343526 ff1564c23501 call dword ptr [image01340000+0x1c264 (0135c264)]
The function is supplied one argument in EBX. And You can see from the way the function is called (the function pointer is accessed from a memory location) that this call could be used to call different functions from python27.dll depending on the task that the file needs to do.
Let's rerun the crackme switch to the child proc and put a breakpoint at (push ebx) , you'll notice that we'll hit the breakpoint many times.
Taking a further look to this function I found that it's always copying each character of the interpreted script filename to the stack, leaving the target file to be executed visible for us. So each time after hitting the breakpoint at <push ebx> , we can display the stack and look for our file which is obviously (challenge1.py). There's a manifest file at the folder in the %temp% giving us a little hint about the filename.
Here's a snippet showing the stack just before starting to execute the interpreted code of challenge1.py :
Now after recognizing the file, we'll need the source to it so maybe it is stored on disk and maybe in memory . I tried to look at the folder stored at %temp% but there was no trace , hopefully the argument passed to the function in EBX is a pointer to a string (in other words pointer to the python source code) so if you dump EBX you'll see the source code right there :)
This will print the flag to validate on the platform.
The CTF just ended (less than 15 min) and here's the write-up , actually I prepared it yesterday.
Yesterday was a hard day at university , but I was happy to see that a CTF was taking place that night and there were some reversing tasks.
The CTF was DEFKTHON 2014 CTF , I was able to solve Reverse300 , and the challenge was quite cool.
They offered 'me' a 32-bit executable (300.exe) which will display "Password!!" when opening it
(I figured later that you can provide a command line argument and hope to get the flag if you have the right key : D which is really hard to predict btw).
The first step I took was to figure out where exactly the process will write to the console and I figured that it will create a child process that will do the job. Before that , and while stepping I saw that the parent will create a temporary folder under %temp% in which multiple "dll"s and "pyd" files will be stored (python27.dll for example) that folder name looks like _MEIxxxx where "x"s are random numbers . This gave me a clear idea about what this challenge is for, the executable was actually generated from a Py2Exe software and sooner or later the python source code will be in memory or in disk.
Now that I knew that the child process is the one that will execute the interpreted code, I tried to debug that child process. It is actually possible to do this under WinDbg (if you know a way to do it under Olly/Immunity please leave a comment below).
To switch the debugger to the Child Process whenever it's created all you have to do is type this command " .childdbg 1 " this will enable child process debugging for the current session.
eax=00000000 ebx=00000000 ecx=a1240000 edx=0009e138 esi=fffffffe edi=00000000
eip=776e103b esp=0036f9f8 ebp=0036fa24 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
ntdll!LdrVerifyImageMatchesChecksum+0x96c:
776e103b cc int 3
1:001> |
0 id: 2fa8 create name: image01340000
1 id: 1e30 child name: image01340000
(After Calling CreateProcess by the parent here we are breaking before executing the child proc)
Now all I had to do is determine what API is used to write to the console , so I've put a breakpoint on kernel32!WriteFile and kernel32!WriteConsole (there are high odds that would be one of these two), And It was WriteFile which writes the message to the console.
Now I'm at WriteFile and I need to go to the call from the child process right ? So I have kept returning from a function to its caller until reaching the original call from the ChildProcess.
Stack Trace :
============
0036d89c 729699ad kernel32!WriteFile
0036f3a8 72969d37 MSVCR90!lseeki64+0x56b
0036f3ec 7292f4c6 MSVCR90!write+0x9f
0036f410 729313ff MSVCR90!flsbuf+0x143
0036f438 729314ac MSVCR90!fwrite_nolock+0x11b
0036f47c 1e0b1ad8 MSVCR90!fwrite+0x61
0036f4a8 1e0abd64 python27!PyString_InsertThousandsGrouping+0x2c8
0036f4c8 1e0abdb6 python27!PyTrash_thread_destroy_chain+0x144
0036f4dc 1e094a55 python27!PyObject_Print+0x16
[...]
[...]
0036f638 0134352c python27!PyRun_SimpleString+0xc
00000000 00000000 image01340000+0x352c
And here's the call to the function from python27.dll (in the folder under %temp%)
01343525 53 push ebx
01343526 ff1564c23501 call dword ptr [image01340000+0x1c264 (0135c264)]
The function is supplied one argument in EBX. And You can see from the way the function is called (the function pointer is accessed from a memory location) that this call could be used to call different functions from python27.dll depending on the task that the file needs to do.
Let's rerun the crackme switch to the child proc and put a breakpoint at (push ebx) , you'll notice that we'll hit the breakpoint many times.
Taking a further look to this function I found that it's always copying each character of the interpreted script filename to the stack, leaving the target file to be executed visible for us. So each time after hitting the breakpoint at <push ebx> , we can display the stack and look for our file which is obviously (challenge1.py). There's a manifest file at the folder in the %temp% giving us a little hint about the filename.
Here's a snippet showing the stack just before starting to execute the interpreted code of challenge1.py :
Now after recognizing the file, we'll need the source to it so maybe it is stored on disk and maybe in memory . I tried to look at the folder stored at %temp% but there was no trace , hopefully the argument passed to the function in EBX is a pointer to a string (in other words pointer to the python source code) so if you dump EBX you'll see the source code right there :)
So the python source is :
==============================================
==============================================#AJIN ABRAHAM | OPENSECURITY.IN
from passlib.hash import cisco_pix as pix
import sys,base64
user=""
xx=""
if(len(sys.argv)>1):
x=sys.argv[1]
hashus = pix.encrypt("DEFCON14-CTF-IS", user=x)
z=[89,86,69,121,100,82,69,103,98,47,48,103,80,71,77,121]
for zz in z:
xx+= chr(zz+(275*100001-275*1000-27225274))
hashgen = pix.encrypt("DEFCON14-CTF-IS", user=base64.decodestring(xx))
if(hashgen==hashus):
print "Oh Man You got it! But :( ===> " + str(base64.encodestring(base64.decodestring(xx)))
else:
print "Naaaaaaa !! You are screweD"
else:
print "Password !!"
As it seems to be "Password!!" is written to the console because no command line arguments were given when executing the file.
I made simple changes to the code to be able to see the flag directly :) as it will be generated only based on the array "z" (so no need for the passlib.hash) :==============================================import sys,base64==============================================
xx=""
z=[89,86,69,121,100,82,69,103,98,47,48,103,80,71,77,121]
for zz in z:
xx+= chr(zz+(275*100001-275*1000-27225274))
print "The Flag : " + str((base64.decodestring(xx)))
This will print the flag to validate on the platform.
And there it is : 300 points + fun.
See you soon,
Souhail Hammou.
Sunday, February 23, 2014
CodeGate CTF 2014 - Reverse 250 Clone Technique Write-up
Hi,
The concept of this Crackme is really simple but reaching the right Track took me hours and hours because I was looking deeper into it and the answer was right in front of me :) ...
The challenge is named "Clone Technique" used in Naruto Manga , the process creates many instances of it (using CreateProcessW) with different command line arguments (3 values).
Example :
2nd process : clone_technique.exe 3026539702 3580248161 2
3rd process : clone_technique.exe 466510610 2867152813 3
4th process : clone_technique.exe 2580226910 609694577 4
The wrong way that I took was fortunately of some benefit because what I did is analyze how the values are generated and I also simulated the algorithm in ASM (check links below).
In the first place I didn't know how the flag would be and I couldn't get any hints so I tried to look and look until I found this weird string in the .data section :
I've put a breakpoint on access to this string and ran the program, then the debugger breaks at a function at : 00401070 (you can also check all the references to this string and you'll find the "push 00407030" to our function).
This function takes 3 arguments : - the first value in the cmdline , the second value and a pointer to the string.
The function will use both values in a loop to decrypt each byte alone of the string and store it in a seperated memory location pointed by EDX using the instruction :
004010E8 |. 8802 |MOV BYTE PTR DS:[EDX],AL
The function returns a pointer to the decrypted string in EAX (the decryption result will be non-ASCII until the used values -keys- are right).
If you have a clear idea now , you will notice that each process will be created with its own cmd line arguments , thus different keys to decrypt the string , thus different result. So we'll need to show the final decrypted string for each process until finding a readable ASCII string.
We'll need to patch the executable and create a code cave which will pop up a MessageBox whenever the string is decrypted (we can also display only the ASCII compatible string which will only be the flag) . I was lazy and tired so , I just put a MessageBox call and kept pressing enter until seeing the flag :
The concept of this Crackme is really simple but reaching the right Track took me hours and hours because I was looking deeper into it and the answer was right in front of me :) ...
The challenge is named "Clone Technique" used in Naruto Manga , the process creates many instances of it (using CreateProcessW) with different command line arguments (3 values).
Example :
2nd process : clone_technique.exe 3026539702 3580248161 2
3rd process : clone_technique.exe 466510610 2867152813 3
4th process : clone_technique.exe 2580226910 609694577 4
The wrong way that I took was fortunately of some benefit because what I did is analyze how the values are generated and I also simulated the algorithm in ASM (check links below).
In the first place I didn't know how the flag would be and I couldn't get any hints so I tried to look and look until I found this weird string in the .data section :
I've put a breakpoint on access to this string and ran the program, then the debugger breaks at a function at : 00401070 (you can also check all the references to this string and you'll find the "push 00407030" to our function).
This function takes 3 arguments : - the first value in the cmdline , the second value and a pointer to the string.
The function will use both values in a loop to decrypt each byte alone of the string and store it in a seperated memory location pointed by EDX using the instruction :
004010E8 |. 8802 |MOV BYTE PTR DS:[EDX],AL
The function returns a pointer to the decrypted string in EAX (the decryption result will be non-ASCII until the used values -keys- are right).
If you have a clear idea now , you will notice that each process will be created with its own cmd line arguments , thus different keys to decrypt the string , thus different result. So we'll need to show the final decrypted string for each process until finding a readable ASCII string.
We'll need to patch the executable and create a code cave which will pop up a MessageBox whenever the string is decrypted (we can also display only the ASCII compatible string which will only be the flag) . I was lazy and tired so , I just put a MessageBox call and kept pressing enter until seeing the flag :
Jump to code cave
We don't have to forget to NOP a "REP STOS" instruction that will cause an access violation after redirecting the execution to our cave code.
Now save the executable , run it and you should see MessageBoxes with total gibberish (invalid key decrypting the string) , keep clicking and clicking and clicking until this will popup :
The Flag.
Script which will generate the same values passed in the command line (complete waste of time :) ) : http://pastebin.com/tcRdpEKF
Crackme Download : https://www.mediafire.com/?bbqubxv3maev71x
Regards.
Subscribe to:
Posts (Atom)
.jpg)









