Android 逆向 apkrev

VSole2021-09-27 16:16:28

题目链接:https://buuoj.cn/match/matches/28/challenges#apkrev

下载后解压可得一个名为 apkrev 的 apk 文件,扔到模拟器里运行。

包含一个输入框和一个按钮,随便输入123,Toast 显示 fail。使用 jeb 打开。

在 MainActivity 上右键反编译。

可以看到,调用了 so 文件中的检验函数 myCheck(),参数为输入的字符串。

IDA 分析 so 文件

把 so 文件(x86)扔进 IDA,并在函数窗口搜索 myCheck 函数,双击跳转,F5,从返回开始看起:

返回值 v28 只在 136 行被赋值为 1,其余均为 0;

显然,132 行的 while 循环是在比较输入字符串经过一系列处理后是否与密文 enc 相同。v27 从 0 开始自增,直至大于 0x1F(即 31)时,循环结束。

先查看 enc:

用脚本将 enc 复制出来。在 IDA 中按快捷键 Shift + F2:

python 源码:

from idaapi import *bytes_addr = 0x00033004bytes_size = 32data = get_bytes(bytes_addr,bytes_size)L = [hex(ch) for ch in data]print (L)# 真密文# ['0x8c', '0xc4', '0x0', '0xe6', '0x6a', '0x88', '0xb8', '0x90', '0xc2', '0x7', '0x6b', '0xa9', '0xc3', '0xa', '0x3e', '0xc0', '0x44', '0xa6', '0xfe', '0x7e', '0xf0', '0x59', '0x4c', '0x83', '0x3d', '0x2b', '0xe2', '0xd3', '0x38', '0xcb', '0x82', '0x5b']

继续分析代码可以看出,输入字符串长度应为 32,且只在此处进行了异或操作:

于是考虑动态调试 so 文件,思路参考 [1],调试方法参考 [2] 和 [3]。

思路:输入错误的 flag,得到假密文,将错误的 flag 、假密文、真密文进行异或,即可得到真 flag。

动态调试

