Solved

File Creation

Posted on 2010-09-05
25
660 Views
Last Modified: 2012-05-10
How do I monitor or detect a new creation of file?

I did test
http://www.osnews.com/story/7376/A-Directory-Monitor-Class-For-Delphi/page1/

Tthe problem is,  you have to specify each drive,  what if I have a..z drives.

So, is there a way to monitor file creation in all drives without specifying?

I did a proxy test with  ZwCreateFile,ZwWriteFile,ZwOpenFile, but it does not detect with this command;

procedure TfMainform.Button1Click(Sender: TObject);
begin
copyfile(application.exename, 'copytest.exe', false);
end;

Probably I need I callback, but I don't know how.
But,  if the problem is in the callback?


Thanks
I don't know which one is a callback.

Is it the TrueZwCreateFile? or the NewZwCreateFile?



function TrueZwCreateFile(

    OUT FileHandle:PHANDLE;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    OUT IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : LARGE_INTEGER;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: ULONG;

    EaBuffer : PVOID;

    const EaLength :ULONG):NTStatus;

    stdcall;

var  Written: dword;

begin

  WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @OldZwq, SizeOf(OldCode), Written);

  Result := ZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize, FileAttributes, ShareAccess,CreateDisposition,CreateOptions, EaBuffer, EaLength);

  WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @JmpZwq, SizeOf(far_jmp), Written);

end;

function NewZwCreateFile(

    OUT FileHandle:PHANDLE;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    OUT IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : LARGE_INTEGER;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: ULONG;

    EaBuffer : PVOID;

    const EaLength :ULONG):NTStatus;

    stdcall;

var

fileName:string;

begin

fileName:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer);



//access violation with this

if IoStatusBlock.Status = FILE_CREATED then

SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar('New Created')));





SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName)));

Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer ,EaLength);

end;



Pep's the code is working, But it say's access violation when I click the Button1.



Any ideas?

Am I doing right?, with the callback?  huh, I don't even know what's the callback name I've write.

Open in new window

0
Comment
Question by:systan
  • 17
  • 7
25 Comments
 
LVL 25

Expert Comment

by:epasquier
ID: 33607692
There are many Directory Notify/Monitor components, they all work pretty much the same, and no, none can monitor all drives at once as they are based on the same Windows API that works on a specific path.
But nothing can prevent you to create dynamically one such component for each drive.

Here is one free and simple : TDirNotify

http://www.carlosb.com/ctrl.php?fm=delphicomps
0
 
LVL 14

Author Comment

by:systan
ID: 33608777
epasquier;
thank you for that link, i'll deal with that later.

I know you are also flexible in programming different modules, with your overall experience in delphi I know you can help me with this,  even if you have a little? background of nt system programming.
So with that experience you are capable to help me with this.

First step;
Lets start with the callback, which one of them is the callback?
Is it the TrueZwCreateFile? or the NewZwCreateFile?
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33608805
I'm not too familiar with your code, but if I'm correct :

the function that is called by Windows is NewZwCreateFile , which calls TrueZwCreateFile, which in turn calls ZwCreateFile (after removing the hook to avoid infinite loop)
0
 
LVL 14

Author Comment

by:systan
ID: 33608874
So, TrueZwCreateFile is the callback ??
Here's the procedure that call's NewZwCreateFile
Procedure SetHook();

var

 Bytes: dword;

begin

  PtrZwq  := GetProcAddress(GetModuleHandle('ntdll.dll'),'ZwCreateFile');

  ReadProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @OldZwq, SizeOf(OldCode), Bytes);

  JmpZwq.PuhsOp  := $68;

  JmpZwq.PushArg := @NewZwCreateFile;

  JmpZwq.RetOp   := $C3;

  WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq, @JmpZwq, SizeOf(far_jmp), Bytes);

end;

Open in new window

0
 
LVL 14

Author Comment

by:systan
ID: 33608900
Madshi's link, talking about file creation and deletion, but most talk about deletion.
http://forum.madshi.net/viewtopic.php?t=2639
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33608916
>> Here's the procedure that call's NewZwCreateFile

No, it does not call it. It replace IN ntdll the first instruction of ZwCreateFile with a call to your own. So next time somewhere this function is called, it will be in fact yours.
0
 
LVL 14

Author Comment

by:systan
ID: 33608920
Here's about ZwCreateFile
http://msdn.microsoft.com/en-us/library/ff566424%28v=VS.85%29.aspx

I'm not good in reading english programming sentences much more on understanding programming language writtings, so I really need help.
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33608946
one thing you need to understand is that when you are in NewZwCreateFile, you are WITHIN the API, not OUTSIDE it. Said otherwise, you have to reverse all the logic you might find in MSDN. When it says that a function will do this and that value can have this flag, that means that it is WHAT YOURS HAVE TO DO.
Or, in your case, since you are calling the real one, that you can only test the OUT parameters at the end of the function.

