views:

292

answers:

4

I have a great idea about cheating on exams. My school uses very old IDE's ( think Turbo Pascal, Turbo C++ , and other 80's ones ), and the thing I'd like to do is this :

  • start my program in the background

  • intercept the keypresses, and instead of sending them directly to the screen, I'd like to read a character from a pre-configured text-file, and send that as the pressed key. This way, no matter what you'll write, the text from that file will get written on the screen.

I found Stephen Toub's article about logging keys, and I think it will serve as a good start on building this "tool". Is there a better alternative to intercepting all the keys pressed in the system than SetWindowsHookEx? Will the code be flagged by the antivirus as a suspicious program? If so, is there anything else I can use to accomplish this without being flagged by the antivirus? Will administrator priviledges be required ?

I know some of you guys will say that If I'd put as much interest in learning as I do in avoiding learning, I'd do great, but I'd like to try this out.

EDIT: I've added a bounty, I'm interested in some techniques for capturing keystrokes ( I'm not interested in low-level hooking or advanced stuff - basic ones are fine ), mainly method names and some links to documentation. I'd also like to know if they would appear as malware to an antivirus.

+2  A: 

SetWindowsHookEx is the best option. I've been told that some antivirus programs will flag it, but I created a little app once using it and scanned it with AVG which returned no virus alerts.

scottm
+1  A: 

As far as I can say, the most reliable way to keylog is to set up a system wide interrupt (I think INT17h?), but that's pretty low level, considering that your post is tagged C#. Go search for a relevant tool... you'll find many...

Aviral Dasgupta
I think http://www.codeproject.com/KB/system/KeyHook.aspx should help
Aviral Dasgupta
+1  A: 

Not that I'm saying cheating is good, but we understand your plea. I dont' think it's possible without getting into API hooks, since .Net wraps WIN32 API's I don't think they have wrapped methods for what you want.

For completeness, let's just add some details:

Unfortunately you have to get into the WIN32 API's: http://msdn.microsoft.com/en-us/library/ms645530%28VS.85%29.aspx

The *WM_SYSKEYDOWN* notification can be used to get the key strokes, but it takes the handle of the window to watch, so it would involve the *GetWindow** API's to get the handle of the window you want to monitor.

Try the SendInput or *keybd_event* [http://msdn.microsoft.com/en-us/library/ms646304%28VS.85%29.aspx%5D functions to simulate keystrokes.

Google "WIN API Viewer" for a utility to easily search for and view said API's, there is a version for .Net code too.

It's one of those things that will take a lot of trial and error, and I wish I had a more definitive answer for you.

Wez
+2  A: 

GOD! I've just found the perfect class for this the other day.. took me a while to find the original source:

http://www.codeproject.com/KB/cs/globalhook.aspx

I used this (and SendKeys) alone exactly for what you need, you'll need to use Handle=true to block the original key message.

SendKeys is a bit ugly... you can look for a replacement if you'd like.. but SendKeys will work for you.

With SendKeys it's something like:

    private void HookManager_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.D){
            e.Handled = true;
            SendKeys.Send("F");
        }
    }

I actually also use this method to determined what prccess' window is in focus, so the app will do nothing if you are on another application:

    /// <summary>
    /// The GetForegroundWindow function returns a handle to the foreground window.
    /// </summary>
    [DllImport("user32.dll")]
    static extern IntPtr GetForegroundWindow();

    static bool IsProcessFocused(string processname)
    {
        if (processname == null || processname.Length == 0)
        {
            throw new ArgumentNullException("processname");
        }

        Process[] runninProcesses = Process.GetProcessesByName(processname);
        IntPtr activeWindowHandle = GetForegroundWindow();

        foreach (Process process in runninProcesses)
        {
            if (process.MainWindowHandle.Equals(activeWindowHandle))
            {
                return true;
            }
        }

        // Process was not found or didn't had the focus.
        return false;
    }
Itay
The link you provided was great! I think it fits my needs perfectly, thanks!
Geo