Advertisement
haken8000

Untitled

Feb 17th, 2020
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.14 KB | None | 0 0
  1. from os import path
  2. import sqlite3
  3. import json
  4. import base64
  5. from Crypto.Cipher import AES  # pycryptodome
  6.  
  7. # 参考にした情報
  8. # https://github.com/gentilkiwi/mimikatz/commit/b098bf37cf71581882e6a1fa45ac58ec87860fd5
  9.  
  10. # https://github.com/borisbabic/browser_cookie3 からパクってきた関数
  11. def crypt_unprotect_data(
  12.         cipher_text=b'', entropy=b'', reserved=None, prompt_struct=None
  13. ):
  14.     # we know that we're running under windows at this point so it's safe to try these imports
  15.     import ctypes
  16.     import ctypes.wintypes
  17.  
  18.     class DataBlob(ctypes.Structure):
  19.         _fields_ = [
  20.             ('cbData', ctypes.wintypes.DWORD),
  21.             ('pbData', ctypes.POINTER(ctypes.c_char))
  22.         ]
  23.  
  24.     blob_in, blob_entropy, blob_out = map(
  25.         lambda x: DataBlob(len(x), ctypes.create_string_buffer(x)),
  26.         [cipher_text, entropy, b'']
  27.     )
  28.     desc = ctypes.c_wchar_p()
  29.  
  30.     CRYPTPROTECT_UI_FORBIDDEN = 0x01
  31.  
  32.     if not ctypes.windll.crypt32.CryptUnprotectData(
  33.             ctypes.byref(blob_in), ctypes.byref(desc), ctypes.byref(blob_entropy),
  34.             reserved, prompt_struct, CRYPTPROTECT_UI_FORBIDDEN, ctypes.byref(blob_out)
  35.     ):
  36.         raise RuntimeError('Failed to decrypt the cipher text with DPAPI')
  37.  
  38.     description = desc.value
  39.     buffer_out = ctypes.create_string_buffer(int(blob_out.cbData))
  40.     ctypes.memmove(buffer_out, blob_out.pbData, blob_out.cbData)
  41.     map(ctypes.windll.kernel32.LocalFree, [desc, blob_out.pbData])
  42.     return description, buffer_out.value
  43.  
  44.  
  45. # ファイルのパスとか
  46. sql_query = "select name,encrypted_value from cookies where (host_key='.nicovideo.jp' or host_key='jk.nicovideo.jp' or host_key='.jk.nicovideo.jp') and path='/' and not is_secure and (name='nicosid' or name='user_session' or name='nickname')"
  47. chrome_cookies = r"%LOCALAPPDATA%\Google\Chrome\User Data\Default\Cookies"
  48. chrome_local_state = r"%LOCALAPPDATA%\Google\Chrome\User Data\Local State"
  49.  
  50. # 暗号化されたクッキーをDBから取得
  51. con = sqlite3.connect(path.expandvars(chrome_cookies))
  52. cur = con.cursor()
  53. cur.execute(sql_query)
  54. nico_cookies = cur.fetchall()
  55. con.close()
  56.  
  57. # AESキーを'Local State'ファイルから取得
  58. with open(path.expandvars(chrome_local_state), 'r') as f:
  59.     encrypted_key = json.load(f)["os_crypt"]["encrypted_key"]
  60. # base64デコードして先頭の'DPAPI'を飛ばしてしてDPAPI unprotect
  61. _, aes_key = crypt_unprotect_data(base64.b64decode(encrypted_key)[5:])
  62. # キーが短い場合はパディングが必要らしいけどよく知らん
  63. while len(aes_key) < 32:
  64.     aes_key = bytearray.fromhex('00') + aes_key
  65. print('AES Key:', aes_key.hex())
  66.  
  67. # クッキーデータをAES-256-GCMでデコードして表示
  68. # encrypted_valueの構造は 'v10' + Nonce[12] + 暗号文本体 + Tag[16] になってる
  69. for cookie in nico_cookies:
  70.     if cookie[1][:3] == b'v10':
  71.         cipher_text = cookie[1][3:]
  72.         nonce = cipher_text[:12]
  73.         tag = cipher_text[-16:]
  74.  
  75.         aes = AES.new(aes_key, AES.MODE_GCM, nonce)
  76.         data = aes.decrypt_and_verify(cipher_text[12:-16:], tag)
  77.         print("{}: {}".format(cookie[0], data.decode('utf-8')))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement