Android逆向实战过掉MoMo签名验证和反调试

2023-11-27 10:59

本文主要是介绍Android逆向实战过掉MoMo签名验证和反调试,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

大家好,我是老袁,一名逆向分析人员,现主要研究Android平台逆向;今天给大家分享一篇,如何过掉MoMo的签名验证和C++层反调试。大神勿喷。

一、使用环境及工具

1.系统:windwos 10(x64)
2.设备:Google nexus 5真机。
3.反编译工具:

    Android Studio 3.2   开发和调试smali代码IDA pro 7.0          分析elf文件jeb                  Apk反编译集成工具(代码质量高)jadx‐gui             dex直接转换成java代码(代码质量高)ApkTools             集成了baksmali和smaliApkDB                将smali代码反编译成dex文件,并重新签名APK(自己编写)

4.抓包工具:Charles
5.分析的样本:com.immomo.momo_8.9.8.apk

二、开启日志信息

一般大型的应用都会自定义自己的日志系统,当发布时只需要去掉打印日志的标志即可,所以我一开始就是去找它的日志接口。通过 jadx打开APk随便打开一段代码,根据日志输出,即可定位到日志的类。
e1e8fdafb47c43a290e8a2a8ff87c357.png
9bb798d3c5de45c3a009eeb56d44455e.png

直接修改上面代码对应的smali代码:

image.png
image.png

三、回编译

现在很多的应用都对自己的APK做了反回编译处理,也就是修改完代码后使用回编译工具回编译时,出现各种错误。例如:对微信做回编译时,资源文件就有问题,实际上是它的资源文件解压库的问题(参见微信开源的资源压缩库[减小APK的体积])。

针对于上面的问题,我自己写了一个工具,大概的原理就是:只处理了APK里面的DEX文件和签名文件。
现在的APK基本上都有采用拆分DEX技术(由于Dex的设计缺陷,一个DEX最多只能保存的类大小为65535),所以反编译后会对应多个smali文件夹。
image.png

该回编译工具的大致实现思路:
  1. 使用smali.jar 针对于某一个smali文件,回编译成功后生成与smali文件夹名字一致的DEX文件。
  2. 使用压缩算法读写APK文件,替换对应的DEX文件。
  3. 在替换完成后,删除压缩包里面的签名文件(META-INF)
  4. 使用签名工具,对新的APK重新签名
    0eecc2e5a09e4e5f9d1f53e8d674aecf.png

四、过签名验证

在上一步中,我已经成功将APK回编译,但是在安装成功后,当我登录时,出现了如下对话框(在线的签名校验)。
5a07c8b3b0b54823ab9451b6d234785b.png

有了这个提示:怎么分析呢?

有几个思路:

  1. 在代码中搜索关键字符串。(可惜找不到,后来验证为从服务端传回来的)
  2. 搜索Java层获取签名信息的方法。(同样找不到,是在C++中获取的)
  3. 分析对话框(每个对话框最后显示都要调用show方法)
    我在跟踪show中,找到了发送消息的函数,从发送的消息中获取到,其中有一个字段中保存了APK的签名信息。
    image.png
    断在弹出对话框代码处
    image.png

根据栈回溯,跟踪找到了向服务器发送的数据
image.png

最后成功找到加密前的数据,在登录时一共获取了43个字段,其中包含了用户名,密码和签名信息等。
image.png
其中有21个字段是从MomoKit.a()中获取到的,其中就包含了签名信息。
image.png
在这个方法中,Codec.Des()解密出“apksign”字符串,Momokit.k()获取出正在的签名信息。
正常APK的签名:“apksign” -> “4f3a531caff3e37c278659cc78bfaecc”,所以我直接写死它。
image.png

最后再重新回编译和重新签名,能够成功安装,并且能成功登陆。

这里需要注意:获取签名信息的类和打印日志的类不在同一个DEX文件中,所以需要在修改过日志的APK的基础上进行修改,我写的工具一开始没有考虑过这个问题,所以我又重新进行了修改,现在可以一键回编译所有的DEX文件了。

五、过C++层的反调试

