|
PasswordChar(*)に隠れた実際のパスワードを表示するサンプル(VB.NET)

|
<このサンプルの概要>
以前自分で入力したパスワードを忘れてしまい困った事が無いでしょうか?
パスワードの設定画面を見てもパスワードがアスタリスク(***)に変換されて表示されるため確認出来ません。
そんな時に役立つのが「パスワードを見るツール」ですが、ブラウザ以外のウィンドウで表示されている
パスワードは意外に簡単に表示する事が出来ます。このサンプルはその「パスワードを見るサンプル」です。
パスワード表示&管理ツールはこのサンプルを元にブラウザ(IE)のパスワードを表示出来るようにしたツールです。
パスワードが見れた後はパスワードをデータベースに登録して管理したくなると思うので、パスワード管理ツールと
連携する機能があります。
具体的にはPasswordChar(*)が設定されたTextBoxから実際のパスワードを取得し表示します。
このサンプルのポイントとなるキーワードは以下の通りです。
(1)PostMessage
(2)SendMessage
(3)EM_GETPASSWORDCHAR
(4)EM_SETPASSWORDCHAR
このサンプルには含まれていませんが、IEのパスワードを調べる方法の概略は以下の通りです。
(1)ブラウザ(IE)のクラス名[Internet Explorer_Server]を探す。
(2)[WM_HTML_GETOBJECT]メッセージを[Internet Explorer_Server]に送る。
(3)[IID_IHTMLDocument]オブジェクトを取得する。
(4)[IID_IHTMLDocument]オブジェクトの[getElementsByTagName]で全てのタグを取得する。
(5)[INPUT]タグの[TYPE]が[password]のものからパスワードを取得する。
ただし(4)、(5)の処理を全てのフレームに対し実行する必要があります。IEのパスワードを表示するツール
の中にはフレーム未対応のものがあり、そのツールでは表示出来無いパスワードがありました。
※転載等色々禁止させてください。
※個人利用の参考としてのみご覧ください。
※決して悪用はしないでください。
★標準モジュール(Module1.vb)
Module Module1
' APIの定義
Private Const WM_GETTEXT = &HD
Private Const EM_GETPASSWORDCHAR = &HD2
Private Const EM_SETPASSWORDCHAR = &HCC
Private Delegate Function D_EnumWindowsProc *** As Integer
Private Delegate Function D_EnumChildWindowsProc *** As Integer
Private Declare Function EnumWindows Lib "user32.dll" (ByVal lpEnumFunc As D_EnumWindowsProc, ByVal lParam As Integer) As Integer
Private Declare Function EnumChildWindows Lib "user32.dll" (ByVal hwndParent As Integer, ByVal lpEnumFunc As D_EnumChildWindowsProc, ByVal lParam As Integer) As Integer
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Byte()) As Integer
Private Declare Function PostMessage Lib "user32.dll" Alias "PostMessageA" (ByVal hWnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Byte()) As Integer
' パスワードを取得するコレクション
Private colPasswd As New Collection
' 表示中の全てのパスワードを取得
Public Function GetAllPasswd() As Collection
Try
' パスワードを取得するコレクション初期化
colPasswd.Clear()
' トップレベルウィンドウの全てハンドル取得して、そこに属するパスワードを全て取得
Dim intRet As Integer = EnumWindows(AddressOf EnumWindowsProc, 0)
Catch ex As Exception
End Try
' リターン
Return colPasswd
End Function
' トップレベルウィンドウの全てハンドル取得して、そこに属するパスワードを全て取得
Public Function EnumWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
Try
' 指定された親ウィンドウに属するパスワードを全て取得
Dim intRet As Integer = EnumChildWindows(hWnd, AddressOf EnumChildWindowsProc, 0)
Catch ex As Exception
End Try
' リターン
Return 1
End Function
' 指定された親ウィンドウに属するパスワードを全て取得
Private Function EnumChildWindowsProc(ByVal hWnd As Integer, ByVal lParam As Integer) As Integer
Try
Dim bytPasswd As Byte() = New Byte(255) {}
Dim strPasswd As String = ""
Dim intRet As Integer
' パスワード文字が設定されているかチェック
Dim pch As Integer = SendMessage(hWnd, EM_GETPASSWORDCHAR, 0, Nothing)
If pch <> 0 Then
' パスワード文字を無効
For i As Integer = 0 To 10
PostMessage(hWnd, EM_SETPASSWORDCHAR, 0, Nothing)
Application.DoEvents()
If SendMessage(hWnd, EM_GETPASSWORDCHAR, 0, Nothing) = 0 Then Exit For
System.Threading.Thread.Sleep(100)
Next
' パスワード文字列取得
intRet = SendMessage(hWnd, WM_GETTEXT, 255, bytPasswd)
strPasswd = StripNulls(bytPasswd)
' パスワード文字を有効
For i As Integer = 0 To 10
PostMessage(hWnd, EM_SETPASSWORDCHAR, pch, Nothing)
Application.DoEvents()
If SendMessage(hWnd, EM_GETPASSWORDCHAR, 0, Nothing) = pch Then Exit For
System.Threading.Thread.Sleep(100)
Next
' パスワードを取得するコレクションにパスワードを追加
If strPasswd <> "" Then
colPasswd.Add(strPasswd)
End If
End If
Catch ex As Exception
End Try
' リターン
Return 1
End Function
' 文字列からNULL文字以降をカット
Private Function StripNulls(ByVal bytOrg As Byte()) As String
Dim strOrg As String = ""
Try
strOrg = System.Text.Encoding.GetEncoding("SHIFT-JIS").GetString(bytOrg)
Dim pt As Integer = strOrg.IndexOf(Chr(0))
If pt >= 0 Then
strOrg = strOrg.Substring(0, pt)
End If
Catch ex As Exception
End Try
Return strOrg
End Function
End Module
★フォームモジュール(Form1.vb)
Public Class Form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' 表示中の全てのパスワードを取得
Dim colPasswd As Collection
colPasswd = GetAllPasswd()
' パスワード有無チェック
If colPasswd.Count <= 0 Then
MessageBox.Show("パスワードはありませんでした。")
Return
End If
' パスワード毎のコレクションループ
For i As Integer = 1 To colPasswd.Count
' パスワードの表示
MessageBox.Show(colPasswd.Item(i))
Next i
End Sub
End Class