下载文件查壳,文件无壳64位
刚用ida打开的时候一脸问号,分析了半天乱七八糟于是动调,发现一直在某个地方进行循环,在百度搜索后知道这个是需要控制流平坦化。
处理文件的时候需要用到脚本,这里贴出官方给出的wp脚本。
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
最后可以得到处理好的代码
__int64 __fastcall main(__int64 a1, char **a2, char **a3) { signed __int64 v4; // [rsp+1E0h] [rbp-110h] signed int j; // [rsp+1E8h] [rbp-108h] signed int i; // [rsp+1ECh] [rbp-104h] signed int k; // [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; __isoc99_scanf("%s", s, (dword_603054 - 1), 3788079310LL); for ( i = 0; ; ++i ) { v12 = i; v13 = i < 64; if ( i >= 64 ) break; v14 = s[i]; v15 = v14; if ( v14 == 10 ) { v16 = &s[i]; *v16 = 0; break; } v17 = i + 1; } for ( j = 0; ; ++j ) { v18 = j; v19 = j < 6; if ( j >= 6 ) break; v20 = s; v4 = *&s[8 * j]; for ( k = 0; ; ++k ) { v21 = k; v22 = k < 64; if ( k >= 64 ) break; v23 = v4; v24 = v4 < 0; if ( v4 >= 0 ) { v27 = v4; v28 = 2 * v4; v4 *= 2LL; } else { v25 = 2 * v4; v26 = 2 * v4; v4 = 2 * v4 ^ 0xB0004B7679FA26B3LL; } v29 = k; } v30 = 8 * j; v31 = &s1[8 * j]; *v31 = v4; v32 = j + 1; } v33 = memcmp(s1, &unk_402170, 0x30uLL); v34 = v33 != 0; if ( v33 != 0 ) puts("Wrong!"); else puts("Correct!"); return v10; }
这部分代码使用的是crc32查表法对数据进行加密。
加密原理实际上就是CRC32算法—输入一组长度48的字符串,每8个字节分为1组,共6组。对每一组取首位,判断正负。正值,左移一位;负值,左移一位,再异或0xB0004B7679FA26B3。重复判断操作64次,得到查表法所用的表。
贴出脚本
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)
flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}