CTF apk 安卓逆向

apk界面如下,看一看其实没有什么用。。。
在这里插入图片描述

1、使用jeb对apk进行分析,找到manifest配置文件(即应用清单,中包含了APP的配置信息,系统需要根据里面的内容运行APP的代码,显示界面),从中找到初始启动类com.crackme.comingsoon.WebviewActivity
在这里插入图片描述
2、WebviewActivity中注册了backdoor和helloworld两个函数,并加载了newVersionLogin.html进行渲染。
在这里插入图片描述
3、newVersionLogin.html中可以访问两个函数,js的login函数,和后台的backdoor函数
在这里插入图片描述
login.js如下,即访问后台的helloworld函数
在这里插入图片描述
4、来看看LoginActivity的逻辑,根据备注对变量进行重命名,方便查看。
在这里插入图片描述
进入相关函数,发现会对账号密码进行检查,其中密码长度为32
在这里插入图片描述
5、返回LoginActivity,LoginActivity.e会进行登录检查,继续跟进
在这里插入图片描述
进入LoginActivity.e函数,有用的是e.p.b函数,继续跟进
在这里插入图片描述

下面是e.p.b函数,参数arg4为password,首先会进入v3.a进行判断,跟进v3.a函数

public void b(String arg3, String arg4) {
        c v4;
        a v3 = this.e.a;
        if(v3 != null) {
            try {
                v4 = v3.a(arg4) ? new c(new b.b.a.a.d.a(UUID.randomUUID().toString(), "for(int i=0;i<38;i++)\n{\n\ttable[i] = (int)flag.charAt(i)-(int)decode.charAt((base+i)%decode.length());\n}\n//int table[] = {-6, 10, 25, -5, 4, 25, 36, 5, -2, 10, 47, 2, -17, 17, 39, 48, 14, 0, 43, 55, 50, 22, 62, -20, -22, 19, -9, -3, 10, 13, 58, 29, 1, 2, 38, -10, 1, 35};")) : new b.b.a.a.c.b(new IOException("Permission deny"));
            }
            catch(Exception v3_1) {
                v4 = new b.b.a.a.c.b(new IOException("Error logging in", v3_1));
            }

            if((v4 instanceof c)) {
                this.d.h(new b.b.a.b.c(new b.b.a.b.a(((b.b.a.a.d.a)v4.a).a)));
                return;
            }

            this.d.h(new b.b.a.b.c(((int)0x7F0C0020)));  // string:login_failed "Login failed"
            return;
        }

        throw null;
    }
// v3.a函数
public boolean a(String arg15) {
        if(arg15.substring(arg15.length() - 2, arg15.length()).equals("==")) {
            byte[] v15 = Base64.decode(arg15.getBytes(), 0);
            return (v15[0] ^ v15.length << 12) != 90227 || v15[v15.length - 1] + v15[1] != 0xE4 || v15[1] + v15[2] + v15[v15.length - 3] + v15[v15.length - 16] + v15[15] + v15[13] + v15[v15.length - 14] + v15[10] + v15[v15.length - 11] + v15[v15.length - 6] != 0x45C || v15[1] - v15[2] + v15[v15.length - 3] != 104 || v15[v15.length - 6] * 2 + (v15[v15.length - 16] * 4 + v15[15] - v15[v15.length - 3]) != 650 || v15[v15.length - 11] * 13 + (v15[13] - v15[v15.length - 14] - v15[10] * 19) - v15[1] * 3 != 0xFFFFFB83 || v15[v15.length - 14] * 12 + (v15[2] * 10 + v15[15] * 9 - v15[10] * 11) - v15[v15.length - 6] * 13 != 661 || v15[v15.length - 14] - v15[13] + v15[v15.length - 16] - v15[v15.length - 3] + v15[2] - v15[1] != -15 || v15[v15.length - 11] * 3 + (v15[v15.length - 14] * 3 + (v15[15] * 3 + v15[v15.length - 3] * 3)) != 0x525 || v15[10] * 7 + v15[v15.length - 14] * 5 - v15[v15.length - 11] * 9 != 344 || v15[v15.length - 11] * 5 + (v15[v15.length - 14] * 4 + (v15[15] * 3 + (v15[v15.length - 3] * 2 + v15[1]))) != 1640 || v15[v15.length - 16] * 7 + (v15[10] * 4 + -v15[v15.length - 6] - v15[13] * 9) != 54 || v15[v15.length - 8] * v15[v15.length - 8] - v15[7] * 108 != 973 || v15[v15.length - 2] - v15[v15.length - 8] != -11 || v15[7] + v15[v15.length - 2] != 0xC7 || v15[3] * v15[4] * v15[5] != 0x15BF34 || v15[3] * v15[4] - v15[5] != 0x37D9 || v15[4] * v15[4] - v15[3] * v15[5] != 3202 || v15[6] * v15[6] * v15[v15.length - 5] + v15[14] * v15[v15.length - 13] != 0x1338C1 || v15[8] * v15[v15.length - 10] + v15[v15.length - 5] + v15[v15.length - 4] != 10309 || v15[6] * v15[v15.length - 5] != 0x2D8F || v15[6] * v15[v15.length - 13] != 0x2D24 || v15[14] * v15[v15.length - 10] - v15[6] * v15[v15.length - 4] != 200 ? 0 : 1;
        }

        return 0;
    }

