DMCTF 2020 re1 名字叫来点简单的算法题……Peid
查壳查算法,没查出来,进IDA
。
定位main
函数,重命名,一气呵成:
盲猜sub_485D1A
里面嵌套了strlen
,跟进去看看,应该差不多,flag
长度要求20
.
那就再进sub_4849EC
看看;
美化一下:
瞬间舒服多了……目测凯撒,直接上他:
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 ans=[] a=[0x73 ,0x65 ,0x6D ,0x66 ] a=a[::-1 ] for i in a: ans.append(i) a=[0x6D ,0x75 ,0x7B ,0x68 ] a=a[::-1 ] for i in a: ans.append(i) a=[0x76 ,0x5F ,0x63 ,0x6B ] a=a[::-1 ] for i in a: ans.append(i) a=[0x5F ,0x6E ,0x72 ,0x6C ] a=a[::-1 ] for i in a: ans.append(i) a=[0x7D ,0x68 ,0x6C ,0x67 ] a=a[::-1 ] for i in a: ans.append(i) for i in ans: if i>=ord ('a' ) and i<=ord ('k' ): print(chr (i-2 ),end='' ) elif i>=ord ('o' ) and i<=ord ('y' ): print(chr (i+1 ),end='' ) elif i==ord ('l' ) or i==ord ('m' ): print("(" ,chr (i-2 ),chr (i),")" ,end='' ) elif i==ord ('n' ): print("(" ,chr (i),chr (i+1 ),")" ,end='' ) else : print(chr (i),end='' )
这个题貌似就是多解……经RX
验证……
DMCTF 2020 re4 DIE
查壳……没结果,拖进IDA
,查看字符串,定位main
函数:
根据红框框,盲猜地图题。 扣地图:
1 0 0 0 0 1 1 0 0 0 1 1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 1 0 0 0 1 1 1 1 1 0 1 0 0 0 0 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 1
看逻辑:
手动走迷宫:
sdssdddsdwwwwdsdsssssdssds 20220002033330202222202202
执行一下:
GWCTF 2019 xxor DIE
查一下,没什么……拖进IDA64
,woc
惊喜!没扣符号表!!!
找到main
函数,美化一下:
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 __int64 __fastcall main (int a1, char **a2, char **a3) { int i; int j; __int64 v6[6 ]; __int64 v7[6 ]; v7[5 ] = __readfsqword(0x28 u); puts ("Let us play a game?" ); puts ("you have six chances to input" ); puts ("Come on!" ); v6[0 ] = 0LL ; v6[1 ] = 0LL ; v6[2 ] = 0LL ; v6[3 ] = 0LL ; v6[4 ] = 0LL ; for ( i = 0 ; i <= 5 ; ++i ) { printf ("%s" , "input: " ); a2 = (char **)((char *)v6 + 4 * i); __isoc99_scanf("%d" , a2); } v7[0 ] = 0LL ; v7[1 ] = 0LL ; v7[2 ] = 0LL ; v7[3 ] = 0LL ; v7[4 ] = 0LL ; for ( j = 0 ; j <= 2 ; ++j ) { dword_601078 = v6[j]; dword_60107C = HIDWORD(v6[j]); a2 = (char **)&unk_601060; sub_400686(&dword_601078, &unk_601060); LODWORD(v7[j]) = dword_601078; HIDWORD(v7[j]) = dword_60107C; } if ( (unsigned int )sub_400770(v7, a2) != 1 ) { puts ("NO NO NO~ " ); exit (0 ); } puts ("Congratulation!\n" ); puts ("You seccess half\n" ); puts ("Do not forget to change input to hex and combine~\n" ); puts ("ByeBye" ); return 0LL ; }__int64 __fastcall main (__int64 a1, char **a2, char **a3) { signed int i; signed int j; __int64 input[5 ]; __int64 flag_enc[5 ]; unsigned __int64 v8; v8 = __readfsqword(0x28 u); puts ("Let us play a game?" ); puts ("you have six chances to input" ); puts ("Come on!" ); input[0 ] = 0LL ; input[1 ] = 0LL ; input[2 ] = 0LL ; input[3 ] = 0LL ; input[4 ] = 0LL ; for ( i = 0 ; i <= 5 ; ++i ) { printf ("%s" , "input: " , (unsigned int )i); __isoc99_scanf("%d" , (char *)input + 4 * i); } flag_enc[0 ] = 0LL ; flag_enc[1 ] = 0LL ; flag_enc[2 ] = 0LL ; flag_enc[3 ] = 0LL ; flag_enc[4 ] = 0LL ; for ( j = 0 ; j <= 2 ; ++j ) { tmp_0_ = input[j]; tmp_1_ = *((_DWORD *)input + j * 2 + 1 ); change((unsigned int *)&tmp_0_, &table); LODWORD(flag_enc[j]) = tmp_0_; *((_DWORD *)flag_enc + j * 2 + 1 ) = tmp_1_; } if ( (unsigned int )check(flag_enc) != 1 ) { puts ("NO NO NO~ " ); exit (0 ); } puts ("Congratulation!\n" ); puts ("You seccess half\n" ); puts ("Do not forget to change input to hex and combine~\n" ); puts ("ByeBye" ); return 0LL ; }
思路比较清晰,输入以后change
函数处理,check
函数比较,出结果。
我们先来看看check
函数,美化:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 signed __int64 __fastcall check (_DWORD *a1) { signed __int64 result; if ( a1[2 ] - a1[3 ] != 0x84A236FF LL || a1[3 ] + a1[4 ] != 0xFA6CB703 LL || a1[2 ] - a1[4 ] != 0x42D731A8 LL ) { puts ("Wrong!" ); result = 0LL ; } else if ( *a1 != 0xDF48EF7E || a1[5 ] != 0x84F30420 || a1[1 ] != 0x20CAACF4 ) { puts ("Wrong!" ); result = 0LL ; } else { puts ("good!" ); result = 1LL ; } return result; }
根据提示,z3
解方程:
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 from z3 import *s=Solver() x0 = Int('x0' ) x1 = Int('x1' ) x2 = Int('x2' ) x3 = Int('x3' ) x4 = Int('x4' ) x5 = Int('x5' ) s.add(x0==0xDF48EF7E ) s.add(x5==0x84F30420 ) s.add(x1==0x20CAACF4 ) s.add(x2-x3==0x84A236FF ) s.add(x3+x4==0xFA6CB703 ) s.add(x2-x4==0x42D731A8 ) if s.check() == sat: m = s.model() print(m) ''' [x2 = 3774025685, x3 = 1548802262, x4 = 2652626477, x1 = 550153460, x5 = 2230518816, x0 = 3746099070] '''
那么相当于知道了flag_enc
,再看change
函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 __int64 __fastcall change (unsigned int *ini, _DWORD *tables) { __int64 result; unsigned int var; unsigned int var_1; int tmp; unsigned int i; var = *ini; var_1 = ini[1 ]; tmp = 0 ; for ( i = 0 ; i <= 63 ; ++i ) { tmp += 0x458BCD42 ; var += (var_1 + tmp + 11 ) ^ ((var_1 << 6 ) + *tables) ^ ((var_1 >> 9 ) + tables[1 ]) ^ 0x20 ; var_1 += (var + tmp + 20 ) ^ ((var << 6 ) + tables[2 ]) ^ ((var >> 9 ) + tables[3 ]) ^ 0x10 ; } *ini = var; result = var_1; ini[1 ] = var_1; return result; }
对change
函数的三行关键代码进行分析,发现var_1
的处理只与此时var
的值有关,其余都是常量;var
的处理只与此时var_1
值有关,其余都是常量。所以直接把加号变成减号就ok
了。
然后还有一点需要注意的就是在IDA
里面你的数据数据类型是什么,你在写exp
的时候数据就用什么数据类型,否则可能会出锅。
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 #include <bits/stdc++.h> using namespace std ;int main () { unsigned int flag_enc[5 ],flag[5 ]; flag_enc[0 ]=3746099070 ;flag_enc[1 ]=550153460 ;flag_enc[2 ]=3774025685 ;flag_enc[3 ]=1548802262 ;flag_enc[4 ]=2652626477 ;flag_enc[5 ]=2230518816 ; unsigned int var[3 ]; unsigned int tables[4 ]={2 ,2 ,3 ,4 }; for (int i=0 ;i<5 ;i+=2 ){ int tmp = 0x458BCD42 *64 ; var[0 ]=flag_enc[i]; var[1 ]=flag_enc[i+1 ]; for (int j=0 ;j<=0x3F ;j++){ var[1 ] -= (var[0 ] + tmp + 20 ) ^ ((var[0 ] << 6 ) + tables[2 ]) ^ ((var[0 ] >> 9 ) + tables[3 ]) ^ 0x10 ; var[0 ] -= (var[1 ] + tmp + 11 ) ^ ((var[1 ] << 6 ) + tables[0 ]) ^ ((var[1 ] >> 9 ) + tables[1 ]) ^ 0x20 ; tmp-=0x458BCD42 ; } flag[i]=var[0 ]; flag[i+1 ]=var[1 ]; } for (int i=0 ;i<6 ;i++) printf ("0x%x\n" ,flag[i]); }
再用sublime
处理一下,用python
稍微跑一下:
1 2 3 4 flag=[0x66 ,0x6c ,0x61 ,0x67 ,0x7b ,0x72 ,0x65 ,0x5f ,0x69 ,0x73 ,0x5f ,0x67 ,0x72 ,0x65 ,0x61 ,0x74 ,0x21 ,0x7d ] for i in flag: print(chr (i),end='' )