赛题下载地址:https://www.lanzous.com/b07r91skd
0x01 lucky_guy
IDA打开
进入patch_me
进入get_flag
随机产生5个数字,每产生一个进入下面switch进行处理
代码分析
分析得到处理顺序
1中得到f2的初始值"icug`of ",2可能执行多次,3中f1为 "GXY{do_not_",因此可以写出C++代码模拟过程。
程序解密
#include <iostream> using namespace std; /* run this program using the console pauser or add your own getch, system("pause") or input loop */ int main(int argc, char** argv) { char v1; char f2[] = "icug`of "; cout << f2 << endl; for (int i = 0; i < 4; ++i) { for (int j = 0; j <= 7; ++j) { if (j % 2 == 1) v1 = f2[j] - 2; else v1 = f2[j] - 1; f2[j] = v1; } cout << f2 << endl; } return 0; }
得到后半部分,"hate_me}"
组合起来就是GXY{do_not_hate_me}
get flag!
GXY{do_not_hate_me}
0x02 simple_CPP
IDA打开
将代码整体分为了三个部分
1 if ( v37 > 0 ) 2 { 3 v5 = 0i64; 4 do 5 { 6 v6 = &Memory; // v6为输入 7 if ( v38 >= 0x10 ) 8 v6 = Memory; 9 v7 = &Dst; // Dst=i_will_check_is_debug_or_not 10 if ( (unsigned __int64)qword_140006060 >= 0x10 ) 11 v7 = (void **)Dst; 12 v3[v5] = v6[v5] ^ *((_BYTE *)v7 + v4++ % 27);// 输入进行变换 13 ++v5; 14 } 15 while ( v4 < v37 ); 16 }
1 do 2 { 3 v14 = *v13 + v8; // 对输入变换后的字符串再进行变换 4 ++v12; 5 ++v13; 6 switch ( v12 ) 7 { 8 case 8: // v11=第8位的 9 v11 = v14; 10 goto LABEL_24; 11 case 16: 12 v10 = v14; // v11第16位的 13 goto LABEL_24; 14 case 24: // v11=第24位 15 v9 = v14; 16 LABEL_24: 17 v14 = 0i64; 18 break; 19 case 32: 20 sub_1400019C0(std::cout, "ERRO,out of range"); 21 exit(1); 22 break; 23 } 24 v8 = v14 << 8; 25 } 26 while ( v12 < (signed int)v37 );
1 v35 = v15[2]; // 1-2 2 v16 = v15[1]; 3 v17 = *v15; // 1-2 4 v18 = sub_14000223C(0x20ui64); 5 if ( IsDebuggerPresent() ) 6 { 7 sub_1400019C0(std::cout, "Hi , DO not debug me !"); 8 Sleep(0x7D0u); 9 exit(0); 10 } 11 v19 = v16 & v17; 12 *v18 = v16 & v17; 13 v20 = v35 & ~v17; // 1-1 14 v18[1] = v20; 15 v21 = ~v16; 16 v22 = v35 & v21; 17 v18[2] = v35 & v21; 18 v23 = v17 & v21; 19 v18[3] = v23; 20 if ( v20 != 1176889593874i64 ) 21 { 22 v18[1] = 0i64; 23 v20 = 0i64; 24 } 25 v24 = v20 | v19 | v22 | v23; 26 v25 = v15[1]; 27 v26 = v15[2]; 28 v27 = v22 & *v15 | v26 & (v19 | v25 & ~*v15 | ~(v25 | *v15)); 29 v28 = 0; 30 if ( v27 == 577031497978884115i64 ) 31 v28 = v24 == 4483974544037412639i64; 32 if ( (v24 ^ v15[3]) == 4483974543195470111i64 ) 33 v0 = v28; 34 if ( (v20 | v19 | v25 & v26) != (~*v15 & v26 | 864693332579200012i64) || v0 != 1 ) 35 { 36 sub_1400019C0(std::cout, "Wrong answer!try again"); 37 j_j_free(v3); 38 } 39 else 40 { 41 v29 = sub_1400019C0(std::cout, "Congratulations!flag is GXY{"); 42 v30 = &Memory; 43 if ( v38 >= 0x10 ) 44 v30 = Memory; 45 v31 = sub_140001FD0(v29, v30, v37); 46 sub_1400019C0(v31, "}"); 47 j_j_free(v3); 48 }
代码分析
针对第三部分:
首先整理第三部分的各个运算式子
v19 = v15[1] & v17[0]
v20 = v15[2] & ~v15[0]
v20 = 1176889593874
v21 = ~v15[1]
v22 = v15[2] & ~v15[1]
v23 = v15[0] & ~v15[1]
v24 = (v15[2] & ~v15[0]) | (v15[1] & v15[0]) | (v15[2] & ~v15[1]) | (v15[0] & ~v15[1])
v24 = 4483974544037412639
v25 = v15[1]
v26 = v15[2]
v27 = (v15[2] & ~v15[1]) & v15[0] | v15[2] & ((v15[1] & v17[0]) | v15[1] &~v15[0] | ~(v15[1] | v15[0]))
v27 = 577031497978884115
v24 ^ v15[3] = 4483974543195470111
((v15[2] & ~v15[0]) | ( v15[1] & v17[0]) | v15[1] & v15[2]) == (~v15[0] & v15[2] | 864693332579200012)
使用z3解方程,得到v15[0]~v15[3]的解
# -*- coding:utf-8 -*- from z3 import * x,y,z,w=BitVecs('x y z w',64) s=Solver() s.add((~x)&z==1176889593874) s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111) s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115) s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639) s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|864693332579200012)) s.check() m = s.model() for i in m: print("%s = 0x%x"%(i,m[i].as_long()))
w = 0x32310600
z = 0x8020717153e3013
y = 0xc00020130082c0c
x = 0x3e3a460533286f0d
针对第二部分:
将x,y,z,w拼接起来,并将x,y,z补足为16位
li=[] # 拼接 li.append(hex(m[x].as_long())[2:].rjust(16,"0")) li.append(hex(m[y].as_long())[2:].rjust(16,"0")) li.append(hex(m[z].as_long())[2:].rjust(16,"0")) li.append(hex(m[w].as_long())[2:-2]) print(li)
['3e3a460533286f0d', '0c00020130082c0c', '08020717153e3013', '323106']
针对第一部分:
就是一个异或的表达式,通过动态调试可以得到Dst的值为"i_will_check_is_debug_or_not",即可得到v7,再将异或逆向就行。
脚本解密
# -*- coding:utf-8 -*- from z3 import * debug_str = "i_will_check_is_debug_or_not" x,y,z,w=BitVecs('x y z w',64) s=Solver() s.add((~x)&z==1176889593874) s.add(((z&~x)|(x&y)|(z&(~y))|(x&(~y)))^w==4483974543195470111) s.add(((z&~y)&x|z&((x&y)|y&~x|~(y|x)))==577031497978884115) s.add(((z&~x)|(x&y)|(z&~y)|(x&~y))==4483974544037412639) s.add(((z&(~x)) | (x&y) | y & z) == (((~x)& z)|864693332579200012)) s.check() m = s.model() for i in m: print("%s = 0x%x"%(i,m[i].as_long())) flag="" li=[] # 拼接 li.append(hex(m[x].as_long())[2:].rjust(16,"0")) li.append(hex(m[y].as_long())[2:].rjust(16,"0")) li.append(hex(m[z].as_long())[2:].rjust(16,"0")) li.append(hex(m[w].as_long())[2:-2]) print(li) v4=0 for i in li: for j in range(0,len(i),2): xx = i[j]+i[j+1] flag += chr(int(xx,16)^ord(debug_str[(v4)%27])) v4 += 1 print(flag)
解出来得到的flag为
We1l_D0n
We1l_D0ndeajoa_S
We1l_D0ndeajoa_Slgebra_a
We1l_D0ndeajoa_Slgebra_am_i
get flag!
通过官方给的提示,第二部分有问题,给了第二部分的解“e!P0or_a”,替换掉我们得到的,得到正确的flag
GXY{We1l_D0ne!P0or_algebra_am_i}