复现一下2022强网杯的安卓题game...

【Reverse】2022 强网杯 game

前言

复现一下这题,因为手头有环境可以学学。强网的时候根本没看。

backup还原

直接GitHub的链接

可以还原出apk

摸瓜分析

在线网站分析 image-20220813083353778

发现有个域名,下面还有个URL

image-20220813083421201

jadx分析

虽然主活动是com.silence.scoreboard.SplashActivity,但是我们先看base的东西

首先是BaseActivity,去BaseApplication注册了一个广播

然后有一个MyReceiver去接收广播消息

image-20220813083526999

跟进BaseApplication

调用了一个scoreboard的链接库

同时在onCreate的时候,会有一个RootUtils.check()和一个OoOO.OOOOOooo()

RootUtils一看就知道是检测root权限的,这个OoOO.OOOOOooo应该是链接库里的方法,也就不去管了

image-20220813083759586

再来到主活动SplashActivity进行分析

image-20220813084526009

onCreate的时候进行isLogin()的判断

如果登录了,就去执行autoLogin自动登录,有个回调函数,搞过安卓网路开发的都知道这个是Retrofit

那么思路先去全局搜索一下http找到RetrofitHelper

找到了服务器的基地址http://47.93.244.181/re/

image-20220813084731978

返回到主活动,继续分析

登录成功就去MainActivity,失败就去LoginActiviy

顺着HttpRequest.login,去看API接口

image-20220813093117264

有个GetFlag.php

image-20220813093201998

需要code、account、username

结合app下载的界面显示,超过9999分就可以获取flag

img

API分析

register,密码用md5加密后post

image-20220813095905967

login,account被encrypt加密了,密码还是md5的形式

image-20220813100226060

autologin,多了一个code,account和username都被加密了

image-20220813100330010

submit,提交分数,在贪吃蛇的界面有调用

image-20220813100356816

image-20220813100420922

addFriend,添加好友,需要一个code来添加

image-20220813100439164

getScoreBoard,查看排行榜 image-20220813100459765

getFlag,需要code,account,username

image-20220813100521181

API测试

先去注册一个,获得了一个code

image-20220813100740086

去scoreboard看看,有users和admins,因为是复现,所以我怀疑users都是比赛时做出来的,直接把分数改成大于9999了

image-20220813100926835

admins中,只有第一个的分数是9999

image-20220813101010315

addFriend接口

因为getFlag这个api,不需要密码的,只需要account和code还有一个username

观察到registerActivity中,注册后会把注册后的json信息回调给setUserInfo方法

image-20220813101552665

image-20220813101853063

这里调用了decrypt,会想起在注册或者login后,会对accouont、username进行encrypt

image-20220813102044392

那么,我们先去尝试加个好友,因为加好友后会显示部分信息

image-20220813103552402

api测试,发现给的太多了,甚至给了account

image-20220813103601039

这个account和username肯定是经过encrypt的,那么思路有了,直接hook这个OooOoo0.decrypt,把加密后的这个admin的account和username都调用一下这个decrypt,那么可以得到admin的account然后获取flag

frida调用decrypt

因为这个app检查了root权限,我手头上的机子用的Magdisk22,可以使用Magdisk Hide功能隐藏root权限,所以打开app是没问题的。

但是经过测试发现,如果先打开frida-server,再启动app,直接闪退

那么换个思路,先打开app,在开启frida-server,使用attach模式来附加到进程上面

hook调用decrypt和encrypt的ts脚本,需要编译成js

const encrypt = (s: any) => {
    let res = ''
    Java.perform(() => {
        res = Java.use("com.silence.utils.OooOoo0").encrypt(s)
    })
    return res
}

const decrypt = (s: any) => {
    let res = ''
    Java.perform(() => {
        res = Java.use("com.silence.utils.OooOoo0").decrypt(s)
    })
    return res
}

rpc.exports = {
    encrypt: encrypt,
    decrypt: decrypt
}

python调用frida

import sys
import frida


def on_message(message, data):
    if message['type'] == 'send':
        print(f"[frida hook] : {str(message['payload'])}")
    else:
        print(f"[frida hook] : {str(message)}")


session = frida.get_usb_device().attach("ScoreBoard")

with open("./ts_script/js/test.js",encoding="utf-8") as f:
    script = session.create_script(f.read())

script.on("message", on_message)
script.load()   # 加载脚本

tmp = script.exports.encrypt("test114")
print(tmp)

tmpp = script.exports.decrypt(tmp)
print(tmpp)

account = script.exports.decrypt("SWeH8ou9yuL8GLThYhY1QlDiWX880+uNZusmIll/Q4Q=")
print(account)

username = script.exports.decrypt("IbaoQT/3eTXIjHDJ2L5TQE==")
print(username)

# sys.stdin.read()

tmptmpp是用来测试加密解密是否成对

account和username两个解密的都是addFriend的API获取的,直接解密

image-20220813104955507

拿到账号&Od987$2sPa?>l<k^j

getFlag

把参数放到api里,直接获取

image-20220813105027626