题目链接:https://adworld.xctf.org.cn/task/answer?type=reverse&number=4&grade=0&id=5074
1.准备
打开测试用例
首先分析程序
得到是win32程序
2.第一种方法
2.1 分析代码
使用IDA打开,找到main函数,F5得到C代码
得知主要是main_0这个函数,打开
1 "If m of the Nth lamp is 1,it's on ,if not it's off\n" 2 "At first all the lights were closed\n"); 3 sub_45A7BE("Now you can input n to change its state\n"); 4 sub_45A7BE( 5 "But you should pay attention to one thing,if you change the state of the Nth lamp,the state of (N-1)th and (N+1)th w" 6 "ill be changed too\n"); 7 sub_45A7BE("When all lamps are on,flag will appear\n"); 8 sub_45A7BE("Now,input n \n"); 9 while ( 1 ) 10 { 11 while ( 1 ) 12 { 13 sub_45A7BE("input n,n(1-8)\n"); 14 sub_459418(); 15 sub_45A7BE("n="); 16 sub_4596D4("%d", &v1); 17 sub_45A7BE("\n"); 18 if ( v1 >= 0 && v1 <= 8 ) 19 break; 20 sub_45A7BE("sorry,n error,try again\n"); 21 } 22 if ( v1 ) 23 { 24 sub_4576D6(v1 - 1); 25 } 26 else 27 { 28 for ( i = 0; i < 8; ++i ) 29 { 30 if ( (unsigned int)i >= 9 ) 31 j____report_rangecheckfailure(); 32 byte_532E28[i] = 0; 33 } 34 } 35 j__system("CLS"); 36 sub_458054(); 37 if ( byte_532E28[0] == 1 38 && byte_532E28[1] == 1 39 && byte_532E28[2] == 1 40 && byte_532E28[3] == 1 41 && byte_532E28[4] == 1 42 && byte_532E28[5] == 1 43 && byte_532E28[6] == 1 44 && byte_532E28[7] == 1 ) 45 { 46 sub_457AB4(); 47 } 48 } 49 }
通过
if ( byte_532E28[0] == 1 && byte_532E28[1] == 1 && byte_532E28[2] == 1 && byte_532E28[3] == 1 && byte_532E28[4] == 1 && byte_532E28[5] == 1 && byte_532E28[6] == 1 && byte_532E28[7] == 1 )
判断出我们需要将这八个数组的值都变为1,也就是8盏灯都闭合。
2.2 分析规则
打开sub_4576D6(v1 - 1);函数
bool __cdecl sub_45E640(int a1) { bool result; // al if ( a1 ) { if ( a1 == 7 ) { byte_532E28[7] = byte_532E28[7] == 0; byte_532E27[7] = byte_532E27[7] == 0; result = 1; byte_532E28[0] = byte_532E28[0] == 0; } else { byte_532E28[a1] = byte_532E28[a1] == 0; byte_532E27[a1] = byte_532E27[a1] == 0; result = byte_532E29[a1] == 0; byte_532E29[a1] = result; } } else { byte_532E28[0] = byte_532E28[0] == 0; byte_532E29[0] = byte_532E29[0] == 0; result = 1; byte_532E28[7] = byte_532E28[7] == 0; } return result; }
分析得到按键与电路闭合的关系:
- 按1--闭合1,2,8
- 按8--闭合1,7,8
- 按i(除1,8)--闭合i-1,i,i+1
2.3 暴力破解
由此并结合C,汇编代码我们写出暴力破解的C++代码:
#include <iostream> #include <vector> using namespace std; #define for(a,b,c) for(int a = b; a < c; ++a) #define N 8 vector<int> flag(8,-1); void func(int *arr){ for(i,0,N){ int n = arr[i]; if(n == 0){ flag[0] *= -1; flag[1] *= -1; flag[7] *= -1; }else{ if(n == 7){ flag[0] *= -1; flag[6] *= -1; flag[7] *= -1; }else{ flag[n] *= -1; flag[n-1] *= -1; flag[n+1] *= -1; } } } } bool Judge(){ for(i,0,8) if(flag[i] == -1) return false; return true; } int main(void) { int array[N] = {0}; for(i,0,8) for(j,0,8) for(k,0,8) for(m,0,8) for(n,0,8) for(p,0,8) for(q,0,8) for(t,0,8){ array[0] = i; array[1] = j; array[2] = k; array[3] = m; array[4] = n; array[5] = p; array[6] = q; array[7] = t; func(array); if(Judge()){ cout << "success:" << i+1 << j+1 << k+1 << m+1 << n+1 << p+1 << q+1 << t+1 << endl; system("PAUSE"); }else{ for(x,0,8) fill(flag.begin(), flag.end(), -1); } } cout << "over!"; system("PAUSE"); return 0; }
2.4 get flag!
输入到程序中
3.第二种方法
3.1 分析代码
通过分析代码,我们很容易获知sub_457AB4()就是输出flag的函数
if ( byte_532E28[0] == 1 && byte_532E28[1] == 1 && byte_532E28[2] == 1 && byte_532E28[3] == 1 && byte_532E28[4] == 1 && byte_532E28[5] == 1 && byte_532E28[6] == 1 && byte_532E28[7] == 1 ) { sub_457AB4(); }
int sub_45E940() { char v1; // [esp+0h] [ebp-164h] signed int i; // [esp+D0h] [ebp-94h] char v3; // [esp+DCh] [ebp-88h] char v4; // [esp+DDh] [ebp-87h] char v5; // [esp+DEh] [ebp-86h] char v6; // [esp+DFh] [ebp-85h] char v7; // [esp+E0h] [ebp-84h] char v8; // [esp+E1h] [ebp-83h] char v9; // [esp+E2h] [ebp-82h] char v10; // [esp+E3h] [ebp-81h] char v11; // [esp+E4h] [ebp-80h] char v12; // [esp+E5h] [ebp-7Fh] char v13; // [esp+E6h] [ebp-7Eh] char v14; // [esp+E7h] [ebp-7Dh] char v15; // [esp+E8h] [ebp-7Ch] char v16; // [esp+E9h] [ebp-7Bh] char v17; // [esp+EAh] [ebp-7Ah] char v18; // [esp+EBh] [ebp-79h] char v19; // [esp+ECh] [ebp-78h] char v20; // [esp+EDh] [ebp-77h] char v21; // [esp+EEh] [ebp-76h] char v22; // [esp+EFh] [ebp-75h] char v23; // [esp+F0h] [ebp-74h] char v24; // [esp+F1h] [ebp-73h] char v25; // [esp+F2h] [ebp-72h] char v26; // [esp+F3h] [ebp-71h] char v27; // [esp+F4h] [ebp-70h] char v28; // [esp+F5h] [ebp-6Fh] char v29; // [esp+F6h] [ebp-6Eh] char v30; // [esp+F7h] [ebp-6Dh] char v31; // [esp+F8h] [ebp-6Ch] char v32; // [esp+F9h] [ebp-6Bh] char v33; // [esp+FAh] [ebp-6Ah] char v34; // [esp+FBh] [ebp-69h] char v35; // [esp+FCh] [ebp-68h] char v36; // [esp+FDh] [ebp-67h] char v37; // [esp+FEh] [ebp-66h] char v38; // [esp+FFh] [ebp-65h] char v39; // [esp+100h] [ebp-64h] char v40; // [esp+101h] [ebp-63h] char v41; // [esp+102h] [ebp-62h] char v42; // [esp+103h] [ebp-61h] char v43; // [esp+104h] [ebp-60h] char v44; // [esp+105h] [ebp-5Fh] char v45; // [esp+106h] [ebp-5Eh] char v46; // [esp+107h] [ebp-5Dh] char v47; // [esp+108h] [ebp-5Ch] char v48; // [esp+109h] [ebp-5Bh] char v49; // [esp+10Ah] [ebp-5Ah] char v50; // [esp+10Bh] [ebp-59h] char v51; // [esp+10Ch] [ebp-58h] char v52; // [esp+10Dh] [ebp-57h] char v53; // [esp+10Eh] [ebp-56h] char v54; // [esp+10Fh] [ebp-55h] char v55; // [esp+110h] [ebp-54h] char v56; // [esp+111h] [ebp-53h] char v57; // [esp+112h] [ebp-52h] char v58; // [esp+113h] [ebp-51h] char v59; // [esp+114h] [ebp-50h] char v60; // [esp+120h] [ebp-44h] char v61; // [esp+121h] [ebp-43h] char v62; // [esp+122h] [ebp-42h] char v63; // [esp+123h] [ebp-41h] char v64; // [esp+124h] [ebp-40h] char v65; // [esp+125h] [ebp-3Fh] char v66; // [esp+126h] [ebp-3Eh] char v67; // [esp+127h] [ebp-3Dh] char v68; // [esp+128h] [ebp-3Ch] char v69; // [esp+129h] [ebp-3Bh] char v70; // [esp+12Ah] [ebp-3Ah] char v71; // [esp+12Bh] [ebp-39h] char v72; // [esp+12Ch] [ebp-38h] char v73; // [esp+12Dh] [ebp-37h] char v74; // [esp+12Eh] [ebp-36h] char v75; // [esp+12Fh] [ebp-35h] char v76; // [esp+130h] [ebp-34h] char v77; // [esp+131h] [ebp-33h] char v78; // [esp+132h] [ebp-32h] char v79; // [esp+133h] [ebp-31h] char v80; // [esp+134h] [ebp-30h] char v81; // [esp+135h] [ebp-2Fh] char v82; // [esp+136h] [ebp-2Eh] char v83; // [esp+137h] [ebp-2Dh] char v84; // [esp+138h] [ebp-2Ch] char v85; // [esp+139h] [ebp-2Bh] char v86; // [esp+13Ah] [ebp-2Ah] char v87; // [esp+13Bh] [ebp-29h] char v88; // [esp+13Ch] [ebp-28h] char v89; // [esp+13Dh] [ebp-27h] char v90; // [esp+13Eh] [ebp-26h] char v91; // [esp+13Fh] [ebp-25h] char v92; // [esp+140h] [ebp-24h] char v93; // [esp+141h] [ebp-23h] char v94; // [esp+142h] [ebp-22h] char v95; // [esp+143h] [ebp-21h] char v96; // [esp+144h] [ebp-20h] char v97; // [esp+145h] [ebp-1Fh] char v98; // [esp+146h] [ebp-1Eh] char v99; // [esp+147h] [ebp-1Dh] char v100; // [esp+148h] [ebp-1Ch] char v101; // [esp+149h] [ebp-1Bh] char v102; // [esp+14Ah] [ebp-1Ah] char v103; // [esp+14Bh] [ebp-19h] char v104; // [esp+14Ch] [ebp-18h] char v105; // [esp+14Dh] [ebp-17h] char v106; // [esp+14Eh] [ebp-16h] char v107; // [esp+14Fh] [ebp-15h] char v108; // [esp+150h] [ebp-14h] char v109; // [esp+151h] [ebp-13h] char v110; // [esp+152h] [ebp-12h] char v111; // [esp+153h] [ebp-11h] char v112; // [esp+154h] [ebp-10h] char v113; // [esp+155h] [ebp-Fh] char v114; // [esp+156h] [ebp-Eh] char v115; // [esp+157h] [ebp-Dh] char v116; // [esp+158h] [ebp-Ch] sub_45A7BE((int)"done!!! the flag is ", v1); v60 = 18; v61 = 64; v62 = 98; v63 = 5; v64 = 2; v65 = 4; v66 = 6; v67 = 3; v68 = 6; v69 = 48; v70 = 49; v71 = 65; v72 = 32; v73 = 12; v74 = 48; v75 = 65; v76 = 31; v77 = 78; v78 = 62; v79 = 32; v80 = 49; v81 = 32; v82 = 1; v83 = 57; v84 = 96; v85 = 3; v86 = 21; v87 = 9; v88 = 4; v89 = 62; v90 = 3; v91 = 5; v92 = 4; v93 = 1; v94 = 2; v95 = 3; v96 = 44; v97 = 65; v98 = 78; v99 = 32; v100 = 16; v101 = 97; v102 = 54; v103 = 16; v104 = 44; v105 = 52; v106 = 32; v107 = 64; v108 = 89; v109 = 45; v110 = 32; v111 = 65; v112 = 15; v113 = 34; v114 = 18; v115 = 16; v116 = 0; v3 = 123; v4 = 32; v5 = 18; v6 = 98; v7 = 119; v8 = 108; v9 = 65; v10 = 41; v11 = 124; v12 = 80; v13 = 125; v14 = 38; v15 = 124; v16 = 111; v17 = 74; v18 = 49; v19 = 83; v20 = 108; v21 = 94; v22 = 108; v23 = 84; v24 = 6; v25 = 96; v26 = 83; v27 = 44; v28 = 121; v29 = 104; v30 = 110; v31 = 32; v32 = 95; v33 = 117; v34 = 101; v35 = 99; v36 = 123; v37 = 127; v38 = 119; v39 = 96; v40 = 48; v41 = 107; v42 = 71; v43 = 92; v44 = 29; v45 = 81; v46 = 107; v47 = 90; v48 = 85; v49 = 64; v50 = 12; v51 = 43; v52 = 76; v53 = 86; v54 = 13; v55 = 114; v56 = 1; v57 = 117; v58 = 126; v59 = 0; for ( i = 0; i < 56; ++i ) { *(&v3 + i) ^= *(&v60 + i); *(&v3 + i) ^= 0x13u; } return sub_45A7BE((int)"%s\n", (unsigned int)&v3); }
这实际上就是一段经过计算,输出flag的代码,for上面是已知条件,下面进行变换,我们可以转换为Python代码,输出flag
3.2 脚本获取flag
arr1 = [18, 64, 98, 5, 2, 4, 6, 3, 6, 48, 49, 65, 32, 12, 48, 65, 31, 78, 62, 32, 49, 32, 1, 57, 96, 3, 21, 9, 4, 62, 3, 5, 4, 1, 2, 3, 44, 65, 78, 32, 16, 97, 54, 16, 44, 52, 32, 64, 89, 45, 32, 65, 15, 34, 18, 16, 0] arr2 = [123, 32, 18, 98, 119, 108, 65, 41, 124, 80, 125, 38, 124, 111, 74, 49, 83, 108, 94, 108, 84, 6, 96, 83, 44, 121, 104, 110, 32, 95, 117, 101, 99, 123, 127, 119, 96, 48, 107, 71, 92, 29, 81, 107, 90, 85, 64, 12, 43, 76, 86, 13, 114, 1, 117, 126, 0] str = '' for i in range(0, 56): arr2[0 + i] ^= arr1[0 + i] arr2[0 + i] ^= 0x13 str = str + chr(arr2[i]); print(str)
3.3 get flag!
zsctf{T9is_tOpic_1s_v5ry_int7resting_b6t_others_are_n0t}