Android 逆向实践

Android 逆向实践

前言

五一放假回来,人有点颓废了,最近对Android的逆向有点兴趣,研究了下,顺便写篇文章记录下吧。

工具下载

apktool

apktool可以对APK反编译和重新打包,经过反编译后我们可以改里面的资源,或者改里面的smali字节码,通过重新打包后修改能生效,但是得重新签名。

相关下载和文档:

apktool.jar下载

apktool.bat脚本

安装说明

这里我们用自己创建个apktool.bat文件,里面填上脚本内容,apktool.bat比直接使用apktool.jar方便一点,而且能判断反编译结束。

jadx-gui

apktool可以反编译和重新打包,但是没办法直接查看Java代码,要理解里面的逻辑就需要用到jd-gui或者jadx-gui了,jd-gui只是一个jar包,jadx-gui基于它,但是用起来更方便。

jadx-gui可以得到Java代码,里面还能对资源代码等全局搜索,方法点击能跳转,不太方便的就是它不能直接修改,只适用于阅读,修改还是得apktool。

相关下载和文档:

jadx-gui下载

ja-gui下载

注意下Java版本吧。

dex2jar

实际上用上面两个工具就可以完成代码阅读及修改了,dex2jar是用来将apk或者dex文件转成jar的,后面也能将jar转回dex文件。

相关下载和文档:

dex-tools一系列工具

我试了下,用来解包multidex的APP好像不太好使,看网上别人说是支持的,我最后还是没用到它。

APK解包

首先要逆向,我们就要对apk进行解包,工具选择apktool,使用命令:

shell 复制代码
apktool.bat d filename.apk

这里我们最好把我们上面的一些工具放到环境变量的path里面去,使用工具就不用输入完整路径了。

这里就用我们公司的破打卡软件为例,输入命令后,等待一段时间,看到"Press any key to continue"就解包结束了:

这时候就可以关闭shell窗口了,提示"processes are running in session"可以不用管,点OK就行:

接下来就可以看到解包的目录了:

这就看需要了,改点图片和资源,去res和asset里面改就行了,要改源码就麻烦点了,后面再讲。

APK源码阅读

源码阅读需要用到jadx-gui,直接打开软件,选择APK打开就行了(不是上一步解包的文件夹),转一会就可以看到源码了:

和Android studio打开apk差不多,不同的是AS只能看字节码,而这里可以看Java代码。

APP代码修改

反编译一个APP的目标当然是改它嘛,下面就来看看一些常见的修改。

资源文件修改

字符串(res/value-xx/string)、图片(asset、res/drawable-xx、minmap)、布局(res/layout)之类的直接到文件里面改,和开发Android目录差不多。

比如想改个版本号,打开apktool.yml文件,拉到最下面就能改了:

比如有些老代码,源码都丢了,但是签名文件还有,就能这样升级了。

打开调试模式

一般release的包是没法调试的,如果有需求可以在AndroidManifest.xml里面修改:

xml 复制代码
<application android:debuggable="false" android:allowNativeHeapPointerTagging="false"
    ...

找到application这两个属性,改成true,就可以打开调试模式了,后面我们在smali里面插入Log也就能显示了。

绕过签名验证

有时候APP会增加签名校验,说白了就是获取本应用的签名和预设的签名文件的MD5值或者SHA值对比,如果不一样那就闪退。

下面拿一个打卡软件为例,说下过程,读者可以举一反三。它这校验失败的时候还提示了一个对话框:

这是很好的一个切入口,我们到jadx-gui里面ctrl + shift + F,全局搜索这句话:

知道这条string的资源名,就能继续搜索代码所在位置了:

这个代码意图够明显了吧,而且没有混淆,稍微动一动就能绕过了,不过注意做一个遵纪守法的好公民!改别人软件是不道德,甚至违法的!

smali字节码操作

虽然不能做违法操作,但是学习下如何操作smali字节码,还是很有意义的。

smali字节码简单学习

我叫它smali字节码还是不对的,它应该叫Dalvik 字节码,说白了就是Dalvik/AndroidRuntime这个虚拟机要执行的字节码,虽然它们也是JVM,但是却又不完完全全是,可以看下官方文档:

官方文档

下面就实践下。

修改方法

虽然jadx-gui里面会提示一个类来自哪个dex文件里面,但是还是比较麻烦,我们可以使用IDE来打开这个解包文件夹:

java 复制代码
/* loaded from: classes7.dex */
public class WelcomeActivity extends com.weaver.platform.BaseActivity

比如使用Visual Studio打开来,通过Ctrl + P就能跳转到文件了,虽然用Android Studio配合双击shift也行,但是AS用起来太卡了。

对于一个方法内的代码,我们可以根据行数随便删除,不过注意下返回值,下面是smali字节码删除前后:

java 复制代码
.method private isTwickPack()Z
    .registers 6

    const/4 v0, 0x0

    .line 418
    :try_start_1
    invoke-virtual {p0}, Lweaver/fw/com/WelcomeActivity;->getApplicationInfo()Landroid/content/pm/ApplicationInfo;
    
    // ...

    .line 461
    invoke-virtual {p0}, Ljava/lang/Exception;->printStackTrace()V

    :cond_85
    return v0
.end method

删除部分代码后:

java 复制代码
.method private isTwickPack()Z
    .locals 1

    const/4 v0, 0x0

    return v0
.end method

实际就是要注意下返回的变量,这里"const/4 v0, 0x0",就是创建了一个变量,里面赋值false并返回。

修改变量

比如说我们有个类的私有变量,想给它赋个初值:

java 复制代码
private String proLocationData;

那么只要找到它的构造方法,在里面设置就行:

