文件名称:
分享一次安卓逆向记录.md
所在目录:
other
文件大小:
10.11 KB
下载地址:
文本预览:
# 一次安卓逆向记录
### 前言
前段事件,因为公司附近有了确诊病例,我刚好与确诊人员有时空交错,所以被居家隔离,于是开启了相对漫长的居家隔离状态,在这段无所事事的时间中,我开始了之前一直想做,但是没有做的小想法——逆向魅族手环`app`。
为什么要逆向这个`APP`呢?因为之前买过一个魅族手环,但是在`2021`的时候,官方的`app`登录服务器停止服务,没法打登录,也就没法实现数据同步,就连基本的时间同步都没法实现,也就没有了任何价值,为了让这个手环还能实现一些价值,于是我趁着这个相对漫长的无所事事的时间,逆向了官方`app`,同时也幸运地取得了成功,所以也就有了今天的内容。本来这块的内容前几天就打算分享的,但是由于工作和一些主观的原因,迟迟一直没有花时间来做一个总结,所以一次又一次地拖,一直拖到今天。
这个手环颜值还是可以的:


### 逆行过程
#### 项目描述
本项目是基于魅族手环`H1`安卓`APP`的一个逆向工程,通过逆向修改,解决了官方停服之后,无法登陆的问题(进行了免登处理),确保打开`APP`直接进入应用首页。
当然,本项目也是我的第一个安卓逆向工程,后续看个人兴趣,会继续探索学习。
#### 环境及工具
本次用到了`AndroidKiller`,版本`v1.3.1`,这是一个逆向集成工具,可以直接将`apk`文件的核心源码反编译为`smail`工程文件,然后我们通过修改`smail`文件,达到自己`APP`魔改的需求。
该工具同时集成了编译、打包、`ABD`调试等功能,用起来很顺手,后续我会专门出一期使用教程。
相关内容已经梳理到个人知识库:
[androidkiller工具使用指南](https://github.com/Syske/person-learning-note/blob/master/%E5%AE%89%E5%8D%93/androidkiller%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.md)
### smail基本语法
因为我们这里直接修改的是`smail`文件,所以学习一些基本语法也是必须的。作为一个`java`后端开发,我的安卓开发经验基本为零,所以在`smail`源码的过程中,踩了很多坑,当然也成长很多,后面我会把本次踩坑的知识点梳理下分享出来。
相关内容已经梳理到个人知识库:
[smail基本语法示例](https://github.com/Syske/person-learning-note/blob/master/%E5%AE%89%E5%8D%93/smail%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95%E7%A4%BA%E4%BE%8B.md)
#### 修改内容
这块主要是说明`APP`的修改能容,算是给各位喜欢琢磨的小伙伴提供一个破解思路,当然仅供参考。
这里先贴几张图,大概说下修改的内容:
##### StartActivity
这里主要是保存用户信息,同时跳转到`RegistInfoActivity`,确保用户信息落库。

对应的`smail`源码如下:
```java
const-string v2, "syske"
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;
invoke-direct {v1, p0}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->(Landroid/content/Context;)V
invoke-virtual {v1, v2, v2}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->saveLoginInfo(Ljava/lang/String;Ljava/lang/String;)V
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;
invoke-direct {v1, p0}, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->(Landroid/content/Context;)V
new-instance v0, Lcom/meizu/smart/wristband/models/newwork/response/Logindata;
invoke-direct {v0}, Lcom/meizu/smart/wristband/models/newwork/response/Logindata;->()V
invoke-virtual {v1, p0, v2, v0}, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->saveUserInfo(Landroid/content/Context;Ljava/lang/String;Lcom/meizu/smart/wristband/models/newwork/response/Logindata;)Z
.line 168
new-instance v0, Landroid/content/Intent;
const-class v2, Lcom/meizu/smart/wristband/meizuUI/login_regist/RegistInfoActivity;
invoke-direct {v0, p0, v2}, Landroid/content/Intent;->(Landroid/content/Context;Ljava/lang/Class;)V
```
完整源码可以直接去库里看。
这里原本是参照某乎大佬修改的,但是发下改了之后没啥用,还是会报错,所以我想着能不能直接改查询接口,于是我直接找到`models/database/servers`包下的`LoginInfoServer`和`UserInfoServer`,并修改对应方法。
##### LoginInfoServer
`LoginInfoServer`我改的是`getLoginInfo`的实现,直接实例化一个新的`LoginInfo`对象返回。

对应`smail`源码如下:
```java
# virtual methods
.method public getLoginInfo()Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.locals 5
.prologue
const/4 v4, 0x0
.line 47
iget-object v3, p0, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->context:Landroid/content/Context;
invoke-static {v3}, Lcom/meizu/smart/wristband/utils/SharePreferencesUtil;->getSharedPreferences(Landroid/content/Context;)Landroid/content/SharedPreferences;
move-result-object v2
.line 49
.local v2, "preferences":Landroid/content/SharedPreferences;
const/4 v1, 0x0
.line 50
.local v1, "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
const-string v3, "account"
invoke-interface {v2, v3, v4}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v0
.line 51
.local v0, "account":Ljava/lang/String;
invoke-static {v0}, Ldolphin/tools/util/StringUtil;->isBlank(Ljava/lang/String;)Z
move-result v3
.line 52
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.end local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->()V
.line 53
.restart local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-virtual {v1, v0}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setAccount(Ljava/lang/String;)V
.line 54
const-string v3, "pwd"
invoke-interface {v2, v3, v4}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v3
invoke-virtual {v1, v3}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setPwd(Ljava/lang/String;)V
.line 57
const-string v4, "syske"
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.restart local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->()V
invoke-virtual {v1, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setAccount(Ljava/lang/String;)V
invoke-virtual {v1, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setPwd(Ljava/lang/String;)V
return-object v1
.end method
```
##### UserInfoServer
`UserInfoServer`也是类似的方法,主要是解决空指针异常:

对应`smail`源码:
```java
# virtual methods
.method public getLoginUser()Lcom/meizu/smart/wristband/models/database/entity/User;
.locals 6
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/sql/SQLException;
}
.end annotation
.prologue
.line 53
new-instance v3, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;
iget-object v4, p0, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->context:Landroid/content/Context;
invoke-direct {v3, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->(Landroid/content/Context;)V
invoke-virtual {v3}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->getLoginInfo()Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.line 54
new-instance v1, Lcom/meizu/smart/wristband/models/database/entity/User;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/entity/User;->()V
.line 55
const-string v5, "syske"
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setId(Ljava/lang/String;)V
.line 56
const/4 v5, 0x0
invoke-static {v5}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result-object v5
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setSync(Ljava/lang/Boolean;)V
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setIsEmpty(Ljava/lang/Boolean;)V
const-string v5, "180"
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setWeight(Ljava/lang/String;)V
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setHeight(Ljava/lang/String;)V
return-object v1
.end method
```
### 结语
至此,免登`app`的改造基本上完成了,是不是很简单,但是就是这几行简简单单的代码,我愣是研究了好几天,然后一点点踩坑,一点点进步,一点点成长,才完成,但是整个过程还是成就感满满的,特别是第一次进入首页的那一刻,感觉一切都是值得的,奥里给
最后附上改造完成的`app`演示视频:
- 未破解前:首次进入app是需要登陆的
- 破解之后:首次进入直接进入(会白屏,这里是因为网络连接失败,重新打开就好了)
### 前言
前段事件,因为公司附近有了确诊病例,我刚好与确诊人员有时空交错,所以被居家隔离,于是开启了相对漫长的居家隔离状态,在这段无所事事的时间中,我开始了之前一直想做,但是没有做的小想法——逆向魅族手环`app`。
为什么要逆向这个`APP`呢?因为之前买过一个魅族手环,但是在`2021`的时候,官方的`app`登录服务器停止服务,没法打登录,也就没法实现数据同步,就连基本的时间同步都没法实现,也就没有了任何价值,为了让这个手环还能实现一些价值,于是我趁着这个相对漫长的无所事事的时间,逆向了官方`app`,同时也幸运地取得了成功,所以也就有了今天的内容。本来这块的内容前几天就打算分享的,但是由于工作和一些主观的原因,迟迟一直没有花时间来做一个总结,所以一次又一次地拖,一直拖到今天。
这个手环颜值还是可以的:


### 逆行过程
#### 项目描述
本项目是基于魅族手环`H1`安卓`APP`的一个逆向工程,通过逆向修改,解决了官方停服之后,无法登陆的问题(进行了免登处理),确保打开`APP`直接进入应用首页。
当然,本项目也是我的第一个安卓逆向工程,后续看个人兴趣,会继续探索学习。
#### 环境及工具
本次用到了`AndroidKiller`,版本`v1.3.1`,这是一个逆向集成工具,可以直接将`apk`文件的核心源码反编译为`smail`工程文件,然后我们通过修改`smail`文件,达到自己`APP`魔改的需求。
该工具同时集成了编译、打包、`ABD`调试等功能,用起来很顺手,后续我会专门出一期使用教程。
相关内容已经梳理到个人知识库:
[androidkiller工具使用指南](https://github.com/Syske/person-learning-note/blob/master/%E5%AE%89%E5%8D%93/androidkiller%E5%B7%A5%E5%85%B7%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%97.md)
### smail基本语法
因为我们这里直接修改的是`smail`文件,所以学习一些基本语法也是必须的。作为一个`java`后端开发,我的安卓开发经验基本为零,所以在`smail`源码的过程中,踩了很多坑,当然也成长很多,后面我会把本次踩坑的知识点梳理下分享出来。
相关内容已经梳理到个人知识库:
[smail基本语法示例](https://github.com/Syske/person-learning-note/blob/master/%E5%AE%89%E5%8D%93/smail%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95%E7%A4%BA%E4%BE%8B.md)
#### 修改内容
这块主要是说明`APP`的修改能容,算是给各位喜欢琢磨的小伙伴提供一个破解思路,当然仅供参考。
这里先贴几张图,大概说下修改的内容:
##### StartActivity
这里主要是保存用户信息,同时跳转到`RegistInfoActivity`,确保用户信息落库。

对应的`smail`源码如下:
```java
const-string v2, "syske"
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;
invoke-direct {v1, p0}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->
invoke-virtual {v1, v2, v2}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->saveLoginInfo(Ljava/lang/String;Ljava/lang/String;)V
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;
invoke-direct {v1, p0}, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->
new-instance v0, Lcom/meizu/smart/wristband/models/newwork/response/Logindata;
invoke-direct {v0}, Lcom/meizu/smart/wristband/models/newwork/response/Logindata;->
invoke-virtual {v1, p0, v2, v0}, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->saveUserInfo(Landroid/content/Context;Ljava/lang/String;Lcom/meizu/smart/wristband/models/newwork/response/Logindata;)Z
.line 168
new-instance v0, Landroid/content/Intent;
const-class v2, Lcom/meizu/smart/wristband/meizuUI/login_regist/RegistInfoActivity;
invoke-direct {v0, p0, v2}, Landroid/content/Intent;->
```
完整源码可以直接去库里看。
这里原本是参照某乎大佬修改的,但是发下改了之后没啥用,还是会报错,所以我想着能不能直接改查询接口,于是我直接找到`models/database/servers`包下的`LoginInfoServer`和`UserInfoServer`,并修改对应方法。
##### LoginInfoServer
`LoginInfoServer`我改的是`getLoginInfo`的实现,直接实例化一个新的`LoginInfo`对象返回。

对应`smail`源码如下:
```java
# virtual methods
.method public getLoginInfo()Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.locals 5
.prologue
const/4 v4, 0x0
.line 47
iget-object v3, p0, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->context:Landroid/content/Context;
invoke-static {v3}, Lcom/meizu/smart/wristband/utils/SharePreferencesUtil;->getSharedPreferences(Landroid/content/Context;)Landroid/content/SharedPreferences;
move-result-object v2
.line 49
.local v2, "preferences":Landroid/content/SharedPreferences;
const/4 v1, 0x0
.line 50
.local v1, "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
const-string v3, "account"
invoke-interface {v2, v3, v4}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v0
.line 51
.local v0, "account":Ljava/lang/String;
invoke-static {v0}, Ldolphin/tools/util/StringUtil;->isBlank(Ljava/lang/String;)Z
move-result v3
.line 52
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.end local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->
.line 53
.restart local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-virtual {v1, v0}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setAccount(Ljava/lang/String;)V
.line 54
const-string v3, "pwd"
invoke-interface {v2, v3, v4}, Landroid/content/SharedPreferences;->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
move-result-object v3
invoke-virtual {v1, v3}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setPwd(Ljava/lang/String;)V
.line 57
const-string v4, "syske"
new-instance v1, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.restart local v1 # "entity":Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->
invoke-virtual {v1, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setAccount(Ljava/lang/String;)V
invoke-virtual {v1, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;->setPwd(Ljava/lang/String;)V
return-object v1
.end method
```
##### UserInfoServer
`UserInfoServer`也是类似的方法,主要是解决空指针异常:

对应`smail`源码:
```java
# virtual methods
.method public getLoginUser()Lcom/meizu/smart/wristband/models/database/entity/User;
.locals 6
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/sql/SQLException;
}
.end annotation
.prologue
.line 53
new-instance v3, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;
iget-object v4, p0, Lcom/meizu/smart/wristband/models/database/servers/UserInfoServer;->context:Landroid/content/Context;
invoke-direct {v3, v4}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->
invoke-virtual {v3}, Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer;->getLoginInfo()Lcom/meizu/smart/wristband/models/database/servers/LoginInfoServer$LoginInfo;
.line 54
new-instance v1, Lcom/meizu/smart/wristband/models/database/entity/User;
invoke-direct {v1}, Lcom/meizu/smart/wristband/models/database/entity/User;->
.line 55
const-string v5, "syske"
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setId(Ljava/lang/String;)V
.line 56
const/4 v5, 0x0
invoke-static {v5}, Ljava/lang/Boolean;->valueOf(Z)Ljava/lang/Boolean;
move-result-object v5
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setSync(Ljava/lang/Boolean;)V
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setIsEmpty(Ljava/lang/Boolean;)V
const-string v5, "180"
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setWeight(Ljava/lang/String;)V
invoke-virtual {v1, v5}, Lcom/meizu/smart/wristband/models/database/entity/User;->setHeight(Ljava/lang/String;)V
return-object v1
.end method
```
### 结语
至此,免登`app`的改造基本上完成了,是不是很简单,但是就是这几行简简单单的代码,我愣是研究了好几天,然后一点点踩坑,一点点进步,一点点成长,才完成,但是整个过程还是成就感满满的,特别是第一次进入首页的那一刻,感觉一切都是值得的,奥里给
最后附上改造完成的`app`演示视频:
- 未破解前:首次进入app是需要登陆的
- 破解之后:首次进入直接进入(会白屏,这里是因为网络连接失败,重新打开就好了)
点赞
回复
X