2019 RoarCTF--polyre
1.准备
获取信息
- 64位文件
2.文件处理
2.1 控制流平坦化
IDA打开后可以看到
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { signed int v3; // ecx signed int v4; // ecx signed int v5; // ecx signed int v6; // ecx signed int v7; // ecx signed int v8; // ecx signed int v9; // ecx signed int v10; // ecx signed int v11; // ecx signed int v12; // ecx signed int v13; // ecx signed int v14; // ecx signed int v15; // ecx signed int v16; // ecx signed int v17; // ecx signed int v18; // ecx signed int v19; // ecx signed int v20; // ecx signed int v21; // ecx signed int v22; // esi signed int v23; // ecx signed int v24; // ecx signed int v25; // ecx signed int v26; // ecx signed int v28; // [rsp+1DCh] [rbp-114h] unsigned __int64 v29; // [rsp+1E0h] [rbp-110h] int v30; // [rsp+1E8h] [rbp-108h] int v31; // [rsp+1ECh] [rbp-104h] char s1[48]; // [rsp+1F0h] [rbp-100h] char s[60]; // [rsp+220h] [rbp-D0h] unsigned int v34; // [rsp+25Ch] [rbp-94h] char *v35; // [rsp+260h] [rbp-90h] int v36; // [rsp+26Ch] [rbp-84h] bool v37; // [rsp+272h] [rbp-7Eh] unsigned __int8 v38; // [rsp+273h] [rbp-7Dh] int v39; // [rsp+274h] [rbp-7Ch] char *v40; // [rsp+278h] [rbp-78h] int v41; // [rsp+284h] [rbp-6Ch] int v42; // [rsp+288h] [rbp-68h] bool v43; // [rsp+28Fh] [rbp-61h] char *v44; // [rsp+290h] [rbp-60h] int v45; // [rsp+298h] [rbp-58h] bool v46; // [rsp+29Fh] [rbp-51h] __int64 v47; // [rsp+2A0h] [rbp-50h] bool v48; // [rsp+2AFh] [rbp-41h] unsigned __int64 v49; // [rsp+2B0h] [rbp-40h] unsigned __int64 v50; // [rsp+2B8h] [rbp-38h] unsigned __int64 v51; // [rsp+2C0h] [rbp-30h] unsigned __int64 v52; // [rsp+2C8h] [rbp-28h] int v53; // [rsp+2D0h] [rbp-20h] int v54; // [rsp+2D4h] [rbp-1Ch] char *v55; // [rsp+2D8h] [rbp-18h] int v56; // [rsp+2E0h] [rbp-10h] int v57; // [rsp+2E4h] [rbp-Ch] bool v58; // [rsp+2EBh] [rbp-5h] unsigned int v59; // [rsp+2ECh] [rbp-4h] v34 = 0; v28 = 2013758019; while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( 1 ) { while ( v28 == -2119479925 ) { v30 = 0; v28 = 1768345936; } if ( v28 != -2087982142 ) break; v28 = -477867459; } if ( v28 != -2048748379 ) break; v28 = 283854908; } if ( v28 != -1971893440 ) break; v28 = -981997032; } if ( v28 != -1876979972 ) break; v28 = 1278104886; } if ( v28 != -1843952179 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v21 = -1358401961; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v21 = -759088748; v28 = v21; } if ( v28 != -1841026192 ) break; v28 = -981997032; } if ( v28 != -1835257763 ) break; v31 = 0; v28 = -194920207; } if ( v28 != -1834653726 ) break; v42 = v30; a3 = (char **)(unsigned int)(dword_603054 - 1); v13 = 762694599; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v13 = 1591698962; v28 = v13; } if ( v28 != -1799275846 ) break; v28 = 1988968584; } if ( v28 != -1780989165 ) break; v29 = *(_QWORD *)&v44[8 * v30]; v28 = -1835257763; } if ( v28 != -1732387288 ) break; a3 = (char **)2110558301; if ( v58 ) a3 = (char **)3153606742LL; v28 = (signed int)a3; } if ( v28 != -1682981725 ) break; a3 = (char **)873723531; if ( v43 ) a3 = (char **)1558414728; v28 = (signed int)a3; } if ( v28 != -1679168360 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v8 = -1608245220; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v8 = -1039797642; v28 = v8; } if ( v28 != -1658420490 ) break; v28 = 738697886; } if ( v28 != -1608245220 ) break; v28 = -1039797642; } if ( v28 != -1593453884 ) break; v29 = v49; v28 = -210664208; } if ( v28 != -1588745861 ) break; v49 = 2 * v29; v28 = -1099829591; } if ( v28 != -1578333348 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v7 = -1015938266; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v7 = 977391758; v28 = v7; } if ( v28 != -1453272720 ) break; v51 = v29; v28 = 1416478473; } if ( v28 != -1395524712 ) break; v57 = memcmp(s1, &unk_402170, 0x30uLL); v24 = 2127761645; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v24 = -2048748379; v28 = v24; } if ( v28 != -1358463792 ) break; v28 = 165194735; } if ( v28 != -1358401961 ) break; *(_QWORD *)v55 = v29; v28 = -759088748; } if ( v28 != -1243245941 ) break; v28 = 1852460924; } if ( v28 != -1241653263 ) break; v31 = v41; a3 = (char **)(unsigned int)(dword_603054 - 1); v11 = 1958488484; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v11 = 397199458; v28 = v11; } if ( v28 != -1146236158 ) break; a3 = (char **)3169640671LL; if ( v46 ) a3 = (char **)174114970; v28 = (signed int)a3; } if ( v28 != -1141360554 ) break; v28 = -1971893440; puts("Wrong!"); } if ( v28 != -1125326625 ) break; v54 = 8 * v30; v28 = 1241066884; } if ( v28 != -1104384261 ) break; v40 = &s[v31]; v28 = -199559592; } if ( v28 != -1099829591 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v17 = -1593453884; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v17 = -210664208; v28 = v17; } if ( v28 != -1039797642 ) break; v39 = v38; a3 = (char **)2686722076LL; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) a3 = (char **)2417987324LL; v28 = (signed int)a3; } if ( v28 != -1015938266 ) break; v28 = -1578333348; } if ( v28 != -1008576722 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v16 = -2087982142; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v16 = -477867459; v28 = v16; } if ( v28 != -1002050507 ) break; v29 = v52; v28 = 1471710476; } if ( v28 != -987629196 ) break; v53 = v31; v28 = 183264728; } if ( v28 != -981997032 ) break; v59 = v34; v28 = 1934644251; } if ( v28 != -853256898 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v10 = 1958488484; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v10 = -1241653263; v28 = v10; } if ( v28 != -759088748 ) break; *(_QWORD *)v55 = v29; a3 = (char **)140103415; v22 = -1358401961; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v22 = 140103415; v28 = v22; } if ( v28 != -744786104 ) break; v38 = s[v31]; v28 = -1679168360; } if ( v28 != -718028952 ) break; v28 = -213314773; } if ( v28 != -506887986 ) break; v31 = 0; v28 = -469992559; __isoc99_scanf("%s", v35, a3); } if ( v28 != -490420216 ) break; a3 = (char **)2841694576LL; if ( v48 ) a3 = (char **)2706221435LL; v28 = (signed int)a3; } if ( v28 != -484679360 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v14 = 550812935; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v14 = 253474089; v28 = v14; } if ( v28 != -477867459 ) break; v46 = v45 < 64; a3 = (char **)2206985154LL; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) a3 = (char **)1590869113; v28 = (signed int)a3; } if ( v28 != -469992559 ) break; __isoc99_scanf( "%s", v35, a3); v31 = 0; a3 = (char **)3788079310LL; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) a3 = (char **)1091618206; v28 = (signed int)a3; } if ( v28 != -351376304 ) break; v28 = -1682981725; } if ( v28 != -309679135 ) break; v28 = 385821084; } if ( v28 != -213314773 ) break; v41 = v31 + 1; v28 = -853256898; } if ( v28 != -210664208 ) break; v29 = v49; v50 = v49; a3 = (char **)2701513412LL; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { a3 = (char **)481625179; } v28 = (signed int)a3; } if ( v28 != -199559592 ) break; *v40 = 0; v28 = 2024088016; } if ( v28 != -197416524 ) break; v30 = v56; v28 = 1478643244; } if ( v28 != -194920207 ) break; v45 = v31; v28 = -1008576722; } if ( v28 != -172688243 ) break; v28 = -1780989165; } if ( v28 != 30189008 ) break; v44 = s; a3 = (char **)325614949; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { a3 = (char **)4122279053LL; } v28 = (signed int)a3; } if ( v28 != 35266435 ) break; v28 = -1002050507; } if ( v28 != 111496758 ) break; v31 = v53 + 1; v28 = 1585728989; } if ( v28 != 140103415 ) break; v28 = 1783499399; } if ( v28 != 165194735 ) break; v52 = 2 * v51; a3 = (char **)2936503504LL; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { a3 = (char **)35266435; } v28 = (signed int)a3; } if ( v28 != 165636912 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v12 = 762694599; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v12 = -1834653726; } v28 = v12; } if ( v28 != 174114970 ) break; v47 = v29; v28 = 2008447103; } if ( v28 != 183264728 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v19 = 111496758; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v19 = 1585728989; } v28 = v19; } if ( v28 != 189818242 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v6 = -1015938266; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v6 = -1578333348; } v28 = v6; } if ( v28 != 253474089 ) break; v43 = v42 < 6; a3 = (char **)550812935; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { a3 = (char **)3943590992LL; } v28 = (signed int)a3; } if ( v28 != 283854908 ) break; v58 = v57 != 0; v28 = 2103827861; } if ( v28 != 325614949 ) break; v28 = 30189008; } if ( v28 != 385821084 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v26 = -309679135; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v26 = -1732387288; } v28 = v26; } if ( v28 != 397199458 ) break; v28 = -1243245941; } if ( v28 != 481625179 ) break; v28 = 1771563692; } if ( v28 != 550812935 ) break; v28 = 253474089; } if ( v28 != 738697886 ) break; v37 = v36 < 64; v28 = 189818242; } if ( v28 != 762694599 ) break; v28 = -1834653726; } if ( v28 != 873723531 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v23 = 2127761645; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v23 = -1395524712; } v28 = v23; } if ( v28 != 895115152 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v3 = -506887986; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) { v3 = -469992559; } v28 = v3; } if ( v28 != 977391758 ) break; a3 = (char **)2175487371LL; if ( v37 ) a3 = (char **)3550181192LL; v28 = (signed int)a3; } if ( v28 != 998079252 ) break; v28 = -194920207; } if ( v28 != 1091618206 ) break; v28 = 1852460924; } if ( v28 != 1241066884 ) break; a3 = (char **)&s1[v54]; v55 = &s1[v54]; v28 = -1843952179; } if ( v28 != 1278104886 ) break; v9 = -718028952; if ( v39 == 10 ) v9 = -1104384261; v28 = v9; } if ( v28 != 1416478473 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v18 = -1358463792; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v18 = 165194735; v28 = v18; } if ( v28 != 1471710476 ) break; v28 = -987629196; } if ( v28 != 1478643244 ) break; v28 = 165636912; } if ( v28 != 1558414728 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v15 = 325614949; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v15 = 30189008; v28 = v15; } if ( v28 != 1585728989 ) break; v31 = v53 + 1; a3 = (char **)(unsigned int)(dword_603054 - 1); v20 = 111496758; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v20 = 1636541262; v28 = v20; } if ( v28 != 1590869113 ) break; v28 = -1146236158; } if ( v28 != 1591698962 ) break; v28 = -484679360; } if ( v28 != 1636541262 ) break; v28 = 998079252; } if ( v28 != 1768345936 ) break; v28 = 165636912; } if ( v28 != 1771563692 ) break; v29 = v50 ^ 0xB0004B7679FA26B3LL; v28 = 1471710476; } if ( v28 != 1783499399 ) break; v56 = v30 + 1; v28 = -197416524; } if ( v28 != 1852460924 ) break; a3 = (char **)(unsigned int)(dword_603054 - 1); v4 = -1799275846; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v4 = 1988968584; v28 = v4; } if ( v28 == 1934644251 ) break; switch ( v28 ) { case 1958488484: v31 = v41; v28 = -1241653263; break; case 1988968584: v36 = v31; a3 = (char **)(unsigned int)(dword_603054 - 1); v5 = -1799275846; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v5 = -1658420490; v28 = v5; break; case 2008447103: v48 = v47 < 0; v28 = -490420216; break; case 2013758019: memset(s, 0, 0x30uLL); memset(s1, 0, 0x30uLL); printf("Input:", 0LL); a3 = (char **)s; v35 = s; v28 = 895115152; break; case 2024088016: v28 = -2119479925; break; case 2103827861: a3 = (char **)(unsigned int)(dword_603054 - 1); v25 = -309679135; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) v25 = 385821084; v28 = v25; break; case 2110558301: v28 = -1841026192; puts("Correct!"); break; case 2127761645: v28 = -1395524712; break; } } return v59; }
得到的代码是一个多重循环,我们需要对代码进行控制流平坦化
参考教程:https://security.tencent.com/index.php/blog/msg/112
使用deflat.py(获取脚本)执行控制流平坦化脚本命令:
python deflat.py polyre 0x400620
2.2 处理虚假控制流程
得到的文件使用IDA打开,反汇编代码
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { signed __int64 v4; // [rsp+1E0h] [rbp-110h] int i; // [rsp+1E8h] [rbp-108h] int v6; // [rsp+1ECh] [rbp-104h] int v7; // [rsp+1ECh] [rbp-104h] char s1[48]; // [rsp+1F0h] [rbp-100h] char s[60]; // [rsp+220h] [rbp-D0h] unsigned int v10; // [rsp+25Ch] [rbp-94h] char *v11; // [rsp+260h] [rbp-90h] int v12; // [rsp+26Ch] [rbp-84h] bool v13; // [rsp+272h] [rbp-7Eh] unsigned __int8 v14; // [rsp+273h] [rbp-7Dh] int v15; // [rsp+274h] [rbp-7Ch] char *v16; // [rsp+278h] [rbp-78h] int v17; // [rsp+284h] [rbp-6Ch] int v18; // [rsp+288h] [rbp-68h] bool v19; // [rsp+28Fh] [rbp-61h] char *v20; // [rsp+290h] [rbp-60h] int v21; // [rsp+298h] [rbp-58h] bool v22; // [rsp+29Fh] [rbp-51h] __int64 v23; // [rsp+2A0h] [rbp-50h] bool v24; // [rsp+2AFh] [rbp-41h] __int64 v25; // [rsp+2B0h] [rbp-40h] __int64 v26; // [rsp+2B8h] [rbp-38h] __int64 v27; // [rsp+2C0h] [rbp-30h] __int64 v28; // [rsp+2C8h] [rbp-28h] int v29; // [rsp+2D0h] [rbp-20h] int v30; // [rsp+2D4h] [rbp-1Ch] char *v31; // [rsp+2D8h] [rbp-18h] int v32; // [rsp+2E0h] [rbp-10h] int v33; // [rsp+2E4h] [rbp-Ch] bool v34; // [rsp+2EBh] [rbp-5h] v10 = 0; memset(s, 0, 0x30uLL); memset(s1, 0, 0x30uLL); printf("Input:", 0LL); v11 = s; if ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ) goto LABEL_43; while ( 1 ) { __isoc99_scanf("%s", v11); v6 = 0; if ( dword_603058 < 10 || (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) == 0 ) break; LABEL_43: __isoc99_scanf("%s", v11); } while ( 1 ) { do v12 = v6; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); v13 = v12 < 64; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ) ; if ( !v13 ) break; v14 = s[v6]; do v15 = v14; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); if ( v15 == 10 ) { v16 = &s[v6]; *v16 = 0; break; } v17 = v6 + 1; do v6 = v17; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); } for ( i = 0; ; ++i ) { do v18 = i; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); do v19 = v18 < 6; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); if ( !v19 ) break; do v20 = s; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); v4 = *(_QWORD *)&v20[8 * i]; v7 = 0; while ( 1 ) { v21 = v7; do v22 = v21 < 64; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); if ( !v22 ) break; v23 = v4; v24 = v4 < 0; if ( v4 >= 0 ) { v27 = v4; do v28 = 2 * v27; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); v4 = v28; } else { v25 = 2 * v4; do v26 = v25; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); v4 = v26 ^ 0xB0004B7679FA26B3LL; } v29 = v7; do v7 = v29 + 1; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); } v30 = 8 * i; v31 = &s1[8 * i]; if ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ) LABEL_55: *(_QWORD *)v31 = v4; *(_QWORD *)v31 = v4; if ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ) goto LABEL_55; v32 = i + 1; } do v33 = memcmp(s1, &unk_402170, 0x30uLL); while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ); v34 = v33 != 0; while ( dword_603058 >= 10 && (((_BYTE)dword_603054 - 1) * (_BYTE)dword_603054 & 1) != 0 ) ; if ( v34 ) puts("Wrong!"); else puts("Correct!"); return v10; }
观察代码,此时开启了虚假控制流程,代码中的条件都是永真条件(while;do...while),因此可以在观察时忽略或删除while语句和do...while语句。
也可以写脚本来处理虚假控制流程,这里提供一个官方WP中给出的脚本,在IDA中的script中执行即可。
def patch_nop(start,end): for i in range(start,end): PatchByte(i, 0x90) def next_instr(addr): return addr+ItemSize(addr) st = 0x0000000000401117 end = 0x0000000000402144 addr = st while(addr<end): next = next_instr(addr) if "ds:dword_603054" in GetDisasm(addr): while(True): addr = next next = next_instr(addr) if "jnz" in GetDisasm(addr): dest = GetOperandValue(addr, 0) PatchByte(addr, 0xe9) PatchByte(addr+5, 0x90) offset = dest - (addr + 5) PatchDword(addr + 1, offset) print("patch bcf: 0x%x"%addr) addr = next break else: addr = next
最终,我们得到控制流平坦化后的代码
1 __int64 __fastcall main(__int64 a1, char **a2, char **a3) 2 { 3 signed __int64 v4; // [rsp+1E0h] [rbp-110h] 4 signed int j; // [rsp+1E8h] [rbp-108h] 5 signed int i; // [rsp+1ECh] [rbp-104h] 6 signed int k; // [rsp+1ECh] [rbp-104h] 7 char s1[48]; // [rsp+1F0h] [rbp-100h] 8 char s[60]; // [rsp+220h] [rbp-D0h] 9 unsigned int v10; // [rsp+25Ch] [rbp-94h] 10 char *v11; // [rsp+260h] [rbp-90h] 11 int v12; // [rsp+26Ch] [rbp-84h] 12 bool v13; // [rsp+272h] [rbp-7Eh] 13 unsigned __int8 v14; // [rsp+273h] [rbp-7Dh] 14 int v15; // [rsp+274h] [rbp-7Ch] 15 char *v16; // [rsp+278h] [rbp-78h] 16 int v17; // [rsp+284h] [rbp-6Ch] 17 int v18; // [rsp+288h] [rbp-68h] 18 bool v19; // [rsp+28Fh] [rbp-61h] 19 char *v20; // [rsp+290h] [rbp-60h] 20 int v21; // [rsp+298h] [rbp-58h] 21 bool v22; // [rsp+29Fh] [rbp-51h] 22 __int64 v23; // [rsp+2A0h] [rbp-50h] 23 bool v24; // [rsp+2AFh] [rbp-41h] 24 __int64 v25; // [rsp+2B0h] [rbp-40h] 25 __int64 v26; // [rsp+2B8h] [rbp-38h] 26 __int64 v27; // [rsp+2C0h] [rbp-30h] 27 __int64 v28; // [rsp+2C8h] [rbp-28h] 28 int v29; // [rsp+2D0h] [rbp-20h] 29 int v30; // [rsp+2D4h] [rbp-1Ch] 30 char *v31; // [rsp+2D8h] [rbp-18h] 31 int v32; // [rsp+2E0h] [rbp-10h] 32 int v33; // [rsp+2E4h] [rbp-Ch] 33 bool v34; // [rsp+2EBh] [rbp-5h] 34 35 v10 = 0; 36 memset(s, 0, 48uLL); 37 memset(s1, 0, 48uLL); 38 printf("Input:", 0LL); 39 v11 = s; 40 __isoc99_scanf("%s", s); 41 for ( i = 0; ; ++i ) 42 { 43 v12 = i; 44 v13 = i < 64; 45 if ( i >= 64 ) // 结束条件,i 46 break; // v14=int(s[i]) 47 v14 = s[i]; // v15=int(s[i]) 48 v15 = v14; 49 if ( v14 == 10 ) // s[i]==10时,s[i]=0即将末尾的换行符'\n'替换为'\0' 50 { 51 v16 = &s[i]; 52 *v16 = 0; 53 break; 54 } 55 v17 = i + 1; 56 } 57 for ( j = 0; ; ++j ) // 第一层循环,j 58 { 59 v18 = j; 60 v19 = j < 6; 61 if ( j >= 6 ) // 结束条件,j取值 62 break; 63 v20 = s; 64 v4 = *(_QWORD *)&s[8 * j]; // 每四字(QWORD)取一个值,相当于取一个四字的最高位字节,v4=int(s[j*8]),可以确定输入的长度为48 65 for ( k = 0; ; ++k ) // 第二层循环,k 66 { 67 v21 = k; 68 v22 = k < 64; 69 if ( k >= 64 ) // 结束条件,k取值 70 break; 71 v23 = v4; 72 v24 = v4 < 0; 73 if ( v4 >= 0 ) // 若v4>=0,左移1位,v4=v4*2 74 { 75 v27 = v4; 76 v28 = 2 * v4; 77 v4 *= 2LL; 78 } 79 else // 否则v4=2*v4^0xB0004B7679FA26B3 80 { 81 v25 = 2 * v4; 82 v26 = 2 * v4; 83 v4 = 2 * v4 ^ 0xB0004B7679FA26B3LL; 84 } 85 v29 = k; 86 } 87 v30 = 8 * j; 88 v31 = &s1[8 * j]; // 将v4的值赋值给s1[8*j] 89 *(_QWORD *)v31 = v4; 90 v32 = j + 1; 91 } 92 v33 = memcmp(s1, &unk_402170, 0x30uLL); // 96 62 53 43 6D F2 8F BC 16 EE 30 05 78 00 01 52 93 // EC 08 5F 93 EA B5 C0 4D 50 F4 53 D8 AF 90 2B 34 94 // 81 36 2C AA BC 0E 25 8B E4 8A C6 A2 81 9F 75 55 95 v34 = v33 != 0; 96 if ( v33 != 0 ) 97 puts("Wrong!"); 98 else 99 puts("Correct!"); 100 return v10; 101 }
3.代码分析
仔细观察代码,实际上这部分代码是使用CRC32的查表法,对数据进行加密。
3.1 CRC64
要理解代码,推荐结合相关CRC算法的说明进行理解
CRC32算法实现:python与C:https://blog.csdn.net/zyj_zhouyongjun183/article/details/78882625
CRC校验码原理、实例、手动计算:https://www.cnblogs.com/bugutian/p/6221783.html
CRC技术的实现与破解:https://bbs.pediy.com/thread-17195.htm
3.2 加密原理
加密原理实际上就是CRC32算法---输入一组长度48的字符串,每8个字节分为1组,共6组。对每一组取首位,判断正负。正值,左移一位;负值,左移一位,再异或0xB0004B7679FA26B3。重复判断操作64次,得到查表法所用的表。
因此我们只需要将整个加密过程逆向操作得到查表法的表,再进行CRC64计算,就能得到flag
4.脚本获取
secret = [0xBC8FF26D43536296, 0x520100780530EE16, 0x4DC0B5EA935F08EC, 0x342B90AFD853F450, 0x8B250EBCAA2C3681, 0x55759F81A2C68AE4] key = 0xB0004B7679FA26B3 flag = "" # 产生CRC32查表法所用的表 for s in secret: for i in range(64): sign = s & 1 # 判断是否为负 if sign == 1: s ^= key s //= 2 # 防止负值除2,溢出为正值 if sign == 1: s |= 0x8000000000000000 # 输出表 print(hex(s)) # 计算CRC64 j = 0 while j < 8: flag += chr(s&0xFF) s >>= 8 j += 1 print(flag)
6.get flag!
查表法的表:
0x6666367b67616c66
0x63362d3039333932
0x2d363563342d3032
0x3539612d30376162
0x6631643365383537
0x7d38
flag:
flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}