blocking file execution and movement with NtCreate/Openfile

c++ / delphi package - dll injection and api hooking
Post Reply
d-man
Posts: 13
Joined: Sun Jul 08, 2007 10:17 pm

blocking file execution and movement with NtCreate/Openfile

Post by d-man »

Hi all - firstly, many thanks for all the help and posts. This forum is a wealth of information.

Ok, i've made several posts about a control system i'm working on. I need to arbitrate application launch so that files on a black-list are blocked.

I order to maintain the validity of the black-list i need to prevent files on this list being moved, copied or renamed or it's file creating stamp being changed.

I have a working system to arbitrate application launch using NtCreateSection. However, i was sticking on controlling moving and copying. Madshi suggested hooking NtOpenFile and NtCreateFile. I created a temporary hooking system to see what is going on.

From my trace, it seems that NtOpenFile is the first API called when executing, copying, moving or renaming. Next, NtCreateFile is called in all of these cases. Finally, NtCreateSection is called, if executing the file.

What i want to know is, is it possible to do all the things i want with one single hook to NtOpenFile. Since this is the first API called in all cases, it seems lightly that i could. However, this API is called many times for many different things. When i limit my trace down just to notepad.exe, this API is still called when the directory is parsed and displayed.

Based on this i need to inspect the parameters that are passed to NtOpenFile and see why the call is being made. This is my sticking point; i cannot find any valid information on determining why the call is being made and how the parameters differ when it is called in different cirumstances. Also does this logic have any fundamental flaws i.e. can applications be launched without these calls?

Any help or pointers would be so helpful.

Many thanks in advance,

D-man
d-man
Posts: 13
Joined: Sun Jul 08, 2007 10:17 pm

In following

Post by d-man »

Having spent a whole night debugging and tracing, i have come to the conclusion that NtOpenFile / NtCreateFile will not work for my needs. There does not seem to be anyway to differentiate why a file is being opened, so other that blocking ALL calls that relate to a black-listed file, this seems impossible. Blocking both calls if the target is on the black-list seems harsh and my cause system instabilities as well as possibly making the target file disappear from view.

Based on this, i have maintained my initial hook to NtCreateSection and started to look at NtSetInformationFile which seems to be the final point of any file move, copy or rename operation. Based on the enum value of the FILE_INFORMATION_CLASS i should be able to determine why the call has been made and if it relates to a black-listed file, and then block or relay accordingly.

However, my hooks seems to make the system act erratically. My hook now does nothing other than relay the call through to the real NtSetInformationFile. However something must be becoming corrupted because my system will now not allow me to access any files, other than for execution. I can copy files but if i try and delete or rename them, the function fails. Does anyone have any ideas where i might be going wrong?

Any pointers or suggestions would be so helpful. Please note that this code below seems to work though causes corruptions. This is the same format that I use for all my native hooks which today have not had issues