ALSO : Out reserved word in Delphi does not have the same meaning as in MSDN
"An out parameter, like a variable parameter, is passed by reference. With an out parameter, however, the initial value of the referenced variable is discarded by the routine it is passed to. The out parameter is for output only; that is, it tells the function or procedure where to store output, but doesn't provide any input."
Which means the value of the pointer is cleared and that is why you have an access violation.
function NewZwCreateFile(

    FileHandle:PHANDLE;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : LARGE_INTEGER;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: ULONG;

    EaBuffer : PVOID;

    const EaLength :ULONG):NTStatus;

    stdcall;

var

fileName:string;

begin

Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer ,EaLength);



fileName:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer);



//access violation with this

if Result And (IoStatusBlock.Status = FILE_CREATED) then

SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar('New Created')));





SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName)));



end;

Open in new window

0
 
LVL 14

Author Comment

by:systan
ID: 33611633
>>if Result And (IoStatusBlock.Status = FILE_CREATED) then
error on runtime;

if ( Result And IoStatusBlock.Status = FILE_CREATED) then
no error during runtime, but errors when I click the button with command copyfile

I guess its very hard, ok, ill test more code's....and .listening..



0
 
LVL 14

Author Comment

by:systan
ID: 33611924
epasquier;
I've analyze what you did, it's correct,  declaring the options/flags after the callback but include the (Result),
however, I have another idea;

Step 2;
Im getting the Allocationsize, but I can't, error during runtime;

if ( Result and AllocationSize<>0) then


What's the correct assignment for AllocationSize if not equal to zero?
0
 
LVL 14

Author Comment

by:systan
ID: 33616231
What's the correct assignment for AllocationSize if not equal to zero?  Please
0
 
LVL 25

Expert Comment

by:epasquier
ID: 33616344
I don't understand your problem with AllocationSize. You simply pass it to the real ZwCreateFile, what else do you want to do with it ?

I think there is an error in your type definition for this parameter. First, it's a pointer. Second, here is the type from MSDN :
typedef union _LARGE_INTEGER {
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } ;
  struct {
    DWORD LowPart;
    LONG  HighPart;
  } u;
  LONGLONG QuadPart;
} LARGE_INTEGER, *PLARGE_INTEGER;

but that is compatible with Int64, so your real definition should be PInt64

and when you want to use it, you must first see it it's assigned (<>nil)

if Assigned(AllocationSize) Then ShowMessageFmt('AllocationSize = %d', [ AllocationSize^ ] );
function NewZwCreateFile(

    FileHandle:pHandle;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : PInt64;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: Cardinal;

    EaBuffer : Pointer;

    const EaLength :Cardinal):NTStatus; stdcall;

Open in new window

0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 
LVL 14

Author Comment

by:systan
ID: 33618988
Thank you epasquier;
As you see I'm not really a delphi pro.
I test the AllocationSize, because, as I understand at CreateFile;
"
If AllocationSize is NULL, no allocation size is specified. If no file is created or overwritten, AllocationSize is ignored.
"
But it seems not working also, I don't know if I stop here, or just continue listening
Here's what I did in AllocationSize;

function NewZwCreateFile(

    FileHandle:pHandle;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : PInt64;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: Cardinal;

    EaBuffer : Pointer;

    const EaLength :Cardinal):NTStatus;

    stdcall;

var

fileName:string;

begin

fileName:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer);

Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,AllocationSize,FileAttributes, ShareAccess,CreateDisposition,CreateOptions,EaBuffer ,EaLength);



if ( Result and DesiredAccess <> 0) then

if Assigned(AllocationSize) then

begin

SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName+' created')));

end;

end;

Open in new window

0
 
LVL 14

Author Comment

by:systan
ID: 33619704
I also try this with NewZwOpenFile;
if ( Result and DesiredAccess = FILE_WRITE_ATTRIBUTES and SYNCHRONIZE and GENERIC_WRITE) then
if ( Result and OpenOptions = FILE_SYNCHRONOUS_IO_NONALERT and FILE_NON_DIRECTORY_FILE) then
SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName+' created')));
end;

But no luck to see file being created.
0
 
LVL 14

Author Comment

by:systan
ID: 33619884
All of a sudden, I think "ZwQueryVolumeInformationFile" is the answer here, but I can't fine a sample of the code snippet given to produce a NewZwQueryVolumeInformationFile.
0
 
LVL 25

Accepted Solution

by:
epasquier earned 500 total points
ID: 33622137
I don't think you have to test for the AllocationSize. A file could be created with that parameter not specified or 0, that just means that the system is not reserving any space for it, it just create an entry in the file table

besides, Result is not a boolean, and your former code was doing an AND binary operation between Result and DesiredAccess , which was only then compared to 0. No chance of that working.
You should always put brackets around single comparisons before using And/Or boolean operators. Delphi does not have the same operator priority than C/C++/Java etc...

Then, have you tested the sendmessage separately (with another app for example) ?
function NewZwCreateFile(

    FileHandle:pHandle;

    const DesiredAccess:ACCESS_MASK;

    const ObjectAttributes:PObjectAttributes;

    IoStatusBlock:PIO_STATUS_BLOCK;

    const AllocationSize : PInt64;

    const FileAttributes, ShareAccess, CreateDisposition,CreateOptions: Cardinal;

    EaBuffer : Pointer;

    const EaLength :Cardinal):NTStatus;

    stdcall;

