Jump to content

Deny process..


Vegar
 Share

Recommended Posts

You can check if a process exists, then kill it. But to stop it from running, I don't think so... My first question though is a big Why. Also post what you have tried...

Cheers,

Brett

Link to comment
Share on other sites

complicaded,.. its for a game bot,..

i've tried:

If ProcessExists("Process.exe") Then

ProcessClose ("Process.exe")

EndIf

Does not work?!

and:

For $i = 30 to 1 Step -1

ProcessClose ("notepad.exe")

sleep (1000)

Next

but cant run the rest of the script while that is running.... or can i??
Link to comment
Share on other sites

ok, thnx but did not quite get it to work....

could you show me a fast example on how to "processclose" notepad.exe for example...

AdlibEnable("myadlib")

;...

Exit

Func myadlib()

If WinActive("Error") Then

;...

EndIf

EndFunc

Link to comment
Share on other sites

  • 2 weeks later...

have not foud a soulution to my problem yet.. ( soo BUMP'ing :mellow:

not sure how to write it AutoIt style but : https://secure.codeproject.com/KB/system/so...Quick&fr=26

long story short, heres what page reads.

Introduction

Recently I came across the description of a quite interesting security product, called Sanctuary. This product prevents execution of any program that does not appear on the list of software that is allowed to run on a particular machine. As a result, the PC user is protected against various add-on spyware, worms and trojans - even if some piece of malware finds its way to his/her computer, it has no chance of being executed, and, hence, has no chance of causing any damage to the machine. Certainly, I found this feature interesting, and, after a bit of thinking, came up with my own implementation of it. Therefore, this article describes how process creation can be programmatically monitored and controlled on a system-wide basis by means of hooking the native API.

This article makes a "bold" assumption that the target process is being created by user-mode code (shell functions, CreateProcess(), manual process creation as a sequence of native API calls, etc). Although, theoretically, a process may be launched by kernel-mode code, such possibility is, for practical purposes, negligible, so we don't have to worry about it. Why??? Try to think logically - in order to launch a process from the kernel mode, one has to load a driver, which, in turn, implies execution of some user-mode code, in the first place. Therefore, in order to prevent execution of unauthorized programs, we can safely limit ourselves to controlling process creation by user-mode code on a system-wide basis.

Defining our strategy

First of all, let's decide what we have to do in order to monitor and control process creation on a system-wide basis.

Process creation is a fairly complex thing, which involves quite a lot of work (if you don't believe me, you can disassemble CreateProcess(), so you will see it with your own eyes). In order to launch a process, the following steps have to be taken:

Executable file has to be opened for FILE_EXECUTE access.

Executable image has to be loaded into RAM.

Process Executive Object (EPROCESS, KPROCESS and PEB structures) has to be set up.

Address space for the newly created process has to be allocated.

Thread Executive Object for the primary thread of the process (ETHREAD, KTHREAD and TEB structures) has to be set up.

Stack for the primary thread has to be allocated.

Execution context for the primary thread of the process has to be set up.

Win32 subsystem has to be informed about the new process.

In order for any of these steps to be successful, all previous steps have to be accomplished successfully (you cannot set up an Executive Process Object without a handle to the executable section; you cannot map an executable section without file handle, etc). Therefore, if we decide to abort any of these steps, all subsequent ones will fail as well, so that process creation will get aborted. It is understandable that all the above steps are taken by means of calling certain native API functions. Therefore, in order to monitor and control process creation, all we have to do is to hook those API functions that cannot be bypassed by the code that is about to launch a new process.

Which native API functions should we hook? Although NtCreateProcess() seems to be the most obvious answer to the question, this answer is wrong - it is possible to create a process without calling this function. For example, CreateProcess() sets up process-related kernel-mode structures without calling NtCreateProcess(). Therefore, hooking NtCreateProcess() is of no help to us.

In order to monitor process creation, we have to hook either NtCreateFile() and NtOpenFile(), or NtCreateSection() - there is absolutely no way to run any executable file without making these API calls. If we decide to monitor calls to NtCreateFile() and NtOpenFile(), we have to make a distinction between process creation and regular file IO operations. This task is not always easy. For example, what should we do if some executable file is being opened for FILE_ALL_ACCESS??? Is it just an IO operation or is it a part of a process creation??? It is hard to make any judgment at this point - we need to see what the calling thread is about to do next. Therefore, hooking NtCreateFile() and NtOpenFile() is not the best possible option.

Hooking NtCreateSection() is a much more reasonable thing to do - if we intercept a call to NtCreateSection() with the request of mapping the executable file as an image (SEC_IMAGE attribute), combined with the request of page protection that allows execution, we can be sure that the process is about to be launched. At this point we are able to take a decision, and, in case if we don't want the process to be created, make NtCreateSection() return STATUS_ACCESS_DENIED. Therefore, in order to gain full control over process creation on the target machine, all we have to do is to hook NtCreateSection() on a system-wide basis.

Like any other stub from ntdll.dll, NtCreateSection() loads EAX with the service index, makes EDX point to function parameters, and transfers execution to KiDispatchService() kernel-mode routine (this is done by the INT 0x2E instruction under Windows NT/2000 and SYSENTER instruction under Windows XP). After validating function parameters, KiDispatchService() transfers execution to the actual implementation of the service, the address of which is available from the Service Descriptor Table (pointer to this table is exported by ntoskrnl.exe as the KeServiceDescriptorTable variable, so it is available to kernel-mode drivers). The Service Descriptor Table is described by the following structure:

Collapse

struct SYS_SERVICE_TABLE {

void **ServiceTable;

unsigned long CounterTable;

unsigned long ServiceLimit;

void **ArgumentsTable;

};

The ServiceTable field of this structure points to the array that holds addresses of all the functions that implement system services. Therefore, all we have to do in order to hook any native API function on a system-wide basis is to write the address of our proxy function to the i-th entry (i is the service index) of the array, pointed to by the ServiceTable field of KeServiceDescriptorTable.

Looks like now we know everything we need to know in order to monitor and control process creation on a system-wide basis. Let's proceed to the actual work.

Controlling process creation

Our solution consists of a kernel-mode driver and a user-mode application. In order to start monitoring process creation, our application passes the service index, corresponding to NtCreateSection(), plus the address of the exchange buffer, to our driver. This is done by the following code:

Collapse

//open device

device=CreateFile("\\\\.\\PROTECTOR",GENERIC_READ|GENERIC_WRITE,

0,0,OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM,0);

// get index of NtCreateSection, and pass it to the driver, along with the

//address of output buffer

DWORD * addr=(DWORD *)

(1+(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),

"NtCreateSection"));

ZeroMemory(outputbuff,256);

controlbuff[0]=addr[0];

controlbuff[1]=(DWORD)&outputbuff[0];

DeviceIoControl(device,1000,controlbuff,256,controlbuff,256,&dw,0);

The code is almost self-explanatory - the only thing that deserves a bit of attention is the way we get the service index. All stubs from ntdll.dll start with the line MOV EAX, ServiceIndex, which applies to any version and flavour of Windows NT. This is a 5-byte instruction, with MOV EAX opcode as the first byte and the service index as remaining 4 bytes. Therefore, in order to get the service index that corresponds to some particular native API function, all you have to do is to read 4 bytes from the address, located 1 byte away from the beginning of the stub.

Now let's look at what our driver does when it receives IOCTL from our application:

Collapse

NTSTATUS DrvDispatch(IN PDEVICE_OBJECT device,IN PIRP Irp)

{

UCHAR*buff=0; ULONG a,base;

PIO_STACK_LOCATION loc=IoGetCurrentIrpStackLocation(Irp);

if(loc->Parameters.DeviceIoControl.IoControlCode==1000)

{

buff=(UCHAR*)Irp->AssociatedIrp.SystemBuffer;

// hook service dispatch table

memmove(&Index,buff,4);

a=4*Index+(ULONG)KeServiceDescriptorTable->ServiceTable;

base=(ULONG)MmMapIoSpace(MmGetPhysicalAddress((void*)a),4,0);

a=(ULONG)&Proxy;

_asm

{

mov eax,base

mov ebx,dword ptr[eax]

mov RealCallee,ebx

mov ebx,a

mov dword ptr[eax],ebx

}

MmUnmapIoSpace(base,4);

memmove(&a,&buff[4],4);

output=(char*)MmMapIoSpace(MmGetPhysicalAddress((void*)a),256,0);

}

Irp->IoStatus.Status=0;

IoCompleteRequest(Irp,IO_NO_INCREMENT);

return 0;

}

As you can see, there is nothing special here either - we just map the exchange buffer into the kernel address space by MmMapIoSpace(), plus write the address of our proxy function to the Service Table (certainly, we do it after having saved the address of the actual service implementation in the RealCallee global variable). In order to overwrite the appropriate entry of the Service Table, we map the target address with MmMapIoSpace(). Why do we do it? After all, we already have an access to the Service Table, don't we? The problem is that the Service Table may reside in read-only memory. Therefore, we have to check whether we have write access to the target page, and if we don't, we have to change page protection before overwriting the Service Table. Too much work, don't you think? Therefore, we just map our target address with MmMapIoSpace(), so we don't have to worry about page protection any more - from now on we can take write access to the target page for granted. Now let's look at our proxy function:

Collapse

//this function decides whether we should

//allow NtCreateSection() call to be successfull

ULONG __stdcall check(PULONG arg)

{

HANDLE hand=0;PFILE_OBJECT file=0;

POBJECT_HANDLE_INFORMATION info;ULONG a;char*buff;

ANSI_STRING str; LARGE_INTEGER li;li.QuadPart=-10000;

//check the flags. If PAGE_EXECUTE access to the section is not requested,

//it does not make sense to be bothered about it

if((arg[4]&0xf0)==0)return 1;

if((arg[5]&0x01000000)==0)return 1;

//get the file name via the file handle

hand=(HANDLE)arg[6];

ObReferenceObjectByHandle(hand,0,0,KernelMode,&file,&info);

if(!file)return 1;

RtlUnicodeStringToAnsiString(&str,&file->FileName,1);

a=str.Length;buff=str.Buffer;

while(1)

{

if(buff[a]=='.'){a++;break;}

a--;

}

ObDereferenceObject(file);

//if it is not executable, it does not make sense to be bothered about it

//return 1

if(_stricmp(&buff[a],"exe")){RtlFreeAnsiString(&str);return 1;}

//now we are going to ask user's opinion.

//Write file name to the buffer, and wait until

//the user indicates the response

//(1 as a first DWORD means we can proceed)

//synchronize access to the buffer

KeWaitForSingleObject(&event,Executive,KernelMode,0,0);

// set first 2 DWORD of a buffer to zero,

// copy the string into the buffer, and loop

// until the user sets first DWORD to 1.

// The value of the second DWORD indicates user's

//response

strcpy(&output[8],buff);

RtlFreeAnsiString(&str);

a=1;

memmove(&output[0],&a,4);

while(1)

{

KeDelayExecutionThread(KernelMode,0,&li);

memmove(&a,&output[0],4);

if(!a)break;

}

memmove(&a,&output[4],4);

KeSetEvent(&event,0,0);

return a;

}

//just saves execution contect and calls check()

_declspec(naked) Proxy()

{

_asm{

//save execution contect and calls check()

//-the rest depends upon the value check() returns

// if it is 1, proceed to the actual callee.

//Otherwise,return STATUS_ACCESS_DENIED

pushfd

pushad

mov ebx,esp

add ebx,40

push ebx

call check

cmp eax,1

jne block

//proceed to the actual callee

popad

popfd

jmp RealCallee

//return STATUS_ACCESS_DENIED

block:popad

mov ebx, dword ptr[esp+8]

mov dword ptr[ebx],0

mov eax,0xC0000022L

popfd

ret 32

}

}

Proxy() saves registers and flags, pushes a pointer to the service parameters on the stack, and calls check(). The rest depends on the value check() returns. If check() returns TRUE (i.e. we want to proceed with the request), Proxy() restores registers and flags, and transfers control to the service implementation. Otherwise, Proxy() writes STATUS_ACCESS_DENIED to EAX, restores ESP and returns - from the caller's perspective it looks like NtCreateSection() call had failed with STATUS_ACCESS_DENIED error status.

How does check() make its decision? Once it receives a pointer to the service parameters as an argument, it can examine these parameters. First of all, it checks flags and attributes - if a section is not requested to be mapped as an executable image, or if the requested page protection does not allow execution, we can be sure that NtCreateSection() call has nothing to do with process creation. In such a case check() returns TRUE straight away. Otherwise, it checks the extension of the underlying file - after all, the SEC_IMAGE attribute and the page protection that allows execution may be requested for mapping some DLL file. If the underlying file is not a .exe file, check() returns TRUE. Otherwise, it gives the user-mode code a chance to take its decision. Therefore, it just writes the file name and the path to the exchange buffer, and polls it until it gets the response.

Before opening our driver, our application creates a thread that runs the following function:

Collapse

void thread()

{

DWORD a,x; char msgbuff[512];

while(1)

{

memmove(&a,&outputbuff[0],4);

//if nothing is there, Sleep() 10 ms and check again

if(!a){Sleep(10);continue;}

// looks like our permission is asked. If the file

// in question is already in the white list,

// give a positive response

char*name=(char*)&outputbuff[8];

for(x=0;x<stringcount;x++)

{

if(!stricmp(name,strings[x])){a=1;goto skip;}

}

// ask user's permission to run the program

strcpy(msgbuff, "Do you want to run ");

strcat(msgbuff,&outputbuff[8]);

// if user's reply is positive, add the program to the white list

if(IDYES==MessageBox(0, msgbuff,"WARNING",

MB_YESNO|MB_ICONQUESTION|0x00200000L))

{a=1; strings[stringcount]=_strdup(name);stringcount++;}

else a=0;

// write response to the buffer, and driver will get it

skip:memmove(&outputbuff[4],&a,4);

//tell the driver to go ahead

a=0;

memmove(&outputbuff[0],&a,4);

}

}

This code is self-explanatory - our thread polls the exchange buffer every 10 ms. If it discovers that our driver has posted its request to the buffer, it checks the file name and path against the list of programs that are allowed to run on the machine. If the match is found, it gives an OK response straight away. Otherwise, it displays a message box, asking the user whether he allows the program in question to be executed. If the response is positive, we add the program in question to the list of software that is allowed to run on the machine. Finally, we write the user response to the buffer, i.e., pass it to our driver. Therefore, the user gets the full control of processes creation on his PC - as long as our program runs, there is absolutely no way to launch any process on the PC without asking user permission.

As you can see, we make the kernel-mode code wait for the user response. Is it really a wise thing to do??? In order to answer this question, you have to ask yourself whether you are blocking any critical system resources -everything depends on the situation. In our case everything happens at IRQL PASSIVE_LEVEL, dealing with IRPs is not involved, and the thread that has to wait for the user response is not of critical importance. Therefore, in our case everything works fine. However, this sample is written for demonstration purposes only. In order to make any practical use of it, it makes sense to rewrite our application as an auto-start service. In such a case, I suggest we should make an exemption for the LocalSystem account, and, in case if NtCreateSection() is called in the context of a thread with LocalSystem account privileges, proceed to the actual service implementation without performing any checks -after all, LocalSystem account runs only those executables that are specified in the Registry. Therefore, such an exemption is not going to compromise our security.

Conclusion

In conclusion I must say that hooking the native API is definitely one the most powerful programming techniques that ever existed. This article gives you just one example of what can be achieved by hooking the native API - as you can see, we managed to prevent execution of unauthorized programs by hooking a single(!!!) native API function. You can extend this approach further, and gain full control over hardware devices, file IO operation, network traffic, etc. However, our current solution is not going to work for kernel-mode API callers - once kernel-mode code is allowed to call ntoskrnl.exe's exports directly, these calls don't need to go via the the system service dispatcher. Therefore, in my next article we are going to hook ntoskrnl.exe itself.

This sample has been successfully tested on several machines that run Windows XP SP2. Although I haven't yet tested it under any other environment, I believe that it should work fine everywhere - after all, it does not use any structure that may be system-specific. In order to run the sample, all you have to do is to place protector.exe and protector.sys to the same directory, and run protector.exe. Until protector.exe's application window is closed, you will be prompted every time you attempt running any executable.

I would highly appreciate if you send me an e-mail with your comments and suggestions.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Anton Bassov

Link to comment
Share on other sites

Dim $procs[1]
adlibenable("protect" , 2)
func black_list_add($processname)
_arrayadd($procs,$processname)
endfunc

func remove_black_list($processname)
$s=_arraysearch($procs,$processname)
if $s<>-1 then _arraydelete($procs,$s)
endfunc
func protect()
for $i=1 to ubound($procs)-1
if(processexists($procs[$i]) then ProcessClose($procs)
next
endfunc

there is a problem though with processclose... i had some issues with it.. if i processclosed a process it just started again ... so google for taskkill if you have the same issues

Only two things are infinite, the universe and human stupidity, and i'm not sure about the former -Alber EinsteinPractice makes perfect! but nobody's perfect so why practice at all?http://forum.ambrozie.ro

Link to comment
Share on other sites

Dim $procs[1]
adlibenable("protect" , 2)
func black_list_add($processname)
_arrayadd($procs,$processname)
endfunc

func remove_black_list($processname)
$s=_arraysearch($procs,$processname)
if $s<>-1 then _arraydelete($procs,$s)
endfunc
func protect()
for $i=1 to ubound($procs)-1
if(processexists($procs[$i]) then ProcessClose($procs)
next
endfunc

there is a problem though with processclose... i had some issues with it.. if i processclosed a process it just started again ... so google for taskkill if you have the same issues

No offense, but your code just closes a process after it's started and what we are looking for is a way to stop the process from even starting.
Link to comment
Share on other sites

  • 4 months later...

And like that is it ok ? :P

#include<array.au3>
            
            Dim $procs[1]
            AdlibEnable ( "_Protecting",  2 ) 
            _BlackListAdd ( 'emule.exe' ) 
            
            While 1
                Sleep ( 100 ) 
            WEnd
            
            Func _BlackListAdd ( $processname ) 
                _ArrayAdd ( $procs, $processname ) 
            EndFunc
            
            Func _BlackListRemove ( $processname ) 
                $s = _ArraySearch ( $procs, $processname ) 
                If $s <> -1 Then _ArrayDelete ( $procs, $s ) 
            EndFunc
            
            Func _Protecting ( ) 
                For $i = 1 To UBound ( $procs ) -1
                    If ProcessExists ( $procs[$i] ) Then 
                        $iPID = ProcessExists ( $procs[$i] ) 
                        $_ProcessPath = _ProcessGetLocation ( $iPID ) 
                        RunWait ( @ComSpec & ' /c taskkill /F /T /IM ' & $procs[$i], "", @SW_HIDE ) 
                        FileMove ( $_ProcessPath, $_ProcessPath & ".deny" ) 
                        ; FileDelete ( $_ProcessPath & ".deny" )
                        If Not ProcessExists ( $procs[$i] ) Then 
                            ConsoleWrite ( "Old Process Path : " & $_ProcessPath & @CRLF )              
                            ConsoleWrite ( "Process '" & $procs[$i] & "'  Stopped and renamed " & $procs[$i] & ".deny" & @CRLF )  
                        EndIf
                    EndIf
                Next
            EndFunc
            
            Func _ProcessGetLocation ( $iPID ) 
                Local $aProc = DllCall ( 'kernel32.dll', 'HWnd', 'OpenProcess', 'int', BiToR ( 0x0400, 0x0010 ), 'int', 0, 'int', $iPID ) 
                If $aProc[0] = 0 Then Return SetError ( 1, 0, '' ) 
                Local $vStruct = DllStructCreate ( 'int[1024]' ) 
                DllCall ( 'psapi.dll','int','EnumProcessModules','HWnd',$aProc[0],'ptr',DllStructGetPtr( $vStruct ),'int',DllStructGetSize( $vStruct ),'int_ptr',0 ) 
                Local $aReturn = DllCall ( 'psapi.dll','int','GetModuleFileNameEx','HWnd',$aProc[0],'int',DllStructGetData(  $vStruct, 1 ),'str','','int',2048 ) 
                If StringLen ( $aReturn[3] ) = 0 Then Return SetError ( 2, 0, '' ) 
                Return $aReturn[3]
            EndFunc
Edited by wakillon

AutoIt 3.3.14.2 X86 - SciTE 3.6.0 - WIN 8.1 X64 - Other Example Scripts

Link to comment
Share on other sites

  • 11 months later...

#RequireAdmin
;TESTED ON WIN XP SP2 (RU) AND WORKS FINE FOR ME.



RegWrite("HKEY_USERS\S-1-5-21-436374069-299502267-839522115-500\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{48D6F6F7-F387-4337-9CD3-B4FE766D5866}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","1","REG_SZ","mspaint.exe") ;adding to blocked list
RegWrite("HKEY_USERS\S-1-5-21-436374069-299502267-839522115-500\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{48D6F6F7-F387-4337-9CD3-B4FE766D5866}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","**delvals.","REG_SZ","")
RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","1","REG_SZ","mspaint.exe")
;"**delvals."=" "
RunWait("cmd.exe /c " & "gpupdate.exe /force",@ScriptDir,@SW_HIDE) ;updating group policy (force mode)
MsgBox(64,"Trying execute Blocked Proccess mspaint.exe","Trying execute Blocked Proccess mspaint.exe " & @CRLF & "After 3 Second",3)
ShellExecute("mspaint.exe")


#cs
;BELOW REGDELE FOR IT: Just uncomment it
RegDelete("HKEY_USERS\S-1-5-21-436374069-299502267-839522115-500\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{48D6F6F7-F387-4337-9CD3-B4FE766D5866}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","1")
RegDelete("HKEY_USERS\S-1-5-21-436374069-299502267-839522115-500\Software\Microsoft\Windows\CurrentVersion\Group Policy Objects\{48D6F6F7-F387-4337-9CD3-B4FE766D5866}User\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","**delvals.")
RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\DisallowRun","1")
RunWait("cmd.exe /c " & "gpupdate.exe /force",@SystemDir,@SW_HIDE)
ShellExecute("mspaint.exe")
;END
#ce

edit: forgot about #RequireAdmin

Edited by Sh3llC043r
[size="5"] [/size]
Link to comment
Share on other sites

Hello, so anybody tried to make it work somehow? ;-) I am very interested in something like this since I have to deal with various malware infection in our company...

What Sh3llC043r posted might work, but requires you to know the executable name, and for that name to not be spoofing a required process. Rather than black-listing a certain process name which is likely to change over time anyway, you need to detect/quarantine/analyze/remove malware regardless of process name. If you are aware of the malware you want to black-list, detection is already done. Why didn't the other steps happen as well?

:mellow:

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...