// Typedefs for NtSetInformationFile
typedef struct _IO_STATUS_BLOCK
{
union
{
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

typedef enum _FILE_INFORMATION_CLASS
{
FileDirectoryInformation=1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileCopyOnWriteInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileObjectIdInformation,
FileTrackingInformation,
FileOleDirectoryInformation,
FileContentIndexInformation,
FileInheritContentIndexInformation,
FileOleInformation,
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;

// Relay / real function pointer
NTSTATUS (NTAPI *NtSetInformationFileNxt)(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG FileInformationLength, FILE_INFORMATION_CLASS FileInformationClass);

// Callback
NTSTATUS NTAPI NtSetInformationFileCallback(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG FileInformationLength, FILE_INFORMATION_CLASS FileInformationClass)
{
// Do nothing, just relay...
return NtSetInformationFileNxt(FileHandle, IoStatusBlock, FileInformation, FileInformationLength, FileInformationClass);
}

int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if (reason==DLL_PROCESS_ATTACH)
{
if (!(GetVersion() & 0x80000000))
{
CollectHooks();
// Hook some other stuff...
HookAPI("ntdll.dll", "NtSetInformationFile", &NtSetInformationFileCallback, (PVOID)NtSetInformationFileNxt);

FlushHooks();
}
}
}
else if (reason==DLL_PROCESS_DETACH)
{
UnhookAPI((PVOID)NtSetInformationFileNxt);
}
return 1;
}
d-man
Posts: 13
Joined: Sun Jul 08, 2007 10:17 pm

Problem found - possibly...

Post by d-man »

Hi all, think i've found the problem, but i'm perplexed as to how to fix it. It looks like my _FILE_INFORMATION_CLASS enumeration is incorrect. I don't have the ddk to hand so was forced to grab it off the net. Not all definitions of this are the same, some have more values that others, this obviously messes things up because it shunts the values down and they appear within the hook to be different functions.

However, i'm struggling to solve the problem because it looks like the _FILE_INFORMATION_CLASS enum may change from OS build to OS build. Can anyone confirm this for me? Does anyone have a solid definition which works across all platforms? This is what i'm currently using:

typedef enum _FILE_INFORMATION_CLASS
{
FileFiller = 0,
FileDirectoryInformation = 1, // 1 Y N D
FileFullDirectoryInformation, // 2 Y N D
FileBothDirectoryInformation, // 3 Y N D
FileBasicInformation, // 4 Y Y F
FileStandardInformation, // 5 Y N F
FileInternalInformation, // 6 Y N F
FileEaInformation, // 7 Y N F
FileAccessInformation, // 8 Y N F
FileNameInformation, // 9 Y N F
FileRenameInformation, // 10 N Y F
FileLinkInformation, // 11 N Y F
FileNamesInformation, // 12 Y N D
FileDispositionInformation, // 13 N Y F
FilePositionInformation, // 14 Y Y F
FileModeInformation = 16, // 16 Y Y F
FileAlignmentInformation, // 17 Y N F
FileAllInformation, // 18 Y N F
FileAllocationInformation, // 19 N Y F
FileEndOfFileInformation, // 20 N Y F
FileAlternateNameInformation, // 21 Y N F
FileStreamInformation, // 22 Y N F
FilePipeInformation, // 23 Y Y F
FilePipeLocalInformation, // 24 Y N F
FilePipeRemoteInformation, // 25 Y Y F
FileMailslotQueryInformation, // 26 Y N F
FileMailslotSetInformation, // 27 N Y F
FileCompressionInformation, // 28 Y N F
FileObjectIdInformation, // 29 Y Y F
FileCompletionInformation, // 30 N Y F
FileMoveClusterInformation, // 31 N Y F
FileQuotaInformation, // 32 Y Y F
FileReparsePointInformation, // 33 Y N F
FileNetworkOpenInformation, // 34 Y N F
FileAttributeTagInformation, // 35 Y N F
FileTrackingInformation // 36 N Y F
FileMaximumInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

Try using a simple "int" for the enumeration value. Those enumerations are usually 4 byte long. Not sure if you need to set some special compiler conditions to make your enumeration declaration use 4 bytes. So I'd suggest to use int. There can't be much going wrong that way. Also does "NTAPI" equal or contain WINAPI? Not sure. Calling convention of the native APIs is usually WINAPI.
d-man
Posts: 13
Joined: Sun Jul 08, 2007 10:17 pm

bingo..

Post by d-man »

Thanks madshi, just worked that out last thing last night. It was more or less exactly as you have stated. The borland compile has an option to for enum's to be true integers (32-bit). This is where it was all going worng. All seems to work now, although the logic in my design is lacking.

I can see and arbitrate renames and moves but the api isn't called for copy exections. It is only called on the destination file with a _FILE_INFORMATION_CLASS id of FileEndOfFileInformation.

So back to the drawing board so to speak. GRRRR
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

This is a complicated problem. A company I've done some work for has hired a driver programmer to do a similar thing in driver land. His driver is meant to backup every file which is modified. Well, it works, but it copies many files which were not really modified but just opened to read something. The problem is that if a program is opening a file with "write access", you never know what will happen to the file. Maybe the program will write to the file, maybe not.
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

Couldn't you hook NtWriteFile and set a flag that says the file was written to, and back it up when NtClose was called?
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

dcsoft wrote:Couldn't you hook NtWriteFile and set a flag that says the file was written to, and back it up when NtClose was called?
Too late. In the moment when you let NtWriteFile pass, the original file data is already destroyed.
d-man
Posts: 13
Joined: Sun Jul 08, 2007 10:17 pm

the futures bright...

Post by d-man »

Ok guys. I have now come a full cirule and decided that the original design was fundimentally flawed.

I thought i'd post just in case anyone else ends up going down the same path.

The basic idea behind the system was application arbitration i.e. what can and can't be launched. We wanted to maintain a black-list of blocked applications as it seemed easier from a users perspective and faster to parse. We were working on the flawed assumption that when new files are ** added ** on the system, there file-stamp would reflect that actual date of copying. With this in mind, it would have been possible to say which files were on the system orginally, which files were black-listed and which files had been newly installed (and thus required additional authorisation). Prior to XP SP2, when a file was copied onto the system, or moved around, it's date created reflected that point in time.

By stopping black-listed files from being moved and stopping the file-stamp from being modified, it would have been possible to maintain this.

However, SP2 changed this and the OS seems to ammend the Date created to frelect that of the source file. Thus the concept was flawed. there is also a problem with black-listed files being deleted and then dragged and dropped from the recycle bin to a new location.

As i have said many times in this post, the design is unmanagable and has been dropped in preference to holding a complete shap-shot with corrisponding check-sums.

Just out of interest, can anyone tell me how to convert to and from a file name in the format of:

\Device\Harddisk\Volume1\Windows\system32\notepad.exe

and how to determine which which drive letter corrisponds to volume1.

Many thanks for all your help,

D-man
dcsoft
Posts: 380
Joined: Sat Dec 11, 2004 2:11 am
Location: San Francisco Bay Area, CA USA
Contact:

Post by dcsoft »

madshi wrote:
dcsoft wrote:Couldn't you hook NtWriteFile and set a flag that says the file was written to, and back it up when NtClose was called?
Too late. In the moment when you let NtWriteFile pass, the original file data is already destroyed.
I thought the idea was to back up the file *after* it has been changed.

-- David
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Re: the futures bright...

Post by madshi »

d-man wrote:Just out of interest, can anyone tell me how to convert to and from a file name in the format of:

\Device\Harddisk\Volume1\Windows\system32\notepad.exe

and how to determine which which drive letter corrisponds to volume1.
I believe iconic (or was it somebody else?) has posted a solution for this to another thread here in the forum. Try "search".
madshi
Site Admin
Posts: 10753
Joined: Sun Mar 21, 2004 5:25 pm

Post by madshi »

dcsoft wrote:I thought the idea was to back up the file *after* it has been changed.
Not in the case of the company I've done work for. They want to back up all files *before* they are changed, so that they can later undo any changes on request.
Post Reply