6、接下来重点分析上面的v3.a函数,从函数中我们可以知道:

条件一:输入以“==”结尾的base64字符串,并且password的长度为32,根据base64的规则,解码后的v15长度为22位:

32*6/8=24
24-2=22 //有几个=号,减去多少

条件二:(v15[0] ^ v15.length << 12) == 90227

v15[0] = 90227 ^ 22<<12 = 115

条件三:多元一次方程:

v15[22-1] + v15[1] == 0xE4
v15[1] + v15[2] + v15[22- 3] + v15[22- 16] + v15[15] + v15[13] + v15[22- 14] + v15[10] + v15[22-11] + v15[22-6] = 0x45C
v15[1] - v15[2] + v15[22- 3] = 104
v15[22- 6] * 2 + (v15[22- 16] * 4 + v15[15] - v15[22- 3]) = 650
v15[22- 11] * 13 + (v15[13] - v15[22- 14] - v15[10] * 19) - v15[1] * 3 = 0xFFFFFB83
v15[22- 14] * 12 + (v15[2] * 10 + v15[15] * 9 - v15[10] * 11) - v15[22- 6] * 13 = 661
v15[22- 14] - v15[13] + v15[22- 16] - v15[22- 3] + v15[2] - v15[1] = -15
v15[22- 11] * 3 + (v15[22- 14] * 3 + (v15[15] * 3 + v15[22- 3] * 3)) = 0x525
v15[10] * 7 + v15[22- 14] * 5 - v15[22- 11] * 9 = 344
v15[22- 11] * 5 + (v15[22- 14] * 4 + (v15[15] * 3 + (v15[22- 3] * 2 + v15[1]))) = 1640
v15[22- 16] * 7 + (v15[10] * 4 + -v15[22- 6] - v15[13] * 9) = 54
v15[22- 8] * v15[22- 8] - v15[7] * 108 = 973
v15[22- 2] - v15[22- 8] = -11
v15[7] + v15[22- 2] = 0xC7
v15[3] * v15[4] * v15[5] = 0x15BF34
v15[3] * v15[4] - v15[5] = 0x37D9
v15[4] * v15[4] - v15[3] * v15[5] = 3202
v15[6] * v15[6] * v15[22- 5] + v15[14] * v15[22- 13] = 0x1338C1
v15[8] * v15[22- 10] + v15[22- 5] + v15[22- 4] = 10309
v15[6] * v15[22- 5] = 0x2D8F
v15[6] * v15[22- 13] = 0x2D24
v15[14] * v15[22- 10] - v15[6] * v15[22- 4] = 200

那就求解呗,这里使用python3,需要安装z3-solver库:

# python3 -m pip install z3-solver
# 5wimming

import z3
import base64