在分析协议的时候,我找到了关键的加解密函数,于是打算通过Hook框架Hook关键的函数并输出它的结果,但是它对Xposed Hook框架(基于注入的方式,只能针对于Java层)有检查,Hook不成功,然后改为用Frida Hook框架(基于调试的方式,支持C++和Java层,并且不仅适用于移动端),还是不成功,最后我只能拿出大杀器(IDA)来找它反调试的地方,一开始由于环境的问题,光是基于IDA调试的环境我都搭建了很久。

在我成功附加上其进程后3秒不到,提示警告接着调试断开,在网上找到了相关的介绍;(网上文章:Android Native Crash [收集 一个异常的处理接口]) 在MoMo C++的代码中大概有100多个地方在检查自己是否有被其他进程附加,如果有就产生异常。

代码如下:
在这里插入图片描述

这样的代码一共在7个so文件中有上面的代码:libsmses.so,libsevenz.so,libmkjni.so,libmjni.so,libcoded_jni.so,libcoded.so,libbsdiff.so。

一开始我是手动修改了几处fopen后面的跳转(if(v9)),让获取状态的代码都不执行,但是编译后发现程序加载不了图片(当然替换so文件,也可以用我写的那个工具,只是需要手动的打开APK包替换掉目标so文件,然后回编译重新签名)。

最后我还是选择只修改上图中“JUMPOUT”也就是“pop {R0-R2,pc}”将这两个字节的代码直接nop掉,但是这样的代码一共有大概100多处,光修改就要差不多两个小时,而且还不确定还有没有其他问题,所以我选择花两个小时学IDA的IDAPython脚本编写。

脚本代码如下:(IDA默认安装python 2.7)

import idautilsdef Main():pattern = '0x07 0xBD'        #pop {R0-R2,pc}addr    = MinEA()first   = Falseindex   = 0firstaddr = idc.FindBinary(addr, SEARCH_NEXT, pattern)for x in xrange(0,30):addr = idc.FindBinary(addr, SEARCH_NEXT, pattern)if addr == -1:continueif first == True:if firstaddr == addr:breakprint '------------------- %d --------------------------'%xprint 'addr:%s' % hex(addr)print 'firstaddr:%s'%hex(firstaddr)if addr != idc.BADADDR:find_start = addr-0x100find_end   = addrprint "funcstart:%s funcend:%s"%(find_start,find_end)cur_first      = Falsecur_first_addr = idc.FindText(find_start, SEARCH_DOWN, 0, 0, 'TracerPid')while find_start < find_end:cur_addr = idc.FindText(find_start, SEARCH_DOWN, 0, 0, 'TracerPid')if cur_first == True:if cur_addr == cur_first_addr:breakif cur_addr == idc.BADADDR:breakelse:print "  TracerPid %s %s"%(hex(cur_addr), idc.GetDisasm(cur_addr))print "  nop_cpde:%s %s"% (hex(addr),idc.GetDisasm(addr))idc.PatchByte(addr,0x00)     # 因为nop只需要1个字节,所以另一个用BFidc.PatchByte(addr+1,0xBF)print "  ----------"print "new_code:%s %s"%(hex(addr),idc.GetDisasm(addr))index += 1cur_first_addr = cur_addrcur_first      = Truecur_addr       = idc.NextHead(find_start)first     = Truefirstaddr = addrprint "find index:%d"%indexMain()

上面的代码能够成功的将一个so文件中所有符合要求的“pop {R0-R2,pc}”nop掉。

当修改完成后,先保存,再dump出so文件。(这是IDA的一个特点,在界面上修改的数据,只是修改了它为真实文件创建的数据库文件而已)。

这里顺便介绍一下IDA的两个插件:KeyPatch(能够直接输入对应的汇编代码),Patch Program(dump功能)。

KeyPatch修改代码

在这里插入图片描述

Program dump出so(在Dump之前一定要先保存数据)

6132e27410504a24912a547613365092.png
image.png

最终成功可以调试C++的代码了,下面是跟踪加密算法的位置
在这里插入图片描述

六、总结

