?
Solved

preventing program execution

Posted on 2003-03-19
12
Medium Priority
?
890 Views
Last Modified: 2016-09-30
Dear genii, (genius - plural??)
I need to write a program to stop programs executing!

I've done research but seem to come accross problems with every idea possible solution i find.

I thought about using PsSetCreateProcessNotifyRoutine, but this seems to be called after the program has been started. if this is the case, then I'd need to terminate the program, which is obviously not a good idea. I need to sneak in somewhere between a request for, say, word.exe and the actual running of word.exe.

Then there's API hooking... system-wide API interceptor that monitors calls made to the CreateProcess function. But, from what I've heard, this doesnt cover all ways that the process can be started.

Then there's IAT (Import Address Table) Patching. Which is way beyond me! I'm just an MFC programmer who has been dropped into the world of system programming.

If anyone could tell me if there is an accepted method for doing this, it would be greatly appreciated. I'm already grey haired and I'm fast approaching baldnes...

cheers,
d.
0
Comment
Question by:dave_p_r_b
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 4
  • 2
  • +2
12 Comments
 
LVL 12

Expert Comment

by:Salte
ID: 8167128
One way you can do it is to do this:

Create a DLL and implement functions that are called foo() for EVERY Win32 system function exported by kernel32.exe. Same arguments and same name - EXACTLY.

Upon initialization, load the real kernel32.exe and map pointers to all the functions in it. Afraid you have to do this dynamically since you otherwise would get name clash between your foo() and kernel32.exe's foo() function.

Have your DLL named kernel32.exe and place it in the windows system directory and have the real kernel32.exe stored some place where your kernel32.exe can reach it. For example rename it to 'realk32.exe' or 'kernel32.dll' or some such and place it where your kernel32.exe can reach it. Note, even though the file is named 'kernel32.exe' it is a DLL and you must build a DLL.

Also, I doubt that the system will call any DllMain for this DLL, it is a DLL but a very special DLL so don't count on it calling any DllMain. rather have a global bool init_done variable which is initialized to false and have every exported function test it and do the initialization before they continue if init_done is false. The initialization will set the variable to true.

Then for every call foo you simply call the function through the pointer since you've loaded realk32.exe and have it available.

One more note, you have to be careful with the LoadLibrary function. If I am not mistaken it is defined in kernel32.exe and so you get a slight problem how you can load that library since you need realk32.exe in order to be able to load any DLL, including realk32.exe!

Well, afriad you have to do some black magic there. All the functions in kernel32.exe are implemented by first collecting arguments and then they do an INT instruction to generate an interrupt to the windows kernel. I am afraid you have to implement the very first LoadLibrary that you call to load realk32.exe by doing the same thing. Warning! This is UNDOCUMENTED, it will most likely change in next version of windows etc etc etc and might even change in next service pack upgrade.

The point is that since it is not documented by microsoft and the documented interface to windows is the Win32 functions, microsoft essentially do as they please without telling anyone if they change things in the INT interface.

You are hereby warned.

Anyway, granted that you get this to work you can then use the Win32 interface to regular LoadLibrary for any requests from user code.

Then, you want to intercept CreateProcess? Simple: Just implement your version of CreateProcess and CreateProcessEx so that they do not blindly call realk32.exe's CreateProcess and CreateProcessEx functions but instead check if your conditions are met to block the exe. Note, if you make such a change you will make it system wide and it will have effect always, so if you block every CreateProcess you will block any attempt to create new processes using the Win32 interface and people won't be able to create ANY process. Your system will most likely need to be reinstalled from CD-ROM if you screw up in this. Since you can't create any process you can't run any command or any application to repair the system even, so the only possible way out is to reboot the system and reinstall it from CD-ROM. Therefore you MUST be very careful when doing things like this.

Also, note that Windows also have a Posix subsystem and the fork() function there might still work, if you want to block that too you probably have to do similar black magic to block the posix subsystem also.

Alf
0
 

Author Comment

by:dave_p_r_b
ID: 8167285
Thank you for your extensive answer!

Intercepting createProcess was one way i thought i could solve the problem, it wasnt a second question. I guess I'm confused.

I cannot afford to have to change the code with possibly each service pack renewal- it just not appropriate i'm afraid!

Do you happen to know if there's a simpler way? Or the answer to psSetcreateNotify...?

Anyway, thanks for your help...
d.
0
 
LVL 15

Expert Comment

by:efn
ID: 8167557
Simple, obvious ways to prevent a program from running are:

