解密chrome cookies文件的encrypted

1.环境

.windows 8 (x64)
.chrome cookies文件(sqlite 3):%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Cookies

2.事由

解密chrome cookies数据的场景.
一个后台程序需要从3个平台抓取数据,每个平台的用户验证方式各不相同.利用浏览器登录后导出cookies实现自动登录.
开发一个工具程序,提供给用户,用户在浏览器登录后,运行该工具程序,导出相关网站的cookies,上传给后台服务程序.
浏览器选用chrome.

3.关于chrome的cookies

.保存在%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Cookies文件中
.该文件是sqlite 3数据库
.encrypted_value是加密后的blob内容
.Windows下加密采用DPAPI,
Decrypting Chrome's cookies on windows
https://stackoverflow.com/questions/24353620/decrypting-chromes-cookies-on-windows
文中有Chromium加密函数源代码.用CryptProtectData加密
.ChromeCookiesView程序可以查看内容
ChromeCookiesView v1.46 
https://nirsoft.net/utils/chrome_cookies_view.html
.浏览器运行期间,其它进程无法打开文件,报以下错误
java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)

4.Java DPAP

官网
Java Data Protection API
http://jdpapi.sourceforge.net/

下载的包有2个文件:
--jdpapi-java-1.0.jar
--jdpapi-native-1.0.dll
jdpapi-native-1.0.dll是IA 32-bit版本,直接使用报以下错误:
Exception in thread "main" java.lang.UnsatisfiedLinkError: E:\tool\jdpapi\jdpapi-native-1.0.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform  

需要自己编译AMD64-bit版本.

获取源代码:

svn checkout https://svn.code.sf.net/p/jdpapi/code/ jdpapi-code
保存目录E:\tool\jdpapi\jdpapi-code(工程主目录,以下目录都是相对主目录)
其中,
-jdpapi\BUILD.txt: 编译说明.
-jdpapi\jdpapi-native\pom.xml:mvn文件

VC编译器采用Visaul Studio 2010,编译x64版本.
<compilerStartOption>增加jni.h,jni_md.h的路径.

<configuration>做以下修改:

  1. <envFactoryName>
  2. org.codehaus.mojo.natives.msvc.MSVC2010x86AMD64EnvFactory
  3. </envFactoryName>
  4. <compilerStartOptions>
  5. <compilerStartOption>/LD /I"C:\Java\jdk1.8.0_91\include" /I"C:\Java\jdk1.8.0_91\include\win32"</compilerStartOption>
  6. </compilerStartOptions>
  7. <javahOS>x64</javahOS

 

由于使用msvc2010编译x64位程序,需要设置环境变量(搜索预期的cl.exe)

进入目录c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64>
运行:

vcvars64.bat

执行命令:

cd jdpapimvn clean package assembly:assembly

执行后会生成jdpapi-java-1.0.1.jar.但编译jdpapi-native失败.
 
生成C++头文件:
执行命令:

cd jdpapi\jdpapi-java\target\classesjavah net.sourceforge.jdpapi.DPAPI

当前目录生成文件net_sourceforge_jdpapi_DPAPI.h,把头文件复制到目录:jdpapi\jdpapi-native\src\main\native

执行命令:

cd jdpapimvn clean package assembly:assembly

编译成功后,生成以下文件:
-jdpapi\jdpapi-java\target\jdpapi-java-1.0.1.jar
-jdpapi\jdpapi-native\target\jdpapi-native.dll

把这2个文件复制到测试目录下E:\tool\jdpapi

5.实现

采用java实现.
复制Cookies文件:Cookies_copy,用于测试.
读一条特定的cookies记录,对encrypted_value字段进行解密.通过sqlite工具或ChromeCookiesView或直接在浏览器中获取实际内容.用于解密后的比对.
解密利用Java DPAPI,通过JNI方式调用Windows DPAPI

代码如下:

  1. package test_cookies;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.File;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.sql.Connection;
  8. import java.sql.DriverManager;
  9. import java.sql.ResultSet;
  10. import java.sql.Statement;
  11. import net.sourceforge.jdpapi.DataProtector;;
  12. public class TestCookies {
  13. static Connection conn = null;
  14. static String dbPath = "C:\\Users\\Think\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\";
  15. static String dbName = dbPath + "Cookies_copy";
  16. private final DataProtector protector;
  17. public TestCookies() {
  18. this.protector = new DataProtector();
  19. }
  20. private String decrypt(byte[] data) {
  21. return protector.unprotect(data);
  22. }
  23. public static void main(String[] args) {
  24. try {
  25. TestCookies testCoolies = new TestCookies();
  26. Class.forName("org.sqlite.JDBC");
  27. conn = DriverManager.getConnection("jdbc:sqlite:" + dbName, null, null);
  28. conn.setAutoCommit(false);
  29. Statement stmt = conn.createStatement();
  30. stmt.setQueryTimeout(3);
  31. String sql = String.format("select * from cookies where host_key like '%%.cainiao.com%%' and name='cna'");
  32. ResultSet rs = stmt.executeQuery(sql);
  33. while (rs.next()) {
  34. String name = rs.getString("name");
  35. String value = rs.getString("value");
  36. InputStream inputStream = rs.getBinaryStream("encrypted_value");
  37. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  38. int ch;
  39. while ((ch = inputStream.read()) != -1) {
  40. byteArrayOutputStream.write(ch);
  41. }
  42. byte[] b = byteArrayOutputStream.toByteArray();
  43. byteArrayOutputStream.close();
  44. System.out.println(String.format("name=%s value=%s encrypted_value=%s",
  45. name, value,testCoolies.decrypt(b)));
  46. }
  47. rs.close();
  48. conn.close();
  49. } catch (Exception e) {
  50. e.printStackTrace();
  51. }
  52. }
  53. static {
  54. System.load("e:/tool/jdpapi/jdpapi-native.dll");
  55. }
  56. }

sqlite-jdbc驱动用3.23.1版本,有的版本会报以下错误:

java.sql.SQLException: not implemented by SQLite JDBC driver

pom.xml增加sqlite-jdbc依赖:

  1. <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
  2. <dependency>
  3. <groupId>org.xerial</groupId>
  4. <artifactId>sqlite-jdbc</artifactId>
  5. <version>3.23.1</version>
  6. </dependency>

 

 

 

(0)

相关推荐