Sunday, January 02, 2005

 

Capture the http headers of IE

Recently I need to capture the http headers of IE. Two expensive examples are listed by Google

HttpWatch
http://www.httpwatch.com/default.htm

IEWatch
http://www.iewatch.com/

1.
One prompt idea is to implement a simple socket interface for Post/Response. A typical example is

Discover WEB. HTTP GET-POST Utility
By Adrian Bacaianu
http://www.codeproject.com/internet/httpget-post.asp

However, it is not good for multi-frame web pages. The main insert content process is listed as follows. We can see taht it does not do with multi-frame web pages.

BOOL CXXXXView::put_bodyHtml(CString cs)
{
IHTMLDocument2* pHtmlDoc2 = (IHTMLDocument2*)GetHtmlDocument();
if( pHtmlDoc2)
{
HRESULT hr = S_OK;
IHTMLElement *pBodyElement;
hr=pHtmlDoc2->get_body( &pBodyElement);
if(pBodyElement!=NULL)
{
BSTR pbBody = cs.AllocSysString();
hr=pBodyElement->put_innerHTML(pbBody); //or similarly put_innerTEXT
pBodyElement->Release();
}
pHtmlDoc2->Release();
if( hr==S_FALSE) return FALSE;
else return TRUE;
}
else return FALSE;
}

Similarly, to use

CInternetSession ISession;
CHttpConnection* pConnection = NULL;
CString strURL;
pConnection = ISession.GetHttpConnection((LPCTSTR)strURL);
CHttpFile* pURLFile = pConnection->OpenRequest("GET", "/");

do not do well either. A example is

HTTP header and source extraction tool
By Code4Food
http://www.codeproject.com/tools/hextract.asp

2.
The second method is to hook the winsocket API and capture the package that send to IE directly. HttpWatch, IEWatch and ieHttpHeaders
http://www.blunck.info/iehttpheaders.html
use this way.

A interesting article written by zwell is listed as below

http://bbs.xplore.cn/viewtopic.php?t=1053&sid=b37cd5e408c5142bba3504069298a687

不知道大家用过WSockExpert没有, 它可以用来截获指定进程网络数据的传输.
前面我还以为它是通过实时远程注入DLL来更改IAT. 不过后来发现在程序一运行时,
它就已经将DLL插入所有进程了,这个跟冰哥写的那个模拟SOCKCAP的程序很相似.
似乎是将DLL注入所有进程, 不过再想一下, 如果是这样的话,那么后来启动的程序
应该不会被注入DLL(除非用定时^_^,这样就太麻烦了), 考虑到这些, 我估计它是
用的HOOK,用HOOK的话就有一点方便:不必考虑有没有读写权限的问题. 也就免
了一些麻烦.
我在BCB环境中用APIHOOK模拟了一个类似的程序,通过HOOK将DLL插入所有
进程,然后截获WINSOCK API.中间遇到了一些问题,参考了冰哥的SOCKCAP和
EYAS大哥的XHOOK. 在XHOOK中将原始DLL做了一个备份, 在执行API时并没有先
将API地址还原,而是直接调用了备份的函数, 这样提高了执行效率.厉害,
以后再改,先放上一个简单的演示,大家可以对它进行修改扩展功能:


DLL代码:

//---------------------------------------------------------------------------
// Mady By ZwelL
// 2004.8
// zwell@sohu.com
//---------------------------------------------------------------------------
#include
#include

#pragma argsused

//自定义APIHOOK结构
typedef struct
{
FARPROC funcaddr;
BYTE olddata[5];
BYTE newdata[5];
}HOOKSTRUCT;

HHOOK g_hHook;
HINSTANCE g_hinstDll;
HMODULE hModule ;
HANDLE g_hForm; //接收信息窗口句柄
DWORD dwIdOld, dwIdNew;

