python - 用C从Chrome中解密 "Saved Password"

标签 python c windows winapi encryption

作为项目的一部分,我们正在尝试解密 Google Chrome 中保存的密码。经过一番挖掘,我们了解到 Chrome 使用 CryptProtectData 函数加密密码,该函数允许您使用登录用户凭据加密数据,即加密的数据只能由同一用户在同一台​​计算机上解密(如果提供了适当的参数,其他用户也可以)。

无论如何,我之前已经编写了一个 Python 脚本来做到这一点,并且它工作得很好。

from os import getenv, unlink
from shutil import copy
import sqlite3
import win32crypt

dbpath = "C:\Users\\"+ getenv('username') +"\AppData\Local\Google\Chrome\User Data\Default\\"
copy(dbpath + "Login Data", dbpath + "Login Data.db")
conn = sqlite3.connect(dbpath + "Login Data.db")
cursor = conn.cursor()
cursor.execute('SELECT action_url, username_value, password_value FROM logins')
for result in cursor.fetchall():
    password = win32crypt.CryptUnprotectData(result[2], None, None, None, 0)[1]
    print result[0] + " - " + result[1] + ":" + password
conn.close()
unlink(dbpath + "Login Data.db")

但是由于项目需要,我必须用C语言编写它。 所以我写了以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Wincrypt.h>
#include "sqlite3.h"

static int callback(void *data, int argc, char **argv, char **azColName){
   int i;
   fprintf(stderr, "%s: \n", (const char*)data);
   for(i=0; i<argc; i++){
      if (i == 2 ){
        DATA_BLOB DataIn;
        DATA_BLOB DataOut;
        BYTE *pbDataInput = (BYTE *) argv[i];
        DWORD cbDataInput = strlen((char *) pbDataInput) + 1;
        DataIn.pbData = pbDataInput;
        DataIn.cbData = cbDataInput;
        if (CryptUnprotectData (&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut))
          printf("%s\n", DataOut.pbData);
        else
          printf("Error number %x.\n", GetLastError());
      }
      // printf("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
   }
   printf("\n");
   return 0;
}

int main(int argc, char* argv[])
{
   sqlite3 *db;
   char *zErrMsg = 0;
   int rc;
   char *sql;
   const char* data = "Callback function called";

   /* Open database */
   rc = sqlite3_open("Login Data.db", &db);
   if( rc ){
      fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db));
      return(0);
   }else{
      fprintf(stderr, "Opened database successfully\n");
   }

   /* Create SQL statement */
   sql = "SELECT action_url, username_value, password_value from logins";

   /* Execute SQL statement, */
   rc = sqlite3_exec(db, sql, callback, (void*)data, &zErrMsg);
   if( rc != SQLITE_OK ){
      fprintf(stderr, "SQL error: %s\n", zErrMsg);
      sqlite3_free(zErrMsg);
   }else{
      fprintf(stdout, "Operation done successfully\n");
   }
   sqlite3_close(db);
   return 0;
}

编译正确,没有任何错误,但解密的数据不正确。

C:\>gcc -o decryptor decryptor.c sqlite3.o -lcrypt32

C:\>decryptor.exe
Opened database successfully
Callback function called: Important Data
Error Number 57.

Operation done successfully

C:\>

根据System Error Codes (0-499) , 0x57代表ERROR_INVALID_PARAMETER(参数不正确)

我错过了什么?

最佳答案

这对我来说效果很好,因为你的加密数据位于 2hex.txt 中(刚刚从数据库浏览器中保存)。您的问题实际上出在 strlen() 函数中,因为它遇到字节序列中的第一个“0”并停止。只是避免它。

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Wincrypt.h>


int main(){
    FILE *fp;
    DATA_BLOB DataIn;
    DATA_BLOB DataOut;
    char result[1000]="";
    unsigned char buf[1000]="";
    int tmpbuf;
    int i=0;
    fp=fopen("3hex.txt","rb");
    printf ("Crypted data:\n");
    for(i=0;(tmpbuf=getc(fp))!=EOF;i++)
    {
        buf[i]=tmpbuf;
        if (i%16==0) printf("\n");
        printf("%02X ",buf[i]);
    }
    DataIn.pbData=buf;
    DataIn.cbData=i+1;
    if (CryptUnprotectData (&DataIn, NULL, NULL, NULL, NULL, 0, &DataOut)) 
    {
        for (i=0;i<DataOut.cbData;i++)
        {
            result[i]=DataOut.pbData[i];
        }
        result[i+1]='\0';
        printf("\nResult as string: %s\n", result);

    }

    else printf("Error number %x.\n", GetLastError());
}

关于python - 用C从Chrome中解密 "Saved Password",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41799602/

相关文章:

python - 如何在 Python 代码继续运行时持续闪烁 LED(或其他 while 循环)

c - socket() 返回 -1 但 errno 0

c - 在进程错误之间复制文件句柄

C 指针和地址

c++ - 将数据填充到本地的recv-Buffer中

c# - 使用 C# 下载文件

windows - Azure 负载平衡一个公共(public)端口到其他计算机上的多个内部端口

python - 如何连接到 Heroku 上的 MySQL?

javascript - 使用 Python 从 Javascript 中提取文本

python Flask通过post和url发送数据