这两天看了看1password感觉不错,准备把Chrome密码迁移过去

然后发现1password不支持导入chrome的密码于是写了个工具来辅助导入

不多说代码如下:

Public Class DPAPI
    ' Wrapper for DPAPI CryptProtectData function.
    <DllImport("crypt32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function CryptProtectData _
    ( _
        ByRef pPlainText As DATA_BLOB, _
        ByVal szDescription As String, _
        ByRef pEntropy As DATA_BLOB, _
        ByVal pReserved As IntPtr, _
        ByRef pPrompt As CRYPTPROTECT_PROMPTSTRUCT, _
        ByVal dwFlags As Integer, _
        ByRef pCipherText As DATA_BLOB _
    ) As Boolean
    End Function
    ' Wrapper for DPAPI CryptUnprotectData function.
    <DllImport("crypt32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Shared Function CryptUnprotectData _
    ( _
        ByRef pCipherText As DATA_BLOB, _
        ByRef pszDescription As String, _
        ByRef pEntropy As DATA_BLOB, _
        ByVal pReserved As IntPtr, _
        ByRef pPrompt As CRYPTPROTECT_PROMPTSTRUCT, _
        ByVal dwFlags As Integer, _
        ByRef pPlainText As DATA_BLOB _
    ) As Boolean
    End Function
    ' BLOB structure used to pass data to DPAPI functions.
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Friend Structure DATA_BLOB
        Public cbData As Integer
        Public pbData As IntPtr
    End Structure
    ' Prompt structure to be used for required parameters.
    <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)> _
    Friend Structure CRYPTPROTECT_PROMPTSTRUCT
        Public cbSize As Integer
        Public dwPromptFlags As Integer
        Public hwndApp As IntPtr
        Public szPrompt As String
    End Structure
    ' DPAPI key initialization flags.
    Private Const CRYPTPROTECT_UI_FORBIDDEN As Integer = 1
    Private Const CRYPTPROTECT_LOCAL_MACHINE As Integer = 4
    ' <summary>
    ' Initializes empty prompt structure.
    ' </summary>
    ' <param name="ps">
    ' Prompt parameter (which we do not actually need).
    ' </param>
    Private Shared Sub InitPrompt _
    ( _
        ByRef ps As CRYPTPROTECT_PROMPTSTRUCT _
    )
        ps.cbSize = Marshal.SizeOf(GetType(CRYPTPROTECT_PROMPTSTRUCT))
        ps.dwPromptFlags = 0
        ps.hwndApp = IntPtr.Zero
        ps.szPrompt = Nothing
    End Sub
    ' <summary>
    ' Initializes a BLOB structure from a byte array.
    ' </summary>
    ' <param name="data">
    ' Original data in a byte array format.
    ' </param>
    ' <param name="blob">
    ' Returned blob structure.
    ' </param>
    Private Shared Sub InitBLOB _
    ( _
        ByVal data As Byte(), _
        ByRef blob As DATA_BLOB _
    )
        ' Use empty array for null parameter.
        If data Is Nothing Then
            data = New Byte(0) {}
        End If
        ' Allocate memory for the BLOB data.
        blob.pbData = Marshal.AllocHGlobal(data.Length)
        ' Make sure that memory allocation was successful.
        If blob.pbData.Equals(IntPtr.Zero) Then
            Throw New Exception( _
                    "Unable to allocate data buffer for BLOB structure.")
        End If
        ' Specify number of bytes in the BLOB.
        blob.cbData = data.Length
        Marshal.Copy(data, 0, blob.pbData, data.Length)
    End Sub
    ' <summary>
    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    ' This function does not use additional entropy and does not
    ' return data description.
    ' </summary>
    ' <param name="cipherText">
    ' Encrypted data formatted as a base64-encoded string.
    ' </param>
    ' <returns>
    ' Decrypted data returned as a UTF-8 string.
    ' </returns>
    ' <remarks>
    ' When decrypting data, it is not necessary to specify which
    ' type of encryption key to use: user-specific or
    ' machine-specific; DPAPI will figure it out by looking at
    ' the signature of encrypted data.
    ' </remarks>
    Public Shared Function Decrypt _
    ( _
        ByVal cipherText As String _
    ) As String
        Dim description As String
        Return Decrypt(cipherText, String.Empty, description)
    End Function
    ' <summary>
    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    ' This function does not use additional entropy.
    ' </summary>
    ' <param name="cipherText">
    ' Encrypted data formatted as a base64-encoded string.
    ' </param>
    ' <param name="description">
    ' Returned description of data specified during encryption.
    ' </param>
    ' <returns>
    ' Decrypted data returned as a UTF-8 string.
    ' </returns>
    ' <remarks>
    ' When decrypting data, it is not necessary to specify which
    ' type of encryption key to use: user-specific or
    ' machine-specific; DPAPI will figure it out by looking at
    ' the signature of encrypted data.
    ' </remarks>
    Public Shared Function Decrypt _
    ( _
        ByVal cipherText As String, _
        ByRef description As String _
    ) As String
        Return Decrypt(cipherText, String.Empty, description)
    End Function
    ' <summary>
    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    ' </summary>
    ' <param name="cipherText">
    ' Encrypted data formatted as a base64-encoded string.
    ' </param>
    ' <param name="entropy">
    ' Optional entropy, which is required if it was specified during
    ' encryption.
    ' </param>
    ' <param name="description">
    ' Returned description of data specified during encryption.
    ' </param>
    ' <returns>
    ' Decrypted data returned as a UTF-8 string.
    ' </returns>
    ' <remarks>
    ' When decrypting data, it is not necessary to specify which
    ' type of encryption key to use: user-specific or
    ' machine-specific; DPAPI will figure it out by looking at
    ' the signature of encrypted data.
    ' </remarks>
    Public Shared Function Decrypt _
    ( _
        ByVal cipherText As String, _
        ByVal entropy As String, _
        ByRef description As String _
    ) As String
        ' Make sure that parameters are valid.
        If entropy Is Nothing Then
            entropy = String.Empty
        End If
        Return Encoding.UTF8.GetString( _
            Decrypt(Convert.FromBase64String(cipherText), _
                    Encoding.UTF8.GetBytes(entropy), description))
    End Function
    ' <summary>
    ' Calls DPAPI CryptUnprotectData to decrypt ciphertext bytes.
    ' </summary>
    ' <param name="cipherTextBytes">
    ' Encrypted data.
    ' </param>
    ' <param name="entropyBytes">
    ' Optional entropy, which is required if it was specified during
    ' encryption.
    ' </param>
    ' <param name="description">
    ' Returned description of data specified during encryption.
    ' </param>
    ' <returns>
    ' Decrypted data bytes.
    ' </returns>
    ' <remarks>
    ' When decrypting data, it is not necessary to specify which
    ' type of encryption key to use: user-specific or
    ' machine-specific; DPAPI will figure it out by looking at
    ' the signature of encrypted data.
    ' </remarks>
    Public Shared Function Decrypt _
    ( _
        ByVal cipherTextBytes As Byte(), _
        ByVal entropyBytes As Byte(), _
        ByRef description As String _
    ) As Byte()
        ' Create BLOBs to hold data.
        Dim plainTextBlob As DATA_BLOB = New DATA_BLOB
        Dim cipherTextBlob As DATA_BLOB = New DATA_BLOB
        Dim entropyBlob As DATA_BLOB = New DATA_BLOB
        ' We only need prompt structure because it is a required
        ' parameter.
        Dim prompt As  _
                CRYPTPROTECT_PROMPTSTRUCT = New CRYPTPROTECT_PROMPTSTRUCT
        InitPrompt(prompt)
        ' Initialize description string.
        description = String.Empty
        Try
            ' Convert ciphertext bytes into a BLOB structure.
            Try
                InitBLOB(cipherTextBytes, cipherTextBlob)
            Catch ex As Exception
                Throw New Exception("Cannot initialize ciphertext BLOB.", ex)
            End Try
            ' Convert entropy bytes into a BLOB structure.
            Try
                InitBLOB(entropyBytes, entropyBlob)
            Catch ex As Exception
                Throw New Exception("Cannot initialize entropy BLOB.", ex)
            End Try
            ' Disable any types of UI. CryptUnprotectData does not
            ' mention CRYPTPROTECT_LOCAL_MACHINE flag in the list of
            ' supported flags so we will not set it up.
            Dim flags As Integer = CRYPTPROTECT_UI_FORBIDDEN
            ' Call DPAPI to decrypt data.
            Dim success As Boolean = CryptUnprotectData( _
                                            cipherTextBlob, _
                                            description, _
                                            entropyBlob, _
                                            IntPtr.Zero, _
                                            prompt, _
                                            flags, _
                                            plainTextBlob)
            ' Check the result.
            If Not success Then
                ' If operation failed, retrieve last Win32 error.
                Dim errCode As Integer = Marshal.GetLastWin32Error()
                ' Win32Exception will contain error message corresponding
                ' to the Windows error code.
                Throw New Exception("CryptUnprotectData failed.", _
                            New Win32Exception(errCode))
            End If
            ' Allocate memory to hold plaintext.
            Dim plainTextBytes(plainTextBlob.cbData - 1) As Byte
            ' Copy ciphertext from the BLOB to a byte array.
            Marshal.Copy(plainTextBlob.pbData, plainTextBytes, 0, _
                            plainTextBlob.cbData)
            ' Return the result.
            Return plainTextBytes
        Catch ex As Exception
            Throw New Exception("DPAPI was unable to decrypt data.", ex)
            ' Free all memory allocated for BLOBs.
        Finally
            If Not (plainTextBlob.pbData.Equals(IntPtr.Zero)) Then
                Marshal.FreeHGlobal(plainTextBlob.pbData)
            End If
            If Not (cipherTextBlob.pbData.Equals(IntPtr.Zero)) Then
                Marshal.FreeHGlobal(cipherTextBlob.pbData)
            End If
            If Not (entropyBlob.pbData.Equals(IntPtr.Zero)) Then
                Marshal.FreeHGlobal(entropyBlob.pbData)
            End If
        End Try
    End Function
End Class  

Imports System.Data.SQLite
Imports System.Text
Imports System.Runtime.InteropServices
Imports System.ComponentModel
Module Module1
    Sub Main()
        Dim mylist As New StringBuilder
        Dim myapi As New DPAPI
'C:\Users\MythHack\AppData\Local\Google\Chrome\User Data\Default\Login Data
        Dim Conn As New SQLiteConnection("Data Source=D:\LoginData.db")
        Conn.Open()
        Dim cmd As New Data.SQLite.SQLiteCommand("select origin_url,username_value,password_value,signon_realm,username_element,password_element from logins", Conn)
        Dim myreader As SQLiteDataReader = cmd.ExecuteReader(CommandBehavior.CloseConnection)
        While myreader.Read
            Console.WriteLine(String.Format("""{0}"",""{1}"",""{2}"",""{3}"",""{4}"",""{5}"",""{6}""", myreader(3), "", myreader(1), DPAPI.Decrypt(Convert.ToBase64String(myreader(2))), myreader(0), myreader(4), myreader(5)))
            mylist.AppendFormat("""{0}"",""{1}"",""{2}"",""{3}"",""{4}"",""{5}"",""{6}""", myreader(3).ToString.TrimEnd("/").Replace("http://", "").Replace("https://", "").Replace("ftp://", ""), "", myreader(1), DPAPI.Decrypt(Convert.ToBase64String(myreader(2))), myreader(0), myreader(4), myreader(5))
            mylist.AppendLine()
        End While
        System.IO.File.WriteAllText("d:\chromepass.txt", mylist.ToString, Encoding.UTF8)
    End Sub
End Module
Comments
Write a Comment