def main():
    v15 = [z3.Int('x%d' % i) for i in range(22)]
    z3solver = z3.Solver()

    z3solver.add(v15[22 - 1] + v15[1] == 228)
    z3solver.add(v15[1] + v15[2] + v15[22 - 3] + v15[22 - 16] + v15[15] + v15[13] + v15[22 - 14] + v15[10] + v15[22 - 11] + v15[22 - 6] == 1116)
    z3solver.add(v15[1] - v15[2] + v15[22 - 3] == 104)
    z3solver.add(v15[22 - 6] * 2 + (v15[22 - 16] * 4 + v15[15] - v15[22 - 3]) == 650)
    z3solver.add(v15[22 - 11] * 13 + (v15[13] - v15[22 - 14] - v15[10] * 19) - v15[1] * 3 == -1149)
    z3solver.add(v15[22 - 14] * 12 + (v15[2] * 10 + v15[15] * 9 - v15[10] * 11) - v15[22 - 6] * 13 == 661)
    z3solver.add(v15[22 - 14] - v15[13] + v15[22 - 16] - v15[22 - 3] + v15[2] - v15[1] == -15)
    z3solver.add(v15[22 - 11] * 3 + (v15[22 - 14] * 3 + (v15[15] * 3 + v15[22 - 3] * 3)) == 1317)
    z3solver.add(v15[10] * 7 + v15[22 - 14] * 5 - v15[22 - 11] * 9 == 344)
    z3solver.add(v15[22 - 11] * 5 + (v15[22 - 14] * 4 + (v15[15] * 3 + (v15[22 - 3] * 2 + v15[1]))) == 1640)
    z3solver.add(v15[22 - 16] * 7 + (v15[10] * 4 + -v15[22 - 6] - v15[13] * 9) == 54)
    z3solver.add(v15[22 - 8] * v15[22 - 8] - v15[7] * 108 == 973)
    z3solver.add(v15[22 - 2] - v15[22 - 8] == -11)
    z3solver.add(v15[7] + v15[22 - 2] == 199)
    z3solver.add(v15[3] * v15[4] * v15[5] == 1425204)
    z3solver.add(v15[3] * v15[4] - v15[5] == 14297)
    z3solver.add(v15[4] * v15[4] - v15[3] * v15[5] == 3202)
    z3solver.add(v15[6] * v15[6] * v15[22 - 5] + v15[14] * v15[22 - 13] == 1259713)
    z3solver.add(v15[8] * v15[22 - 10] + v15[22 - 5] + v15[22 - 4] == 10309)
    z3solver.add(v15[6] * v15[22 - 5] == 11663)
    z3solver.add(v15[6] * v15[22 - 13] == 11556)
    z3solver.add(v15[14] * v15[22 - 10] - v15[6] * v15[22 - 4] == 200)

    z3solver.check()
    model = z3solver.model()

    result = [115]
    for i in v15[1:]:
        result.append(model.eval(i).as_long())
    print(result)

    str_result = ""
    for i in result:
        str_result += chr(i)
    print('origin result', str_result)
    
    base64_result = base64.b64encode(str_result.encode())
    print('base64 result', base64_result)


if __name__ == '__main__':
    main()

求出结果:

[115, 108, 114, 118, 122, 99, 107, 101, 101, 108, 121, 112, 100, 119, 109, 116, 108, 109, 100, 110, 98, 120]
origin result: slrvzckeelypdwmtlmdnbx
base64 result: b'c2xydnpja2VlbHlwZHdtdGxtZG5ieA=='

7、继续看接下来的函数,字符串里面就是将flag和table进行运算,得到password,所以根据该函数可以倒推flag

v4 = v3.a(password) ? new c(new b.b.a.a.d.a(UUID.randomUUID().toString(), "for(int i=0;i<38;i++)\n{\n\ttable[i] = (int)flag.charAt(i)-(int)decode.charAt((base+i)%decode.length());\n}\n//int table[] = {-6, 10, 25, -5, 4, 25, 36, 5, -2, 10, 47, 2, -17, 17, 39, 48, 14, 0, 43, 55, 50, 22, 62, -20, -22, 19, -9, -3, 10, 13, 58, 29, 1, 2, 38, -10, 1, 35};")) : new b.b.a.a.c.b(new IOException("Permission deny"));

写出倒推函数:

# python3
# 5wimming
def get_flag():
    password = 'c2xydnpja2VlbHlwZHdtdGxtZG5ieA=='
    table = [-6, 10, 25, -5, 4, 25, 36, 5, -2, 10, 47, 2, -17, 17, 39, 48, 14, 0, 43, 55, 50, 22, 62, -20, -22, 19, -9, -3, 10, 13, 58, 29, 1, 2, 38, -10, 1, 35]
    for base in range(32):
        flag = ''
        for i in range(38):
            flag += chr(table[i] + ord(password[(base + i) % len(password)]))
        if 'flag' in flag:
            print(flag)
            break


if __name__ == '__main__':
    get_flag()

得到结果flag:

flag{slirnvzckneweltoypdcwemtnlsmdnbx}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值