转份本地,见附件
========================================================
获取IE历史记录探究性学习
突然对此感兴趣,所以研究一下,顺便给大家献献丑.
在互联网上搜索相关代码,你会发现多半以删除历史记录类的代码为主,而真正实现获取的获取IE记录的比较少.
先说说常规方法:利用COM接口IUrlHistory接口实现访问.
翻阅SDK你会发现,MS对此的文档少的几乎无法使用,既无Example,而且连基本的CLSID也没有提供。当然对于一些方法的参数的调用说明也是有问题的,比如说明是Reserved,但是并没有制定要给定什么值,但实战中必须给1才能够正确调用。
这里就直接给一个网上的代码,很好理解。不作过多解释。
#include <stdio.h>
#include <windows.h>
#include <UrlHist.h> // IUrlHistoryStg2
#include <shlobj.h> // CLSID_CUrlHistory, SHAddToRecentDocs
#include <atlbase.h> // USES_CONVERSION;
void GetIEHistory()
......{
USES_CONVERSION;//Unicode转Ansi用
CoInitialize(NULL); //初始化
IUrlHistoryStg2* pUrlHistoryStg2 = NULL;
HRESULT hr = CoCreateInstance(CLSID_CUrlHistory,
NULL, CLSCTX_INPROC, IID_IUrlHistoryStg2,
(void**)&pUrlHistoryStg2);
/**//**//**//*if (SUCCEEDED(hr))
{
hr = pUrlHistoryStg2->ClearHistory();
pUrlHistoryStg2->Release();
}*/
IEnumSTATURL* pEnumURL;
hr = pUrlHistoryStg2->EnumUrls(&pEnumURL);
STATURL suURL;
ULONG pceltFetched;
suURL.cbSize = sizeof(suURL);
hr = pEnumURL->Reset();
while((hr = pEnumURL->Next(1, &suURL, &pceltFetched)) == S_OK)
......{
//hr = pUrlHistoryStg2->DeleteUrl(suURL.pwcsUrl, 0);
printf("%s ", W2T(suURL.pwcsUrl));
}
pEnumURL->Release();
pUrlHistoryStg2->Release();
CoUninitialize();
}
原文地址请见
http://blog.csdn.net/yzzm521/archive/2006/12/26/1462789.aspx
但这些能够找到的代码由一个问题:
如果你让上面的代码LOOP10次的话,你会惊奇的发现内存将会迅速上升,当然不会下降。这貌似就是传说中的内存泄露,但是翻阅整个关于这个接口的MSDN文档,并找不到任何有价值的信息,当然常规的IUnknown::Release肯定已经是执行了的。可以想见问题不是出在这里。
故需我们拿上秘密武器OllyDbg开始调试:
我们单步会发现在p_IEnumSTATURL->Next(1,&statUrl,&bSusFill);这个语句一旦执行内存就会上升。
当然这个方法是填充一个结构。而这个结构的定义
typedef struct _STATURL {
DWORD cbSize;
LPWSTR pwcsUrl;
LPWSTR pwcsTitle;
FILETIME ftLastVisited;
FILETIME ftLastUpdated;
FILETIME ftExpires;
DWORD dwFlags;
} STATURL, *LPSTATURL
如上
看这个结构中Offset + 04 和Offset + 08 两个字段是一个指针类型指向一个Unicode文本。按照猜测问题应该出在这里:
这个时候我们可以打开IDA来分析,当然直接用OD也是可以的,我们进入Next这个方法来到
6EE6AD2A <> 8BFF mov edi,edi ; CEnumSTATURL::Next(ulong,_STATURL *,ulong *)
6EE6AD2C . 55 push ebp
6EE6AD2D . 8BEC mov ebp,esp
6EE6AD2F . 53 push ebx
6EE6AD30 . 57 push edi
6EE6AD31 . 8B7D 14 mov edi,dword ptr ss:[ebp+14]
6EE6AD34 . 33DB xor ebx,ebx
6EE6AD36 . 33C0 xor eax,eax
6EE6AD38 . 3BFB cmp edi,ebx
6EE6AD3A . 74 02 je short ieframe.6EE6AD3E
6EE6AD3C . 891F mov dword ptr ds:[edi],ebx
6EE6AD3E > 395D 0C cmp dword ptr ss:[ebp+C],ebx
6EE6AD41 . 74 55 je short ieframe.6EE6AD98
6EE6AD43 . 56 push esi
6EE6AD44 . 8B75 08 mov esi,dword ptr ss:[ebp+8]
6EE6AD47 . 395E 10 cmp dword ptr ds:[esi+10],ebx
6EE6AD4A .^ 0F84 78FFFFFF je ieframe.6EE6ACC8
6EE6AD50 > 8BCE mov ecx,esi
6EE6AD52 . E8 4C000000 call <ieframe.CEnumSTATURL::RetrieveNextUrlInfo(void)>
6EE6AD57 . 3BC3 cmp eax,ebx
6EE6AD59 . 75 3C jnz short ieframe.6EE6AD97
6EE6AD5B . 8B8E 68100000 mov ecx,dword ptr ds:[esi+1068]
6EE6AD61 . 3BCB cmp ecx,ebx
6EE6AD63 . 74 32 je short ieframe.6EE6AD97
6EE6AD65 . FFB6 5C100000 push dword ptr ds:[esi+105C] ; /Arg3
6EE6AD6B . 8D46 14 lea eax,dword ptr ds:[esi+14] ; |
6EE6AD6E . FF71 04 push dword ptr ds:[ecx+4] ; |Arg2
6EE6AD71 . 50 push eax ; |Arg1
6EE6AD72 . E8 209E0800 call <ieframe.StrCmpNW(x,x,x)> ; \ieframe.6EEF4B97
6EE6AD77 . 85C0 test eax,eax
6EE6AD79 .^ 75 D5 jnz short ieframe.6EE6AD50
6EE6AD7B > FF75 10 push dword ptr ss:[ebp+10]
6EE6AD7E . FF76 0C push dword ptr ds:[esi+C]
6EE6AD81 . FFB6 68100000 push dword ptr ds:[esi+1068]
6EE6AD87 . 53 push ebx
6EE6AD88 . E8 1FDC0800 call <ieframe.CUrlHistory::s_GenerateSTATURL(ushort cons>
6EE6AD8D . 3BC3 cmp eax,ebx
6EE6AD8F . 7C 06 jl short ieframe.6EE6AD97
6EE6AD91 . 3BFB cmp edi,ebx
6EE6AD93 . 74 02 je short ieframe.6EE6AD97
6EE6AD95 . FF07 inc dword ptr ds:[edi]
6EE6AD97 > 5E pop esi
6EE6AD98 > 5F pop edi
6EE6AD99 . 5B pop ebx
6EE6AD9A . 5D pop ebp
6EE6AD9B . C2 1000 retn 10
分析上面三个CALL我们发现最后一个s_GenerateSTATUrl引起了我们的注意:
.text:75CD8A94 mov edi, 824h
.text:75CD8A99 push edi
.text:75CD8A9A lea eax, [ebp-104Ch]
.text:75CD8AA0 push eax
.text:75CD8AA1 push 16h
.text:75CD8AA3 call [EMAIL="?_GetStringProp@CHistoryData@@QBEJKPAGK@Z"]?_GetStringProp@CHistoryData@@QBEJKPAGK@Z[/EMAIL] ; CHistoryData::_GetStringProp(ulong,ushort *,ulong)
.text:75CD8AA8 test eax, eax
.text:75CD8AAA jge short loc_75CD8AC8
.text:75CD8AAC push 1 ; int
.text:75CD8AAE lea eax, [ebp-1050h]
.text:75CD8AB4 push eax ; int
.text:75CD8AB5 lea eax, [ebp-104Ch]
.text:75CD8ABB push eax ; unsigned __int16 *
.text:75CD8ABC push ebx ; int
.text:75CD8ABD mov [ebp-1050h], edi
.text:75CD8AC3 call [EMAIL="_PrepareURLForDisplayUTF8W@16"]_PrepareURLForDisplayUTF8W@16[/EMAIL] ; PrepareURLForDisplayUTF8W(x,x,x,x)
.text:75CD8AC8
.text:75CD8AC8 loc_75CD8AC8: ; CODE XREF: sub_75CD89B0+FAj
.text:75CD8AC8 lea eax, [esi+4]
.text:75CD8ACB push eax ; int
.text:75CD8ACC lea eax, [ebp-104Ch]
.text:75CD8AD2 push eax ; lpString
.text:75CD8AD3 call [EMAIL="_SHStrDupW@8"]_SHStrDupW@8[/EMAIL] ; SHStrDupW(x,x)
.text:75CD8AD8 mov [ebp-1050h], eax
.text:75CD8ADE
.text:75CD8ADE loc_75CD8ADE: ; CODE XREF: sub_75CD89B0-8D7F0j
.text:75CD8ADE ; sub_75CD89B0+CCj
.text:75CD8ADE test dword ptr [ebp+10h], 40000h
.text:75CD8AE5 jz short loc_75CD8AFE
在这个CALL中多次用到 SHStrDupW这个函数,熟悉C语言的朋友应该知道StrDup这个函数的用法,即便是查阅MSDN也会发现
Makes a copy of a string in newly allocated memory.
Syntax
HRESULT SHStrDup(
LPCTSTR pszSource,
LPTSTR *ppwsz
);
Parameters
pszSource
[in] A pointer to the null-terminated string to be copied.
ppwsz
[out] A pointer to an allocated Unicode string containing the result. SHStrDup allocates memory for this string with CoTaskMemAlloc. You should free the string with CoTaskMemFree when it is no longer needed.
我们需要用CoTaskMemFree释放内存
因此我们只需要简单得讲这两个字符串指针进行释放即可,代码如下:
void GetUrlHistoryMethod1()
{
HRESULT hr = ::CoInitialize(NULL);
IUrlHistoryStg * p_IUrlHistoryStg;
STATURL statUrl;
IEnumSTATURL * p_IEnumSTATURL;
hr = ::CoCreateInstance(
CLSID_CUrlHistory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IUrlHistoryStg,
(void **)&p_IUrlHistoryStg
);
if(!hr){
hr = p_IUrlHistoryStg->EnumUrls(&p_IEnumSTATURL);
if(!hr){
ULONG bSusFill = FALSE;
hr = p_IEnumSTATURL->Reset();
statUrl.cbSize = sizeof(statUrl);
hr = p_IEnumSTATURL->Next(1,&statUrl,&bSusFill);
int n = 0;
while(bSusFill && !hr)
{
/*
typedef struct _STATURL
{
DWORD cbSize;
LPWSTR pwcsUrl;
LPWSTR pwcsTitle;
FILETIME ftLastVisited;
FILETIME ftLastUpdated;
FILETIME ftExpires;
DWORD dwFlags;
} STATURL;
*/
printf(" [%d] Url : %S,Title : %S \r\n",n,statUrl.pwcsUrl,statUrl.pwcsTitle);
n++;
::CoTaskMemFree(statUrl.pwcsTitle);
::CoTaskMemFree(statUrl.pwcsUrl);
p_IEnumSTATURL->Next(1,&statUrl,&bSusFill);
}
p_IEnumSTATURL->Release();
}
p_IUrlHistoryStg->Release();
}
::CoFreeAllLibraries();
::CoUninitialize();
}
当然你会发现内存占用不会递增了。
不过如果你对这种半文档化东西不是十分放心的话,我们可以考虑文档化的东西,但这需要我们自己动一些脑精:
如果我们跟踪IUrlHistory接口的实现你会发现它本质上还是调用的WININET函数实现。因此我们只需要逆向这部分即可。接着先前贴的那段代码:
我们发现CEnumSTATURL::RetrieveNextUrlInfo(void) 这样一个名字比较引人注目
我们进入这个函数
[EMAIL="?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ"]?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ[/EMAIL] proc near
.text:75C4ADA3 ; CODE XREF: CEnumSTATURL::Next(ulong,_STATURL *,ulong *)+28p
.text:75C4ADA3 ; CEnumSTATURL::Next(ulong,_STATURL *,ulong *)+AC5C7p
.text:75C4ADA3
.text:75C4ADA3 var_4 = dword ptr -4
.text:75C4ADA3
.text:75C4ADA3 ; FUNCTION CHUNK AT .text:75C2A7B8 SIZE 00000041 BYTES
.text:75C4ADA3 ; FUNCTION CHUNK AT .text:75CF6F44 SIZE 00000043 BYTES
.text:75C4ADA3
.text:75C4ADA3 mov edi, edi
.text:75C4ADA5 push ebp
.text:75C4ADA6 mov ebp, esp
.text:75C4ADA8 push ecx
.text:75C4ADA9 and [ebp+var_4], 0
.text:75C4ADAD push esi
.text:75C4ADAE mov esi, ecx
.text:75C4ADB0 cmp dword ptr [esi+1068h], 0
.text:75C4ADB7 jz short loc_75C4ADDA
.text:75C4ADB9 push ebx
.text:75C4ADBA lea ebx, [esi+1064h]
.text:75C4ADC0 push edi
.text:75C4ADC1
.text:75C4ADC1 loc_75C4ADC1: ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+AC1B3j
.text:75C4ADC1 push ebx ; int
.text:75C4ADC2 push dword ptr [esi+1068h] ; int
.text:75C4ADC8 push dword ptr [esi+10h] ; hEnumHandle
.text:75C4ADCB call [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)
.text:75C4ADD0 test eax, eax
.text:75C4ADD2 jz loc_75C2A7B8
.text:75C4ADD8
.text:75C4ADD8 loc_75C4ADD8: ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)-205AFj
.text:75C4ADD8 ; CEnumSTATURL::RetrieveNextUrlInfo(void)+AC1C0j ...
.text:75C4ADD8 pop edi
.text:75C4ADD9 pop ebx
.text:75C4ADDA
.text:75C4ADDA loc_75C4ADDA: ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+14j
.text:75C4ADDA lea eax, [esi+1064h]
.text:75C4ADE0 mov edx, [eax]
.text:75C4ADE2 mov ecx, 3E8h
.text:75C4ADE7 cmp edx, ecx
.text:75C4ADE9 pop esi
.text:75C4ADEA ja loc_75CF6F80
.text:75C4ADF0
.text:75C4ADF0 loc_75C4ADF0: ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+AC1DFj
.text:75C4ADF0 mov [eax], ecx
.text:75C4ADF2 mov eax, [ebp+var_4]
.text:75C4ADF5 leave
.text:75C4ADF6 retn
.text:75C4ADF6 [EMAIL="?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ"]?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ[/EMAIL] endp
唯一一个Call:
; int __stdcall FindNextUrlCacheEntryBinary(HANDLE hEnumHandle,int,int)
.text:75C4ADFC [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] proc near
.text:75C4ADFC ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+28p
.text:75C4ADFC
.text:75C4ADFC var_1014 = dword ptr -1014h
.text:75C4ADFC var_1010 = dword ptr -1010h
.text:75C4ADFC uBytes = dword ptr -100Ch
.text:75C4ADFC var_1008 = dword ptr -1008h
.text:75C4ADFC NextCacheEntryInfo= _INTERNET_CACHE_ENTRY_INFOA ptr -1004h
.text:75C4ADFC var_4 = dword ptr -4
.text:75C4ADFC hEnumHandle = dword ptr 8
.text:75C4ADFC arg_4 = dword ptr 0Ch
.text:75C4ADFC arg_8 = dword ptr 10h
.text:75C4ADFC
.text:75C4ADFC ; FUNCTION CHUNK AT .text:75C2A792 SIZE 00000026 BYTES
.text:75C4ADFC ; FUNCTION CHUNK AT .text:75CF6DF5 SIZE 0000006E BYTES
.text:75C4ADFC
.text:75C4ADFC mov edi, edi
.text:75C4ADFE push ebp
.text:75C4ADFF mov ebp, esp
.text:75C4AE01 mov eax, 1014h
.text:75C4AE06 call __chkstk
.text:75C4AE0B mov eax, ___security_cookie
.text:75C4AE10 xor eax, ebp
.text:75C4AE12 mov [ebp+var_4], eax
.text:75C4AE15 mov eax, [ebp+arg_4]
.text:75C4AE18 and [ebp+var_1010], 0
.text:75C4AE1F push ebx
.text:75C4AE20 mov ebx, [ebp+hEnumHandle]
.text:75C4AE23 push esi
.text:75C4AE24 mov esi, [ebp+arg_8]
.text:75C4AE27 mov [ebp+var_1014], eax
.text:75C4AE2D mov eax, 1000h
.text:75C4AE32 push edi
.text:75C4AE33 mov [ebp+uBytes], eax
.text:75C4AE39 mov [ebp+NextCacheEntryInfo.dwStructSize], eax
.text:75C4AE3F lea eax, [ebp+uBytes]
.text:75C4AE45 push eax ; lpdwNextCacheEntryInfoBufferSize
.text:75C4AE46 lea edi, [ebp+NextCacheEntryInfo]
.text:75C4AE4C mov eax, edi
.text:75C4AE4E push eax ; lpNextCacheEntryInfo
.text:75C4AE4F push ebx ; hEnumHandle
.text:75C4AE50 call [EMAIL="_FindNextUrlCacheEntryA@12"]_FindNextUrlCacheEntryA@12[/EMAIL] ; FindNextUrlCacheEntryA(x,x,x)
.text:75C4AE55 test eax, eax
.text:75C4AE57 mov [ebp+var_1008], eax
.text:75C4AE5D jz loc_75C2A792
.text:75C4AE63
.text:75C4AE63 loc_75C4AE63: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-2064Fj
.text:75C4AE63 push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AE64 call [EMAIL="?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z"]?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z[/EMAIL] ; _ValidateHistoryData(_INTERNET_CACHE_ENTRY_INFOA *)
.text:75C4AE69 push dword ptr [esi] ; int
.text:75C4AE6B push [ebp+var_1014] ; struct _INTERNET_CACHE_ENTRY_INFOW *
.text:75C4AE71 push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AE72 call [EMAIL="?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z"]?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z[/EMAIL] ; CacheEntryInfoAToCacheEntryInfoW(_INTERNET_CACHE_ENTRY_INFOA *,_INTERNET_CACHE_ENTRY_INFOW *,int)
.text:75C4AE77 test eax, eax
.text:75C4AE79 jnz loc_75CF6E41
.text:75C4AE7F
.text:75C4AE7F loc_75C4AE7F: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-20649j
.text:75C4AE7F ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+AC056j
.text:75C4AE7F cmp [ebp+var_1010], 0
.text:75C4AE86 jnz loc_75CF6E57
.text:75C4AE8C
.text:75C4AE8C loc_75C4AE8C: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-20661j
.text:75C4AE8C ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+AC062j
.text:75C4AE8C mov ecx, [ebp+var_4]
.text:75C4AE8F mov eax, [ebp+var_1008]
.text:75C4AE95 pop edi
.text:75C4AE96 pop esi
.text:75C4AE97 xor ecx, ebp
.text:75C4AE99 pop ebx
.text:75C4AE9A call @__security_check_cookie@4 ; __security_check_cookie(x)
.text:75C4AE9F leave
.text:75C4AEA0 retn 0Ch
.text:75C4AEA0 [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] endp
它竟然就是调用的FindNextUrlCacheEntryA函数,而这个函数是文档化的:
其中这个函数会返回一个LPINTERNET_CACHE_ENTRY_INFO,得结构,这个结构中有我们要的大部分信息,但是却缺少一个十分重要的内容:也就是我们的历史记录的标题,因此我们还需要继续看
public: static long __stdcall CUrlHistory::s_GenerateSTATURL(unsigned short const *, struct _INTERNET_CACHE_ENTRY_INFOW *)
方法,用调试工具跟踪会发现:
loc_75CD8AFE: ; CODE XREF: CUrlHistory::s_GenerateSTATURL(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong,_STATURL *)+139j
.text:75CD8AFE mov ecx, [ebp+lpHistoryData]
.text:75CD8B04 test ecx, ecx
.text:75CD8B06 jz short loc_75CD8AE7
.text:75CD8B08 push 10h
.text:75CD8B0A call [EMAIL="?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z"]?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z[/EMAIL] ; CHistoryData::_FindExtra(uint)
.text:75CD8B0F test eax, eax
.text:75CD8B11 jz short loc_75CD8AE7
.text:75CD8B13 cmp byte ptr [eax+3], 1Fh
.text:75CD8B17 jnz short loc_75CD8AE7
.text:75CD8B19 lea ecx, [esi+8]
.text:75CD8B1C push ecx ; int
.text:75CD8B1D add eax, 4
.text:75CD8B20 push eax ; lpString
.text:75CD8B21 call [EMAIL="_SHStrDupW@8"]_SHStrDupW@8[/EMAIL] ; SHStrDupW(x,x)
.text:75CD8B26 test eax, eax
.text:75CD8B28 mov [ebp+var_1050], eax
.text:75CD8B2E jge short loc_75CD8AE7
.text:75CD8B30 jmp loc_75CF71F0
当到这里的时候,lpTitle就会出现了,因此核心点就是CHistoryData::_FindExtra(uint)函数。进而这个函数的THIS指针是一个由一个局部变量实现,向上翻阅这个变量的引用会发现:
.text:75CD89E7 push edx
.text:75CD89E8 call [EMAIL="?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z"]?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z[/EMAIL] ; CHistoryData::s_GetHistoryData(_INTERNET_CACHE_ENTRY_INFOW *)
.text:75CD89ED mov [ebp+lpHistoryData], eax
这个函数会对这个变量进行赋值操作,查找其参数会发现
.text:75CD89C5 mov edx, [ebp+LPINTERNET_CACHE_ENTRY_INFO]
.text:75CD89C8 test edx, edx
这个参数来自传入参数2,也就是除THIS指针以外的参数1。
push [ebp+lpStatUrl]
.text:75C4AD7E push dword ptr [esi+0Ch]
.text:75C4AD81 push dword ptr [esi+1068h]
.text:75C4AD87 push ebx
.text:75C4AD88 call [EMAIL="?s_GenerateSTATURL@CUrlHist"]?s_GenerateSTATURL@CUrlHist[/EMAIL]
调用的[esi+1068h],很显然是一个ClassMember。而这个只可能跟
mov ecx, esi
.text:75C4AD52 call [EMAIL="?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ"]?RetrieveNextUrlInfo@CEnumSTATURL@@AAEJXZ[/EMAIL] ; CEnumSTATURL::RetrieveNextUrlInfo(void)
有关因为ESI传递给ECX作为THIS指针
mov edi, edi
.text:75C4ADA5 push ebp
.text:75C4ADA6 mov ebp, esp
.text:75C4ADA8 push ecx
.text:75C4ADA9 and [ebp+var_4], 0
.text:75C4ADAD push esi
.text:75C4ADAE mov esi, ecx
.text:75C4ADB0 cmp dword ptr [esi+1068h], 0
.text:75C4ADB7 jz short loc_75C4ADDA
.text:75C4ADB9 push ebx
.text:75C4ADBA lea ebx, [esi+1064h]
.text:75C4ADC0 push edi
.text:75C4ADC1
.text:75C4ADC1 loc_75C4ADC1: ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+AC1B3j
.text:75C4ADC1 push ebx ; int
.text:75C4ADC2 push dword ptr [esi+1068h] ; int
.text:75C4ADC8 push dword ptr [esi+10h] ; hEnumHandle
.text:75C4ADCB call [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)
.text:75C4ADD0 test eax, eax
.text:75C4ADD2 jz loc_75C2A7B8
因此顺利找到引用
进入这个FindNextUrlCacheEntryBinary
.text:75C4ADFC ; int __stdcall FindNextUrlCacheEntryBinary(HANDLE hEnumHandle,int,int)
.text:75C4ADFC [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] proc near
.text:75C4ADFC ; CODE XREF: CEnumSTATURL::RetrieveNextUrlInfo(void)+28p
.text:75C4ADFC
.text:75C4ADFC var_1014 = dword ptr -1014h
.text:75C4ADFC var_1010 = dword ptr -1010h
.text:75C4ADFC uBytes = dword ptr -100Ch
.text:75C4ADFC var_1008 = dword ptr -1008h
.text:75C4ADFC NextCacheEntryInfo= _INTERNET_CACHE_ENTRY_INFOA ptr -1004h
.text:75C4ADFC var_4 = dword ptr -4
.text:75C4ADFC hEnumHandle = dword ptr 8
.text:75C4ADFC arg_4 = dword ptr 0Ch
.text:75C4ADFC arg_8 = dword ptr 10h
.text:75C4ADFC
.text:75C4ADFC ; FUNCTION CHUNK AT .text:75C2A792 SIZE 00000026 BYTES
.text:75C4ADFC ; FUNCTION CHUNK AT .text:75CF6DF5 SIZE 0000006E BYTES
.text:75C4ADFC
.text:75C4ADFC mov edi, edi
.text:75C4ADFE push ebp
.text:75C4ADFF mov ebp, esp
.text:75C4AE01 mov eax, 1014h
.text:75C4AE06 call __chkstk
.text:75C4AE0B mov eax, ___security_cookie
.text:75C4AE10 xor eax, ebp
.text:75C4AE12 mov [ebp+var_4], eax
.text:75C4AE15 mov eax, [ebp+arg_4]
.text:75C4AE18 and [ebp+var_1010], 0
.text:75C4AE1F push ebx
.text:75C4AE20 mov ebx, [ebp+hEnumHandle]
.text:75C4AE23 push esi
.text:75C4AE24 mov esi, [ebp+arg_8]
.text:75C4AE27 mov [ebp+var_1014], eax
.text:75C4AE2D mov eax, 1000h
.text:75C4AE32 push edi
.text:75C4AE33 mov [ebp+uBytes], eax
.text:75C4AE39 mov [ebp+NextCacheEntryInfo.dwStructSize], eax
.text:75C4AE3F lea eax, [ebp+uBytes]
.text:75C4AE45 push eax ; lpdwNextCacheEntryInfoBufferSize
.text:75C4AE46 lea edi, [ebp+NextCacheEntryInfo]
.text:75C4AE4C mov eax, edi
.text:75C4AE4E push eax ; lpNextCacheEntryInfo
.text:75C4AE4F push ebx ; hEnumHandle
.text:75C4AE50 call [EMAIL="_FindNextUrlCacheEntryA@12"]_FindNextUrlCacheEntryA@12[/EMAIL] ; FindNextUrlCacheEntryA(x,x,x)
.text:75C4AE55 test eax, eax
.text:75C4AE57 mov [ebp+var_1008], eax
.text:75C4AE5D jz loc_75C2A792
.text:75C4AE63
.text:75C4AE63 loc_75C4AE63: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-2064Fj
.text:75C4AE63 push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AE64 call [EMAIL="?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z"]?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z[/EMAIL] ; _ValidateHistoryData(_INTERNET_CACHE_ENTRY_INFOA *)
.text:75C4AE69 push dword ptr [esi] ; int
.text:75C4AE6B push [ebp+var_1014] ; struct _INTERNET_CACHE_ENTRY_INFOW *
.text:75C4AE71 push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AE72 call [EMAIL="?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z"]?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z[/EMAIL] ; CacheEntryInfoAToCacheEntryInfoW(_INTERNET_CACHE_ENTRY_INFOA *,_INTERNET_CACHE_ENTRY_INFOW *,int)
.text:75C4AE77 test eax, eax
.text:75C4AE79 jnz loc_75CF6E41
.text:75C4AE7F
.text:75C4AE7F loc_75C4AE7F: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-20649j
.text:75C4AE7F ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+AC056j
.text:75C4AE7F cmp [ebp+var_1010], 0
.text:75C4AE86 jnz loc_75CF6E57
.text:75C4AE8C
.text:75C4AE8C loc_75C4AE8C: ; CODE XREF: FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)-20661j
.text:75C4AE8C ; FindNextUrlCacheEntryBinary(void *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+AC062j
.text:75C4AE8C mov ecx, [ebp+var_4]
.text:75C4AE8F mov eax, [ebp+var_1008]
.text:75C4AE95 pop edi
.text:75C4AE96 pop esi
.text:75C4AE97 xor ecx, ebp
.text:75C4AE99 pop ebx
.text:75C4AE9A call @__security_check_cookie@4 ; __security_check_cookie(x)
.text:75C4AE9F leave
.text:75C4AEA0 retn 0Ch
.text:75C4AEA0 [EMAIL="?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindNextUrlCacheEntryBinary@@YGHPAXPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] endp
.text:75C4AEA0
.text:75C4AEA0 ; ---------------------------------------------------------------------------
.text:75C4AEA3 align 8
.text:75C4AEA8 ; [00000006 BYTES: COLLAPSED FUNCTION FindNextUrlCacheEntryA(x,x,x). PRESS KEYPAD "+" TO EXPAND]
.text:75C4AEAE db 5 dup(90h)
.text:75C4AEB3
.text:75C4AEB3 ; =============== S U B R O U T I N E =======================================
.text:75C4AEB3
.text:75C4AEB3 ; Attributes: bp-based frame
.text:75C4AEB3
.text:75C4AEB3 ; private: long __thiscall CEnumSTATURL::RetrieveFirstUrlInfo(void)
.text:75C4AEB3 [EMAIL="?RetrieveFirstUrlInfo@CEnumSTATURL@@AAEJXZ"]?RetrieveFirstUrlInfo@CEnumSTATURL@@AAEJXZ[/EMAIL] proc near
.text:75C4AEB3 ; CODE XREF: CEnumSTATURL::Next(ulong,_STATURL *,ulong *)-48p
.text:75C4AEB3
.text:75C4AEB3 var_8 = dword ptr -8
.text:75C4AEB3 var_4 = dword ptr -4
.text:75C4AEB3
.text:75C4AEB3 ; FUNCTION CHUNK AT .text:75CF6EC5 SIZE 0000007F BYTES
.text:75C4AEB3
.text:75C4AEB3 mov edi, edi
.text:75C4AEB5 push ebp
.text:75C4AEB6 mov ebp, esp
.text:75C4AEB8 push ecx
.text:75C4AEB9 push ecx
.text:75C4AEBA and [ebp+var_4], 0
.text:75C4AEBE push ebx
.text:75C4AEBF push esi
.text:75C4AEC0 push edi
.text:75C4AEC1 mov ebx, 3E8h
.text:75C4AEC6 mov esi, ecx
.text:75C4AEC8 push ebx ; uBytes
.text:75C4AEC9 lea edi, [esi+1064h]
.text:75C4AECF push 40h ; uFlags
.text:75C4AED1 mov [edi], ebx
.text:75C4AED3 call ds:__imp__LocalAlloc@8 ; LocalAlloc(x,x)
.text:75C4AED9 test eax, eax
.text:75C4AEDB mov [esi+1068h], eax
.text:75C4AEE1 jz loc_75CF6EC5
.text:75C4AEE7 push edi ; int
.text:75C4AEE8 lea ecx, [esi+14h]
.text:75C4AEEB push eax ; struct _INTERNET_CACHE_ENTRY_INFOW *
.text:75C4AEEC push ecx ; lpSrcStr
.text:75C4AEED
.text:75C4AEED loc_75C4AEED: ; CODE XREF: CEnumSTATURL::RetrieveFirstUrlInfo(void)+AC05Cj
.text:75C4AEED call [EMAIL="?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] ; FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)
.text:75C4AEF2 test eax, eax
.text:75C4AEF4 mov [esi+10h], eax
.text:75C4AEF7 jz loc_75CF6ED1
.text:75C4AEFD
.text:75C4AEFD loc_75C4AEFD: ; CODE XREF: CEnumSTATURL::RetrieveFirstUrlInfo(void)+AC019j
.text:75C4AEFD ; CEnumSTATURL::RetrieveFirstUrlInfo(void)+AC06Fj ...
.text:75C4AEFD mov eax, [edi]
.text:75C4AEFF cmp eax, ebx
.text:75C4AF01 ja loc_75CF6F3D
.text:75C4AF07
.text:75C4AF07 loc_75C4AF07: ; CODE XREF: CEnumSTATURL::RetrieveFirstUrlInfo(void)+AC08Cj
.text:75C4AF07 mov eax, [ebp+var_4]
.text:75C4AF0A mov [edi], ebx
.text:75C4AF0C pop edi
.text:75C4AF0D pop esi
.text:75C4AF0E pop ebx
.text:75C4AF0F leave
.text:75C4AF10 retn
.text:75C4AF10 [EMAIL="?RetrieveFirstUrlInfo@CEnumSTATURL@@AAEJXZ"]?RetrieveFirstUrlInfo@CEnumSTATURL@@AAEJXZ[/EMAIL] endp
.text:75C4AF10
.text:75C4AF10 ; ---------------------------------------------------------------------------
.text:75C4AF11 db 5 dup(90h)
.text:75C4AF16
.text:75C4AF16 ; =============== S U B R O U T I N E =======================================
.text:75C4AF16
.text:75C4AF16 ; Attributes: bp-based frame
.text:75C4AF16
.text:75C4AF16 ; int __stdcall FindFirstUrlCacheEntryBinary(LPCWSTR lpSrcStr,struct _INTERNET_CACHE_ENTRY_INFOW *,int)
.text:75C4AF16 [EMAIL="?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] proc near
.text:75C4AF16 ; CODE XREF: CEnumSTATURL::RetrieveFirstUrlInfo(void):loc_75C4AEEDp
.text:75C4AF16
.text:75C4AF16 var_1114 = dword ptr -1114h
.text:75C4AF16 uBytes = dword ptr -1110h
.text:75C4AF16 hEnumHandle = dword ptr -110Ch
.text:75C4AF16 FirstCacheEntryInfo= _INTERNET_CACHE_ENTRY_INFOA ptr -1108h
.text:75C4AF16 DstStr = byte ptr -108h
.text:75C4AF16 var_4 = dword ptr -4
.text:75C4AF16 lpSrcStr = dword ptr 8
.text:75C4AF16 arg_4 = dword ptr 0Ch
.text:75C4AF16 arg_8 = dword ptr 10h
.text:75C4AF16
.text:75C4AF16 ; FUNCTION CHUNK AT .text:75C4AFCC SIZE 0000000B BYTES
.text:75C4AF16 ; FUNCTION CHUNK AT .text:75CF6D67 SIZE 0000008E BYTES
.text:75C4AF16
.text:75C4AF16 mov edi, edi
.text:75C4AF18 push ebp
.text:75C4AF19 mov ebp, esp
.text:75C4AF1B mov eax, 1114h
.text:75C4AF20 call __chkstk
.text:75C4AF25 mov eax, ___security_cookie
.text:75C4AF2A xor eax, ebp
.text:75C4AF2C mov [ebp+var_4], eax
.text:75C4AF2F mov eax, [ebp+lpSrcStr]
.text:75C4AF32 push ebx
.text:75C4AF33 mov ebx, [ebp+arg_4]
.text:75C4AF36 push esi
.text:75C4AF37 mov esi, [ebp+arg_8]
.text:75C4AF3A push edi
.text:75C4AF3B push 104h ; cchMultiByte
.text:75C4AF40 lea ecx, [ebp+DstStr]
.text:75C4AF46 push ecx ; lpDstStr
.text:75C4AF47 push eax ; lpSrcStr
.text:75C4AF48 call [EMAIL="_SHUnicodeToAnsi@12"]_SHUnicodeToAnsi@12[/EMAIL] ; SHUnicodeToAnsi(x,x,x)
.text:75C4AF4D and [ebp+var_1114], 0
.text:75C4AF54 mov eax, 1000h
.text:75C4AF59 mov [ebp+uBytes], eax
.text:75C4AF5F mov [ebp+FirstCacheEntryInfo.dwStructSize], eax
.text:75C4AF65 lea eax, [ebp+uBytes]
.text:75C4AF6B push eax ; lpdwFirstCacheEntryInfoBufferSize
.text:75C4AF6C lea edi, [ebp+FirstCacheEntryInfo]
.text:75C4AF72 mov eax, edi
.text:75C4AF74 push eax ; lpFirstCacheEntryInfo
.text:75C4AF75 lea eax, [ebp+DstStr]
.text:75C4AF7B push eax ; lpszUrlSearchPattern
.text:75C4AF7C call [EMAIL="_FindFirstUrlCacheEntryA@12"]_FindFirstUrlCacheEntryA@12[/EMAIL] ; FindFirstUrlCacheEntryA(x,x,x)
.text:75C4AF81 test eax, eax
.text:75C4AF83 mov [ebp+hEnumHandle], eax
.text:75C4AF89 jz loc_75CF6D67
.text:75C4AF8F
.text:75C4AF8F loc_75C4AF8F: ; CODE XREF: FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+BDj
.text:75C4AF8F push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AF90 call [EMAIL="?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z"]?_ValidateHistoryData@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@@Z[/EMAIL] ; _ValidateHistoryData(_INTERNET_CACHE_ENTRY_INFOA *)
.text:75C4AF95 push dword ptr [esi] ; int
.text:75C4AF97 push ebx ; struct _INTERNET_CACHE_ENTRY_INFOW *
.text:75C4AF98 push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AF99 call [EMAIL="?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z"]?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACHE_ENTRY_INFOA@@PAU_INTERNET_CACHE_ENTRY_INFOW@@H@Z[/EMAIL] ; CacheEntryInfoAToCacheEntryInfoW(_INTERNET_CACHE_ENTRY_INFOA *,_INTERNET_CACHE_ENTRY_INFOW *,int)
.text:75C4AF9E mov ebx, eax
.text:75C4AFA0 test ebx, ebx
.text:75C4AFA2 jnz loc_75CF6DC8
.text:75C4AFA8
.text:75C4AFA8 loc_75C4AFA8: ; CODE XREF: FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+BFj
.text:75C4AFA8 ; FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+ABECEj
.text:75C4AFA8 cmp [ebp+var_1114], 0
.text:75C4AFAF jnz loc_75CF6DE9
.text:75C4AFB5
.text:75C4AFB5 loc_75C4AFB5: ; CODE XREF: FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+ABE5Aj
.text:75C4AFB5 ; FindFirstUrlCacheEntryBinary(ushort const *,_INTERNET_CACHE_ENTRY_INFOW *,ulong *)+ABEDAj
.text:75C4AFB5 mov ecx, [ebp+var_4]
.text:75C4AFB8 mov eax, [ebp+hEnumHandle]
.text:75C4AFBE pop edi
.text:75C4AFBF pop esi
.text:75C4AFC0 xor ecx, ebp
.text:75C4AFC2 pop ebx
.text:75C4AFC3 call @__security_check_cookie@4 ; __security_check_cookie(x)
.text:75C4AFC8 leave
.text:75C4AFC9 retn 0Ch
.text:75C4AFC9 [EMAIL="?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z"]?FindFirstUrlCacheEntryBinary@@YGPAXPBGPAU_INTERNET_CACHE_ENTRY_INFOW@@PAK@Z[/EMAIL] endp
这里根据PDB信息中的CacheEntryInfoAToCacheEntryInfoW可以猜测出这里就是进行Unicode-〉ANSI的转换操作,其中
push edi ; struct _INTERNET_CACHE_ENTRY_INFOA *
.text:75C4AE72 call [EMAIL="?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACH"]?CacheEntryInfoAToCacheEntryInfoW@@YGHPAU_INTERNET_CACH[/EMAIL]
的参数EDI来自
.text:75C4AE46 lea edi, [ebp+NextCacheEntryInfo]
.text:75C4AE4C mov eax, edi
.text:75C4AE4E push eax ; lpNextCacheEntryInfo
.text:75C4AE4F push ebx ; hEnumHandle
.text:75C4AE50 call [EMAIL="_FindNextUrlCacheEntryA@12"]_FindNextUrlCacheEntryA@12[/EMAIL] ; FindNextUrlCacheEntryA(x,x,x)
那么问题也就解决了
回到
CUrlHistory::s_GenerateSTATURL
函数,其中ARG.2我们就推测出应该是LPINTERNET_CACHE_ENTRY_INFOW
因此public: static class CHistoryData * __stdcall CHistoryData::s_GetHistoryData(struct _INTERNET_CACHE_ENTRY_INFOW *)
.text:75CD8434 [EMAIL="?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z"]?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z[/EMAIL] proc near
.text:75CD8434 ; CODE XREF: CUrlHistory::s_QueryUrlCommon(ushort const *,ushort const *,ulong,_STATURL *)+9Ap
.text:75CD8434 ; CommitHistoryData(CInternetShortcut *,IPropertyStore *)+F1p ...
.text:75CD8434
.text:75CD8434 arg_0 = dword ptr 8
.text:75CD8434
.text:75CD8434 ; FUNCTION CHUNK AT .text:75C4B1B3 SIZE 00000007 BYTES
.text:75CD8434 ; FUNCTION CHUNK AT .text:75CF6D17 SIZE 00000012 BYTES
.text:75CD8434
.text:75CD8434 mov edi, edi
.text:75CD8436 push ebp
.text:75CD8437 mov ebp, esp
.text:75CD8439 mov eax, [ebp+arg_0]
.text:75CD843C mov eax, [eax+_INTERNET_CACHE_ENTRY_INFOW.lpHeaderInfo]
.text:75CD843F test eax, eax
.text:75CD8441 jz short loc_75CD845E
.text:75CD8443 movzx ecx, word ptr [eax]
.text:75CD8446 cmp ecx, 14h
.text:75CD8449 jz loc_75CF6D17
.text:75CD844F
.text:75CD844F loc_75CD844F: ; CODE XREF: CHistoryData::s_GetHistoryData(_INTERNET_CACHE_ENTRY_INFOW *)+1E8E8j
.text:75CD844F ; CHistoryData::s_GetHistoryData(_INTERNET_CACHE_ENTRY_INFOW *)+1E8F0j
.text:75CD844F test eax, eax
.text:75CD8451 jz short loc_75CD845E
.text:75CD8453 cmp word ptr [eax+2], 2
.text:75CD8458 jnz loc_75C4B1B3
.text:75CD845E
.text:75CD845E loc_75CD845E: ; CODE XREF: CHistoryData::s_GetHistoryData(_INTERNET_CACHE_ENTRY_INFOW *)-8D27Fj
.text:75CD845E ; CHistoryData::s_GetHistoryData(_INTERNET_CACHE_ENTRY_INFOW *)+Dj ...
.text:75CD845E pop ebp
.text:75CD845F retn 4
.text:75CD845F [EMAIL="?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z"]?s_GetHistoryData@CHistoryData@@SGPAV1@PAU_INTERNET_CACHE_ENTRY_INFOW@@@Z[/EMAIL] endp
显然是返回lpHeaderInfo
逆向:CHistoryData::_FindExtra(uint)
[EMAIL="?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z"]?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z[/EMAIL] proc near
.text:75CD8408 ; CODE XREF: CUrlHistory::AddUrlAndNotifyCP(ushort const *,ushort const *,ulong,int,IOleCommandTarget *,IUnknown *,uint *)-40920p
.text:75CD8408 ; CHistoryData::_HasFragment(ushort const *)+Ap ...
.text:75CD8408
.text:75CD8408 arg_0 = dword ptr 8
.text:75CD8408
.text:75CD8408 ; FUNCTION CHUNK AT .text:75CD8475 SIZE 00000004 BYTES
.text:75CD8408
.text:75CD8408 mov edi, edi
.text:75CD840A push ebp
.text:75CD840B mov ebp, esp
.text:75CD840D mov eax, [ecx]
.text:75CD840F mov edx, 0FFFFh
.text:75CD8414 push esi
.text:75CD8415 and eax, edx
.text:75CD8417
.text:75CD8417 loc_75CD8417: ; CODE XREF: CHistoryData::_FindExtra(uint)+20j
.text:75CD8417 add eax, ecx
.text:75CD8419 jz short loc_75CD8475
.text:75CD841B mov ecx, [eax]
.text:75CD841D and ecx, edx
.text:75CD841F jz short loc_75CD8475
.text:75CD8421 movzx esi, byte ptr [eax+2]
.text:75CD8425 cmp esi, [ebp+arg_0]
.text:75CD8428 jnz short loc_75CD8417
.text:75CD842A
.text:75CD842A loc_75CD842A: ; CODE XREF: CHistoryData::_FindExtra(uint)+6Fj
.text:75CD842A pop esi
.text:75CD842B pop ebp
.text:75CD842C retn 4
.text:75CD842C [EMAIL="?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z"]?_FindExtra@CHistoryData@@QBEPBUHISTEXTRA@@I@Z[/EMAIL] endp
调用参数,以及实际文本指针偏移
test eax, eax
.text:75CD8B11 jz short loc_75CD8AE7
.text:75CD8B13 cmp byte ptr [eax+3], 1Fh
.text:75CD8B17 jnz short loc_75CD8AE7
.text:75CD8B19 lea ecx, [esi+8]
.text:75CD8B1C push ecx ; int
.text:75CD8B1D add eax, 4
.text:75CD8B20 push eax ; lpString
代码如下:
//Powered by fOx,转载请保留作者信息 : Email [EMAIL="Destiny-fOx@hotmail.com"]Destiny-fOx@hotmail.com[/EMAIL]
LPBYTE p = (LPBYTE)(pInfo->lpHeaderInfo);
p += *(PWORD)p;
if(p != NULL)
if(p[2] != 0x10)
p = NULL;
else
{
if(p[3] == 0x1F)
p += 4;
else
p = NULL;
}
至此我们就得到了文本指针,但如果跟踪发现
即时你使用的是FindNextUrlCacheEntryA
函数这个文本也是一个Unicode。当然我想具体原因应该是这里的HeaderInfo应该是存在硬盘上的原始数据,当然这里就不会进行文本转换。因此默认格式是Unicode。
贴一个完整代码:
//Powered by fOx,转载请保留作者信息 : Email [EMAIL="Destiny-fOx@hotmail.com"]Destiny-fOx@hotmail.com[/EMAIL]
void GetUrlHistoryMethod2()
{
HANDLE hFind = NULL;
DWORD dwSize = NULL;
hFind = ::FindFirstUrlCacheEntryA("visited:",NULL,&dwSize);
HANDLE hHeap = ::HeapCreate(NULL,0x100,0x10000000);
LPINTERNET_CACHE_ENTRY_INFOA pInfo = (LPINTERNET_CACHE_ENTRY_INFOA)::HeapAlloc(hHeap,LPTR,dwSize);
hFind = ::FindFirstUrlCacheEntryA("visited:",pInfo,&dwSize);
if(hFind)
{
int n = 0;
while(pInfo != NULL)
{
/*
typedef struct _INTERNET_CACHE_ENTRY_INFOA {
DWORD dwStructSize; // version of cache system.0
LPSTR lpszSourceUrlName; // embedded pointer to the URL name string.4
LPSTR lpszLocalFileName; // embedded pointer to the local file name.8
DWORD CacheEntryType; // cache type bit mask.C
DWORD dwUseCount; // current users count of the cache entry.10
DWORD dwHitRate; // num of times the cache entry was retrieved.
DWORD dwSizeLow; // low DWORD of the file size.
DWORD dwSizeHigh; // high DWORD of the file size.
FILETIME LastModifiedTime; // last modified time of the file in GMT format.
FILETIME ExpireTime; // expire time of the file in GMT format
FILETIME LastAccessTime; // last accessed time in GMT format
FILETIME LastSyncTime; // last time the URL was synchronized
// with the source
LPSTR lpHeaderInfo; // embedded pointer to the header info.
DWORD dwHeaderInfoSize; // size of the above header.
LPSTR lpszFileExtension; // File extension used to retrive the urldata as a file.
union { // Exemption delta from last access time.
DWORD dwReserved;
DWORD dwExemptDelta;
}; // Exemption delta from last access
} INTERNET_CACHE_ENTRY_INFOA, * LPINTERNET_CACHE_ENTRY_INFOA;
*/
LPBYTE p = (LPBYTE)(pInfo->lpHeaderInfo);
p += *(PWORD)p;
if(p != NULL)
if(p[2] != 0x10)
p = NULL;
else
{
if(p[3] == 0x1F)
p += 4;
else
p = NULL;
}
printf("[%d] SourceUrlName : %s ,LocalFileName : %s Title : %S \r\n"
,n,pInfo->lpszSourceUrlName,pInfo->lpszLocalFileName,p);
n++;
pInfo = NULL;
dwSize = 1000;
pInfo = (LPINTERNET_CACHE_ENTRY_INFOA)::HeapAlloc(hHeap,LPTR,dwSize);
if(pInfo == NULL)
{
DWORD dwError = ::GetLastError();
printf("HeapAlloc Error : %d\r\n",dwError);
}
BOOL bSus = ::FindNextUrlCacheEntryA(hFind,pInfo,&dwSize);
if(bSus == FALSE)
{
pInfo = NULL;
DWORD dwError = ::GetLastError();
printf("Error : %d\r\n",dwError);
}
}
::FindCloseUrlCache(hFind);
::HeapDestroy(hHeap);
}
}
以上代码在Windows Vista Ultimate. IE 7.0 测试成功。至于其他版本是否也正确希望大家帮忙验证。当然Windows Xp 也是可以的。至于这种方法的优点也比较显然,首先是节约了必要的资源开销,至少不会加载OLE库,和COM自动化,初始化这两个库实际上也是比较占用时间的。其次加快调用速度,避免内存重复复制带来的开销,毕竟一般电脑上的历史数据是非常多的,即便是那么一点点也是有好处的。不过缺点就是HeaderInfo是未文档化的,将来的版本可能会改变。
Powered by fOx
Email:Destiny-fOx@hotmail.com
转载请保留作者信息,谢谢