1、使用雷电模拟器,首先确定模拟器的安卓版本,安装 device info hw.apk ( https://www.cr173.com/soft/845060.html )查看相关信息: 

平台为 android_x86,所以选择 IDA/dbgsrv 目录下的 android_x86_server 文件,使用 adb push 命令传输到模拟器,在添加可执行权限后运行。

2、新建 cmd 窗口,命令如下:

D:\IDA Pro\IDA Pro 7.5\dbgsrv>adb push android_x86_serveradb.exe: push requires an argument D:\IDA Pro\IDA Pro 7.5\dbgsrv>adb push android_x86_server /data/local/tmpandroid_x86_server: 1 file pushed, 0 skipped. 30.5 MB/s (1130104 bytes in 0.035s) D:\IDA Pro\IDA Pro 7.5\dbgsrv>adb shellaosp:/ # suaosp:/ # cd /data/local/tmpaosp:/data/local/tmp # lltotal 1104-rw-rw-rw- 1 root root 1130104 2020-12-11 22:18 android_x86_serveraosp:/data/local/tmp # chmod 777 android_x86_serveraosp:/data/local/tmp # ./android_x86_serverIDA Android x86 32-bit remote debug server(ST) v7.5.26. Hex-Rays (c) 2004-2020Listening on 0.0.0.0:23946...

3、再建一个 cmd 命令行窗口,使用 forward 程序进行端口转发:

C:\Users\admin>adb forward tcp:23946 tcp:2394623946 C:\Users\admin>adb forward --listemulator-5554 tcp:23946 tcp:23946

4、打开 IDA,选择菜单 Debugger -> Attach -> Remote Linux debugger;

Hostname 设置为 127.0.0.1,OK;

选择要附加的进程,找到 com.example.re,OK;

进入调试界面后,在右侧 Modules 窗口搜索需要调试的库:libnative-test.so;

双击,跳转到对应的 so 库,即可看到 so 库里的方法,搜索方法:myCheck();

双击函数名,跳转到对应的函数代码,F5,与静态分析看到的 myCheck 方法相同;

在比较处下断:

5、开始调试:

注意,要求输入字符串长度为 32,因此输入:flag{11111111111111111111111111};

程序在断点处停下,先查看 enc:

再查看 v38(在栈上):

通过 python 脚本复制:

from idaapi import *bytes_addr = 0xCFFFD6F8bytes_size = 32data = get_bytes(bytes_addr,bytes_size)L = [hex(ch) for ch in data]print (L)# 假密文#['0xdd', '0x9f', '0x58', '0xb3', '0x72', '0x80', '0xef', '0x96', '0xc1', '0x2', '0x3b', '0xfe', '0x97', '0xc', '0x39', '0x94', '0x43', '0xaf', '0xac', '0x78', '0xf8', '0x59', '0x4c', '0x84', '0x68', '0x2a', '0xe4', '0x86', '0x68', '0x9c', '0xd2', '0x13']

6、至此,可通过脚本计算出 flag:

enc = [0x8C, 0x0C4, 0x0, 0x0E6, 0x6A, 0x88, 0x0B8, 0x90, 0x0C2, 0x7, 0x6B, 0x0A9, 0x0C3, 0x0A, 0x3E, 0x0C0, 0x44, 0x0A6, 0x0FE, 0x7E, 0x0F0, 0x59, 0x4C, 0x83, 0x3D, 0x2B, 0x0E2, 0x0D3, 0x38, 0x0CB, 0x82, 0x5B] fake_flag = "flag{11111111111111111111111111}" fake_flag_cipher = [0xdd, 0x9f, 0x58, 0xb3, 0x72, 0x80, 0xef, 0x96, 0xc1, 0x2, 0x3b, 0xfe, 0x97, 0xc, 0x39, 0x94, 0x43, 0xaf, 0xac, 0x78, 0xf8, 0x59, 0x4c, 0x84, 0x68, 0x2a, 0xe4, 0x86, 0x68, 0x9c, 0xd2, 0x13] for i in range(32):    print(chr(ord(fake_flag[i])^fake_flag_cipher[i]^enc[i]), end='')# 7792c9f724afe76e68c79116d07dafa5

7、提交验证:

over!

dataida
本作品采用《CC 协议》,转载必须注明作者和本文链接
源码分析1、LLVM编译器简介LLVM 命名最早源自于底层虚拟机的缩写,由于命名带来的混乱,LLVM就是该项目的全称。LLVM 核心库提供了与编译器相关的支持,可以作为多种语言编译器的后台来使用。自那时以来,已经成长为LLVM的主干项目,由不同的子项目组成,其中许多是正在生产中使用的各种 商业和开源的项目,以及被广泛用于学术研究。
可以看到有两个printf函数打印了一些数据出来,我们点第一个打印的字符串。
STL容器逆向与实战
2023-02-08 09:53:04
当然可能还存在许许多多的STL容器,但是大体的分析思路是类似的。
安卓加固脱壳分享
2023-04-03 10:04:45
smali不熟悉的话,可以反编译dex再转jar 直接用java gui看java代码。首先启动ida server 为了防止被检测到,最好将 android_server 改一个名字。执行此命令后,手机上会提示 Walting For Debugger 字样。因为我们是以调试方式启动,所以 apk 在运行后 PC会在第一条指令处等待?因为我们要看他加载哪个so来解密so和dex文件。所以要勾选加载LIB时中断。如果是多个so解密dex,这样我们还能观察几个解密so的加载顺序。选择相应的包名。等待状态,这时?需要使用 JDB唤醒进程。
target_func: sark.Function 类型,表示要查找交叉引用关系的目标函数对象。max_depth: int 类型,表示查找引用关系的最大深度。② 然后根据 include_data_xref 的设置,获取该函数中所有的引用 refes。③ 遍历函数的所有引用 ref,如果该引用 ref 指向目标函数,则在有向图 G 中通过 add_edge 函数添加一条从当前函数到目标函数的边,并返回 True。④ 如果引用指向另一个函数,则递归调用 find_cross_refs 函数查找两个函数之间的交叉引用关系。⑤ 如果所有引用遍历完,仍然没有找到交叉引用,则返回 False。
IDA Pro是反汇编程序 反汇编程序用于将机器代码转换为人类可读的格式,称为汇编语言。我们每天使用的软件的源代码并不总是可用。像IDA Pro这样的反汇编程序能够创建其执行的映射,以显示处理器实际以称为汇编语言的...
近期接着之前的进度终于啃完了这一章,这里给大家继续同步K A, Monnappa.《Forensic Learning Malware Analysis》精要翻译,以及翻译过程中的一些小实践记录。
1背景最近有统计覆盖率信息的需求,多方搜索后发现IDA插件Lighthouse具有统计覆盖率的功能,通过读取DynamoRIO或者Pin产生的覆盖率日志文件,在IDA中以图形化形式展现代码的详细执行路径。
巧解一道CTF Android题
2022-08-10 16:15:40
无须还原代码,穷举爆破。我们打开jeb工具,定位到当前activity。我们看一下saveSN方法,可以看到这是一个native方法。我们解包一下apk,获取到so文件。下面进入ida分析。导出函数并没有相关java的native方法,说明是动态注册。我们看下JNI_ONLOAD函数:jint JNI_OnLoad{ if ( !
EXP编写学习之绕过GS
2023-02-20 09:58:16
栈中的守护天使 :GSGS原理向栈内压入一个随机的DWORD值,这个随机数被称为canary ,IDA称为 Security Cookie。Security Cookie 放入 ebp前,并且data节中存放一个 Security Cookie的副本。栈中发生溢出时,Security Cookie首先被淹没,之后才是ebp和返回地址。函数返回之前,会添加一个Security Cookie验证操作,称为Security Check。检测到溢出时,系统将进入异常处理流程,函数不会正常返回,ret也不会被执行。函数使用无保护的关键字标记。缓冲区不是8字节类型 且 大小不大于4个字节。可以为函数强制启用GS。
VSole
网络安全专家