小工具      在线工具  汉语词典  css  js  c++  java

Android问题的逆向动态调试

android,adb 额外说明

收录于:40天前

该题来自海淀区网络与信息安全管理员大赛。题中将加密验证算法封装到.so中,并在程序中动态调用check。

本题通过System.loadLibrary("native-lib")加载libnative-lib.so文件,可以通过jeb提取

图1 问题关键代码

调试环境选择与配置

  • mumu模拟器x64位版本,经测试发现sprintf会导致程序崩溃

  • 在测试了叶神模拟器的x64和x32版本后,sprintf导致程序崩溃。

  • 测试Thunderbolt 5模拟器后,sprintf导致程序崩溃。动态调试libnative-lib.so时,无法下载libart.so。

  • 最后选择mumu x32位版本进行调试。

  • 动态调试使用IDA+MUMU x86模拟器调试动态库libnative-lib.so

    调试环境

    adb的基本配置

  • mumu模拟器使用的adb是adb_server.exe。这里,为了方便使用,将adb_server.exe更名为adb.exe。打开 cmd 终端并将 adb 连接到模拟器。

adb connect 127.0.0.1:7555

图2 adb服务器连接

  • 通过adb将apk包安装到Android模拟器中

adb install test.apk
  • 通过cmd再打开一个终端,通过adb shell可以直接进入到模拟器shell中

图3 adb shell连接

应用配置

  • 在新的cmd终端中,通过动态调试方式启动应用程序

./adb shell am start -D -n com.example.dynamic/.MainActivity
  • android包的实际包和类如下图com.example.dynamic/.MainActivity

图4 adb启动程序分析

  •  运行 adb shell am start命令后,mumu模拟器中如图5所示

    图5 adb动态调试器

IDA配置

  • 将IDA的动态服务器android_x86_server上传到模拟器/data/local/tmp。 tmp文件夹具有可执行权限

./adb push android_x86_server /data/local/tmp

图6 查看tmp文件夹权限

  • 授予 android_x86_server 可执行权限

chmod +x android_x86_server
  • 执行android_x86_server会监听23946端口,但是仍然需要通过adb转发到本地监听进行端口转发。

./adb.exe forward tcp:23946 tcp:23946

图7 启动IDA调试服务器端

  • 使用上述步骤启动服务器端IDA的监控。

  • 配置本地IDA远程linux调试参数,如图8

图8 配置IDA动态调试

  • 通过attach进程打开远程进程

图 9 IDA 远程连接

  • 选择对应的进程,这里我们选择1535进程

图10 Attach到指定进程

  • 通过上述步骤,IDA服务器和.so文件关联在一起,被调试的程序仍然需要被唤醒。此时mumu模拟器依然如图11所示

图11 动态程序界面

  • 通过jdb唤醒被调试的程序。在本机调试时,jdb使用java sdk自带的jdb,需要两步。

    • 通过adb转发进程。进程号为1535,如图n所示。

./adb forward tcp:8700 jdwp:1535
  • 通过jdb唤醒操作

jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700
  • 返回IDA,选择F9继续运行程序,会弹出一个框选择本地程序是否与远程程序相同。主要匹配的是动态库libnative-lib.so的名称。

图12 IDA提示检测到本地.so

  • • IDA中断点断在ptrace前,mumu模拟器中界面未完全同步

图13 附加到调试进程后的动态界面

  • IDA中的界面如下

图 14 IDA 中显示的断点

.so 的调试

反调试绕过

  • 这个.so使用了ptrace反调试。在 ptrace 处设置断点。设置断点时有两种选择。

    1. 1.一是设置IDA调试,加载lib时设置挂起。

图15 IDA调试选项配置

  • 当看到IDA中载入libnative-lib.so时,通过快捷键Ctrl-S打开加载的段,查找libnative-lib.so所在内存1

    图16 在ID​​A中查看代码片段

  • 还可以在模拟器shell中查看具体内存信息

图17 在adb shell中查看数据在内存中的地址分布

  • 动态调试时,通过重置ptrace的返回值来绕过反调试。

图18 重置eax的值

