记一个手游app数据文件的破解
出于一些很猥琐的需要,同时自己也想做一些新鲜的尝试,周末用了大半天时间破解了某款手游的数据文件。
过程比我预想的要顺利,主要原因还是我们开发人员的懈怠,咳咳。
过程如下:
- 下载安装包,解压,发现几个XXX.db文件,最感兴趣的是一个50多M的XXX.db
- 用UltraEdit打开XXX.DB文件,没有任何线索。只发现这几个文件有相同的文件头
- 搜索.DB文件可能是什么文件,发现了开源库sqlite,这是一个轻量级的数据库组件,IOS就用了这个,顿时眼前一亮
- 下载sqlite的命令行工具,发现打不开.DB文件
- 自己存了一个sqlite的数据库文件做测试,发现根本就是明文存储的
- 是时候祭出神器IDA pro了,反汇编libXXX.so,发现大量sqlite3_XXX函数,.db文件应该是sqlite数据库文件没错
- 搜索sqlite加密的相关信息,官方的加密实现是需要授权的,但有一个wxsqlite的开源实现。私下推测该app用了wxsqlite
- wxsqlite是AES算法加密的,必须找到密匙,否则无法解密,心里凉了半截
- 继续看反汇编,找到keySqlite函数,发现key就明文写在代码里,是一串1....,额
- 下载wxsqlite,写了几行代码进行测试,发现依然打不开。自己创建了一个加密数据库文件,发现跟app的db文件差别很大。
- 阅读wxsqlite的代码,发现加密算法是在sqlite3Codec函数中调用的。在汇编中找到sqlite3Codec,发现它调用了一个My_Encrypt_Func(呵呵)
- 阅读My_Encrypt_Func的汇编代码,发现就是按字节取反(呵呵呵)
- 写个小程序,将db文件按字节取反。再用UltraEdit打开,看到了熟悉的明文信息
- 这回数据文件可以用sqlite命令行打开了,dump成txt文件,得到表结构和所有的数据
- 最后是那个50多M的db文件。打印出表结构发现是一个字符串name和一个二进制对象。写个小程序,遍历所有表项,将二进制对象存成png文件。任务完成
- 如果是用wxsqlite加密实现,并且密匙是通过网络获取的,那就得先想办法在运行时hook api截获密匙。破解难度会上升一大截...
- 加密函数的arm汇编看上去效率很低....让我好生奇怪。写了一段同样的代码自己编了一下,发现该lib是debug的,这....
- 加密相关的函数名暴露在动态库中是很危险的,给函数声明加上static,export符号表中没有了,我们就只能看到一个地址跳转啦
.text:002C46E0 EXPORT My_Encrypt_Func .text:002C46E0 My_Encrypt_Func ; CODE XREF: sqlite3Codec+11Cp .text:002C46E0 ; sqlite3Codec+190p .text:002C46E0 .text:002C46E0 var_3C = -0x3C .text:002C46E0 var_38 = -0x38 .text:002C46E0 var_34 = -0x34 .text:002C46E0 var_30 = -0x30 .text:002C46E0 var_28 = -0x28 .text:002C46E0 var_20 = -0x20 .text:002C46E0 var_4 = -4 .text:002C46E0 .text:002C46E0 STR R11, [SP,#var_4]! .text:002C46E4 ADD R11, SP, #4+var_4 .text:002C46E8 SUB SP, SP, #0x1C .text:002C46EC STR R0, [R11,#0x20+var_30] .text:002C46F0 STR R1, [R11,#0x20+var_34] .text:002C46F4 STR R2, [R11,#0x20+var_38] .text:002C46F8 STR R3, [R11,#0x20+var_3C] .text:002C46FC MOV R3, #0 .text:002C4700 STR R3, [R11,#0x20+var_28] .text:002C4704 B loc_2C473C .text:002C4708 ; --------------------------------------------------------------------------- .text:002C4708 .text:002C4708 loc_2C4708 ; CODE XREF: My_Encrypt_Func+68j .text:002C4708 LDR R3, [R11,#-0x10] .text:002C470C LDRB R3, [R3] .text:002C4710 MVN R3, R3 .text:002C4714 STRB R3, [R11,#-9] .text:002C4718 LDR R3, [R11,#-0x10] .text:002C471C LDRB R2, [R11,#-9] .text:002C4720 STRB R2, [R3] .text:002C4724 LDR R3, [R11,#-0x10] .text:002C4728 ADD R3, R3, #1 .text:002C472C STR R3, [R11,#-0x10] .text:002C4730 LDR R3, [R11,#-8] .text:002C4734 ADD R3, R3, #1 .text:002C4738 STR R3, [R11,#-8] .text:002C473C .text:002C473C loc_2C473C ; CODE XREF: My_Encrypt_Func+24j .text:002C473C LDR R2, [R11,#-8] .text:002C4740 LDR R3, [R11,#-0x14] .text:002C4744 CMP R2, R3 .text:002C4748 BCC loc_2C4708 .text:002C474C MOV R3, #0 .text:002C4750 MOV R0, R3 .text:002C4754 SUB SP, R11, #0 .text:002C4758 LDR R11, [SP+0x20+var_20],#4 .text:002C475C BX LR .text:002C475C ; End of function My_Encrypt_Func
用release编译的,运行效率怎么也得差几十倍
.text:00001D88 ; My_Encrypt_Func(unsigned char *, unsigned int, unsigned char *, unsigned int) .text:00001D88 EXPORT _Z15My_Encrypt_FuncPhjS_j .text:00001D88 _Z15My_Encrypt_FuncPhjS_j .text:00001D88 MOVS R3, #0 .text:00001D8A B loc_1D94 .text:00001D8C ; --------------------------------------------------------------------------- .text:00001D8C .text:00001D8C loc_1D8C ; CODE XREF: My_Encrypt_Func(uchar *,uint,uchar *,uint)+Ej .text:00001D8C LDRB R2, [R0,R3] .text:00001D8E MVNS R2, R2 .text:00001D90 STRB R2, [R0,R3] .text:00001D92 ADDS R3, #1 .text:00001D94 .text:00001D94 loc_1D94 ; CODE XREF: My_Encrypt_Func(uchar *,uint,uchar *,uint)+2j .text:00001D94 CMP R3, R1 .text:00001D96 BNE loc_1D8C .text:00001D98 MOVS R0, #0 .text:00001D9A BX LR .text:00001D9A ; End of function My_Encrypt_Func(uchar *,uint,uchar *,uint)
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。