//------------------------------------------------------------------------
// 由于要截获两个库里面的函数,所以每个函数定义了两个HOOK结构
// 在编程过程中因为没有考虑到这个问题,导致很多包没有截获到,
// 后来想到了冰哥在模仿SOCKCAP的程序中每个函数截了两次才明白
// 一个是wsock32.dll, 一个是ws2_32.dll
//------------------------------------------------------------------------
HOOKSTRUCT recvapi;
HOOKSTRUCT recvapi1;
HOOKSTRUCT sendapi;
HOOKSTRUCT sendapi1;
HOOKSTRUCT sendtoapi;
HOOKSTRUCT sendtoapi1;
HOOKSTRUCT WSASendapi;

void HookOn();
void HookOff();
BOOL Init();
extern "C" __declspec(dllexport) __stdcall
BOOL InstallHook();
extern "C" __declspec(dllexport) __stdcall
BOOL UninstallHook();

BOOL hookapi(char *dllname, char *procname, DWORD myfuncaddr, HOOKSTRUCT *hookfunc);
int WINAPI Myrecv(SOCKET s, char FAR *buf, int len, int flags);
int WINAPI Myrecv1(SOCKET s, char FAR *buf, int len, int flags);
int WINAPI Mysend(SOCKET s, char FAR *buf, int len, int flags);
int WINAPI Mysend1(SOCKET s, char FAR *buf, int len, int flags);
int WINAPI Mysendto(SOCKET s, const char FAR * buf, int len,
int flags, const struct sockaddr FAR * to, int tolen);
int WINAPI Mysendto1(SOCKET s, const char FAR * buf, int len,
int flags, const struct sockaddr FAR * to, int tolen);
int WINAPI MyWSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);
void sndmsg(char *buf);

//---------------------------------------------------------------------------
// 入口函数
// 在一载入库时就进行API截获
// 释放时还原
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
g_hinstDll = hinst;
g_hForm = FindWindow(NULL, "ZwelL");
if(!Init())
{
MessageBoxA(NULL,"Init","ERROR",MB_OK);
return(false);
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UninstallHook();
break;
}
return TRUE;
}

//-----------------------------------------------------------------------
BOOL Init()
{
hookapi("wsock32.dll", "recv", (DWORD)Myrecv, &recvapi);
hookapi("ws2_32.dll", "recv", (DWORD)Myrecv1, &recvapi1);
hookapi("wsock32.dll", "send", (DWORD)Mysend, &sendapi);
hookapi("ws2_32.dll", "send", (DWORD)Mysend1, &sendapi1);
hookapi("wsock32.dll", "sendto", (DWORD)Mysendto, &sendtoapi);
hookapi("ws2_32.dll", "sendto", (DWORD)Mysendto1, &sendtoapi1);
hookapi("wsock32.dll", "WSASend", (DWORD)MyWSASend, &WSASendapi);
dwIdNew = GetCurrentProcessId(); // 得到所属进程的ID
dwIdOld = dwIdNew;
HookOn(); // 开始拦截
return(true);
}
//---------------------------------------------------------------------------
LRESULT WINAPI Hook(int nCode, WPARAM wParam, LPARAM lParam)
{
return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
}
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) __stdcall
BOOL InstallHook()
{
g_hHook = SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)Hook, g_hinstDll, 0);
if (!g_hHook)
{
MessageBoxA(NULL, "SET ERROR", "ERROR", MB_OK);
return(false);
}
return(true);
}
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport) __stdcall
BOOL UninstallHook()
{
HookOff();
if(g_hHook == NULL)
return true;
return(UnhookWindowsHookEx(g_hHook));
}

