-
-
[原创] 看雪CTF.TSRC 2018团队赛第五题
-
发表于: 2018-12-10 11:31 3460
-
因为这个apk文件没有so文件,所以仅仅是静态分析也可以做出来。首先通过dex2jar工具转换到jar文件,在通过jd-gui打开这个jar文件就可以查看这个程序的java源码。不过这个程序使用了proguard保护机制,对变量名和函数名进行了混淆,不过这并不妨碍对这个程序验证逻辑的分析。反编译效果如下:

当点击按钮进行验证时会执行onClick函数,然后通过a函数进行判断,验证逻辑如下:
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 | 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函数的代码如下:
1 2 3 4 5 6 7 8 9 10 | 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对应的信息
1 2 3 | < 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代码:
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 41 42 43 44 45 46 47 | 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才能通过验证,所以可以直接采用穷举来解这个题。穷举脚本如下:
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 | 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

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 | 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函数的代码如下:
1 2 3 4 5 6 7 8 9 10 | 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对应的信息
1 2 3 | < 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代码:
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 41 42 43 44 45 46 47 | 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才能通过验证,所以可以直接采用穷举来解这个题。穷举脚本如下:
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 | 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

1 2 3 4 5 6 7 8 9 10 | 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对应的信息
1 2 3 | < 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代码:
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 41 42 43 44 45 46 47 | 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才能通过验证,所以可以直接采用穷举来解这个题。穷举脚本如下:
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 | 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

1 2 3 | < 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代码:
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
最后于 2018-12-10 11:36
被会飞的鱼油编辑
,原因:
赞赏
他的文章
- vmp3.5模拟x86分支指令je、jne、jge和jl的分析 20129
- [原创]vmp trace的优化处理 19068
- [原创]基于LSTM的二进制代码相似性检测 22037
- [原创]混合布尔算术运算的混淆及反混淆 20832
- [原创]利用机器学习分析vmp的思路 19303
赞赏
雪币:
留言: