题目无壳,ida定位main分析函数流程
__int64 sub_7FF65CDA1290() { bool v0; // si __int64 v1; // rax unsigned __int8 *v2; // rax unsigned __int8 *v3; // rbx int v4; // er10 __int64 v5; // r11 _BYTE *v6; // r9 void **v7; // r8 __int64 v8; // rdi __int64 v9; // r15 __int64 v10; // r12 __int64 v11; // rbp signed int v12; // ecx unsigned __int8 *v13; // rdx __int64 v14; // rdi __int64 *v15; // r14 __int64 v16; // rbp __int64 v17; // r13 _QWORD *v18; // rdi __int64 v19; // r12 __int64 v20; // r15 __int64 v21; // rbp __int64 v22; // rdx __int64 v23; // rbp __int64 v24; // rbp __int64 v25; // r10 __int64 v26; // rdi __int64 v27; // r8 bool v28; // dl __int64 v29; // rax void *v30; // rdx __int64 v31; // rax __int64 v32; // rax _BYTE *v33; // rcx __int64 v35; // [rsp+20h] [rbp-68h] void *Memory; // [rsp+30h] [rbp-58h] unsigned __int64 v37; // [rsp+40h] [rbp-48h] unsigned __int64 v38; // [rsp+48h] [rbp-40h] v0 = 0; v37 = 0i64; v38 = 15i64; LOBYTE(Memory) = 0; v1 = sub_7FF65CDA19C0(std::cout, "I'm a first timer of Logic algebra , how about you?"); std::basic_ostream<char,std::char_traits<char>>::operator<<(v1, sub_7FF65CDA1B90); sub_7FF65CDA19C0(std::cout, "Let's start our game,Please input your flag:"); sub_7FF65CDA1DE0(std::cin, &Memory); // 输入点 std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_7FF65CDA1B90); if ( v37 - 5 > 25 ) // 长度小于30 { v32 = sub_7FF65CDA19C0(std::cout, "Wrong input ,no GXY{} in input words"); std::basic_ostream<char,std::char_traits<char>>::operator<<(v32, sub_7FF65CDA1B90); goto LABEL_45; } v2 = (unsigned __int8 *)sub_7FF65CDA24C8(32ui64); v3 = v2; if ( v2 ) { *(_QWORD *)v2 = 0i64; *((_QWORD *)v2 + 1) = 0i64; *((_QWORD *)v2 + 2) = 0i64; *((_QWORD *)v2 + 3) = 0i64; } else { v3 = 0i64; } v4 = 0; if ( v37 > 0 ) { v5 = 0i64; do { v6 = &Memory; if ( v38 >= 0x10 ) v6 = Memory; // v6 = Memory v7 = &Dst; if ( (unsigned __int64)qword_7FF65CDA6060 >= 0x10 ) v7 = (void **)Dst; // v7 = (void **)Dst v3[v5] = v6[v5] ^ *((_BYTE *)v7 + v4++ % 27);// 计算得到v3 ++v5; } while ( v4 < v37 ); } v8 = 0i64; v9 = 0i64; v10 = 0i64; v11 = 0i64; if ( (signed int)v37 > 30 ) // 长度是0-30 goto LABEL_28; v12 = 0; if ( (signed int)v37 <= 0 ) goto LABEL_28; v13 = v3; do { v14 = *v13 + v8; // v14 = v13[v8] ++v12; ++v13; switch ( v12 ) { case 8: // 8 v11 = v14; // v11 = v13[8] x goto LABEL_24; case 16: // 16 v10 = v14; // v10 = v13[16] y goto LABEL_24; case 24: // 24 v9 = v14; // v9 = v13[24] LABEL_24: v14 = 0i64; break; case 32: // 32 sub_7FF65CDA19C0(std::cout, "ERRO,out of range"); exit(1); break; } v8 = v14 << 8; } while ( v12 < (signed int)v37 ); if ( v11 ) { v15 = (__int64 *)sub_7FF65CDA24C8(0x20ui64); *v15 = v11; // v11 = 4483973367147818765 v15[1] = v10; // v10 = 290580315766788 v15[2] = v9; // v9 = 577031497978884115 v15[3] = v8; // v8 = 842073600 goto LABEL_29; } LABEL_28: v15 = 0i64; // 错误分支 LABEL_29: v35 = v15[2]; v16 = v15[1]; v17 = *v15; v18 = sub_7FF65CDA223C(0x20ui64); if ( IsDebuggerPresent() ) // 反调试 { sub_7FF65CDA19C0(std::cout, "Hi , DO not debug me !"); Sleep(0x7D0u); exit(0); } v19 = v16 & v17; // z3 *v18 = v16 & v17; v20 = v35 & ~v17; v18[1] = v20; v21 = ~v16; v22 = v35 & v21; v18[2] = v35 & v21; v23 = v17 & v21; v18[3] = v23; if ( v20 != 1176889593874i64 ) // v20 = v15[2] & ~v15[0] { v18[1] = 0i64; v20 = 0i64; } v24 = v20 | v19 | v22 | v23; v25 = v15[1]; v26 = v15[2]; v27 = v22 & *v15 | v26 & (v19 | v25 & ~*v15 | ~(v25 | *v15)); v28 = 0; if ( v27 == 577031497978884115i64 ) v28 = v24 == 4483974544037412639i64; if ( (v24 ^ v15[3]) == 4483974543195470111i64 ) v0 = v28; if ( (v20 | v19 | v25 & v26) != (~*v15 & v26 | 864693332579200012i64) || v0 != 1 ) { sub_7FF65CDA19C0(std::cout, "Wrong answer!try again"); j_j_free(v3); } else { v29 = sub_7FF65CDA19C0(std::cout, "Congratulations!flag is GXY{"); v30 = &Memory; if ( v38 >= 0x10 ) v30 = Memory; v31 = sub_7FF65CDA1FD0(v29, v30, v37); sub_7FF65CDA19C0(v31, "}"); j_j_free(v3); } LABEL_45: if ( v38 >= 0x10 ) { v33 = Memory; if ( v38 + 1 >= 0x1000 ) { v33 = (_BYTE *)*((_QWORD *)Memory - 1); if ( (unsigned __int64)((_BYTE *)Memory - v33 - 8) > 0x1F ) invalid_parameter_noinfo_noreturn(); } j_j_free(v33); } return 0i64; }第一个关键点,将输入的内容与Dst进行加密,但Dst暂时不知道内容,后面会有解释
if ( v37 > 0 ) { v5 = 0i64; do { v6 = &Memory; if ( v38 >= 0x10 ) v6 = Memory; // v6 = Memory v7 = &Dst; if ( (unsigned __int64)qword_7FF65CDA6060 >= 0x10 ) v7 = (void **)Dst; // v7 = (void **)Dst v3[v5] = v6[v5] ^ *((_BYTE *)v7 + v4++ % 27);// 计算得到v3 ++v5; } while ( v4 < v37 ); }第二个关键点,分别将加密后的数据分成三组分别赋值给v11,v10,v9
do { v14 = *v13 + v8; // v14 = v13[v8] ++v12; ++v13; switch ( v12 ) { case 8: // 8 v11 = v14; // v11 = v13[8] goto LABEL_24; case 16: // 16 v10 = v14; // v10 = v13[16] goto LABEL_24; case 24: // 24 v9 = v14; // v9 = v13[24] LABEL_24: v14 = 0i64; break; case 32: // 32 sub_7FF65CDA19C0(std::cout, "ERRO,out of range"); exit(1); break; } v8 = v14 << 8; } while ( v12 < (signed int)v37 );再往下是一个方程计算,这段代码之前有赋值操作,所有的方程都可以用x,y,z,w表示
LABEL_29: v35 = v15[2]; v16 = v15[1]; v17 = *v15; v18 = sub_7FF65CDA223C(0x20ui64); if ( IsDebuggerPresent() ) // 反调试 { sub_7FF65CDA19C0(std::cout, "Hi , DO not debug me !"); Sleep(0x7D0u); exit(0); } v19 = v16 & v17; // z3 *v18 = v16 & v17; v20 = v35 & ~v17; v18[1] = v20; v21 = ~v16; v22 = v35 & v21; v18[2] = v35 & v21; v23 = v17 & v21; v18[3] = v23; if ( v20 != 1176889593874i64 ) // v20 = v15[2] & ~v15[0] { v18[1] = 0i64; v20 = 0i64; } v24 = v20 | v19 | v22 | v23; v25 = v15[1]; v26 = v15[2]; v27 = v22 & *v15 | v26 & (v19 | v25 & ~*v15 | ~(v25 | *v15)); v28 = 0; if ( v27 == 577031497978884115i64 ) v28 = v24 == 4483974544037412639i64; if ( (v24 ^ v15[3]) == 4483974543195470111i64 ) v0 = v28; if ( (v20 | v19 | v25 & v26) != (~*v15 & v26 | 864693332579200012i64) || v0 != 1 ) { sub_7FF65CDA19C0(std::cout, "Wrong answer!try again"); j_j_free(v3); }提取替换的伪代码
z & ~x == 1176889593874 z & ~x | y & x | z & ~y | x & ~y == 4483974544037412639 z & ~y &x | z &(y & x | y & ~x | ~(y | x)) == 577031497978884115 (z & ~x | y & x | z & ~y | x & ~y) ^ w == 4483974543195470111直接z3脚本
coding=utf-8 from z3 import * x,y,z,w = BitVecs("x y z w",64)#創建一個位向量 s = Solver()#創建一個解的對象 s.add(z & (~x) == 1176889593874) s.add(z & (~x) | y & x | z & (~y) | x & (~y) == 4483974544037412639) s.add(z & (~y) &x | z &(y & x | y & (~x) | ~(y | x)) == 577031497978884115) s.add((z & (~x) | y & x | z & (~y) | x & (~y)) ^ w == 4483974543195470111) print(s.check()) print(s.model())得到
[w = 842073600, y = 290580315766788, x = 4483973367147818765, z = 577031497978884115]这个xyzw就对应字符串v3
w = 0x32 31 06 00 x = 0x3e 3a 46 05 33 28 6f 0d z = 0x8 02 07 17 15 3e 30 13 y = 0x1 08 48 00 80 00 04
y为7个字节,数组中需要用0代替 再回看算法,开启动态调试到dst位置 解密脚本,替换e!P0or_a为y段的代码
opcode =[0x3e,0x3a,0x46,0x05,0x33,0x28,0x6f,0x0d,0x1,0x08,0x48,0x00,0x00,0x80,0x00,0x04,0x8,0x02,0x07,0x17,0x15,0x3e,0x30,0x13,0x32,0x31,0x06,0x00] x = "i_will_check_is_debug_or_not" flag = "" for i in range(len(opcode)-1): flag += chr((ord(x[i%27])) ^ opcode[i]) print(flag) #We1l_D0ne!P0or_algebra_am_iflag{We1l_D0ne!P0or_algebra_am_i}