“数字经济”云安全共测大赛-web-gameapp

  1. 引言
  2. 开始
    1. 设置代理
    2. 逆向apk
      1. 方法一
        1. 获取dex文件
        2. 将dex转化为jar
        3. 更改数据
        4. 批量发送
      2. 方法二

引言

好久之前的比赛了,个人感觉应该算APK逆向题,划到Web里有点牵强了。。。

开始

这里简单说一下思路,赛方已关闭题中所需的服务器,没法复现了

设置代理

有师傅说可以在夜神模拟器里设置代理,我没试过。我这里使用了Proxifier将夜神模拟器的流量转发到了burp中,抓包就行

抓包的过程中发现app post过去的包有点像RSA加密后的东西,逆向apk即可

逆向apk

方法一

用到的软件有两个:jd-gui dex2jar

获取dex文件

将apk改为zip,解压,结果如图:

classes.dex即为我们需要的dex文件

将dex转化为jar

使用dex2jar,下载地址:https://sourceforge.net/projects/dex2jar/files/

使用方法(Windows下):

d2j-dex2jar.bat [path of dex file]

主要是靠lib d2j_invoke.bat d2j-dex2jar.bat来完成转换,也可以将这三个文件复制到dex所在目录中,这样就不用找dex文件绝对路径了。

执行完之后我们就得到了jar文件,使用jd-gui打开即可看到源码,如图

genKeyPair()可以很明显的看到RSA公钥私钥,根据下方的private_decrypt之类的方法可以判断出哪个是公钥哪个是私钥,也可以根据常识来判断(一般私钥比公钥长)

位数 私钥长度(Base64) 公钥长度(Base64) 明文长度 密文长度
512 428 128 1~53 88
1024 812 216 1~117 172
2048 1588 392 1~245 344

更改数据

已知公钥私钥还有密文,我们只需要解密post发送的数据,更改,再加密,再发送即可

网上找到的RSA加密、解密脚本如下:

(Windows安M2Crypto太麻烦了,建议扔到kali里去跑)

import M2Crypto


def public_decrypt(msg):
    public = '''
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCqtXUIVoPUcBV1Wl3g8rGGNvMY
ImonQdMC1Y8USwIwf7Y0GcBP/h6fAJPAS9//qYZzy8ZfDKH1+ezifFFCUTCCa/8a
YFoms223okyzeTlUIRHbIkto1JxYOazbsE6+KmE+yJiij4839SYuC1KsLWT82uHE
A3Hau/DTzW4g4xhvzQIDAQAB
-----END PUBLIC KEY-----
'''
    bio = M2Crypto.BIO.MemoryBuffer(public)
    rsa_pub = M2Crypto.RSA.load_pub_key_bio(bio)
    ctxt_pri = msg.decode("base64")
    output = rsa_pub.public_decrypt(ctxt_pri, M2Crypto.RSA.pkcs1_padding)
    return output


def private_encrypt(data):
    private = """
-----BEGIN PRIVATE KEY-----
MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKq1dQhWg9RwFXVa
XeDysYY28xgiaidB0wLVjxRLAjB/tjQZwE/+Hp8Ak8BL3/+phnPLxl8MofX57OJ8
UUJRMIJr/xpgWiazbbeiTLN5OVQhEdsiS2jUnFg5rNuwTr4qYT7ImKKPjzf1Ji4L
UqwtZPza4cQDcdq78NPNbiDjGG/NAgMBAAECgYBUdazusCdPbxke09QI3Oq6VeuW
cEiHHckx6Ml+p9Hwfu99/ZOpwDgUQSvZA3FTQ+PS3OpL0qs7USlDsXBe2F6gCZ/e
1BvkEPE/FymHbzbSpr8BwjEel/kup842z11SujNxHbeznrXKNfvDlqR5HM7CurYE
rBW0X8She8lNAqXBXQJBANj3pPvSHFQ4ugkWst6XCX/gd5vQuvPzeUwHpReSdRsm
A6Jmv8oP03MQzjvsyrMoPatMzhN5Qtfpw12Febfl1pcCQQDJa2RGtK2jCiKxzKcb
Up9pPiSxtsdavneKoCG/tndICyGfeT1NRGSQsJCHIhxdee4QQYWUrzhbFBLLZDq4
sj07AkEAykt0T7si4MAXbPv2AKZQnCN9QhGHDof3k5UZL/ZFK+/wuY4Vyl+hJosH
z0XD5PFjNoGhLvUEBu6VUnBuAbHRtwJBAKysnHLhQlqbvdKfmEMcOf2HgP25rH5m
+ySk00n/q5LfuBt3XM54653/QGgZHigk96qIAXTOIooyU0p6yry8UTECQQCy8tuf
lq8/8ISRdkHixENX+APeYr4hjmn5mUFJgB4qFUp1ReR0nA2oGf6IkzAWEwLvEchu
KMtF7eEv1kHS+3Wd
-----END PRIVATE KEY-----
"""
    rsa_pri = M2Crypto.RSA.load_key_string(private)
    ctxt_pri = rsa_pri.private_encrypt(data, M2Crypto.RSA.pkcs1_padding)
    ctxt64_pri = ctxt_pri.encode('base64')
    return ctxt64_pri

这样就可以对抓到的数据进行解密更改加密了

批量发送

根据测试,每次获得的分数最大为100,所以我们需要写一个脚本来重复发送,如下:

import requests


def login():
    url = "http://121.40.219.183:9999/startgame/"
    headers = {
        'Content-type': 'xxx',
        'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 5.1.1; Nexus 6 Build/LYZ28N)',
    }
    data = """
        bidARzWhRiGD2LrHi2RCjFrjCuDUS2vIb1Z9WnNAGMFKgbSBwIty/RGzvkHou4ViVF2mne8HnCMY
    pojx/z1tsG6bSrj/39j5z9eYA9YMRnjOyar4EjXdWgpXoDKaED14+UdXaeyp1fkbFolNL4Bjjzgv
    F2m7q/mdIi+UM138Vpg="""
    s = requests.session()
    s.post(url, headers=headers, data=data)
    return s


def add_source(obj):
    url = "http://121.40.219.183:9999/score/"
    data = """
    WzvU2mUZW0+WmRD3/4a3KLaVYVhp3MffjGdAO1E++KzmvVzt73/6elnS0bCAoMuc69S7kofyqbGR
    SXsWM0DPUWzMJFCT+inkrU9jFKM99M8DJwA8LQ+rLvaTgGd83RtJHVUho7YpnyqT3XsCI5bB+CMn
    vKAKTU6sqzqyV2hfX3E="""
    headers = {
        'Content-type': 'xxx',
        'User-Agent': 'Dalvik/2.1.0 (Linux; U; Android 5.1.1; Nexus 6 Build/LYZ28N)',
    }
    while True:
        content = obj.post(url, headers=headers, data=data)
        print(content.text)
        if "flag" in content.text:
            break


a = login()
add_source(a)

然后就拿到flag了

方法二

可以用AndroidKiller一把梭,直接拿到RSA公钥私钥,如图

剩下的步骤跟方法一相同,不再赘述


如果我的文章能帮到您的话我会很开心.如需转载记得注明出处:)
目录