//---------------------------------------------------------------------------
// 根据输入结构截获API
//---------------------------------------------------------------------------
BOOL hookapi(char *dllname, char *procname, DWORD myfuncaddr, HOOKSTRUCT *hookfunc)
{
hModule = LoadLibrary(dllname);
hookfunc->funcaddr = GetProcAddress(hModule, procname);
if(hookfunc->funcaddr == NULL)
return false;

memcpy(hookfunc->olddata, hookfunc->funcaddr, 6);
hookfunc->newdata[0] = 0xe9;
DWORD jmpaddr = myfuncaddr - (DWORD)hookfunc->funcaddr - 5;
memcpy(&hookfunc->newdata[1], &jmpaddr, 5);
return true;
}
//---------------------------------------------------------------------------
void HookOnOne(HOOKSTRUCT *hookfunc)
{
HANDLE hProc;
dwIdOld = dwIdNew;
hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwIdOld);
VirtualProtectEx(hProc, hookfunc->funcaddr, 5, PAGE_READWRITE,&dwIdOld);
WriteProcessMemory(hProc, hookfunc->funcaddr, hookfunc->newdata, 5, 0);
VirtualProtectEx(hProc, hookfunc->funcaddr, 5, dwIdOld, &dwIdOld);
}
//---------------------------------------------------------------------------
void HookOn()
{
HookOnOne(&recvapi);
HookOnOne(&sendapi);
HookOnOne(&sendtoapi);
HookOnOne(&recvapi1);
HookOnOne(&sendapi1);
HookOnOne(&sendtoapi1);
HookOnOne(&WSASendapi);
}
//---------------------------------------------------------------------------
void HookOffOne(HOOKSTRUCT *hookfunc)
{
HANDLE hProc;
dwIdOld = dwIdNew;
hProc = OpenProcess(PROCESS_ALL_ACCESS, 0, dwIdOld);
VirtualProtectEx(hProc, hookfunc->funcaddr,5, PAGE_READWRITE, &dwIdOld);
WriteProcessMemory(hProc, hookfunc->funcaddr, hookfunc->olddata, 5, 0);
VirtualProtectEx(hProc, hookfunc->funcaddr, 5, dwIdOld, &dwIdOld);
}

