Note: This post is the third in a three-part series. You may want to read Part I: McAfee Host Intrusion Prevention Should Die and Part II: McAfee Assassin before continuing with this post.
After programming McAfee Assassin Rev 1 and distributing it for testing I was relatively pleased with the outcome. It effectively dismissed the annoying McAfee Host Intrusion Prevention dialogs and allowed me to work without constantly clicking them. However, I found some issues with McAfee Assassin that I felt decreased its user experience:
- Using the Win32 API to simulate keyboard commands was actually slower than I had expected. It took one to two seconds for a given dialog to be dismissed. With two seconds of application sleep between polls, it could take up to four seconds for a dialog to be dismissed.
- If more than one McAfee Host Intrusion Prevention dialog is generated at the same time, a set of “Next” and “Previous” buttons are added to each dialog. McAfee Assassin Rev 1 was unable to handle this and would not dismiss such dialogs.
I decided to focus on the performance issue first. While four seconds doesn’t seem like a really big deal, it’s long enough for the user to start moving the cursor toward the dialog, expecting to click the “Allow” button. It further posed problems when running automated JUnit tests through Eclipse, as Eclipse creates some application hooks and tries to open a connection to localhost. The McAfee Host Intrusion Prevention dialogs force the JUnit test runner to be terminated immediately, and the only way I’ve found to run them is to check the “Create a rule for this connection” checkbox on the McAfee HIPS dialog, then re-run the JUnit tests in the next 60 seconds.
Remembering something from C++ classes in college, I did some research and found that the Win32 API provides functions for interacting with GUI window elements (including buttons and other controls) regardless of the process that launched the window itself. I used WinID to inspect the McAfee HIPS dialogs and locate the individual components in which I was interested, intending to use the information to programmatically access and click the required buttons.
It was not as easy as I had thought it would be. I couldn’t locate a Win32 API function to find a specific control if I didn’t already have a handle to its parent control. It turns out the GUI layout of the McAfee HIPS controls includes some invisible container components that have to be located before the buttons and checkboxes can be clicked or manipulated.
Eventually I figured out the appropriate control hierarchies and set to work. McAfee Assassin Rev 2 still polls for McAfee HIPS dialogs in a loop but now uses the Win32 API to manipulate a dialog’s controls. It’s able to determine which type of McAfee HIPS dialog it’s looking at and changes its behavior accordingly. As a result, McAfee Assassin Rev 2 is much faster than Rev 1 and works more accurately because it doesn’t rely on series of keyboard commands.
C++ Code:
//============================================================================
// Name : McAfeeAssassin.cpp
// Version : 1.1
// Copyright : No copyright
// Description : McAfee Host Intrusion Prevention dialog automatic Allow clicker.
// Usage : McAfeeAssassin.exe -sleep milliseconds -title windowtitle
// -sleep milliseconds to sleep between checks for new dialogs
// -title the dialog title for which to check
//============================================================================
#define _WIN32_WINNT 0x0501 // Windows XP = 0501H
#define NOCOMM // Exclude unnecessary dlls
#define _WINNETWK_H
#define _WINREG_H
#define _WINSVC_H
#include
#include
#include
#include
#include
using namespace std;
const string SLEEP_PARAM = "sleep";
const string DIALOG_TITLE_PARAM = "title";
void loop() {
while(1) {
HWND windowHandle;
windowHandle = FindWindow(NULL, DIALOG_TITLE.c_str());
if(windowHandle != NULL) {
ShowWindow(windowHandle, SW_SHOW);
SetActiveWindow(windowHandle);
SetForegroundWindow(windowHandle);
// If the window has more than one tab, it's probably a firewall dialog. We'll need to select the "Connection Information" tab and click the
// "Create firewall application rule for all ports and protocols" checkbox
HWND tabHandle;
tabHandle = FindWindowEx(windowHandle, 0, "SysTabControl32", "Tab1");
if(tabHandle != NULL) {
// Sadly, the Allow button and firewall checkbox are children of anonymous layout controls, so we have to locate a handle to the
// layout control first
HWND buttonLayoutHandle;
buttonLayoutHandle = FindWindowEx(windowHandle, NULL, NULL, "");
// If this is a firewall dialog, there will be a second tab. If -1 is returned when selecting the tab, we know there
// is only one tab available.
if(-1 != TabCtrl_SetCurSel(tabHandle, 1)) {
// We're now on the Connection Information tab
// Look for the "create firewall application rule" checkbox
// Sadly, the Allow button and firewall checkbox are children of an anonymous layout control, so we have to locate a handle to the
// layout control first
HWND layoutHandle;
layoutHandle = FindWindowEx(windowHandle, NULL, NULL, "");
HWND checkboxHandle;
checkboxHandle = FindWindowEx(layoutHandle, 0, "Button", "&Create a firewall application rule for all ports and protocols");
if(checkboxHandle != NULL) {
// Select the checkbox
SendMessage (checkboxHandle, BM_CLICK, 0 , 0);
}
// If the firewall dialog is displayed, the Connection Information tab's layout window is before the Application Info's in the Z-order
buttonLayoutHandle = FindWindowEx(windowHandle, layoutHandle, "#32770", "");
}
// Locate the Allow button and click it
HWND buttonHandle;
buttonHandle = FindWindowEx(buttonLayoutHandle, NULL, "Button", "&Allow");
SendMessage (buttonHandle, BM_CLICK, 0 , 0);
}
}
Sleep(SLEEP_MS);
}
int main(int argcount, char *argvalues[]) {
cout << "|----------------------------------------------|\n";
cout << "| McAfeeAssassin v1.1 |\n";
cout << "| Author Unknown |\n";
cout << "| Trolls for McAfee Host Intrusion Prevention |\n";
cout << "| dialogs and simulates \"allow\" action. |\n";
cout << "| Works on \"Network Application Alert\" and |\n";
cout << "| \"Application Creation Alert\" dialogs. |\n";
cout << "| Found necessary because these dialogs do not |\n";
cout << "| adhere to the application and firewall rules |\n";
cout << "| set in the McAfee Host Intrusion Prevention |\n";
cout << "| editor. |\n";
cout << "| |\n";
cout << "| USAGE: |\n";
cout << "| McAfeeAssassin -sleep milliseconds -title |\n";
cout << "| windowtitle |\n";
cout << "| |\n";
cout << "| -sleep: milliseconds to sleep between checks |\n";
cout << "| -title: the dialog title for which to poll |\n";
cout << "|----------------------------------------------|\n";
// Hide this window
HWND console = GetConsoleWindow();
ShowWindow(console, SW_HIDE);
parseArgs(argcount, argvalues);
// init();
loop();
return 0;
}
Requires the following DLLs in your Windows path (can just be copied to %SYSTEMROOT%\system32):
- cygwin1.dll
- cygcc_s-1.dll
- cygstdc++-6.dll
Binary download: McAfeeAssassin.exe





