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:///questions/24353620/decrypting-chromes-cookies-on-windows 文中有Chromium加密函数源代码.用CryptProtectData加密 .ChromeCookiesView程序可以查看内容 ChromeCookiesView v1.46 https:///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./
下载的包有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./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>做以下修改:
org.codehaus.mojo.natives.msvc.MSVC2010x86AMD64EnvFactory <compilerStartOption>/LD /I"C:\Java\jdk1.8.0_91\include" /I"C:\Java\jdk1.8.0_91\include\win32"</compilerStartOption>
由于使用msvc2010编译x64位程序,需要设置环境变量(搜索预期的cl.exe)
进入目录c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\amd64> 运行:
vcvars64.bat
执行命令:
cd jdpapi
mvn clean package assembly:assembly
执行后会生成jdpapi-java-1.0.1.jar.但编译jdpapi-native失败. 生成C++头文件: 执行命令:
cd jdpapi\jdpapi-java\target\classes
javah net.sourceforge.jdpapi.DPAPI
当前目录生成文件net_sourceforge_jdpapi_DPAPI.h,把头文件复制到目录:jdpapi\jdpapi-native\src\main\native
执行命令:
cd jdpapi
mvn 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
代码如下:
import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import net.sourceforge.jdpapi.DataProtector;; public class TestCookies { static Connection conn = null; static String dbPath = "C:\\Users\\Think\\AppData\\Local\\Google\\Chrome\\User Data\\Default\\"; static String dbName = dbPath + "Cookies_copy"; private final DataProtector protector; this.protector = new DataProtector(); private String decrypt(byte[] data) { return protector.unprotect(data); public static void main(String[] args) { TestCookies testCoolies = new TestCookies(); Class.forName("org.sqlite.JDBC"); conn = DriverManager.getConnection("jdbc:sqlite:" + dbName, null, null); conn.setAutoCommit(false); Statement stmt = conn.createStatement(); String sql = String.format("select * from cookies where host_key like '%%.cainiao.com%%' and name='cna'"); ResultSet rs = stmt.executeQuery(sql); String name = rs.getString("name"); String value = rs.getString("value"); InputStream inputStream = rs.getBinaryStream("encrypted_value"); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); while ((ch = inputStream.read()) != -1) { byteArrayOutputStream.write(ch); byte[] b = byteArrayOutputStream.toByteArray(); byteArrayOutputStream.close(); System.out.println(String.format("name=%s value=%s encrypted_value=%s", name, value,testCoolies.decrypt(b))); System.load("e:/tool/jdpapi/jdpapi-native.dll");
sqlite-jdbc驱动用3.23.1版本,有的版本会报以下错误:
java.sql.SQLException: not implemented by SQLite JDBC driver
pom.xml增加sqlite-jdbc依赖:
<!-- https:///artifact/org.xerial/sqlite-jdbc --> <groupId>org.xerial</groupId> <artifactId>sqlite-jdbc</artifactId> <version>3.23.1</version>
|