-
-
[原创] 看雪CTF.TSRC 2018团队赛第五题
-
2018-12-10 11:31 2679
-
因为这个apk文件没有so文件,所以仅仅是静态分析也可以做出来。首先通过dex2jar工具转换到jar文件,在通过jd-gui打开这个jar文件就可以查看这个程序的java源码。不过这个程序使用了proguard保护机制,对变量名和函数名进行了混淆,不过这并不妨碍对这个程序验证逻辑的分析。反编译效果如下:
当点击按钮进行验证时会执行onClick函数,然后通过a函数进行判断,验证逻辑如下:
private void a() { try { c(); if ((this.j != 0) && (this.i != 0) && (this.h != 0)) { d(); a(e() + f() + g() + h()); return; } this.n.setText(getString(2131427370)); } catch (Exception localException) { this.n.setText(getString(2131427370)); } } private void a(int paramInt) { if ((paramInt <= 34) && (paramInt >= 34)) {} try { this.n.setText(String.format("%s%s", new Object[] { getString(2131427369), this.l[paramInt] })); ((Button)findViewById(2131165273)).setEnabled(false); } catch (Exception localException) { this.n.setText(getString(2131427370)); } this.n.setText(getString(2131427370)); }
可以清晰的看出这个程序的验证逻辑,this.l是个String类型的数组,在b函数中初始化。b函数的代码如下:
private void b() { for (int i1 = 0; i1 <= 72; i1++) { if (i1 != 34) { this.l[i1] = getResources().getString(2131427374); } else { this.l[i1] = getResources().getString(2131427375); } } }
通过jadx可以查看到资源文件中的字符串id对应的信息
<public type="string" name="success00" id="2131427374" /> <public type="string" name="success34" id="2131427375" /> <string name="success34">\10財穀有餘主得內助富貴之命\10\10\10此命福氣果如何,僧道門中衣祿多;\10離祖出家方為妙,朝晚拜佛念彌陀。\10\10\10\10此命推來為人性躁;\10與人做事反為不美;\10離祖成家;\10三番四次自成自立安享福;\10直自三十六至四十六;\10財不謀而自至;\10福不求而自得;\10有貴人助;\10家庭安寧;\10妻宮若要無刑;\10猴、豬、羊、蛇不可配;\10龍、虎、馬、牛方得安;\10雖有二子;\10終生帶暗方可.\10兄弟六親如冰碳;\10在家不得安然;\10初限駁雜多端;\10勞碌奔波不能聚錢;\10常有憂愁.\10壽元七十八歲;\10死於三月中.</string>
所以这个带参数的a函数是最终的验证
,接下来就可以重点分析c,d,e,f,g,h这几个函数。通过c函数判断出sn的长度要大于8个字符,1983<int(sn[0:4])<2007,1<=int(sn[4:6])<=12,1<=
int(sn[6:8])<=31
。我把这几个函数的运算逻辑转换到如下python代码:
a = [ 16, 6, 7, 10, 9, 16, 10, 8, 8, 9, 6, 6 ] b = [ 5, 10, 8, 15, 16, 15, 8, 16, 8, 16, 9, 17, 8, 17, 10, 8, 9, 18, 5, 15, 10, 9, 8, 9, 15, 18, 7, 8, 16, 6 ] c = [ 6, 7, 18, 9, 5, 16, 9, 15, 18, 8, 9, 5 ] d = [ 7, 7, 9, 12, 8, 7, 13, 5, 14, 5, 9, 17, 5, 7, 12, 8, 8, 6, 19, 6, 8, 16, 10, 6, 12, 9, 6, 7, 12, 5, 9, 8, 7, 8, 15, 9, 16, 8, 8, 19, 12, 6, 8, 7, 5, 15, 6, 16, 15, 7, 9, 12, 10, 7, 15, 6, 5, 14, 14, 9 ] e=0 f=0 g=0 h=0 i=0 j=0 k=0 m = [ "23to01", "01to03", "03to05", "05to07", "07to09", "09to11", "11to13", "13to15", "15to17", "17to19", "19to21", "21to23" ] def calc(sn): j = int(sn[0:4]) # 1983<j<2007 i = int(sn[4:6]) # 1 <= i <= 12 h = int(sn[6:8]) # 1 <= h <= 31 if ((j == 1989) or (j == 2004)): h = 31 if ((i == 1) or (i == 4) or (i == 5) or (i == 7) or (i == 10) or (i == 11) or (i == 12)): j = 1999 if ((j <= 1994) and ((i == 2) or (i == 6) or (i == 8))): i = 3 if ((j >= 1996) and ((i == 2) or (i == 6) or (i == 8))): i = 9 if ((j == 1995) and ((h > i + 2) or (i == h))): i = 6 g = j f = i e = h t1 = d[(g-1900)%60] t2 = c[f-1] t3 = b[e-1] t4 = 0 t_str = sn[8::] for i2 in range(len(m)): if(t_str == m[i2]): if(f==2 and t_str==m[6]): t4 = 63 break k = a[i2] t4=k return t1+t2+t3+t4
calc(sn)的返回值要为34才能通过验证,所以可以直接采用穷举来解这个题。穷举脚本如下:
def calc2(j,i,h,t_str): if ((j == 1989) or (j == 2004)): h = 31 if ((i == 1) or (i == 4) or (i == 5) or (i == 7) or (i == 10) or (i == 11) or (i == 12)): j = 1999 if ((j <= 1994) and ((i == 2) or (i == 6) or (i == 8))): i = 3 if ((j >= 1996) and ((i == 2) or (i == 6) or (i == 8))): i = 9 if ((j == 1995) and ((h > i + 2) or (i == h))): i = 6 g1 = j f1 = i e1 = h t1 = d[(g1-1900)%60] t2 = c[f1-1] t3 = b[e1-1] t4 = 0 for i2 in range(len(m)): if(t_str == m[i2]): if(f==2 and t_str==m[6]): t4 = 63 break k1 = a[i2] t4=k1 return t1+t2+t3+t4 for j in range(1984,2007): for i in range(1,13): for h in range(1,32): for t_str in m: try: if(calc2(j,i,h,t_str) == 34): print(("%04d%02d%02d%s")%(j,i,h,t_str)) except: continue
穷举出两个值
1995020305to07 ,1995020311to13。正确的sn为1995020305to07
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
最后于 2018-12-10 11:36
被会飞的鱼油编辑
,原因:
赞赏
他的文章
[原创]vmp trace的优化处理
16818
[原创]基于LSTM的二进制代码相似性检测
19666
[原创]混合布尔算术运算的混淆及反混淆
18719
[原创]利用机器学习分析vmp的思路
17278
看原图