前言

最近心血来潮,想弄一下yiban的自动签到方面的,于是开始对这个APP进行逆向和https抓包

获取登陆密码加密公钥

需要进行APP逆向,因为apk加密过,不能直接反编译,故使用blackdex

使用blackdex进行易班的dex获取

安装后直接点一下就行,操作很简单

Screenshot_20220430-201159

获取的dex文件如下

360截图17860530668961

经查找,需要的程序处于hook_9210292.dex

以下程序可知是RSA加密,用的加密方式是PKCS1Padding

360截图18280511263163

获取公钥相关函数如下

360截图17290505195055

根据此篇博客得知函数在so文件中,

经查找,5.0.9版本的写法不变

360截图17991018385854

IDA反编译so文件

经过此篇博客的提示,5.0.4版本的易班,libyiban.so中直接可以找到RSA公钥

5.0.4

但是从5.0.5开始,就不管用了

5.0.5

根据此篇博客提示, 考虑使用frida对易班进行hook

使用frida进行hook

Windows安装frida

后来发现15.1.17好像不太好用,于是换了12.10.0,下面安装演示用的是15.1.17)

使用PIP来进行安装

1
2
3
pip install frida -i https://mirrors.aliyun.com/pypi/simple

pip install frida-tools -i https://mirrors.aliyun.com/pypi/simple

安装完成

360截图16240127100116109

360截图169407159794139

或使用easy_install

先到这里下载.egg文件

注意:请根据你的python版本进行下载,我这里是python2.7

360截图16940724335440

1
easy_install frida-15.1.17-py2.7-win-amd64.egg

在安卓端运行server

下载编译好的server二进制文件

注意:手机要有root权限

先到这里下载frida-server

我这里手机是aarch64架构的mi 9

360截图18231119757695

所以下载这个

360截图17571118496176

然后对其解压

360截图18141223287425

adb传输server文件到手机

将frida-server-15.1.17-android-arm64放在安卓手机,

这里选择了mnt/sdcard,因为直接用/data/local/tmp传不上去

(下面命令采用相对路径,所以.\frida-server-15.1.17-android-arm64要放在命令行所在目录)

1
adb push .\frida-server-15.1.17-android-arm64 mnt/sdcard/

image-20220430204419021

进入adb shell模式启动server

需要使用root权限运行server

将frida-server-15.1.17-android-arm64复制到tmp目录,因为sdcard目录似乎不能执行

1
2
3
4
adb shell
su
mv mnt/sdcard/frida-server-15.1.17-android-arm64 /data/local/tmp
cd /data/local/tmp

赋予可执行权限

1
2
su
chmod +x frida-server-15.1.17-android-arm64

启动并后台运行server服务(手机如果重启需要再次运行以下命令启动server)

1
2
su
./frida-server-15.1.17-android-arm64 &

使用adb转发端口

退出adb shell

在cmd里敲如下命令转发端口(当然如果不使用远程调试可以不转发,可以使用usb模式)

1
adb forward tcp:27042 tcp:27042

测试是否成功

1
frida-ps -R

360截图18430709243136

测试样例

安装APP

这个app是frida官网上下载下来的app

下载地址:本站网址/static/post/yiban_hook/ext/rps.apk

运行测试程序

命令
1
python3 ctf.py
ctf.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

import frida, sys

def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)

jscode = """
Java.perform(function () {
// Function to hook is defined here
var MainActivity = Java.use('com.example.seccon2015.rock_paper_scissors.MainActivity');

// Whenever button is clicked
var onClick = MainActivity.onClick;
onClick.implementation = function (v) {
// Show a message to know that the function got called
send('onClick');

// Call the original onClick handler
onClick.call(this, v);

// Set our values after running the original onClick handler
this.m.value = 0;
this.n.value = 1;
this.cnt.value = 999;

// Log to the console that it's done, and we should have the flag!
console.log('Done:' + JSON.stringify(this.cnt));
};
});
"""

process =frida.get_remote_device().attach('com.example.seccon2015.rock_paper_scissors')
script = process.create_script(jscode)
script.on('message', on_message)
print('[*] Running CTF')
script.load()
sys.stdin.read()
运行效果

点击APP中任意按钮,会打印出数据

360截图16780701736895

开始hook

编写利用程序

以下程序为python3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
import frida, sys

jscode ="""
setTimeout(function (){
Java.perform(
function () {
var JNIHelper = Java.use('com.yiban.app.jni.JNIHelper');
var r1 = JNIHelper.getEncodePwdPublicKey();
console.log('------EncodePwdPublicKey------')
console.log(r1)
console.log('------End------')
}
);

});
"""