java 复制代码
.method public constructor <init>()V
    .locals 6
    
    // ...
    
    const-string v1, "{"type":"wgs84","errCode":0,"errMsg":"get LocationAddress Success"}"

    .line 16681
    iput-object v1, p0, Lcom/weaver/platform/fragment/WebViewFragment;->proLocationData:Ljava/lang/String;

要修改局部变量也同理,先创建一个常量,再赋值过去就行。不过要注意下,如果string内部有中文,要转换下。

打印日志

说实话,日志函数实际就是一个静态方法,用起来只要传递两个变量进去就行了,但是要注意下把对象toString再输出,举个例子:

java 复制代码
val jSONObject = JSONObject()
jSONObject.put("type", "wgs84")
Log.d("TAG", jSONObject.toString())

对于的smali字节码如下:

java 复制代码
.line 24
new-instance v0, Lorg/json/JSONObject;

invoke-direct {v0}, Lorg/json/JSONObject;-><init>()V

.line 25
.local v0, "jSONObject":Lorg/json/JSONObject;
const-string v1, "type"

const-string v2, "wgs84"

invoke-virtual {v0, v1, v2}, Lorg/json/JSONObject;->put(Ljava/lang/String;Ljava/lang/Object;)Lorg/json/JSONObject;

.line 26
const-string v1, "TAG"

invoke-virtual {v0}, Lorg/json/JSONObject;->toString()Ljava/lang/String;

move-result-object v2

invoke-static {v1, v2}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I

其实忽略jSONObject的toString过程,我们只要实现Log的invoke-static操作就可以了。

一些技巧

这里给一些我摸索出来的技巧吧,希望有所帮助

利用AS编写代码来替换

这个smali字节码看起来真的头疼,如果不知道怎么改的话,可以在另一个APP里面编写代码,然后打包下,用AS打开APK,参考里面的写法就行。

利用Visual Studio插件验证语法

Visual Studio里面有smali语法的插件,可以帮忙验证写法有没有问题。

利用代码行号定位

在jadx-gui里面我们可以看到代码对应的行数,这就能让我们快速的定位smali文件里面的位置,配合Java的方法签名,还是能较快理解代码的。

匿名函数说明

在看smali文件的时候,经常会碰到各种匿名函数,就很烦,数量很多,找起来麻烦,虽然用Visual Studio的ctrl+P可以快速跳转文件,但是这些个access方法还是很累人:

java 复制代码
// 在WebViewFragment$82中拿到WebViewFragment的locationUtil变量,并执行它的destroyLocation方法
.line 6005
iget-object p1, p0, Lcom/weaver/platform/fragment/WebViewFragment$82;->this$0:Lcom/weaver/platform/fragment/WebViewFragment;

invoke-static {p1}, Lcom/weaver/platform/fragment/WebViewFragment;->access$5600(Lcom/weaver/platform/fragment/WebViewFragment;)Lcom/weaver/platform/util/LocationUtil;

move-result-object p1

invoke-virtual {p1}, Lcom/weaver/platform/util/LocationUtil;->destroyLocation()V

还要配合搜索功能,在WebViewFragment.smali里面搜索5600,看看他是干嘛的:

java 复制代码
.method static synthetic access$5600(Lcom/weaver/platform/fragment/WebViewFragment;)Lcom/weaver/platform/util/LocationUtil;
    .locals 0

    .line 378
    iget-object p0, p0, Lcom/weaver/platform/fragment/WebViewFragment;->locationUtil:Lcom/weaver/platform/util/LocationUtil;

    return-object p0
.end method

.method static synthetic access$5602(Lcom/weaver/platform/fragment/WebViewFragment;Lcom/weaver/platform/util/LocationUtil;)Lcom/weaver/platform/util/LocationUtil;
    .locals 0

    .line 378
    iput-object p1, p0, Lcom/weaver/platform/fragment/WebViewFragment;->locationUtil:Lcom/weaver/platform/util/LocationUtil;

    return-object p1
.end method

实际就是getter和setter方法嘛,只不过,阅读起来很影响体验。

APK重新打包

上面修改号自己想要的东西后,我们就可以,给它打包回去了,还是用apktool,命令如下:

shell 复制代码
apktool.bat b file-dir

经过一段时间,就能在dist目录找到修改后的APK,注意这里的APK并没有签名,这时候我们随便找个签名工具给它签上就OK了,我这用的爱加密的签名工具,也可以用360的签名工具,这里就详细说了,下班了。

小结

花了点时间,对Android逆向进行了一点点实践,学习了下几个工具的使用、smali文件的修改等等,还是有点收获吧!

相关推荐
编程乐学(Arfan开发工程师)3 小时前
06、基础入门-SpringBoot-依赖管理特性
android·spring boot·后端
androidwork3 小时前
使用 Kotlin 和 Jetpack Compose 开发 Wear OS 应用的完整指南
android·kotlin
繁依Fanyi4 小时前
Animaster:一次由 CodeBuddy 主导的 CSS 动画编辑器诞生记
android·前端·css·编辑器·codebuddy首席试玩官
奔跑吧 android6 小时前
【android bluetooth 框架分析 02】【Module详解 6】【StorageModule 模块介绍】
android·bluetooth·bt·aosp13·storagemodule
田一一一10 小时前
Android framework 中间件开发(三)
android·中间件·framework·jni
androidwork15 小时前
掌握 Kotlin Android 单元测试:MockK 框架深度实践指南
android·kotlin
田一一一15 小时前
Android framework 中间件开发(二)
android·中间件·framework
追随远方15 小时前
FFmpeg在Android开发中的核心价值是什么?
android·ffmpeg
神探阿航16 小时前
HNUST湖南科技大学-安卓Android期中复习
android·安卓·hnust
千里马-horse18 小时前
android vlc播放rtsp
android·media·rtsp·mediaplayer·vlc