Sunday, May 15, 2016

Windows Internals [Process II - Code]


Before I begin, please comment on the posts, so I know what is wrong and what is right with the posts. Please consider that I am not charging you for this information and your comments will be a motivation.

If you haven't read the part I of this, I would recommend you to do so now. And if you have then let us go directly to the code.

//****************************************************************************/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT _pdrvobj,IN PUNICODE_STRING _CM_Entry)
{
        char *eproc;
        long cpid;
       
        _pdrvobj->DriverUnload=Kext_Unload;

         eproc = (char*)PsGetCurrentProcess();
         cpid = *((long*)(eproc + 156));
    
         while(1)
         {
                DbgPrint("%d : %s", *((long*)(eproc + 156)),eproc + 508);
                eproc =    (char*)(((char*)(((LIST_ENTRY*)(eproc + 160))->Flink)) - 160);
                if( cpid == *((long*)(eproc + 156)) )break;
         }
        
   
    return STATUS_SUCCESS;
}
//******************************************************************************/

A small piece of code isn't it? :)   So what are we seeing here. First we use a documented function that is accessible to driver writers easily to get a pointer to the structure EPROCESS (PsGetCurrentProcess()). Remember that I am using the Windows 2000 driver kit to compile and every bit of compatibility that I am explaining and assuring is tested. At this point I am keeping it bare metal so I am only going to use pointers and simple data types to manipulate the kernel info in the algorithm not high-level structures.  So if you add 156 bytes from the start of EPROCESS you get the process ID which is declared long. long takes 4 bytes. So now that we dereference that memory location, we can get the PID of a process. Since this is driver entry called in arbitrary context , I assume mostly it will show the current process as "System". You can see that in the part I of this article. It is system that is the first process in the list. Next is the grand loop. Inside this, I use the existing pointer to EPROCESS and go to offset 508 to get the process name. Ok what is the next line that is a mess? Couple of things are done here. So, after the PID the next information that is stored in EPROCESS is LIST_ENTRY. As driver writers would know this is used for managing a doubly linked list and driver writers often use this. It is a self-referential structure with a forward and a backward link. What do they store? As you can imagine they store pointer to the next LIST_ENTRY. And the next important question is not, what the next ENTRY points to but where it is contained. It is contained in the next EPROCESS structure or structure that is created to inform about the next process. So if we jump 160 bytes from start of EPROCESS use the value contained in that address, go to that address and subtract 160 from it, we get starting address of next EPROCESS. I have done a lot of casting to char*. We need to cast the so extracted LIST_ENTRY address before subtracting 160. Otherwise it will subtract LIST_ENTRY sized value from that (pointer arithmetic). A lot of that code can be simplified if we introduce, the EPROCESS structure itself and cast some of these addresses to be of type EPROCESS.

Therefore you can re-write that to the below having declared structures necessarily...

//****************************************************************************/
typedef struct EPROC
{
        char blah[156]; //At this point we are not worried about what is in these 156 bytes
        long pid;
        LIST_ENTRY *Flink,*Blink;
}__EPROCESS,*__PEPROCESS;

NTSTATUS DriverEntry(IN PDRIVER_OBJECT _pdrvobj,IN PUNICODE_STRING _CM_Entry)
{

         __PEPROCESS eproc;
        long pid;
           
        eproc = (__PEPROCESS)PsGetCurrentProcess();
        cpid = eproc->pid;

        while(1)
        {
              DbgPrint("%d:%s",eproc->pid,(char*)eproc + 508);

              eproc = (__PEPROCESS) ((char*)eproc->Flink - 160);
               
              if(eproc->pid == cpid) break;
        }                                  
}
//****************************************************************************/

But would we ever stop with that? For starters, you could manipulate these pointers and change their values causing certain havoc. This is what root kits do like hiding the process. Similar structures exist for everything else managed by the kernel - security related structures, networking related, file system related.. imagine what power we have now, having understood how to manipulate the low level structures? There are so many websites and blogs that talk about these. One is a blog that I follow myself. Joanna's Invisible things. She is definitely one of my most favorite Gray Hats. :)

