I was asked if it’s possible to intercept IE’s HTTPS requests. It is, it’s not difficult, and you don’t need admin rights to do it on your own processes. In other words, a malware doesn’t even need admin rights to spy on your IE process, if said malware is also running under your user account.
We need to hook the API calls to WinINet functions, like HTTPOpenRequest. We can do this by patching the Delayed Import Address Table of executables calling WinINet functions. In our case, to spy on IE, we need to patch the DIAT of urlmon.dll. One simple way to hook these API calls, is to develop a DLL that will patch the DIAT, diverting the calls to our own functions. Our functions will just call the original functions while intercepting the data.
Here is an example for HTTPOpenRequest:

HookHTTPOpenRequestA is our hook function for HTTPOpenRequest. It will just output the flags, verb and objectname parameters to the debugger, and then call the original HTTPOpenRequest function with unmodified arguments (which we saved in variable OriginalHTTPOpenRequestA). BTW, if the declaration and use of OriginalHTTPOpenRequestA looks confusing to you, read the explanation of function pointers in C.
Patching the DIAT is easy, use the PatchDIAT function that I provide with my Basic Process Manipulation Tool Kit (it’s in iat.c).

PatchDIAT needs the name of the executable we want to patch (urlmon.dll), the name of the API to patch (wininet.dll), the name of the function to patch (HttpOpenRequestA), the address of our hooking function (HookHttpOpenRequestA) and a variable to store the address of the original function (OriginalHttpOpenRequestA). PatchDIAT returns S_OK when patching was successful.
We package everything in a DLL, while hooking some other functions, like InternetReadFile (to intercept actual data), and then inject this DLL in IE with my toolkit:


I’ve stored a test file on my server: https://DidierStevens.com/files/temp/test.txt. When you browse to this test file with the patched IE, you’ll see this in Sysinternal’s DebugView:

Lines 0 to 4 indicate the patching IE was successful.
Line 5 shows IE opening a connection to didierstevens.com on port 443 (that’s 1BB in hexadecimal).
Line 6 shows the preparation of an HTTPS GET request to file /files/temp/test.txt. Flags 00C00000 indicate HTTPS and keep-alive.
Line 7 shows that the call to InternetReadFile was successful and read 25 bytes (0×19).
Line 8 shows the actual data retrieved by IE: This is just a text file.
The next lines indicate we unloaded our DLL with success (thus undoing the patch).
As you can see, we can intercept data before it is encrypted by the HTTPS connection (/files/temp/test.txt) and after it is decrypted (This is just a text file.). This works because we patch the executable before it calls API functions that handle the encryption/decryption, so we get access to the unencrypted data.
I kept my demo DLL very simple to show you the basic principles. A complete spying program would have to hook more functions and tie all the data together to present it in a user friendly way.
It’s also simple to adapt my IE spying DLL to tamper with the data. For example, it could redirect IE to another web site by changing the lpszServerName argument before it calls the original InternetConnect function.
[...] To Add: Nice post here describing the basic principals of DLL hooking (one of the techniques used in Signpost), and how it [...]
Pingback by The First Rule of Programming: It’s Always Your Fault | Mike Andrews — Saturday 22 March 2008 @ 18:36
very interesting Didier… could something similar be possible for FFox?
Comment by donald — Monday 7 April 2008 @ 6:50
FF doesn’t use wininet, but a similar approach must be possible. Somewhere in the FF code, calls need to be made to functions to use TLS. If these functions reside in a DLL, you can use the same technique (IAT patching). But if these functions are in the FF executable, you’ll need another technique to intercept the calls (like a trampoline).
Comment by Didier Stevens — Monday 7 April 2008 @ 19:18
Very interesting post. I’m about to try it out. Do you know if this should work for IE7 as well? Thank you
Comment by Tim — Thursday 26 June 2008 @ 18:50
I did a quick test and it doesn’t work with IE7. A quick disassembly shows that urlmon.dll imports HttpOpenRequestW (delayed import) from wininet.dll, and not HttpOpenRequestA. So I suppose that for IE7, you have to hook the wide-byte version of HttpOpenRequest.
Comment by Didier Stevens — Thursday 26 June 2008 @ 19:40
Would you mind posting your complete source? It would be much appreciated.
Thanks!
Comment by Tim — Friday 27 June 2008 @ 16:40
Also, I appreciate your feedback. I hadn’t noticed your reply when I last commented.
Comment by Tim — Friday 27 June 2008 @ 17:26
I have one more question. I was able to compile your code correctly, but I am unable to get it packaged into a dll. I’m a beginner with c/c++. I’m using cygwin on windows and have all the necessary packages. Do you use a specific command to package your code into a dll? I attempted to load it into Visual Studio Express 2008, but it didn’t recognize the function pointer syntax, and was giving me errors. I would really like to try out your example. I appreciate your time.
Thanks
Comment by Tim — Friday 27 June 2008 @ 21:34
I seem to have deleted the source code by mistake, I’ll have to search through some backups or write it again.
It gets compiled along with my bpmtk. So first of all, try to compile the bpmtk with it’s make file bpmtk.mak
I have some instructions in the make file:
# Developed with Borland’s free C++ compiler: http://cc.codegear.com/Free.aspx?id=24778
# You need to install the MS Platform SDK for BCC: http://sourceforge.net/projects/bccsdk/
# I decompress it in the BORLAND\bccsdk_0_0_7_1 directory, next to BORLAND\BCC55
Comment by Didier Stevens — Saturday 28 June 2008 @ 7:58
Hi!
I am trying to hook in IE7 but i am unable to do so.
I have implemented a hooking mechanism similar to the one in your BPMTK (great code!). But i have included a scan to check all the modules loaded.
As far as I can see in the debug (I am not an expert in this area), URLMON is linking to:
[3376] msvcrt.dll
[3376] ntdll.dll
[3376] ole32.dll
[3376] OLEAUT32.dll
[3376] RPCRT4.dll
[3376] SHLWAPI.dll
[3376] USER32.dll
[3376] ADVAPI32.dll
[3376] KERNEL32.dll
[3376] iertutil.dll
So the hook for HttpOpenRequestW (or HttpOpenRequestA) does not suceed with that DLL and I cannot get any traffic capture.
Do you have an idea of how IE7 handles the SSL?, maybe I am doing something wrong…
Thanks for your help (this blog was very helpful to me!)
(sorry for my bad english)
Comment by Pablo — Wednesday 17 December 2008 @ 20:06
I’ll try to take a look at it during the holiday.
Comment by Didier Stevens — Sunday 21 December 2008 @ 15:09