可以直接右键或者使用快捷键0来重置eax寄存器。

  • 另一种方法是直接在ptrace的上方和下方设置断点。调试时,当IDA弹出窗口如图17所示时,程序会直接在ptrace断点处中断。如果没有弹出弹窗,说明直接在IDA中分析so时当前断点无效。

图片-20221125160753773

图19 重置eax的值

注册原生方法

  • Native文件中的代码如下

static JNINativeMethod jniMethods[] = {
 {"check", "(Ljava/lang/String;)Z", (void *)hello},
};
boolean xxxx( char* s) {
 // do something
 return JNI_TRUE;
}
#在JNI_OnLoad中调用RegisterNatives方法注册Natives方法到JVM,建立映射关系。
int JNI_OnLoad(JavaVM *vm, void *reserved)
{
    JNIEnv *env;
    if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
        return JNI_ERR;
    }

    jclass cls = (*env)->FindClass(env, "LHelloJNI");
    if (cls == NULL)
        return JNI_ERR;

    int len = sizeof(jniMethods) / sizeof(jnimethods[0]);
    (*env)->RegisterNatives(env, cls, jniMethods, len);

    return JNI_VERSION_1_4;
}

检查功能的定位

  • 在apk文件中,反编译后可以看到check函数位于libnative-lib.so中,但是libnative-lib.so中没有check函数

图20 查找检查功能

  • Java可以通过静态注册和动态注册来调用.so库函数。问题是通过动态注册来调用该函数。

  • 上图中,methods 列是 JNINativeMethod 的数组。 JNINativeMethod 结构包含三个成员。

const char \*name: Java中声明的native方法。
const char \*signature:方法的签名。
void \*fnPtr: 函数指针
  • • 问题的方法中,检查字符串,对应的函数指针为_Z4xxxxP7_JNIEnvP8_jobjectP8_jstring; xxxx(_JNIEnv *,_jobject *,_jstring *) 是 xxxx 函数。

图21 定位检查功能

MD5的简单调试

  • MD5_init的流程如下。根据初始值,可以大致确定问题,并通过md5计算哈希值。

*(_OWORD *)v63 = xmmword_B2E6FA40;
.rodata:B2E6FA40 xmmword_B2E6FA40 xmmword 1032547698BADCFEEFCDAB8967452301h
  • fff函数转换后的md5值放在[esp+0B4]中

.text:B2E51040 8D 84 24 B4 00 00 00    lea     eax, [esp+0B4h]
.text:B2E51047 89 44 24 04             mov     [esp+4], eax
.text:B2E5104B 8D 44 24 58             lea     eax, [esp+58h]
.text:B2E5104F 89 04 24                mov     [esp], eax
.text:B2E51052 E8 A9 E7 FF FF          call    __Z4ffffP7MD5_CTXPh ; ffff(MD5_CTX *,uchar *)
  • 读取[esp+0xB4]的值

Python>esp=get_reg_value('esp')
Python>data=get_bytes(esp+0xb4,16)
Python>data.hex()
'a82e0cb168bfe134f22dbde167cf046c'
  • 计算wojiushidaan0的md5值!!!通过 python 作为

>>> import hashlib
>>> result=hashlib.md5("wojiushidaan0!!!".encode())
>>> result
<md5 _hashlib.HASH object @ 0x00000167FF8BDEF0>
>>> result.hexdigest()
'a82e0cb168bfe134f22dbde167cf046c'
  • 两者可以相互关联。题目计算wojiushidaan0的md5值!!!

  • 当程序最终与memcmp进行比较时,值为

.text:B2F11398 89 54 24 08             mov     [esp+8], edx
.text:B2F1139C 8B 44 24 14             mov     eax, [esp+14h]
.text:B2F113A0 89 44 24 04             mov     [esp+4], eax    ; s2
.text:B2F113A4 89 0C 24                mov     [esp], ecx      ; s1
.text:B2F113A7 E8 84 E4 FF FF          call    _memcmp
  • 将 eax 的值提取为

b'c640fc761edbd22f431efb861bc0e28a'
  • 将 ecx 的值提取为

b'12345678123456781234567812345678'
  • 程序的输入是

图22 调试标志结果

  • 可以推断问题的正确输入是

标志{c640fc761edbd22f431efb861bc0e28a}

