「Internet Explorer7 の認証パスワードとオートコンプリートの操作」(4) オートコンプリートによるパスワード (2) | ScanNetSecurity[国内最大級のサイバーセキュリティ専門ポータルサイト]
2018.11.14(水)

「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 会員限定記事特集をもっと見る

カテゴリ別新着記事

(。・ω・)ゞ !!11月末迄 ScanNetSecurity創刊20周年特別キャンペーン実施中。会員限定 PREMIUM 記事読み放題。現在通常料金半額以下!!
(。・ω・)ゞ !!11月末迄 ScanNetSecurity創刊20周年特別キャンペーン実施中。会員限定 PREMIUM 記事読み放題。現在通常料金半額以下!!

サイバーセキュリティの専門誌 ScanNetSecurity は 1998年の創刊から20周年を迎え、感謝を込めた特別キャンペーンを実施中。創刊以来史上最大割引率。次は30周年が来るまでこの価格はもうありません!

×