「Internet Explorer7 の認証パスワードとオートコンプリートの操作」(4) オートコンプリートによるパスワード (2) | ScanNetSecurity
2024.03.29(金)

「Internet Explorer7 の認証パスワードとオートコンプリートの操作」(4) オートコンプリートによるパスワード (2)

執筆:SapporoWorks
http://homepage2.nifty.com/spw/

特集 特集
執筆:SapporoWorks
http://homepage2.nifty.com/spw/

Internet Explorer(以下IE)では、認証パスワードを「保存する」に設定していた場合や、オートコンプリートを有効にしている場合、それぞれのデータがコンピュータに保存されます。これらのデータの操作方法については、正式に公開されている訳では有りませんでしたが、IE 4.01 より前のものは、WnetEnumCachedPasswords(※1)、以降のものは、IPStoreインターフェース(※2)を使用したProtected Storageサービスで操作が可能なことが知られておりました。

Internet Explorerの認証パスワードとオートコンプリートの操作
http://codezine.jp/a/article.aspx?aid=147

今回、IEが7にバージョンアップされたことにより、この保存形式が全面的に変更され従来の方法では読み出せなくなってしまいました。本稿では、IE7でこれらのデータを操作する方法を解説します。なお、本稿は、C++言語、MicrosoftのPlatform SDK、及びMSDNライブラリの知識がある方を対象とさせて頂いております。本稿で使用したサンプルコード・実行ファイルや、実際のプログラムへの実装は、下記で行っておりますので、併せて参照いただければ幸いです。

本稿のサポートページ
http://www.sapporoworks.ne.jp/ie7_pass/
サンプルコードは、Microsoft Visual Studio 2005 C++ で作成され、
WindowsXP(SP2)で動作を確認しております。

HideSeek Ver2.1.0以降でIE7に対応
http://homepage2.nifty.com/spw/software/hideseek/

※1 WnetEnumCachedPasswords
:WnetEnumCachedPasswordsは、非公開APIであるためmpr.dllからGetProcAddressでアドレスを取得して使用できます。

※2 IPStoreインターフェース
http://msdn.microsoft.com/library/en-us/devnotes/winprog/ipstore.asp

────

>>オートコンプリートによるパスワード その2

対象となっているレジストリキー[Storage2]に、含まれる値をすべて列挙し、URL履歴の一覧から導出したハッシュ文字列と比較して、同一であった場合は、そのURLをパスワードとしてレジストリ値をデコードします。デコードはCryptUnprotectDataで行いますが、要領は、Web認証パスワードの時と同じです。

下記のコードは、その動作を実装したものです。

──────────────────────────────────
void main(int argc,char* argv[])
{
// 履歴からURLを取得する
wchar_t *UrlHistory[URL_HISTORY_MAX];
int UrlListoryMax = GetUrlHistory(UrlHistory);

char *KeyStr = {"Software\Microsoft\Internet Explorer\IntelliForms\Storage2"};
HKEY hKey;
// 対象レジストリの値を列挙する
if(ERROR_SUCCESS==RegOpenKeyEx(HKEY_CURRENT_USER,KeyStr,0,KEY_QUERY_VALUE,&hKey)){
for(int i=0;;i++){
char Val[1024];
DWORD Size = 1024;
if(ERROR_NO_MORE_ITEMS==RegEnumValue(hKey,i,Val, &Size, NULL,NULL, NULL,
NULL))
break;
// 取得したレジストリの値名と履歴URLのハッシュ値を比較する
for(int n=0;n char HashStr[1024];
// URLをパスワードとしてハッシュを計算する
GetHashStr(UrlHistory[n],HashStr);
if(strcmp(Val,HashStr)==0){// パスワード(URL)を発見
printf("ur : %ls",UrlHistory[n]);
printf("hash : %s",HashStr);
// 対象レジストリからデータを取得する
DWORD BufferLen;
DWORD dwType;
RegQueryValueEx(hKey,Val,0,&dwType,NULL,&BufferLen);
BYTE *Buffer = new BYTE[BufferLen];

if(RegQueryValueEx(hKey,Val,0,&dwType,Buffer,&BufferLen)==ERROR_SUCCESS){
DATA_BLOB DataIn;
DATA_BLOB DataOut;
DATA_BLOB OptionalEntropy;
DataIn.pbData = Buffer;
DataIn.cbData = BufferLen;
OptionalEntropy.pbData = (unsigned char *)UrlHistory[n];
OptionalEntropy.cbData = (wcslen(UrlHistory[n])+1)*2;
//プロテクト解除

if(CryptUnprotectData(&DataIn,0,&OptionalEntropy,NULL,NULL,1,&DataOut)){
PrintData((char *)DataOut.pbData);// デコードしたデータの表示
LocalFree(DataOut.pbData);
}
delete [] Buffer;
}
break;
}
}
}
RegCloseKey(hKey);
}
}
──────────────────────────────────

デコードされたデータの内部構造は、次のようになっています…

【執筆:SapporoWorks】

──
(この記事には続きがあります。続きはScan本誌をご覧ください)
http://www.ns-research.jp/cgi-bin/ct/p.cgi?m-sc_netsec
《ScanNetSecurity》

Scan PREMIUM 会員限定記事

もっと見る

Scan PREMIUM 会員限定記事特集をもっと見る

カテゴリ別新着記事

「経理」「営業」「企画」「プログラミング」「デザイン」と並ぶ、事業で成功するためのビジネスセンスが「セキュリティ」
「経理」「営業」「企画」「プログラミング」「デザイン」と並ぶ、事業で成功するためのビジネスセンスが「セキュリティ」

ページ右上「ユーザー登録」から会員登録すれば会員限定記事を閲覧できます。毎週月曜の朝、先週一週間のセキュリティ動向を総括しふりかえるメルマガをお届け。(写真:ScanNetSecurity 名誉編集長 りく)

×