Android 逆向实践

Android 逆向实践

前言

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

工具下载

apktool

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

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

jadx-gui

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

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

dex2jar

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

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

APK解包

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

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里面修改:

<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来打开这个解包文件夹:

/* loaded from: classes7.dex */
public class WelcomeActivity extends com.weaver.platform.BaseActivity

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

在这里插入图片描述

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

.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

删除部分代码后:

.method private isTwickPack()Z
    .locals 1

    const/4 v0, 0x0

    return v0
.end method

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

修改变量

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

private String proLocationData;

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

.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再输出,举个例子:

val jSONObject = JSONObject()
jSONObject.put("type", "wgs84")
Log.d("TAG", jSONObject.toString())

对于的smali字节码如下:

.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操作就可以了。

一些技巧

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

利用adb命令确定页面

一般要修改一个页面,首先就要确定这个页面所在的文件,可以通过adb命令实现:

adb shell
dumpsys activity top | grep ACTIVITY

找到对应的smali文件去修改就行了。

利用AS编写代码来替换

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

利用Visual Studio插件验证语法

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

利用代码行号定位

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

匿名函数说明

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

// 在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,看看他是干嘛的:

.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,命令如下:

apktool.bat b file-dir

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

小结

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

如果你看到了这里,觉得文章写得不错就给个赞呗?
更多Android进阶指南 可以扫码 解锁更多Android进阶资料


在这里插入图片描述
敲代码不易,关注一下吧。ღ( ´・ᴗ・` )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值