a.  Delete the program file from the disk.

b.  Use access control:  as the all-powerful Administrator, don't allow the user the privilege of running the program.

I suspect you have considered and rejected these for some reasons, but I thought I'd throw them in, since they seem to answer the question as written, and you are looking for an "accepted method" and "simpler way."
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:Salte
ID: 8167748
I guess his problem is that

1. He can't delete the program since he want to allow it to run, just not at this moment.

2. He can't set the security for program X since he doesn't know which programs he want to disallow. My guess is that he wants to within a certain start time and end time prohibit ANY program or process from being created but when end_time or some event occur, he wants to set the system back to 'normal' situation where any program can start.

This is probably best done through some notification.

However, I believe that attempting to stop ANY CreateProcess is potentially dangerous and not a good thing. Users do want to create a process from time to time while running your program and for perfectly legitimate reasons.

I guess you are running some kind of application and you want to prevent users from running 'dangerous' applications to spy on your application or 'debug' your application while it runs.

I think there are games that has run into that exact problems. A game such as Everquest checks your currently running processes and tries to identify if any of them are on their 'no no' list and if so exit their game. They also scan the hard disk to see if they find any such 'no no' applications.

The problems here are several and it is on the whole utterly futile:

a. Users can rename the application and using a hex editor change other parameters of the executable so that it will avoid detection.

b. Users can simply run such spy programs on another computer. Everquest runs it main communication as TCP/IP packets (both TCP and UDP) and if a user has two computers it is fairly easy for him to set up a snooping program on a unix machine that forward the packets to the PC. Everquest running on the PC has no way of knowing that the snooping software is running.

So you end up going through all sorts of troubles and those who really want to break your scan can easily do so. Those who suffer from the scan are those who run perfectly legitimate software.

They even tried to block the computer from switching tasks. This caused all sorts of problems when firewall and other programs popped up a dialog box and you couldn't switch to them or you could but then the computer would hang when you tried to switch back to EverQuest. Trust me, I have played that game and know all to well that headache.

Fortunately they have come to their senses and you can now switch task to/from everquest - they must have realized that it was an exercize in futility.

So my advice to you if this is your situation or similar to it:  Forget it, just live with it. If users want to run an application while your program is active, let them do it, it is very hard to stop them and you will most likely block and cause troubles for those who just want to do innocent stuff while those who really want to break your code can easily do so anyway.

Alf
0
 

Author Comment

by:dave_p_r_b
ID: 8167878
Hi,
I didnt bore you with the details of the background of needing this functionality, perhaps i should have been a little more open.

Its not an issue of people changing executeables... they are just everyday users. If they are going to go to so much effort, I'm not even going to try and stop them.

The application is to run over a network and is to limit the number of times a program can be run concurrently on different machines...

hope this clears it up a bit.


D.
0
 
LVL 22

Expert Comment

by:grg99
ID: 8168124
Do you have the source code to the program that is to be controlled?

If so, then it's not too hard to do,
except you're likely to get left with too high a running program count if your program crashes before it gets a chance to decrement some running-program counter.

If you want to limit programs whose .exe files live on the server, you could just move the programs to some other directory, lets call it "hidden_Bins".  Then make batch files named after each program, say "FreeCell.Bat".
Then from that batch file increment and check your counters and allow or disallow usage.

If you make the batch files "Execute only", then your clients wont be able to see where the binaries are hidden.  This is dangerously close to "security thru obscurity", but is probably good enough for many purposes.



Regards,


grg99

0
 
LVL 15

Expert Comment

by:efn
ID: 8168157
Yes, those details matter.  With that information, I will offer a couple more simple, possibly useless ideas, leaving the heavy duty black magic voodoo system programming to Alf.

This now sounds like a license management kind of problem.  If you have control of the application that is supposed to run or not, the usual approach is to have it check with a server.  If the server says a license is available, the program proceeds to run.  If the server says the limit has been reached, the program tells the user, "Have your cheap company buy some more licenses for our fine software" and exits.  There are commercial software components that can do this for you.

If you don't have control of the application, perhaps you can wrap it in another program that checks whether it can run.  That is, instead of running regulated program X directly, the user runs gateway program Y.  Y checks with the server and starts X if it is allowed.

If you can't do either of these and you really need to have some monitor sitting there all the time watching everything the user tries to run and deciding whether it's OK depending on what's going on elsewhere in the network, then I think Alf's detailed advice applies.
0
 
LVL 12

