Hooking NtCreateFile to sandbox a process

May 7, 2009 at 7:39 PM
Hi,
I have been playing with EasyHook for sometime and tried to sandbox a processes file accesses hooking NtCreateFile. Basically, this is the approach that Google uses to sandbox it's browser. I wanted to do that using managed code.
My approach was to hook the function, and then replace the filename in the ObjectAttributes to point to a sandboxed location instead of the original file.
Before changing the filepath, I query whether the file already exists in the sandbox and if it does not, I copy it using File.Copy, and then call the original API with the new filepath instead of the one requested.
This approach has so far worked with a few processes like notepad++ but seems to fail with MS word.
With MS word, for some mysterious reason, the NtCreateFile function is called for the sandboxed file as well when it should not be so. I read the tutorial and it advised to move the code which might result in the same API being called by the .net framework to it's own dedicated thread. I did that but the thread now gets stuck waiting for the call to complete and hangs.
I replace the following parameters in NtCreateFile call:
ObjectName
Length
RootDirectory
Can someone please share their thoughts on this problem and suggest where I may be wrong in this approach?
Coordinator
May 8, 2009 at 1:18 PM

>Basically, this is the approach that Google uses to sandbox it's browser

Are you sure? I can imagine much better ways of sandboxing a browser (since google is the vendor and has access to the source code)...


>I did that but the thread now gets stuck waiting for the call to complete and hangs.

This is probably because to complete it will call File.Copy and File.Exists and these guys will internally call NtCreateFile and now you run into an execution loop...

> With MS word, for some mysterious reason, the NtCreateFile function is called for the sandboxed file as well when it should not be so

Please clarify this, I have no idea what you are talking about ;-). But I think it might be something wrong with your code determining whether to sandbox a file or not.

 

May 8, 2009 at 1:50 PM

Thanks for the reply Christoph,

>Are you sure? I can imagine much better ways of sandboxing a browser (since google is the vendor and has access to the source code)...

Yup. I'm sure. You can check their implementation in the source code. They have a project called sandbox within the chrome branch. And that's the implementation they do.

They do not do redirection of the call, but simply pass the request to the broker (which is the main browser window) from the tab process and then the browser decides whether to allow it or not. Google also uses tokens and job object to provide security, but that's not of any interest to me.

For more on google's sandbox, you may read up here:

http://dev.chromium.org/developers/design-documents/sandbox/

>This is probably because to complete it will call File.Copy and File.Exists and these guys will internally call NtCreateFile and now you run into an execution loop...

I'm not sure whether this should be the case. I spawn the thread and then set the ACL to exclude that thread from interceptions. When I get an interception in the main thread, I pass the parameters to the worker thread (which is excluded from interceptions), and then wait for it to complete. I donot execute any code that might lead to NtCreateFile being called in the intercepted thread (Atleast I think so :-) ).

The problem that occurs is that the thread spawns correctly, and everything seems to be going fine. File.copy works as well, and the file gets copied correctly. But as soon as I call the native api on the copied file, the thread hangs and never completes. This is totally unexpected. I was wondering whether this might be due to marshalling class calling NTCreatefile, but that should also not get intercepted because the thread is excluded from interceptions :-(

>Please clarify this, I have no idea what you are talking about ;-). But I think it might be something wrong with your code determining whether to sandbox a file or not.

Yup. You are right. There was a bug in my code. This has been fixed.

I would love to hear your thoughts about the sandboxing approach that I am taking and if you have any ideas on how to do it, I'll be glad to hear them. This is a critical part of a project that I have taken and it's important that I get it right.

Using Easyhook, I think that I can achieve all the functionality that a normal sandbox is expected to provide. However, for me, the file handling part is the most important right now.

Apr 3, 2010 at 9:24 AM

Hi achintya

     I was trying to hook the ntcreatefile function from ntdll.dll. but for that i need the header files used while using the function. I think the header file required is  ntddk.h. From where can i get the corresponding file. I am using Visual C++ 6.0 from Windows XP. I tried to install the wdk latest version in it but it said there is some configuration problem in installing that and i could not install. Please help.

    I am a beginner and i have also one more doubt. As u said earlier in the post are all the browsers using ntcreate file while creating any file. why are they no using the create file function in kernel32.dll?

Hope reply, Thanks in advance.........

 

Apr 8, 2010 at 4:56 AM

1)  One way to hook undocumented API is to use LoadLibrary and GetProcAddress to get the function pointer.  You may not need the DDK/WDK header then.

2)  CreateFileW (Kernel32.dll) invoke NtCreateFile (ntdll.dll).  Once you hook NtCreateFile( along with other undocumented API like NtOpenFile ), you do not need to care about CreateFileW.

 

Apr 10, 2010 at 6:25 PM
Edited Apr 10, 2010 at 6:26 PM

Hi Foonson

        Thanks for your time. I already tried with the loadlibrary and getprocaddress. I got the both the addresses . i checked if they returned the NULL value and they are working fine. then i removed the memory protection using the virtual protect and changed the address of the memory with my functions address. but still i cannt execute my function...... Can u help

Apr 12, 2010 at 2:31 AM

Please provide more information to identify your issues.

Apr 13, 2010 at 1:22 PM
Edited Apr 13, 2010 at 1:28 PM

PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ImageDirectoryEntryToData
    (
        hModuleOfCaller,
        TRUE,
        IMAGE_DIRECTORY_ENTRY_IMPORT,
        &ulSize
    );
    
    

    if (pImportDesc == NULL)
        return;

    while (pImportDesc->Name)
    {
        PSTR pszModName = (PSTR)((PBYTE) hModuleOfCaller + pImportDesc->Name);
        
        if (stricmp(pszModName, LibraryName) == 0)
        {

            break; // Found
        }

        pImportDesc++;
    }
    if (pImportDesc->Name == 0)
        return;
    PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)( (PBYTE) hModuleOfCaller + pImportDesc->FirstThunk );
    PROC pfnCurrent = OldFunctionPointer;
    while (pThunk->u1.Function)
    {
        PROC* ppfn = (PROC*) &pThunk->u1.Function;
             BOOL bFound = (*ppfn == pfnCurrent);
        if (bFound)
        {
            MEMORY_BASIC_INFORMATION mbi;
           ::VirtualQuery(ppfn, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
            if (FALSE == ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect))
            {
                return;
            }
            *ppfn = *NewFunctionPointer;
            BOOL bResult = TRUE;
            DWORD dwOldProtect;
            ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&dwOldProtect);
            
            break;
        } // if

        pThunk++;

    }

 

 

 

 

This is the code which i used to hook.

this works fine with hooking createfile in kernel32.dll but not working with ntdll.dll

can u help

Apr 14, 2010 at 2:09 AM
Edited Apr 15, 2010 at 2:52 AM
In the first place, I do not have an answer for you. Hooking by modifying IAT have a few drawbacks. Why not give EasyHook a try.