def message(message, data):
if message["type"] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)

process = frida.get_remote_device().attach('com.yiban.app')
script= process.create_script(jscode)
script.on("message", message)
script.load()
sys.stdin.read()

操作

使用frida管理app的启动

1
frida -R -f com.yiban.app

如下

360截图16831109111110101

再运行hook程序

1
python3 exp.py

360截图170010168899140

在frida命令窗口启动app(APP版本为5.0.4)

1
%resume

360截图176610194258100

结果

结果如下

360截图18430703115122145

这里不方便贴上公钥,自己尝试的话也不要说是看了此文

至此,自动登录易班APP已经解决(2022.05.08已验证此公钥可用)

相关程序

给出rsa加密程序,需要pycrypto库

至于登录验证和登录后的学校跳转,这里就不赘述了,http canary抓个包即可知晓

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_v1_5
import base64

def enc_passwd(pwd):
#密码加密
PUBLIC_KEY = \
'''-----BEGIN PUBLIC KEY-----
RSA公钥放此处
-----END PUBLIC KEY-----'''
cipher = PKCS1_v1_5.new(RSA.importKey(PUBLIC_KEY))
return base64.b64encode(cipher.encrypt(pwd.encode())).decode()

其它问题

经测试frida-12.10.0对付易班5.0.7会出现以下错误

frida15好像没有这个问题,但是在15完全hook不起来

360截图18141220354878

自动完成晚点签到

抓包可知向/nightAttendance/student/index/signIn?CSRF=

发送类似如下数据即可完成签到

1
2
3
4
5
6
{
"PhoneModel": "手机型号名称",
'Code': "设备码",
'SignInfo':'{"Reason":"","AttachmentFileName":"","LngLat":"%s,%s","Address":"地址的文字描述"}'% (经度, 纬度),
'OutState':1
}

获取每日健康打卡任务密钥

抓包分析

经过fiddle抓包,可知流程如下

  • 访问/officetask/client/来进入“我的任务”版块
  • 访问/officeTask/client/index/detail?TaskId=来根据ID获取任务详情
  • 访问/workFlow/c/my/form/(任务id)来获取任务表单
  • 向/workFlow/c/my/apply进行post提交数据来完成任务

发现打卡任务完成时发送了一串base64

360截图18720119102130107

经过两次base64解编码,发现并未得到数据,

以此猜测数据经过加密后才进行两次base64编码

360截图17571117476795

通过对比两次打卡抓到的数据,

以及AES加密密文不会变(RSA有随机数,加密出来的东西每次都不一样),

aes部分内容改变的话,加密出来的密文也只有部分内容改变

360截图17860530397349

APP逆向分析

在易班app里面并没有发现有关任务处理提交的处理程序,

因此猜测更倾向于任务办理这个版块基于web app,

即此过程基于网页,相关加密处理应该藏在js之中

前面流程的url以及列出来了,只需要找到任务提交前的那个页面加载过的js,就有可能找到加密算法与密钥

初步分析,锁定/workflow/client/umi.30b93de2.js(因为其它js已经看过了,没有发现什么有价值的东西)

360截图175711139010385

JS逆向分析(带点运气成分)

先将抓包得到的umi.30b93de2.js进行格式化与解密(因为js压缩可以加快js的加载,而js加密或混淆可以防止被逆向),

这里使用的是在线工具

这个js有62809行。。。。

360截图16720330102367

看到这里就更确定算法在这里面了

360截图17380331465666

搜索enc,找到如下部分

看了一眼,这个匿名函数还有base64码表替换的实现

360截图16240127656289

搜索前面的标记名字

360截图17001013443252

找到了一处,但是好像没什么用

360截图184701296510481

但是并不妨碍继续追踪

360截图18141218285122

找到一处,似乎就是AES的调用,可知用的CBC模式,Padding这里没有写

仔细一看还有个s和l,一数都是十六,然后CBC模式需要key和iv,不妨把这两个填进去试试。

360截图16900203091842

解密成功

这里用的是在线AES解密

居然被我找到了,Padding为PKCS7解密成功哈哈哈哈

360截图169802099311397

AES的加密解密密钥是一样的,

至此,已经可以编写自动化程序自动进行打卡任务

结束

到这里就结束了,希望yiban不要再更新安全策略了。。。想自动完成签到打卡还真不容易

EOF