Posted by & filed under article.

Every morning I open the Buypass desktop app and enter my personal pin. In return I get a passcode (that I cant copy) so I need to type it into Check Point Endpoint Security in order to logon to the network. Security wise this is great, however too tiresome. Therefore the idea of automating the process came to life! A quick view of the results in action can be viewed in the video below.

Technical approach

By starting the Buypass process from the C# application, the process handle for Buypass is return to the application.

process = Process.Start(processPath);

Proceeding to start the process as defined by the processPath, that when properly configured will point to the Buypass executable file. We have no way of knowing precisely when the Buypass application is ready, however some cleaver guy on stackoverflow checks for a non-zero window handler to confirm the application is fully loaded.

isFormRdy = (process.MainWindowHandle != IntPtr.Zero);

Since we cant know excactly how long time the application will require before fully loaded, a timer is started to poll the process and to check if the window handle is not null with a interval of 500ms. Now knowing when the Buypass application is loaded and ready to receive the pin as input, I use the System.Windows.Forms.SendKeys function to type the personal pin. It’s therefore critical that no other application steels the input focus at this point or else it will for instance write out the personal pin into Word if Word was selected right after Buypass is fully loaded. Followed by the pin, the SendKey function is used to send the enter keypress.

SendKeys.SendWait(privatePin);
SendKeys.SendWait("{ENTER}");

At this point Buypass will generate what I assume to be an image of the passcode. Before proceeding to grab a screenshot of the passcode, I pass the window handle from the process and a referenced variable to the User32 API GetWindowRect.

[DllImport("user32.dll")]
public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

// Get the possition of the form.
IntPtr ptr = process.MainWindowHandle;
Rect pRect = new Rect();
GetWindowRect(ptr, ref pRect);

Now knowing the position of the Buypass application, its possible to target the passcode area with some offsets so that a screenshot is grabbed of the passcode and only the passcode. Reducing the noise drastically compared to running OCR on the whole screen.

Further I assume from the network traffic that Buypass produces, a network call to a server is issued in order to verify the client with the provided pin. Dealing with network we cant be exactly sure when the passcode is available. For instance if there is a network lag, a screen capture might occur before the passcode is available. Since we cant be certain, a recursive retry function is used to retry the screen capture and process OCR up to five times with a delay of one second.

Log("OCR returned: " + word.Text);
if(word.Text.Length >= 5) {
  Clipboard.SetText(word.Text);
  Log("Password copied to clipboard.");
} else {
  Thread.Sleep(1000);
  Log("OCR not accepted. Retrying... " + retry);
  CaptureScreen(rect, retry - 1);
}

To accept the OCR results, it needs to return a string containing at least 5 characters. Finally returning the password to the Clipboard.

Also, if the application is started with the argument -run, it will start the process of opening Buypass and grabbing the passcode, before exiting Buypass and Byepass leaving a clean exit!

 

The project is available on GitHub: https://github.com/Olavz/byepass

Please leave a comment if you found this interesting or if you would like to suggest improvements.

Cheers

One Response to “Using C# and OCR to say bye to Buypass with Byepass”

  1. Henning

    G +1 to this post. Great explanation of the process, and even though I don’t understand it all it’s still an interesting read!

    Reply

Leave a Reply

  • (will not be published)