![]() |
General Programming »
Internet / Network »
DNS
Intermediate
Intercept and Rewrite DNS Requests Using Regular ExpressionsBy Dan FarinoA tool and code for injecting a DLL into a running Firefox process to rewrite DNS lookups. |
C++WinXP, Win2003, MFC, VS2005, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
I was asked by our QA Ninja at work if I could come up with a way to make changes to the hosts file affecting only Firefox, without affecting any other applications running on the system, such as Internet Explorer. Frequently, people testing web applications will make changes to the hosts file in order to direct their web traffic to a staging or development server. However, changes to the hosts file affect the entire system. To have one browser be able to talk to the staging server while another is still talking to the production site would be quite useful during testing.
As a quick overview, here's how the hosts file works. Let's say, for example, you want to be able to type www.mycompany.com into your web browser but have the actual traffic go to staging.mycompany.com. In Windows, what you would normally do is to manually perform a DNS lookup for staging.mycompany.com and put the host name and IP address into your %SYSTEMROOT%\system32\drivers\etc\hosts file, like this:
192.168.0.1 www.mycompany.com
Now, when any application performs a DNS lookup for www.mycompany.com, the DNS resolver will return 192.168.0.1, which, in this case, is actually the address for staging.mycompany.com.
This is an effective way to redirect requests. However, it is not without its shortcomings, namely:
My solution was to create an application I call DnsHijack. Here's what DnsHijack enables you to do:
replace mycompany\.com$ staging.mycompany.com
s/// (i.e. you can use the $1, $2, etc. variables to refer to captures). For example: replace ^(.+)\.mycompany\.com$ $1.staging.mycompany.comThis will result in:
| www.mycompany.com | → | www.staging.mycompany.com |
| another.server.mycompany.com | → | another.server.staging.mycompany.com |
DnsHijack works by injecting a DLL into the Firefox process and hooking the gethostbyname function using the Detours library available from Microsoft Research. gethostbyname is the Winsock function that will be called by Firefox when it needs to perform a DNS lookup.
There are four files involved:
gethostbyname Winsock function.
In order to use DnsHijack, you'll need to copy the above files to your Firefox directory (mine is C:\Program Files\Mozilla Firefox). Then, launch Firefox and run DnsHijack.exe. Here's what happens next:
CreateToolhelp32Snapshot, Process32First and Process32Next.)
OpenProcess).
VirtualAllocEx).
WriteProcessMemory).
LoadLibraryW function in kernel32.dll (using GetProcAddress). The address returned is actually an address in our current address space (DnsHijack.exe), not Firefox's. Fortunately, kernel32.dll is one of the first DLLs loaded into a Windows process, meaning it is almost always loaded at its preferred base address, which, in turn, means it is mapped to the same address in every process. So, even though our LoadLibraryW pointer technically refers to DnsHijack's address space, it should work in Firefox's address space as well.
CreateRemoteThread). Here's why this works: every thread needs a "start address" which is simply the address where the thread begins its execution (also called the "thread function"). The thread function for our new thread is set to the address of LoadLibraryW, which we found in the previous step. CreateRemoteThread also allows us to pass a single pointer-sized argument to the thread function and, fortunately, the function we've chosen as our thread function, LoadLibraryW, takes exactly one argument. In this case, we pass the address of the string ("DnsHijackDll.dll") we wrote into Firefox's address space. This means we are effectively calling LoadLibraryW(L"DnsHijackDll.dll") from inside the Firefox process. This loads the DLL and causes the DllMain function in DnsHijackDll.dll to be called. So, at this point we have code running in the Firefox process (specifically, our DllMain function). Here's what DllMain does:
std::vector containing all of the configuration rules.
gethostbyname function. When using the Detours library to hook a function, a function pointer is returned (which I store in the variable real_gethostbyname) that we can use to call the original, unhooked function. We'll use this function pointer to perform the actual DNS lookup once we're done doing any rewriting.
The function that replaces gethostbyname is named, in this case, my_gethostbyname. So, when Firefox calls gethostbyname, my_gethostbyname is actually called (because of the Detour) and performs the following:
real_gethostbyname, passing in either the original name, or if a "replace" rule was matched, the replacement DNS name. Either way, return the result to the caller (which, in this case, will be Firefox's code). DllMain, causing another DLL to load could result in a deadlock since, during DllMain's execution, the process-wide OS Loader lock is being held.
DllMain and for each re-written DNS query, you can use Sysinternals' excellent DebugView utility. Just start it up before running DnsHijack.exe.
I hope that DnsHijack is useful application for web testers. In addition, for developers, it should serve as a good example of using techniques like DLL injection and function detouring. Please post any feature requests or bugs you find. Thanks!
| You must Sign In to use this message board. | |||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 2 Nov 2006 Editor: Smitha Vijayan |
Copyright 2006 by Dan Farino Everything else Copyright © CodeProject, 1999-2009 Web22 | Advertise on the Code Project |