Of course you cannot easily do that now, since Windows has kernel patch guard etc. And if you didn't know already, similar techniques are used in the other operating systems and no system is immune to these attacks. For there is always a way if there is the will... So what do you have in your mind?

Windows Internals [Process I - Theory]


Before I begin, please comment on the posts, so I know what is wrong and what is right with the posts. Please consider that I am not charging you for this information and your comments will be a motivation.

In this post I will show you a bit about windows process internals. I am writing this with few assumptions - you know "C" programming, you know about windows driver programming basics and that you also have the book Inside Windows 2000 (3rd ed) by David Solomon and Mark Russinovich (or equivalent). Well yes, do not be surprised that I am discussing about windows 2000 here when we already have a windows 10 in the market. Some great minds have said - "Keep it simple, but not simpler". So let us keep the problem simple and I will also ensure it isn't made quite simpler that the problem definition itself is confined with wrong constraints. But any windows internals book would do. If you want to test this code you will also need Windows 2000 (itself) or modify some values that I will tell you later. You will need the driver kit of course. An understanding of Windows API and C is a plus.

Most of you would only need to just know that like any other operating system, windows also uses several structures to maintain processes. As I understand from the great minds who wrote the internals book (my role models in fact) , windows do not contain "Tasks" unlike *NIX.

However the basic strategy is more of less same for the algorithms used in these operating systems. In a nutshell (thinking as a developer), you need a structure that holds all information about a process. This can be a very complex structure indeed. It can have a lot of nested structures within but as we know, let us keep it simple. So this will contain information about say the name of the process, the ID assigned to the process (internally called client id). It will contain few more details like when the process started or how much time elapsed since the process started, information about the threads that it contains etc. As you see the moment we talk about a significant entity like "thread" you realize that a thread itself would contain some information related to it. This might be in another structure. Therefore you will have some nested structure within this structure for process. And now when you take the internals book that I said above and go to the page where the authors listed the structure of process, you may get bewildered :) There is a lot of information stored in the structure and in that book it is printed on 3 - 4 pages. Imagine how much the Kernel developers of Windows would have thought about it. As the great Niklaus Wirth put it Program = DataStructure + Algorithm.

I always like to see what is it that we are dealing with, so the above image shows the output of our effort. It shows information that DbgPrint() in a driver code gives. Of course you would recognize these are process names with their IDs.

Ok a little bit theory on the basics. So Processes in windows is basically managed primarily with two important structures. EPROCESS and KPROCESS. A kernel debugger (along with symbols) can show you the information. Now that these things are documented online you can always look at that. Finally you can always check the internals book for the information. KPROCESS keeps a lot of very low level aspects of a process like scheduling where as Executive structure (EPROCESS) keeps a high-level view of process information. Even much of the operating system deals with and relies on the EPROCESS for their programming chores. Usually programmers (system) won't need to access these structures directly. Even driver writers won't need to worry about them. But that is internals right?  So EPROCESS contains some information and for the rest it "contains" KPROCESS within.

Security professionals would know about this because these structures were exploited in the past to hide process and keep other activities stealth (rootkit). One of the areas I am trying to specialize in is rootkits. Today we don't get to see them because of the strict "code integrity" that operating systems like Windows have introduced (since Vista actually) and every version there is something new. Digital Signature, patch guard etc. Perhaps in another post I can show you some of those hackish code. It is indeed very interesting. You may also want to know (as I said in Native api related post), these structures were used by some software to protect their code. Antivirus for example used to use these structures, over write some data with pointers that work like a "detour", "trampoline" and so on.

So what is the task we have in hand and what are we going to learn from it? We will try to access this EPROCESS structure in the kernel (not user mode so you need to write a driver), we will use it to enumerate the process as shown above. We thereby learn how process information is handled internally (to some extent).