//---------------------------------------------------------------------------
void HookOff()
{
HookOffOne(&recvapi);
HookOffOne(&sendapi);
HookOffOne(&sendtoapi);
HookOffOne(&recvapi1);
HookOffOne(&sendapi1);
HookOffOne(&sendtoapi1);
HookOffOne(&WSASendapi);
}
//---------------------------------------------------------------------------
int WINAPI Myrecv(SOCKET s, char FAR *buf, int len, int flags)
{
int nReturn;
HookOffOne(&recvapi);
nReturn = recv(s, buf, len, flags);
HookOnOne(&recvapi);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "recv|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//---------------------------------------------------------------------------
int WINAPI Myrecv1(SOCKET s, char FAR *buf, int len, int flags)
{
int nReturn;
HookOffOne(&recvapi1);
nReturn = recv(s, buf, len, flags);
HookOnOne(&recvapi1);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "recv1|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//---------------------------------------------------------------------------
int WINAPI Mysend(SOCKET s, char FAR *buf, int len, int flags)
{
int nReturn;
HookOffOne(&sendapi);
nReturn = send(s, buf, len, flags);
HookOnOne(&sendapi);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "send|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//---------------------------------------------------------------------------
int WINAPI Mysend1(SOCKET s, char FAR *buf, int len, int flags)
{
int nReturn;
HookOffOne(&sendapi1);
nReturn = send(s, buf, len, flags);
HookOnOne(&sendapi1);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "send1|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//--------------------------------------------------------------------------
int WINAPI Mysendto(SOCKET s, const char FAR * buf, int len,
int flags, const struct sockaddr FAR * to, int tolen)
{
int nReturn;
HookOffOne(&sendtoapi);
nReturn = sendto(s, buf, len, flags, to, tolen);
HookOnOne(&sendtoapi);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "sendto|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//--------------------------------------------------------------------------
int WINAPI Mysendto1(SOCKET s, const char FAR * buf, int len,
int flags, const struct sockaddr FAR * to, int tolen)
{
int nReturn;
HookOffOne(&sendtoapi1);
nReturn = sendto(s, buf, len, flags, to, tolen);
HookOnOne(&sendtoapi1);

char *tmpbuf=new char[len+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "sendto1|%d|%d|%s",
GetCurrentProcessId(),
len,
buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}
//----------------------------------------------------------------------------
int WINAPI MyWSASend(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesSent,
DWORD dwFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
)
{
int nReturn;
HookOffOne(&WSASendapi);
nReturn = WSASend(s, lpBuffers, dwBufferCount,
lpNumberOfBytesSent, dwFlags, lpOverlapped, lpCompletionRoutine);
HookOnOne(&WSASendapi);

char *tmpbuf=new char[*lpNumberOfBytesSent+100];
memset(tmpbuf, 0, sizeof(tmpbuf));
sprintf(tmpbuf, "WSASend|%d|%d|%s",
GetCurrentProcessId(),
lpNumberOfBytesSent,
lpBuffers->buf);
sndmsg(tmpbuf);
delete tmpbuf;
return(nReturn);
}

//-----------------------------------------------------------------
// 向窗口发送消息
// 考虑到简单性,用了COPYDATASTRUCT结构
// 用内存映射应该会快一点
//-----------------------------------------------------------------
void sndmsg(char *buf)
{
COPYDATASTRUCT cds;
cds.dwData=sizeof(COPYDATASTRUCT);
cds.cbData=strlen(buf);
cds.lpData=buf;
SendMessage(g_hForm,WM_COPYDATA,(WPARAM)NULL,(LPARAM)&cds);
}






主窗体代码:
//---------------------------------------------------------------------------

#include
#pragma hdrstop

#include "main_Form.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "HexEdit"
#pragma resource "*.dfm"
TForm1 *Form1;

HINSTANCE hdll;
BOOL __stdcall (*InstallHook)();
BOOL __stdcall (*UninstallHook)();
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Application->OnHint=DisplayHint;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
g_dindex=0;

hdll = LoadLibrary("dll.dll");
if(hdll == NULL)
MessageBox(NULL, "LoadLibrary", "Error", MB_OK|MB_ICONERROR);
InstallHook = GetProcAddress(hdll, "InstallHook");
if(!InstallHook)
{
MessageBox(NULL, "InstallHook", "Error", MB_OK|MB_ICONERROR);
}
UninstallHook = GetProcAddress(hdll, "UninstallHook");
if(!UninstallHook)
{
MessageBox(NULL, "UninstallHook", "Error", MB_OK|MB_ICONERROR);
}
InstallHook();

startBtn->Enabled=false;
stopBtn->Enabled=true;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
g_dindex=0;
UninstallHook();
FreeLibrary(hdll);
startBtn->Enabled=true;
stopBtn->Enabled=false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::OnCopyData(TMessage &Msg)
{
COPYDATASTRUCT *cds=(COPYDATASTRUCT*)Msg.LParam;
AnsiString tmpbuf = (char *)cds->lpData;
TListItem *li=lv->Items->Add();
li->Caption=g_dindex;
if(tmpbuf.SubString(1, tmpbuf.Pos("|")-1).Pos("send")>0)
{
li->ImageIndex=1;
}
else
{
li->ImageIndex=0;
}

li->SubItems->Add(tmpbuf.SubString(1, tmpbuf.Pos("|")-1));
tmpbuf=tmpbuf.SubString(tmpbuf.Pos("|")+1, tmpbuf.Length());
li->SubItems->Add(tmpbuf.SubString(1, tmpbuf.Pos("|")-1));
tmpbuf=tmpbuf.SubString(tmpbuf.Pos("|")+1, tmpbuf.Length());
li->SubItems->Add(tmpbuf.SubString(1, tmpbuf.Pos("|")-1));
li->SubItems->Add(tmpbuf.SubString(tmpbuf.Pos("|")+1, tmpbuf.Length()));
}

void __fastcall TForm1::lvInsert(TObject *Sender, TListItem *Item)
{
g_dindex++;
lv->Perform(LVM_SCROLL,0,10);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::lvClick(TObject *Sender)
{
if(lv->ItemIndex < 0)
return;
HexEdit1->LoadFromBuffer(lv->Items->Item[lv->ItemIndex]->SubItems->Strings[3].c_str(),
lv->Items->Item[lv->ItemIndex]->SubItems->Strings[3].Length());
}
//---------------------------------------------------------------------------

void __fastcall TForm1::SpeedButton3Click(TObject *Sender)
{
lv->Clear();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
if(stopBtn->Enabled)
Button2Click(Sender);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::lvAdvancedCustomDrawItem(TCustomListView *Sender,
TListItem *Item, TCustomDrawState State, TCustomDrawStage Stage,
bool &DefaultDraw)
{
if(Item->ImageIndex==0)
{
lv->Canvas->Brush->Color = 0x00FFF5EC;
}
}
//---------------------------------------------------------------------------

void __fastcall TForm1::lvKeyUp(TObject *Sender, WORD &Key,
TShiftState Shift)
{
if(lv->ItemIndex < 0)
return;
HexEdit1->LoadFromBuffer(lv->Items->Item[lv->ItemIndex]->SubItems->Strings[3].c_str(),
lv->Items->Item[lv->ItemIndex]->SubItems->Strings[3].Length());
}
//---------------------------------------------------------------------------
void __fastcall TForm1::DisplayHint(TObject *Sender)
{
StatusBar1->SimpleText=GetLongHint(Application->Hint);
}

However, I do not want to hack socket.dll since other programs may also do the same thing. I just do not want to bother them.

3.
Use WinPcap
http://winpcap.polito.it/

That's too luxurious.

4.
Use IHttpNegotiate supported by URL moniker
http://msdn.microsoft.com/library/default.asp?url=/workshop/networking/moniker/reference/ifaces/ihttpnegotiate/
ihttpnegotiate.asp

There are not many smaples.

5.
Use virtual proxy

I prefer this method. A good starting point can be found at

Virtual Host Proxy Server
Franck JEANNIN June 23, 1999
http://www.codeguru.com/Cpp/I-N/internet/generalinternet/article.php/c3407/

The problem is the simple winsocket wrap socket class does not support Socket 5 and SSL. Thus, we need a more powerful tools

CAsyncSocketEx - Replacement for CAsyncSocket with proxy and SSL support
By Tim Kosse
http://www.codeproject.com/internet/casyncsocketex.asp

which support

PROXYTYPE_NOPROXY
PROXYTYPE_SOCKS4
PROXYTYPE_SOCKS4A
PROXYTYPE_SOCKS5
PROXYTYPE_HTTP11

6.
Use Asynchronous Pluggable Protocol

See

Asynchronous Pluggable Protocol Implementation with ATL
Dave Stone December 13, 1998
http://www.codeguru.com/Cpp/COM-Tech/atl/misc/article.php/c37

http://msdn.microsoft.com/workshop/networking/pluggable/pluggable.asp

Asynchronous Pluggable Protocols Reference
http://www.microsoft.com/workshop/networking/pluggable/reference/reference.asp

Asynchronous Pluggable Protocols Overview
http://www.microsoft.com/workshop/networking/pluggable/overview.asp

IInternetProtocolRoot
http://www.microsoft.com/workshop/networking/pluggable/reference/ifaces/
IInternetProtocolRoot/IInternetProtocolRoot.asp

IInternetProtocol
http://www.microsoft.com/workshop/networking/pluggable/reference/ifaces/
IInternetProtocol/IInternetProtocol.asp

IInternetProtocolSink
http://www.microsoft.com/workshop/networking/pluggable/reference/ifaces/
IInternetProtocolSink/IInternetProtocolSink.asp

Asynchronous Pluggable Protocol Implementation with ATL(按:这个简单)
http://www.codeguru.com/atl/asyncpp.shtml

附带说一下,IE打开PDF文件等也用了Asynchronous Pluggable Protocol技术,相对的Mozilla和Firefox则是直接yongshell。在Mozilla和Firefox里面,好像是检测到不能直接支持的MIME,就试图调用外部文件打开。有的时候,Mozilla自带的支持不为大家喜欢,所以只好自己动手删掉原有连接,比如下面的问题经常遇到
“Search for nppdf32.dll (the Adobe Acrobat Reader plug-in file) and delete it. Then Mozilla won't be able to find the plug-in, so it'll launch Adobe Acrobat as an external helper application to open the file.”

Shell:这种方式大家都不用了,太危险,参见下面的描述
http://www.eeye.com/html/Research/Advisories/AD20020308.html

Windows Shell Overflow

Release Date:
March 8, 2002

Severity:
Medium

Vendor:
Microsoft

Systems Affected:
Microsoft Windows 98
Microsoft Windows 98 Second Edition
Microsoft Windows NT 4.0
Microsoft Windows NT 4.0 Terminal Server Edition
Microsoft Windows 2000

Overview:
There exists a buffer-overflow vulnerability within the Microsoft Windows Shell that can lead to execution of malicious code. The vulnerability exists in the way the Windows Shell manipulates URL handlers that point to programs that do not exist.

The Windows Shell exposes functionality to allow developers to write their own custom URL handlers. For example, programs such as, ICQ, AIM, MS Conference, mIRC, Windows Media Player, and Outlook/Express install custom URL handlers so that functionality can be passed from a URL to a program. For instance, we could write a custom URL handler called "eeye", and then anytime someone performed a request for 'eeye://data' the data would be passed to whatever program was written to handle the "eeye" URL.

Technical Details:
The current problem arises when a URL handler has been mapped in the system registry to a program that does not exist.

The mapping to the URL handler is in the form of:
HKEY_CLASSES_ROOT\urlhandler\shell\open\command and whatever executable is pointed to by the (Default) registry key is the executable that handles that specific URL.

As an example, AOL Instant Messenger installs a URL handler to HKEY_CLASSES_ROOT\aim. The reason we know AIM is a URL handler is because the existence of the key "URL Protocol" tells the Windows Shell that Aim is a URL handler. By enumerating the registry for "URL Protocol" keys, we can determine all of the installed URL handlers. This allows us to identify a URL handler that is installed yet mapped to a non-existent program.

So if the AIM handler (HKEY_CLASSES_ROOT\aim\shell\open\command) was pointing to a file that did not exist, then that URL handler could be exploited via a buffer overflow via the data passed to the URL handler. For example: aim://overflow Where "overflow" is 324 or so bytes. This allows us to take control of EIP and control the flow of execution within the program, meaning we can make the victim machine execute any code we sen.

It is very important to clarify that this is not a problem within AIM or the URL handler program itself. The problem lies within vulnerable code in the Microsoft Windows Shell.

Certain URL handlers could become exploitable in the case that a program is uninstalled and the uninstaller does not cleanly remove the mapping in the registry, or if a user deletes a program folder which leaves the URL mapping to a invalid file.

On a default installation of Windows the buffer overflow does exist although exploiting it is impossible (as far as we know) because there are no default URL handlers pointing to files that don't exist. Over time, however, when programs are installed and removed a system can become vulnerable.

This vulnerability is a local vulnerability, but because of the integrated nature of Windows it is possible to exploit this vulnerability remotely using any program that supports URL. For instance, in order to get a system to process exploit URLs we could email an attack URL within an Outlook email, or we could put an attack URL within an "evil" web page that visitors are directed to.

When this vulnerability is exploited, locally or remotely, the exploit code will execute with the the same permissions of the user being attacked. So if the user executing the "evil" URL is Administrator, then the exploit code will execute as Administrator.

Because of differing variables, not all systems may be vulnerable to this buffer overflow; however, we still encourage all users to install the Microsoft patch as soon as possible.

CVE ID: CAN-2002-0070
This is a candidate for inclusion in the CVE list (http://cve.mitre.org) which provides standardized names for security problems.

Vendor Status:
Microsoft has released a patch and security bulletin which is located at:
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/MS02-014.asp

Credit:
Marc Maiffret

Related Links:
http://www.microsoft.com/technet/treeview/default.asp?url=/technet/security/bulletin/MS02-014.asp

Greetings:
Mr. Self Destruct and his Lollipop

Copyright (c) 1998-2004 eEye Digital Security
Permission is hereby granted for the redistribution of this alert electronically. It is not to be edited in any way without express consent of eEye. If you wish to reprint the whole or any part of this alert in any other medium excluding electronic medium, please email alert@eEye.com for permission.

Disclaimer
The information within this paper may change without notice. Use of this information constitutes acceptance for use in an AS IS condition. There are no warranties, implied or express, with regard to this information. In no event shall the author be liable for any direct or indirect damages whatsoever arising out of or in connection with the use or spread of this information. Any use of this information is at the user's own risk.



<< Home

This page is powered by Blogger. Isn't yours?