图23 验证标志结果

  • 在调试md5时,利用IDA的着色功能,通过单步调试对执行的代码进行着色。

  • IDAPro逐步执行调试脚本

def get_new_color(current_color):
  colors = [0xffe699, 0xffcc33, 0xe6ac00, 0xb38600]
  if current_color == 0xFFFFFF:
    return colors[0]
  if current_color in colors:
    pos = colors.index(current_color)
    if pos == len(colors)-1:
      return colors[pos]
    else:
      return colors[pos+1]
  return 0xFFFFFF

addr = ida_dbg.get_ip_val()
while addr < 0xB2ED241F:
  event = wait_for_next_event(WFNE_ANY, -1)
  t = step_over()
  addr = ida_dbg.get_ip_val()
  current_color = get_color(addr, CIC_ITEM)
  new_color = get_new_color(current_color)
  set_color(addr, CIC_ITEM, new_color)

#https://www.cnblogs.com/blacksunny/p/7300271.html参考踪迹修改后的step over

需要改进的方面

  • 绕过反调试依赖于动态调试期间修改寄存器实现

. . .

相关推荐

额外说明

PostgreSQL 11 新特性之快速增加包含非空默认值的列

文章目录 在 PostgreSQL 11 之前,为表增加一个包含非空默认值的字段,将会导致表数据的重新写入,为每一行添加该字段,并且填充默认值。如果针对大表执行这种操作,将会非常耗时。 以下是一个 PostgreSQL 10 中添加字段(包含非空默认值)

额外说明

使用PLSQL Developer工具连接oracle

1、先按照常规安装PLSQL Developer。我这里安装的是64位的,安装目录为:D:\Program Files\PLSQL Developer   2、运行“plsqldev.exe”,运行PLSQL Developer,弹出框如下: 稍微看一下

额外说明

MFC弹出确认和取消对话框

UINT flag; flag = MessageBox(TEXT("确认要退出程序吗?"), TEXT("温馨提示"), MB_YESNO | MB_ICONQUESTION); if (flag == IDNO) { return; } ![在这里

额外说明

【Web前端开发】CSS中最常用的11个选择器

文章目录 1.CSS介绍 2.CSS的语言规则 3.CSS的引入方式 4.选择器 4.1 标签选择器 4.2 类选择器 4.3 id选择器 4.4 通配符选择器 4.5 复合选择器 4.5.1 后代选择器 4.5.2 子代选择器 4.6 并集选择器 4.

额外说明

Dockerd的迁移与备份

1、容器保存为镜像 (1) 通过以下命令将容器保存为镜像 # 保存nginx容器为镜像 docker commit 容器名称 镜像名称 例如:docker commit mynginx mynginx_i (2)用 docker ps -a 查看所有

额外说明

面向对象--封装 demo 练习

封装是面向对象的三大特征之一,它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。 封装可以实现以下目的: 1、 隐藏类的实现细节 2、 使用者只能通过提供的方法来访问数据,

额外说明

国科大.高级人工智能.2022期末考试真题回忆版

选择 通过图灵测试意味着? 图神经网络 因果中的条件独立性判断 GAN tanh的曲线 哪一个是时序差分? 判断 启发函数的可采纳、一致的含义 广搜是代价一致搜索的特例 贪心搜索是A星算法的特例 爬山法的概念 大题 设计RNN网络用于法语翻译 格子游戏

额外说明

zookeeper入门——(二)

1.完全分布式的zookeeper安装: 1.如果你启动了zookeeper,需要把zookeeper停止。进入到zookeeper的bin目录下,输入命令jps查看是否有QuorumPeerMain,没有则说明关闭了。 2.回到/home/softwa

额外说明

Windows系统缺少MSVCP60.DLL文件导致程序无法运行问题

其实很多用户玩单机游戏或者安装软件的时候就出现过这种问题,如果是新手第一时间会认为是软件或游戏出错了,其实并不是这样,其主要原因就是你电脑系统的该dll文件丢失了或没有安装一些系统软件平台所需要的动态链接库,这时你可以下载这个MSVCP60.DLL文件(

额外说明

如何为WordPress安装和设置简单的Facebook Connect

One of our users over at 我们的 Facebook 社区页面 asked us to cover the installation and setup of Simple Facebook Connect plugin for W

ads via 小工具