上面的内容就是今天要分享的,由于我是第一次写文章,写的不好,希望大家见谅,并且对平台的排版工具不太熟悉,暂时就只能这样了,我这篇文章里面涉及的知识比较多,可能对初学者来说有点难度,不过没关系,我会在后面的文章中,一点一点的剖析这篇文章里面的知识。感兴趣的同学可以关注我的公众号,欢迎来扰。
在这里插入图片描述

这篇关于Android逆向实战过掉MoMo签名验证和反调试的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/427540

相关文章

SpringBoot整合 Quartz实现定时推送实战指南

《SpringBoot整合Quartz实现定时推送实战指南》文章介绍了SpringBoot中使用Quartz动态定时任务和任务持久化实现多条不确定结束时间并提前N分钟推送的方案,本文结合实例代码给大... 目录前言一、Quartz 是什么?1、核心定位:解决什么问题?2、Quartz 核心组件二、使用步骤1

SpringBoot整合AOP及使用案例实战

《SpringBoot整合AOP及使用案例实战》本文详细介绍了SpringAOP中的切入点表达式,重点讲解了execution表达式的语法和用法,通过案例实战,展示了AOP的基本使用、结合自定义注解以... 目录一、 引入依赖二、切入点表达式详解三、案例实战1. AOP基本使用2. AOP结合自定义注解3.

Python数据验证神器Pydantic库的使用和实践中的避坑指南

《Python数据验证神器Pydantic库的使用和实践中的避坑指南》Pydantic是一个用于数据验证和设置的库,可以显著简化API接口开发,文章通过一个实际案例,展示了Pydantic如何在生产环... 目录1️⃣ 崩溃时刻:当你的API接口又双叒崩了!2️⃣ 神兵天降:3行代码解决验证难题3️⃣ 深度

Android使用java实现网络连通性检查详解

《Android使用java实现网络连通性检查详解》这篇文章主要为大家详细介绍了Android使用java实现网络连通性检查的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录NetCheck.Java(可直接拷贝)使用示例(Activity/Fragment 内)权限要求

Java 队列Queue从原理到实战指南

《Java队列Queue从原理到实战指南》本文介绍了Java中队列(Queue)的底层实现、常见方法及其区别,通过LinkedList和ArrayDeque的实现,以及循环队列的概念,展示了如何高效... 目录一、队列的认识队列的底层与集合框架常见的队列方法插入元素方法对比(add和offer)移除元素方法

Spring Boot基于 JWT 优化 Spring Security 无状态登录实战指南

《SpringBoot基于JWT优化SpringSecurity无状态登录实战指南》本文介绍如何使用JWT优化SpringSecurity实现无状态登录,提高接口安全性,并通过实际操作步骤... 目录Spring Boot 实战:基于 JWT 优化 Spring Security 无状态登录一、先搞懂:为什

C++11中的包装器实战案例

《C++11中的包装器实战案例》本文给大家介绍C++11中的包装器实战案例,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录引言1.std::function1.1.什么是std::function1.2.核心用法1.2.1.包装普通函数1.2.

Nginx概念、架构、配置与虚拟主机实战操作指南

《Nginx概念、架构、配置与虚拟主机实战操作指南》Nginx是一个高性能的HTTP服务器、反向代理服务器、负载均衡器和IMAP/POP3/SMTP代理服务器,它支持高并发连接,资源占用低,功能全面且... 目录Nginx 深度解析:概念、架构、配置与虚拟主机实战一、Nginx 的概念二、Nginx 的特点

Spring IOC核心原理详解与运用实战教程

《SpringIOC核心原理详解与运用实战教程》本文详细解析了SpringIOC容器的核心原理,包括BeanFactory体系、依赖注入机制、循环依赖解决和三级缓存机制,同时,介绍了SpringBo... 目录1. Spring IOC核心原理深度解析1.1 BeanFactory体系与内部结构1.1.1

2025最新版Android Studio安装及组件配置教程(SDK、JDK、Gradle)

《2025最新版AndroidStudio安装及组件配置教程(SDK、JDK、Gradle)》:本文主要介绍2025最新版AndroidStudio安装及组件配置(SDK、JDK、Gradle... 目录原生 android 简介Android Studio必备组件一、Android Studio安装二、A