var

 Msg:string;

 Hnd:THandle;

begin

 Result := TrueZwCreateFile(FileHandle,DesiredAccess,ObjectAttributes,

            IoStatusBlock,AllocationSize,FileAttributes,ShareAccess,

            CreateDisposition,CreateOptions,EaBuffer ,EaLength);

 if (Result=STATUS_SUCCESS) And (IoStatusBlock^.Information=FILE_CREATED)

  then 

   begin

    Msg:= WideCharToString(ObjectAttributes^.ObjectName^.Buffer)+' created';

    Hnd:=FindWindow('TForm1', nil); // you'll have to do better than that later

    if Hnd<>0 Then Hnd:=FindWindowEx(Hnd, 0, 'TListBox', nil);

    if Hnd<>0 Then SendMessage(Hnd,LB_INSERTSTRING, 0, Integer(PChar(Msg)));

   end;

end;

Open in new window

0
 
LVL 14

Author Comment

by:systan
ID: 33623877
I'm sorry epasquier but I've tested also that code snippet you've gave, its not detecting, I have to try another procedure.

But don't know if this can be done by a CBT hook, I hope may be it can.

While surfing the net I found this one, but only detects deleting files, but not files created or appended.
http://delphi.about.com/library/code/ncaa030403b.htm

But we'll stick on this Zwxxx or Ntxxx, its a superb functions.
0
 
LVL 14

Author Comment

by:systan
ID: 33624760
Step 3;
I know came up with ""ZwQueryVolumeInformationFile" but it seems I doubt, so I go to step 4
The "ZwWriteFile"
http://msdn.microsoft.com/en-us/library/ff567121%28v=VS.85%29.aspx
Buffer [in]
    Pointer to a caller-allocated buffer that contains the data to write to the file.

The result of the filename cant be read, it's ascii, how am I going to see it?
function NewZwWriteFile(

    const FileHandle: THANDLE;

    const Event:THANDLE;

    const ApcRoutine: Pointer;

    const ApcContext : Pointer;

    OUT   IoStatusBlock:PIO_STATUS_BLOCK;

    const Buffer : Pointer;

    const Length:cardinal;

    const ByteOffset: PInt64;

    const Key:PULONG): NTStatus;

    stdcall;

var

fileName:string;

begin

fileName:= WideCharToString(Buffer);

Result := TrueZwWriteFile(FileHandle,Event, ApcRoutine, ApcContext, IoStatusBlock, Buffer, Length, ByteOffset,Key);

SendMessage(FindWindowEx(FindWindow('TForm1', nil), 0, 'TListBox', nil), LB_INSERTSTRING, 0, Integer(PChar(fileName)));

end;

Open in new window

0
 
LVL 25

Expert Comment

by:epasquier
ID: 33624934
The buffer is the data, not the file name. You have to use the FileHandle, and see if you can get the file name associated with it

http://msdn.microsoft.com/en-us/library/aa366789%28VS.85%29.aspx
0
 
LVL 14

Author Comment

by:systan
ID: 33624977
Actually I have that code;
But,
Buffer [in]
    Pointer to a caller-allocated buffer

So, I can get the application who has the buffer?
copyfile(application.exename, 'copytest.exe', false);

But I'll try to test your recommendations.
function GetFileNameFromHandle(hFile: THandle): string;

var

  dwFileSizeHi: Cardinal;

  dwFileSizeLo: Cardinal;

  hFileMap: Cardinal;

  pMem: Pointer;

begin

  Result := '';

  // Get the file size.

  dwFileSizeHi := 0;

  dwFileSizeLo := GetFileSize(hFile, @dwFileSizeHi);

  if (dwFileSizeLo = 0) and (dwFileSizeHi = 0) then

    exit;

  // Create a file mapping object.

  hFileMap := CreateFileMapping(hFile, nil, PAGE_READONLY, 0, 1, nil);

  if (hFileMap <> INVALID_HANDLE_VALUE) then

  try

    // Create a file mapping to get the file name.

    pMem := MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1);

    if Assigned(pMem) then

    try

      SetLength(Result, MAX_PATH);

//    SetLength(Result, GetMappedFileName(GetCurrentProcess(), pMem, PChar(Result), MAX_PATH));

    finally

      UnmapViewOfFile(pMem);

    end;

  finally

    CloseHandle(hFileMap);

  end;

end;

Open in new window

0
 
LVL 14

Author Comment

by:systan
ID: 33629154
>>So, I can get the application who has the buffer?
Actually I want either of them, the source file or the destination file created.
I hope there is one possible function to do this kind of job.
0
 
LVL 14

Author Comment

by:systan
ID: 33687676
Oh, using ZwWriteFile if ZwCreateFile is called already, I have to research nore in this area.
0
 
LVL 14

Author Comment

by:systan
ID: 33688048
I doubt "ZwQueryVolumeInformationFile" is also be called.
0
 
LVL 14

Author Closing Comment

by:systan
ID: 33690816
epasquier;
if you have the time to catch the problem, please do continue post here.

Thank you for the contribution, it helped me, specialy variables from plong to pint64 and others.
0

Featured Post

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now