fisher
各种反调试检测
把反调试全部patch掉
很多的函数里对输入数据都做sha1校验,输入数据的sha1校验结果需要为2e95a5c5f9643df668d3965a6cdf19541bc0496b
看了好久没找到sha1突破点
一开始只看了反编译c代码,被错误的输出干扰了
需要注意try catch
try里面做了sha1校验,当校验通过时会抛出异常,进入到catch块,校验不通过返回0
突破点在catch块内,看catch块的末尾可以找到输出字符串的部分
左边是正确时的输出,字符串解密之后是you win! your flag: flag{your input}
核心的加密运算在call [rax+0x18]
,加密完跟N17EHf1DWHD40DWH/f79E05EfIH1E179E1
字符串比较
函数里面第一个大循环把输入拷贝了一遍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
| v20 = (BYTE *)Src[1]; if ( v4 != v3 ) { while ( 1 ) { v21 = &v3[(unsigned int)v18]; if ( v20 == v48 ) { sub_7FF6786A9B10((const void **)Src, v20, v21); v22 = (BYTE *)Src[1]; } else { *v20 = *v21; v22 = (BYTE *)++Src[1]; } v18 = (unsigned int)(v18 + 1); a1 = v49; if ( (unsigned int)v18 == *((_QWORD *)&v49 + 1) - (_QWORD)v49 ) break; v23 = *(_BYTE *)(v49 + v18); if ( v23 == *((_BYTE *)Src[0] + v19) ) { v41[0] = 88; if ( v22 == v48 ) { sub_7FF6786A9B10((const void **)Src, v22, v41); v20 = (BYTE *)Src[1]; } else { *v22 = 88; v20 = (BYTE *)++Src[1]; } } else { if ( v22 == v48 ) { sub_7FF6786A9B10((const void **)Src, v22, (_BYTE *)(v49 + v18)); v20 = (BYTE *)Src[1]; } else { *v22 = v23; v20 = (BYTE *)++Src[1]; } LODWORD(v18) = v18 + 1; } v19 += 2; v3 = (BYTE *)v49; a1 = *((_QWORD *)&v49 + 1) - v49; if ( (unsigned __int64)(unsigned int)v18 >= *((_QWORD *)&v49 + 1) - (_QWORD)v49 ) goto LABEL_42; } v41[0] = 88; if ( v22 == v48 ) { sub_7FF6786A9B10((const void **)Src, v22, v41); v20 = (BYTE *)Src[1]; } else { *v22 = 88; v20 = (BYTE *)++Src[1]; } }
|
第二个大循环对输入字符串做了一些处理,按两个字符一组,忽略字符表以外的字符,第一个字符和第二字符相同时在中间加X
,字符串长度为奇数末尾加X
字符表ghijklpqrstuvwxyzABCabcDEFdef0123GHI4567JKL+/MNOmnoPQRSXYZ8TUVW9
接下来核心加密部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| do { v10 = *((_BYTE *)*a2 + v6); sub_7FF6786AA6D3(2i64, (__int64)a2); v11 = 0; v12 = 0i64; v13 = a1 + 9; while ( 2 ) { v14 = 0; for ( i = 0i64; i < 8; ++i ) { if ( v10 == *((_BYTE *)v13 + i) ) { i1 = v11; i_ = v12; j1 = v14; goto LABEL_10; } ++v14; } ++v11; ++v12; ++v13; if ( v12 < 8 ) continue; break; } LABEL_10: v16 = v6 + 1; v17 = *((_BYTE *)*a2 + v16); sub_7FF6786AA6D3(2i64, (__int64)v13); v18 = 0; v19 = 0i64; v20 = a1 + 9; while ( 2 ) { v21 = 0; for ( j = 0i64; j < 8; ++j ) { if ( v17 == *((_BYTE *)v20 + j) ) { i2 = v18; j2 = v21; goto LABEL_17; } ++v21; } ++v18; ++v19; ++v20; if ( v19 < 8 ) continue; break; } LABEL_17: if ( i1 == i2 ) { v23 = 8 * i_ + 72; v24 = (char *)a1 + v23 + (int)(j1 + 1) % 8; v25 = *(_BYTE **)(a3 + 8); if ( v25 == *(_BYTE **)(a3 + 16) ) { sub_7FF6786A9B10((const void **)a3, v25, v24); } else { *v25 = *v24; ++*(_QWORD *)(a3 + 8); } sub_7FF6786AA6D3(2i64, (__int64)v25); v26 = (char *)a1 + v23 + (j2 + 1) % 8; a2 = *(void ***)(a3 + 8); if ( a2 == *(void ***)(a3 + 16) ) { sub_7FF6786A9B10((const void **)a3, a2, v26); } else { *(_BYTE *)a2 = *v26; ++*(_QWORD *)(a3 + 8); } } else { v27 = *a1; if ( j1 == j2 ) (*(void (__fastcall **)(__int64 *, _QWORD, __int64, _QWORD, int))v27)(a1, j1, a3, i1, i2); else (*(void (__fastcall **)(__int64 *, _QWORD, _QWORD, __int64, int, int))(v27 + 8))(a1, i1, j1, a3, i2, j2); } v6 = v16 + 1; } while ( v6 < (unsigned int)len );
|
在while循环里,两个字符一组,查字符表索引,每个字符对应两个索引
用python还原一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| table = "ghijklpqrstuvwxyzABCabcDEFdef0123GHI4567JKL+/MNOmnoPQRSXYZ8TUVW9" def enc(c1, c2): i1 = table.index(c1) // 8 j1 = table.index(c1) % 8 i2 = table.index(c2) // 8 j2 = table.index(c2) % 8 if (i1 == i2): indx1 = 8 * i1 + (j1 + 1) % 8 indx2 = 8 * i2 + (j2 + 1) % 8 else: if (j1 == j2): indx1 = 8 * ((i1 + 1) % 8) + j1 indx2 = 8 * ((i2 + 1) % 8) + j2 else: indx1 = 8 * i1 + j2 indx2 = 8 * i2 + j1 return table[indx1]+table[indx2]
|
要根据两个字符的ij情况分类做替换,写出逆过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| def dec(c1, c2): i1 = table.index(c1) // 8 j1 = table.index(c1) % 8 i2 = table.index(c2) // 8 j2 = table.index(c2) % 8 if (i1 == i2): indx1 = 8 * i1 + (j1 - 1) % 8 indx2 = 8 * i2 + (j2 - 1) % 8 else: if (j1 == j2): indx1 = 8 * ((i1 - 1) % 8) + j1 indx2 = 8 * ((i2 - 1) % 8) + j2 else: indx1 = 8 * i1 + j2 indx2 = 8 * i2 + j1 return table[indx1]+table[indx2]
flag = "" for i in range(0, len(ans), 2): flag += dec(ans[i], ans[i+1])
print(flag)
for i in range(0, len(flag), 2): print(enc(flag[i], flag[i+1]), end='') print("") print(ans)
|
跑一下得到下面的flag
6c324d2c86a72b864a2X2f30e46d202X20
算hash不对,根据前面补X
的规则,把两个X
去掉
ack,得到flagflag{6c324d2c86a72b864a22f30e46d20220}