xx
exe文件,运行一下,发现什么都没有
查壳,无壳,64位文件

拖入ida,看main,像c++,掏出ai分析一波
int __fastcall main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rbx
__int64 v4; // rax
__int128 *v5; // rax
__int64 v6; // r11
__int128 *v7; // r14
int v8; // edi
__int128 *v9; // rsi
char v10; // r10
int v11; // edx
__int64 v12; // r8
unsigned __int64 v13; // rcx
__int64 v14; // rcx
unsigned __int64 v15; // rax
unsigned __int64 i; // rax
__int64 v17; // rax
size_t v18; // rsi
_BYTE *v19; // rbx
_BYTE *v20; // r9
int v21; // r11d
char *v22; // r8
__int64 v23; // rcx
char v24; // al
__int64 v25; // r9
__int64 v26; // rdx
__int64 v27; // rax
size_t Size; // [rsp+20h] [rbp-48h] BYREF
__int128 v30; // [rsp+28h] [rbp-40h] BYREF
int v31; // [rsp+38h] [rbp-30h]
int v32; // [rsp+3Ch] [rbp-2Ch]
int Code[4]; // [rsp+40h] [rbp-28h] BYREF
int v34; // [rsp+50h] [rbp-18h]
*(_OWORD *)Code = 0i64;
v34 = 0;
sub_1400018C0(std::cin, argv, Code);
v3 = -1i64;
v4 = -1i64;
do
++v4;
while ( *((_BYTE *)Code + v4) );
if ( v4 != 19 )
{
sub_140001620(std::cout, "error\n");
_exit((int)Code);
}
v5 = (__int128 *)operator new(5ui64);
v6 = *(_QWORD *)&::Code;
v7 = v5;
v8 = 0;
v9 = v5;
do
{
v10 = *((_BYTE *)v9 + (char *)Code - (char *)v5);
v11 = 0;
*(_BYTE *)v9 = v10;
v12 = 0i64;
v13 = -1i64;
do
++v13;
while ( *(_BYTE *)(v6 + v13) );
if ( v13 )
{
do
{
if ( v10 == *(_BYTE *)(v6 + v12) )
break;
++v11;
++v12;
}
while ( v11 < v13 );
}
v14 = -1i64;
do
++v14;
while ( *(_BYTE *)(v6 + v14) );
if ( v11 == v14 )
_exit(v6);
v9 = (__int128 *)((char *)v9 + 1);
}
while ( (char *)v9 - (char *)v5 < 4 );
*((_BYTE *)v5 + 4) = 0;
do
++v3;
while ( *((_BYTE *)Code + v3) );
v15 = 0i64;
v30 = *v7;
while ( *((_BYTE *)&v30 + v15) )
{
if ( !*((_BYTE *)&v30 + v15 + 1) )
{
++v15;
break;
}
if ( !*((_BYTE *)&v30 + v15 + 2) )
{
v15 += 2i64;
break;
}
if ( !*((_BYTE *)&v30 + v15 + 3) )
{
v15 += 3i64;
break;
}
v15 += 4i64;
if ( v15 >= 0x10 )
break;
}
for ( i = v15 + 1; i < 0x10; ++i )
*((_BYTE *)&v30 + i) = 0;
v17 = sub_140001AB0(Code, v3, &v30, &Size);
v18 = Size;
v19 = (_BYTE *)v17;
v20 = operator new(Size);
v21 = 1;
*v20 = v19[2];
v22 = v20 + 1;
v20[1] = *v19;
v20[2] = v19[3];
v20[3] = v19[1];
v20[4] = v19[6];
v20[5] = v19[4];
v20[6] = v19[7];
v20[7] = v19[5];
v20[8] = v19[10];
v20[9] = v19[8];
v20[10] = v19[11];
v20[11] = v19[9];
v20[12] = v19[14];
v20[13] = v19[12];
v20[14] = v19[15];
v20[15] = v19[13];
v20[16] = v19[18];
v20[17] = v19[16];
v20[18] = v19[19];
v20[19] = v19[17];
v20[20] = v19[22];
v20[21] = v19[20];
v20[22] = v19[23];
for ( v20[23] = v19[21]; v21 < v18; ++v22 )
{
v23 = 0i64;
if ( v21 / 3 > 0 )
{
v24 = *v22;
do
{
v24 ^= v20[v23++];
*v22 = v24;
}
while ( v23 < v21 / 3 );
}
++v21;
}
*(_QWORD *)&v30 = 0xC0953A7C6B40BCCEui64;
v25 = v20 - (_BYTE *)&v30;
*((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;
v26 = 0i64;
v31 = -939386845;
v32 = -95004953;
do
{
if ( *((_BYTE *)&v30 + v26) != *((_BYTE *)&v30 + v26 + v25) )
_exit(v8 * v8);
++v8;
++v26;
}
while ( v26 < 24 );
v27 = sub_140001620(std::cout, "You win!");
std::ostream::operator<<(v27, sub_1400017F0);
return 0;
}
*(_OWORD *)Code = 0i64;
v34 = 0;
sub_1400018C0(std::cin, argv, Code);
v3 = -1i64;
v4 = -1i64;
do
++v4;
while ( *((_BYTE *)Code + v4) );
if ( v4 != 19 )
{
sub_140001620(std::cout, "error\n");
输入的明文长度必须是19位
do
{
v10 = *((_BYTE *)v9 + (char *)Code - (char *)v5);
v11 = 0;
*(_BYTE *)v9 = v10;
v12 = 0i64;
v13 = -1i64;
do
++v13;
while ( *(_BYTE *)(v6 + v13) );
if ( v13 )
{
do
{
if ( v10 == *(_BYTE *)(v6 + v12) )
break;
++v11;
++v12;
}
while ( v11 < v13 );
}
v14 = -1i64;
do
++v14;
while ( *(_BYTE *)(v6 + v14) );
if ( v11 == v14 )
_exit(v6);
v9 = (__int128 *)((char *)v9 + 1);
}
while ( (char *)v9 - (char *)v5 < 4 );
*((_BYTE *)v5 + 4) = 0;
输入的内容检查 是否在 Code 中出现过,并记录其位置

简单来说就是输入的必须是qwertyuiopasdfghjklzxcvbnm1234567890中的字符
v5 = (__int128 *)operator new(5ui64);
v6 = *(_QWORD *)&::Code;
v7 = v5;
v8 = 0;
v9 = v5;
do
{
v10 = *((_BYTE *)v9 + (char *)Code - (char *)v5);
v11 = 0;
*(_BYTE *)v9 = v10;
v12 = 0i64;
v13 = -1i64;
do
++v13;
while ( *(_BYTE *)(v6 + v13) );
if ( v13 )
{
do
{
if ( v10 == *(_BYTE *)(v6 + v12) )
break;
++v11;
++v12;
}
while ( v11 < v13 );
}
v14 = -1i64;
do
++v14;
while ( *(_BYTE *)(v6 + v14) );
if ( v11 == v14 )
_exit(v6);
v9 = (__int128 *)((char *)v9 + 1);
}
while ( (char *)v9 - (char *)v5 < 4 );
*((_BYTE *)v5 + 4) = 0;
do
++v3;
while ( *((_BYTE *)Code + v3) );
这一部分是最难懂的,我看别人的是取前4位(作为后面加密的key),验证这4位都在‘qwertyuiopasdfghjklzxcvbnm1234567890‘中
v15 = 0i64;
v30 = *v7;
while ( *((_BYTE *)&v30 + v15) )
{
if ( !*((_BYTE *)&v30 + v15 + 1) )
{
++v15;
break;
}
if ( !*((_BYTE *)&v30 + v15 + 2) )
{
v15 += 2i64;
break;
}
if ( !*((_BYTE *)&v30 + v15 + 3) )
{
v15 += 3i64;
break;
}
v15 += 4i64;
if ( v15 >= 0x10 )
break;
}
for ( i = v15 + 1; i < 0x10; ++i )
*((_BYTE *)&v30 + i) = 0;
用0将key填充到16位
![]()
v17 = sub_140001AB0(Code, v3, &v30, &Size)
sub_140001AB0跟进后是xxtea加密
v20[1] = *v19;
v20[2] = v19[3];
v20[3] = v19[1];
v20[4] = v19[6];
v20[5] = v19[4];
v20[6] = v19[7];
v20[7] = v19[5];
v20[8] = v19[10];
v20[9] = v19[8];
v20[10] = v19[11];
v20[11] = v19[9];
v20[12] = v19[14];
v20[13] = v19[12];
v20[14] = v19[15];
v20[15] = v19[13];
v20[16] = v19[18];
v20[17] = v19[16];
v20[18] = v19[19];
v20[19] = v19[17];
v20[20] = v19[22];
v20[21] = v19[20];
v20[22] = v19[23];
加密后的结果位置互换
for ( v20[23] = v19[21]; v21 < v18; ++v22 )
{
v23 = 0i64;
if ( v21 / 3 > 0 )
{
v24 = *v22;
do
{
v24 ^= v20[v23++];
*v22 = v24;
}
while ( v23 < v21 / 3 );
}
++v21;
}
*(_QWORD *)&v30 = 0xC0953A7C6B40BCCEui64;
v25 = v20 - (_BYTE *)&v30;
*((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;
v26 = 0i64;
v31 = -939386845;
v32 = -95004953;
do
{
if ( *((_BYTE *)&v30 + v26) != *((_BYTE *)&v30 + v26 + v25) )
_exit(v8 * v8);
++v8;
++v26;
}
while ( v26 < 24 );
v27 = sub_140001620(std::cout, "You win!");
std::ostream::operator<<(v27, sub_1400017F0);
return 0;
}
最后就是异或和比较
脚本是别人的
import struct
_DELTA = 0x9E3779B9
def _long2str(v, w):
n = (len(v) - 1) << 2
if w:
m = v[-1]
if (m < n - 3) or (m > n): return ''
n = m
s = struct.pack('<%iL' % len(v), *v)
return s[0:n] if w else s
def _str2long(s, w):
n = len(s)
m = (4 - (n & 3) & 3) + n
s = s.ljust(m, b"\0")
v = list(struct.unpack('<%iL' % (m >> 2), s))
if w: v.append(n)
return v
def encrypt(str, key):
if str == '': return str
v = _str2long(str, True)
k = _str2long(key.ljust(16, b"\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
sum = 0
q = 6 + 52 // (n + 1)
while q > 0:
sum = (sum + _DELTA) & 0xffffffff
e = sum >> 2 & 3
for p in range(n):
y = v[p + 1]
v[p] = (v[p] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
z = v[p]
y = v[0]
v[n] = (v[n] + ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[n & 3 ^ e] ^ z))) & 0xffffffff
z = v[n]
q -= 1
return _long2str(v, False)
def decrypt(str, key):
if str == '': return str
v = _str2long(str, False)
k = _str2long(key.ljust(16, b"\0"), False)
n = len(v) - 1
z = v[n]
y = v[0]
q = 6 + 52 // (n + 1)
sum = (q * _DELTA) & 0xffffffff
while (sum != 0):
e = sum >> 2 & 3
for p in range(n, 0, -1):
z = v[p - 1]
v[p] = (v[p] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))) & 0xffffffff
y = v[p]
z = v[n]
v[0] = (v[0] - ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[0 & 3 ^ e] ^ z))) & 0xffffffff
y = v[0]
sum = (sum - _DELTA) & 0xffffffff
return _long2str(v, True)
tg=[0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0, 0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35,
0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56, 0xFA ]
order=[2,0,3,1,6,4,7,5,10,8,11,9,14,12,15,13,18,16,19,17,22,20,23,21]
flag=[0]*24
for i in range(23,-1,-1):
for j in range(i//3):
tg[i]^=tg[j]
print('逆异或操作后:'+' '.join(map(hex,tg)))
for i in range(24):
flag[order[i]]=tg[i]
print('逆加密字符串替换后:'+' '.join(map(hex,flag)))
x=decrypt(bytes(flag),'flag'.encode())
print(x)
seven
下载附件,sys文件,很少见,查一下,
.sys 文件是 Windows 操作系统中的系统文件,通常用于存储设备驱动程序、系统设置和核心功能
直接拖入ida,(拖入后能发现是64位)
函数是比较少的,先查找一下字符串

看到星星和点,第一反应可能是迷宫题
跟进看一下代码
__int64 __fastcall sub_1400012F0(__int64 a1, __int64 a2)
{
__int64 v3; // rsi
unsigned __int64 v4; // rdx
int v5; // ecx
__int16 *v6; // rdi
__int64 v7; // rbp
__int16 v8; // dx
char v9; // dl
const CHAR *v10; // rcx
if ( *(int *)(a2 + 48) >= 0 )
{
v3 = *(_QWORD *)(a2 + 24);
v4 = *(_QWORD *)(a2 + 56) / 0xCui64;
if ( (_DWORD)v4 )
{
v5 = dword_1400030E4;
v6 = (__int16 *)(v3 + 2);
v7 = (unsigned int)v4;
while ( *(_WORD *)(v3 + 4) )
{
LABEL_30:
v6 += 6;
if ( !--v7 )
goto LABEL_31;
}
aO[v5] = 46;
v8 = *v6;
if ( *v6 == 17 )
{
if ( (v5 & 0xFFFFFFF0) != 0 )
{
v5 -= 16;
goto LABEL_13;
}
v5 += 208;
dword_1400030E4 = v5;
}
if ( v8 != 31 )
goto LABEL_14;
if ( (v5 & 0xFFFFFFF0) == 208 )
v5 -= 208;
else
v5 += 16;
LABEL_13:
dword_1400030E4 = v5;
LABEL_14:
if ( v8 == 30 )
{
if ( (v5 & 0xF) != 0 )
--v5;
else
v5 += 15;
dword_1400030E4 = v5;
}
if ( v8 == 32 )
{
if ( (v5 & 0xF) == 15 )
v5 -= 15;
else
++v5;
dword_1400030E4 = v5;
}
v9 = aO[v5];
if ( v9 == 42 )
{
v10 = "-1s\n";
}
else
{
if ( v9 != 55 )
{
LABEL_29:
aO[v5] = 111;
goto LABEL_30;
}
v10 = "The input is the flag!\n";
}
dword_1400030E4 = 16;
DbgPrint(v10);
v5 = dword_1400030E4;
goto LABEL_29;
}
}
LABEL_31:
if ( *(_BYTE *)(a2 + 65) )
*(_BYTE *)(*(_QWORD *)(a2 + 184) + 3i64) |= 1u;
return *(unsigned int *)(a2 + 48);
}
ai分析一下,v5只能是17, 31, 30, 32,最后并遍历检验了一下
- 如果
v9是42,输出"-1s\n"。 - 如果
v9是55,输出"The input is the flag!\n",并将dword_1400030E4设为16
十六进制17-->w; 31-->s; 30-->a; 32-->d
分别对应上,下,左,右。
能走点,不能走*
分析完毕,看地图

为了便于移动和字母大小一样,我改了下字母,理论上通过代码可以分析出迷宫的长和宽,但我不想看了,就这样简单弄了一下,已经能看出迷宫的大致样子
hctf{ddddddddddddddssaasasasasasasasasas}

被折叠的 条评论
为什么被折叠?



