【原创】安卓逆向实例 - ProCCD复古CCD相机胶片滤镜
# 0x00 前言最近老是下雨,突发奇想:想和喜欢的人去拍照,感受下雨天的浪漫
然后就找到这个App:**ProCCD复古CCD相机胶片滤镜**
第一次尝试着去逆向**Pro会员**,一波三折,还好赶在周末之前完成了
# 0x01 准备工作
1、下载最新版本的ProCCD复古CCD相机胶片滤镜
应用宝App介绍主页:
> https://sj.qq.com/appdetail/com.cerdillac.proccd.cn
应用宝直链下载:
> https://8ffcfc786802a12cddaea5ca998645ad.dlied1.cdntips.net/dd.myapp.com/sjy.00004/16891/apk/428A0EF4CDB2A17595F0F2AA085BF1B6.apk?mkey=63bf5b17db80b624&f=0000&fsname=com.cerdillac.proccd.cn_2.4.6_64.apk&cip=219.128.144.209&proto=https
!(data/attachment/forum/202301/12/150956hbf7bifp9bweioib.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "Screenshot_20230112-150913.png")
2、用到的工具
去签:MT管理器、NP管理器
逆向:jadx、Android Killer
# 0x02 静态分析
## “常用”的 isVIP
> 注意:软件有签名校验,自行使用 MT 或 NP ,去签之后再进行分析
1、先把 apk 拖进 jadx 中进行一下静态分析,然后搜索 `isVIP` 关键字,关注到有个 `VipState`
!(data/attachment/forum/202301/12/151356niqcw53lw2zkzgwk.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
2、跟进 `VipState` ,看到这里大概就是这连绵阴雨天气中的第一缕阳光
!(data/attachment/forum/202301/12/151618uphbru221hrcrurd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
3、返回 Android Killer 修改代码、保存、编译、安装
以下为原始代码,未作修改,然后继续往下看
```smail
.class public Lcom/lightcone/wxpay/billing/bean/VipState;
.super Ljava/lang/Object;
.source "VipState.java"
# instance fields
.field public expiredTime:J
.field public isVip:Z
# direct methods
.method public constructor <init>()V
.locals 2
.line 1
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
const-wide/16 v0, -0x1
.line 2
iput-wide v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->expiredTime:J
return-void
.end method
# virtual methods
.method public formatVipExpiresTime()Ljava/lang/String;
.locals 5
.annotation runtime Lcom/fasterxml/jackson/annotation/JsonIgnore;
.end annotation
.line 1
iget-boolean v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->isVip:Z
if-eqz v0, :cond_1
iget-wide v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->expiredTime:J
const-wide/16 v2, 0x0
cmp-long v4, v0, v2
if-gtz v4, :cond_0
goto :goto_0
.line 2
:cond_0
new-instance v0, Ljava/text/SimpleDateFormat;
const-string v1, "yyyy/MM/dd"
invoke-direct {v0, v1}, Ljava/text/SimpleDateFormat;-><init>(Ljava/lang/String;)V
.line 3
new-instance v1, Ljava/util/Date;
iget-wide v2, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->expiredTime:J
invoke-direct {v1, v2, v3}, Ljava/util/Date;-><init>(J)V
invoke-virtual {v0, v1}, Ljava/text/SimpleDateFormat;->format(Ljava/util/Date;)Ljava/lang/String;
move-result-object v0
return-object v0
:cond_1
:goto_0
const-string v0, ""
return-object v0
.end method
.method public isPermanentVip()Z
.locals 5
.annotation runtime Lcom/fasterxml/jackson/annotation/JsonIgnore;
.end annotation
.line 1
iget-wide v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->expiredTime:J
const-wide/16 v2, 0x0
cmp-long v4, v0, v2
if-nez v4, :cond_0
iget-boolean v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->isVip:Z
if-eqz v0, :cond_0
const/4 v0, 0x1
goto :goto_0
:cond_0
const/4 v0, 0x0
:goto_0
return v0
.end method
.method public isVipEffective()Z
.locals 1
.annotation runtime Lcom/fasterxml/jackson/annotation/JsonIgnore;
.end annotation
.line 1
iget-boolean v0, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->isVip:Z
if-eqz v0, :cond_0
invoke-virtual {p0}, Lcom/lightcone/wxpay/billing/bean/VipState;->isVipExpires()Z
move-result v0
if-nez v0, :cond_0
const/4 v0, 0x1
goto :goto_0
:cond_0
const/4 v0, 0x0
:goto_0
return v0
.end method
.method public isVipExpires()Z
.locals 5
.annotation runtime Lcom/fasterxml/jackson/annotation/JsonIgnore;
.end annotation
.line 1
invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
move-result-wide v0
iget-wide v2, p0, Lcom/lightcone/wxpay/billing/bean/VipState;->expiredTime:J
cmp-long v4, v0, v2
if-lez v4, :cond_0
const-wide/16 v0, 0x0
cmp-long v4, v2, v0
if-eqz v4, :cond_0
const/4 v0, 0x1
goto :goto_0
:cond_0
const/4 v0, 0x0
:goto_0
return v0
.end method
```
**在这个代码中不管改什么、怎么改、始终都是无法成功逆向Pro会员 ,此刻觉得自己真的还是好菜**
## 原因分析
1、回头仔细把每个函数都仔细观察了一遍,发现了疑点
> **isVipEffective()** 这个方法是检测 VIP 的有效性,但是检测的逻辑和判断似乎不在这
!(data/attachment/forum/202301/12/152347i5jf46y7i6mamvwm.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
2、那么知道了 **isVipEffective()** 是判断 VIP 的有效性了,那么就得去寻找哪个判断逻辑调用了这个方法
> jadx 直接查找用例
!(data/attachment/forum/202301/12/152946yfs0uafts0jfsjs0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
## 逆向 Pro 会员
1、通过观察查找用例的代码,发现方法 **k** 似乎有点特殊
!(data/attachment/forum/202301/12/153221qjinijb4xy4bvi6v.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
2、跟进 **k** ,就可以看到判断的逻辑了
> 先是判断 VipState 不为 null , 接着调用 isVipEffective()
!(data/attachment/forum/202301/12/153314yrjj2iru6nn2nmju.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
3、复制 jadx 中的文件名到 Android Killer 查找对应的 smail 文件
> 文件路径为:e.e.r.g.d
!(data/attachment/forum/202301/12/154531a88xxl8stxog8g5t.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
4、先来看下 smail代码
> 第二种快速定位的方法:可以直接搜索关键词 VipState
!(data/attachment/forum/202301/12/154649wu1y3wro9yzythtv.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
> 找到对应的 k 方法
!(data/attachment/forum/202301/12/160332sywr2urvyu2v2wuz.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
5、我觉得 smail 代码好像和 jadx 编译的有点出入,然后打开了 JD-GUI 看了一下
!(data/attachment/forum/202301/12/155018thnh2veii2gxinkn.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
然后复制了一下 JD-GUI 的 smail 文件路径,对比一下
`*\ProjectSrc\smali\!\e\e\r\g\d.class`
修改后,会员滤镜已经可以使用了
!(data/attachment/forum/202301/12/160321jy0v545hsomxddob.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "image.png")
# 总结
每个逆向工具编译的代码可能不一样,要学会使用多工具对比法
期待拍照那天的到来
很不错{:5_116:} 这个还没学到,现看现学! 谢谢分享这技术学习了! 比较实用,谢谢分享! 安卓逆向这么爽吗,可以直接看到源码?
页:
[1]