• 记一个手游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符号表中没有了。我们就仅仅能看到一个地址跳转啦

    反汇编出来的加密函数,跟自己写的并用debug编译出来是一样的
    .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)


  • 相关阅读:
    博客园安卓客户端合仔茶版本V4.0震撼发布
    提示功能的检索框
    .net 玩自动化浏览器
    《表单篇》DataBase之大数据量经验总结
    自定义表主键
    一次网络程序Debug过程
    关于.NET下开源及商业图像处理(PSD)组件
    利用反射从程序集dll中动态调用方法
    Linux内核源码分析方法
    wcf基础教程之 契约(合同)Contract
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/5138271.html
Copyright © 2020-2023  润新知