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文件的修改等等,还是有点收获吧!

相关推荐
Antonio91520 分钟前
【音视频】Android NDK 与.so库适配
android·音视频
sun0077009 小时前
android ndk编译valgrind
android
AI视觉网奇10 小时前
android studio 断点无效
android·ide·android studio
jiaxi的天空10 小时前
android studio gradle 访问不了
android·ide·android studio
No Silver Bullet11 小时前
android组包时会把从maven私服获取的包下载到本地吗
android
catchadmin11 小时前
PHP serialize 序列化完全指南
android·开发语言·php
tangweiguo0305198713 小时前
Kable使用指南:Android BLE开发的现代化解决方案
android·kotlin
00后程序员张15 小时前
iOS App 混淆与资源保护:iOS配置文件加密、ipa文件安全、代码与多媒体资源防护全流程指南
android·安全·ios·小程序·uni-app·cocoa·iphone
柳岸风17 小时前
Android Studio Meerkat | 2024.3.1 Gradle Tasks不展示
android·ide·android studio
编程乐学17 小时前
安卓原创--基于 Android 开发的菜单管理系统
android