Expert Comment

by:Salte
ID: 8168621
ah....

do you have the code of the program? If so, do it this way:

at program start up, check how many concurrent users there are that are using the program (check below for how to check this). If the number is too many, exit the program and refuse to run.

If you do not have the source code available, 'hide' the program some obscure place, possibly not even store it on the hard disk for the users but instead have the program stored in a central server which also count how many concurrent users.

Then replace the program on the user's hard disk with a small application which first connects to that server and then say "I want to run XXXX.exe". THe server check if the number of allowed users are too high, if so it answer "no" and if not too high it sends over the executable.

The application will then exit if it gets a no and will do a CreateProcess() on the received application if "yes". Then the application will sit and wait for the application XXXX.exe to finish and when it is done it deletes the file from the hard disk.

To check for how many concurrent users, you can in a network solution just use such a server in any case, and just have your application contact the server and say "I am application XXX and the user wants to run me now". The server checks how many concurrent and if too many he will say "no" and the application terminates, if "yes" the application continues.

I believe this is safe and simple way to do it. If you want to avoid the copying of the exe file you cna let the user have the exe file but hidden in some obscure place and perhaps encrypted so that he cannot execute it (it doesn't show up as an exe file even). Then if he is allowed to run the application, instead of having the server send over the whole application .exe file it just send over the decryption key, your application will then decrypt the file and place the decrypted .exe file some place and run it and then delete it when you're done as above.

Of course, this scheme isn't foolproof. If the user go to task manager and recognizes the name of your application and terminates it, the file will stay on his hard disk and he can run it as often as he likes. However, provided that users aren't that smart you should be able to stop 99% of those who's trying to just start the icon to run the application if the count is too high.

One word of advice: You must have the ability for a privileged user (that is you) to reset the count from time to time. If user start the program and then his computer hangs up he will reboot and the server will think he is running the application while he isn't. In this case you must somehow be able to understand that.

When the application terminates and you remove the .exe file or whatever you of course also tell the server that the user is no longer using the application so someone else can use it.

Alf
0
 

Author Comment

by:dave_p_r_b
ID: 8168769
No code... it will be commercial programs such as word.

Thanks for all your input people... appreciated...
If i were to attempt the system programmers method... what would it be? ( incidentily, i'm not bright enough to be a systems programmer! - but I'm going to ask so that I could at least try! )

I'm ok with the network bit... that's someone else's task... it's purely controlling program execution..

d.
0
 
LVL 6

Expert Comment

by:Mafalda
ID: 8170457
I think that it is more clear talking about processes and not programs ...
It seems that you want to prevent programs from executing more then N times at the same time etc (creating N processes or more).
You need to read the processes currently running like Windows Task Manager does, and count the occurences of a specific process, then if there are too many kill the latest ones.
This should be a program that runs all the time and checks the tasks every M minutes/seconds.

0
 

Author Comment

by:dave_p_r_b
ID: 8172461
I dont want to kill a program after it has started. Surely, this is not safe? To kill a program when it is has hung, is one matter, but to kill a program after it has started or while it is still running could cause data loss- right?

I know it seems impossible to stop a program starting before it starts but i was hoping their would be a some way of sneaking in between the operating system being told that program X should run and the operating system actually starting X.

ok... now i am bald!

D.
0
 
LVL 12

Accepted Solution

by:
Salte earned 750 total points
ID: 8172491
There is one way, replace the real word.exe with your own program.

This program contact a server and say "I want to start WORD" and the server keep track of how many is running word on the network and if the count is smaller than the max then it will respond "yes" otherwise it respond "no".

Your program "word.exe" will then read that response, if it is no it will display a message box saying that the user cannot start word because there already too many people running it. If the response is "yes" that program do a CreateProcess on "realword.exe" and wait for realword.exe to finish. When the program is done running (the user exits from word) your program can tell the server "I am no longer using WORD" and the server will decrease the counter so that next time someone wants to start word they can do so.

This is the essential idea and it doesn't require you to have the source code for word.exe only that you can rename the file to something else.

If you in addition could stuff it in some zip file or something and encrypt it and let the server pass the encryption key when it says "yes" and have your word.exe unpack the program before it does CreateProcess and then delete the unpacked program before it exits is just some added security you can place around it.

If you thik it is unlikely that people will look around and find the realword.exe (which doesn't have to be given a meaningful name but could instead be called x0f23jzp__.exe or some other non-sense) then you don't have to do those steps.

Alf
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

777 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