2020 腾讯游戏安全技术竞赛 决赛-Android-Writeup
[TOC]
APK结构
1 | t2/assets |
有一个elf和一个音频文件。secret音频文件可正常播放。
初探java层
java层逻辑比较简单,主要有四个class。
- Class MainActivity。重点关注onCreate函数,将Il10I01L和secret,一个elf一个音频copy出来,测试Il10I01L。检查前会先用root将Il10I01L起起来。
- Class Native。加载libcrackme.so及两个函数的封装。
- Class RootUtils。获得su权限
- Class MyApplication。java层无交叉引用,应该是一个测试/log模块。
初探Il10I01L
go语言编写的elf,尝试利用GoUtils恢复符号信息,go1.7,恢复成功。
Main_main逻辑比较简单,检查文件/data/local/tmp/324972397429374
是否存在,创建该文件并其中写入长度116的字符串:
1 | 39475934759034275930478590743598734095873490573495873490759347593475934759374957349573947593475973495734957349579437 |
libcrackme.so
尝试恢复符号表
根据.so中的字符串确定编译版本为ndk-r14。自己下载了一个ndk-r14b,编译出带调试信息的.so,用rizzo创建函数签名,希望以此恢复符号表,无果。可能是ndk toolchains的问题吧,没有继续深究了,只好怼无符号的so了。
动态注册函数
JNI_OnLoad中使用RegisterNatives动态注册了两个函数,字符串在.init_array的函数中被赋值。识别出cmd、verify函数。
动态调试
启动android_server后发现verify时应用会自动退出,遂
1 | /data/local/tmp # mkdir tmp |
可以正常verify,判断至少有检测23946端口反调试。
IDA附加上去后,再次运行即会自动退出,猜测有time相关反调试。
suspend那20个线程,patch掉tp_syscall_imp,就可以调试了,但这样可能会出一些问题。
字符串解密
字符串解密函数在0xCEEF6928,通过传入不同参数,返回相应字符串。
1 | encrypted_string = [ |
得到所有解密的字符串:
1 | idx (len): string |
利用idapython在IDA中注释:
1 | import idautils |
.init_proc函数
反调+mprotect将代码段设置为可写。
JNI_OnLoad函数
跟java层做了一些交互,有usb相关的,暂时看不出有什么用。
起了十对(20个)TrashThread。值得注意的是TrashThread为TPThread的子类。
线程函数使用time进行反调试。
cmd函数
处理”files_dir:”时起了一个selfcheck类的线程,内部十分复杂。struct_2_init内部也有反调试。
selfcheck继承自TPThread。
verify函数
将go跑起来后,自修改一段代码、encode license后进loc_CEF538DC检查,出来后还原。
IDApython将这块区域异或0xDB。
1 | from idaapi import * |
sub_CEF598DC函数
用户名16字节
注册码24字节
进入到check函数
典型的平坦化控制流
绕过下图中的反调,挂起那20个线程即可进行调试。
key使用逐字节比较,用于比较的数组由name生成。
调试获得一对可用的id和key:
1 | id: 1234567890123456 |
加密方式
动态调了一下,确认了几个大数运算函数功能,怀疑是ECDSA
192bit椭圆曲线secp192r1,产生384bit签名,用低192bit验证。
利用IDApython 进行trace
代码
1 | from idaapi import * |
发现是使用的大数运算源码,https://github.com/esxgx/easy-ecc/blob/master/ecc.c。标函数。
有部分代码被内联进入ECDSA_sign中,重写如下:
1 | EccPoint_mult(只走到 vli_modMult_fast(z, z, p_point->x); /* xP * Yb * (X1 - X0) */, trace 383 |
发现就是一个点乘操作EccPoint_mult函数(https://github.com/esxgx/easy-ecc/blob/master/ecc.c#L956)。。。。。
keygen
sage代码:
1 | import hashlib |
python:
1 | #!/usr/bin/env python3 |
再附上两对name-key:
1 | # 0987654321123456 |
其他
调试方式:
挂起那20个线程,检查tracer pid函数前下断点,手动修改PC(其实就只有下图中一处)