Guest User

Untitled

a guest
Jun 26th, 2018
144
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.47 KB | None | 0 0
  1. Public Class SafariDecryptor
  2.  
  3. #Region "private APIs & structs"
  4.  
  5. <DllImport("kernel32.dll")> _
  6. Private Shared Function LocalFree(ByVal hMem As IntPtr) As IntPtr
  7. End Function
  8.  
  9. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Unicode)>
  10. Private Structure DATA_BLOB
  11. Public cbData As Integer
  12. Public pbData As IntPtr
  13. End Structure
  14.  
  15. <DllImport("Crypt32.dll", SetLastError:=True, CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
  16. Private Shared Function CryptUnprotectData _
  17. ( _
  18. ByRef pDataIn As DATA_BLOB, _
  19. ByVal szDataDescr As String, _
  20. ByRef pOptionalEntropy As DATA_BLOB, _
  21. ByVal pvReserved As IntPtr, _
  22. ByRef pPromptStruct As IntPtr, _
  23. ByVal dwFlags As Integer, _
  24. ByRef pDataOut As DATA_BLOB _
  25. ) As Boolean
  26.  
  27. End Function
  28.  
  29. #End Region
  30.  
  31. Private Shared salt As Byte() = {&H1D, &HAC, &HA8, &HF8, &HD3, &HB8, _
  32. &H48, &H3E, &H48, &H7D, &H3E, &HA, _
  33. &H62, &H7, &HDD, &H26, &HE6, &H67, _
  34. &H81, &H3, &HE7, &HB2, &H13, &HA5, _
  35. &HB0, &H79, &HEE, &H4F, &HF, &H41, _
  36. &H15, &HED, &H7B, &H14, &H8C, &HE5, _
  37. &H4B, &H46, &HD, &HC1, &H8E, &HFE, _
  38. &HD6, &HE7, &H27, &H75, &H6, &H8B, _
  39. &H49, &H0, &HDC, &HF, &H30, &HA0, _
  40. &H9E, &HFD, &H9, &H85, &HF1, &HC8, _
  41. &HAA, &H75, &HC1, &H8, &H5, &H79, _
  42. &H1, &HE2, &H97, &HD8, &HAF, &H80, _
  43. &H38, &H60, &HB, &H71, &HE, &H68, _
  44. &H53, &H77, &H2F, &HF, &H61, &HF6, _
  45. &H1D, &H8E, &H8F, &H5C, &HB2, &H3D, _
  46. &H21, &H74, &H40, &H4B, &HB5, &H6, _
  47. &H6E, &HAB, &H7A, &HBD, &H8B, &HA9, _
  48. &H7E, &H32, &H8F, &H6E, &H6, &H24, _
  49. &HD9, &H29, &HA4, &HA5, &HBE, &H26, _
  50. &H23, &HFD, &HEE, &HF1, &H4C, &HF, _
  51. &H74, &H5E, &H58, &HFB, &H91, &H74, _
  52. &HEF, &H91, &H63, &H6F, &H6D, &H2E, _
  53. &H61, &H70, &H70, &H6C, &H65, &H2E, _
  54. &H53, &H61, &H66, &H61, &H72, &H69}
  55.  
  56. Public Structure UserEntry
  57. Public Username As String
  58. Public encPassword As String
  59. Public decPassword As String
  60. Public Description As String
  61. Public Label As String
  62. Public Path As String
  63. Public Comment As String
  64. Public Server As String
  65. Public Protocol As Integer
  66. Public AuthenticationType As Integer
  67. Public Port As Integer
  68. Public UserIndex As Integer
  69. End Structure
  70.  
  71. Public Shared Function FetchUserEntries() As UserEntry()
  72. Dim plutilPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) & "\Common Files\Apple\Apple Application Support\plutil.exe"
  73. Dim rawKeychainPath As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) & "\Apple Computer\Preferences\keychain.plist"
  74. Dim fixedPath As String = Nothing
  75.  
  76. If Not ConvertKeychain(plutilPath, rawKeychainPath, fixedPath) Then
  77. Return Nothing
  78. End If
  79.  
  80. Return ParseEntries(fixedPath.Remove(fixedPath.Length - 2)).ToArray()
  81. End Function
  82.  
  83. Private Shared Function ParseEntries(ByVal keychain As String) As List(Of UserEntry)
  84. Dim full As String = File.ReadAllText(keychain)
  85. Dim outEntries As New List(Of UserEntry)()
  86. Dim blocks As String()
  87.  
  88. For i As Integer = 1 To (InlineAssignHelper(blocks, Regex.Split(Regex.Split(full, "<array>")(1), "<dict>"))).Length - 1
  89. Dim tmpEntry As New UserEntry()
  90.  
  91. tmpEntry.Username = GetBetween(blocks(i), "<string>", "</string>", 0)
  92. tmpEntry.AuthenticationType = Int32.Parse(GetBetween(blocks(i), "<integer>", "</integer>", 0))
  93. tmpEntry.Comment = GetBetween(blocks(i), "<string>", "</string>", 1)
  94. tmpEntry.encPassword = GetBetween(blocks(i), "<data>", "</data>", 0)
  95. tmpEntry.Description = GetBetween(blocks(i), "<string>", "</string>", 2)
  96. tmpEntry.Label = GetBetween(blocks(i), "<string>", "</string>", 3)
  97. tmpEntry.Path = GetBetween(blocks(i), "<string>", "</string>", 4)
  98. tmpEntry.Port = Int32.Parse(GetBetween(blocks(i), "<integer>", "</integer>", 1))
  99. tmpEntry.Protocol = Int32.Parse(GetBetween(blocks(i), "<integer>", "</integer>", 2))
  100. tmpEntry.Server = GetBetween(blocks(i), "<string>", "</string>", 5)
  101. tmpEntry.UserIndex = i - 1
  102.  
  103. tmpEntry.decPassword = DecryptPassword(Convert.FromBase64String(tmpEntry.encPassword))
  104.  
  105. outEntries.Add(tmpEntry)
  106. Next
  107.  
  108. Return outEntries
  109. End Function
  110.  
  111. Private Shared Function DecryptPassword(ByVal pwBuffer As Byte()) As String
  112. Dim dIn As DATA_BLOB, dOut As DATA_BLOB, optEntropy As DATA_BLOB
  113. Dim pwLen As Integer = 0
  114. Dim outStr As Char()
  115.  
  116. 'I think we need to marshal the buffer manually in VB.NET?
  117. Dim p_pwBuffer = Marshal.AllocHGlobal(pwBuffer.Length + 4) ' we need to make an extra 4 byte space for integer
  118. Marshal.Copy(pwBuffer, 0, p_pwBuffer, pwBuffer.Length)
  119.  
  120. 'Same with salt
  121. Dim p_salt = Marshal.AllocHGlobal(salt.Length)
  122. Marshal.Copy(salt, 0, p_salt, salt.Length)
  123.  
  124. dIn.cbData = pwBuffer.Length
  125. dIn.pbData = p_pwBuffer
  126.  
  127. optEntropy.cbData = salt.Length
  128. optEntropy.pbData = p_salt
  129.  
  130. If Not CryptUnprotectData(dIn, Nothing, optEntropy, IntPtr.Zero, IntPtr.Zero, 0, dOut) Then
  131. Return Nothing
  132. End If
  133.  
  134. 'Probably have to free allocated memory for pwBuffer and salt as well
  135. Marshal.FreeHGlobal(p_pwBuffer)
  136. Marshal.FreeHGlobal(p_salt)
  137.  
  138. pwLen = Marshal.ReadInt32(dOut.pbData)
  139. Dim bData As Byte() = New Byte(pwLen) {}
  140.  
  141. dOut.pbData = New IntPtr(dOut.pbData.ToInt32() + 4) ' skip pw length
  142. Marshal.Copy(dOut.pbData, bData, 0, pwLen)
  143.  
  144. LocalFree(dOut.pbData)
  145.  
  146. outStr = New Char(pwLen - 1) {}
  147.  
  148. For i As Integer = 0 To pwLen - 1
  149. outStr(i) = ChrW(bData(i))
  150. Next
  151.  
  152. Return New String(outStr)
  153. End Function
  154.  
  155. Private Shared Function ConvertKeychain(ByVal plutil As String, ByVal keychain As String, ByRef fixedPath As String) As Boolean
  156. fixedPath = Nothing
  157.  
  158. If Not File.Exists(plutil) Then
  159. Return False
  160. End If
  161.  
  162. Dim p As New Process()
  163. p.StartInfo.FileName = plutil
  164. p.StartInfo.Arguments = " -convert xml1 -s -o """ & (InlineAssignHelper(fixedPath, Path.GetDirectoryName(Reflection.Assembly.GetExecutingAssembly().Location) + "\fixed_keychain.xml"" ")) & """" & keychain & """"
  165. p.StartInfo.CreateNoWindow = False
  166. p.StartInfo.RedirectStandardOutput = True
  167. p.StartInfo.UseShellExecute = False
  168. p.Start()
  169. p.WaitForExit()
  170.  
  171. Return p.StandardOutput.ReadToEnd().Length = 0
  172. End Function
  173.  
  174. Private Shared Function GetBetween(ByVal input As String, ByVal str1 As String, ByVal str2 As String, ByVal index As Integer) As String
  175. Dim temp As String = Regex.Split(input, str1)(index + 1)
  176. Return Regex.Split(temp, str2)(0)
  177. End Function
  178. Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, ByVal value As T) As T
  179. target = value
  180. Return value
  181. End Function
  182. End Class
Add Comment
Please, Sign In to add comment