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}