定位到关键函数
int sub_401090()
{
int v1; // [esp+20h] [ebp-140h]
int v2; // [esp+24h] [ebp-13Ch]
int k; // [esp+2Ch] [ebp-134h]
int i; // [esp+30h] [ebp-130h]
int v5; // [esp+30h] [ebp-130h]
int j; // [esp+30h] [ebp-130h]
int v7; // [esp+30h] [ebp-130h]
char v8; // [esp+34h] [ebp-12Ch]
DWORD NumberOfBytesRead; // [esp+3Ch] [ebp-124h] BYREF
unsigned __int8 Buffer; // [esp+43h] [ebp-11Dh] BYREF
char v11[16]; // [esp+44h] [ebp-11Ch] BYREF
char v12[256]; // [esp+54h] [ebp-10Ch] BYREF
memset(v12, 0, sizeof(v12));
ReadFile(hObject, &Buffer, 1u, &NumberOfBytesRead, 0);
if ( Buffer != 5 )
{
sub_401690((int)"Wrong!\n");
CloseHandle(hObject);
exit(0);
}
ReadFile(hObject, v12, Buffer, &NumberOfBytesRead, 0);
for ( i = 0; i < Buffer; ++i )
{
if ( v12[i] != byte_405100[i] )
{
sub_401690((int)"Wrong!\n");
CloseHandle(hObject);
exit(0);
}
}
v5 = 0;
v8 = 0;
while ( v5 < Buffer )
v8 += v12[v5++];
ReadFile(hObject, v11, 0x10u, &NumberOfBytesRead, 0);
v2 = 18;
for ( j = 0; j < 16; ++j )
v11[j] ^= v8;
v7 = 0;
v1 = 1;
while ( v7 < 16 )
{
for ( k = 6; k >= 0; k -= 2 )
{
switch ( ((unsigned __int8)v11[v7] >> k) & 3 )
{
case 0:
v2 -= 18;
break;
case 1:
++v2;
break;
case 2:
v2 += 18;
break;
case 3:
--v2;
break;
default:
break;
}
if ( aN[v2] == 42 || aN[v2] == 32 )
{
v1 = 0;
break;
}
if ( aN[v2] == 75 )
{
sub_401690((int)"Congratulations! you found it!\n");
break;
}
}
++v7;
}
CloseHandle(hObject);
return v1;
}
从文件中读入一个5,然后从byte_405100中读取5个字符,点进去可知为"nkman"然后求和得v8,v8作为异或的值
aN为一个迷宫。
******************
N...*****...*....*
**.*****..*...**.*
...*****.*****.*.*
.**....*..*...*..*
....**.*.*..*...**
*.**...*.*.*******
..*****..*......**
.*......**.****.**
...*****...*K...**
******************
然后继续从文件中读入,异或v8,手动走一下迷宫
ddssaassdssassddwdddddwdwwwwwdwddsddwdddsssasaawaasassdddddssaaa
switch语句简单看一下得出上是0,右是1,下是2,左是3
1122332212232211011111010000010112110111222323303323221111122333
关键是这句话的理解for ( k = 6; k >= 0; k -= 2 ) (v11[v7] >> k) & 3
这句话是将v11的每两个二进制位转换为一个四进制位,
那我们就需要转换回去,转回16进制再加上05和'nkman'即为flag
v12 = [0x6E, 0x6B, 0x6D, 0x61, 0x6E]#nkman
v8 = 0
for i in range(5):
v8 += v12[i]
v8 ^= 0x200
#因为ReadFile(hObject, &Buffer, 1u, &NumberOfBytesRead, 0);
#这段读入函数只读取了v11中的0x10u即16个字节的数据,也就是取了低八位,
#所以等价于与v8的低八位的异或,v8是0x215,我们只取0x15
#有以下迷宫,N为起点,K为终点,只能走'.'的地方,上下左右分别用wsad表示
# ******************
# N...*****...*....*
# **.*****..*...**.*
# ...*****.*****.*.*
# .**....*..*...*..*
# ....**.*.*..*...**
# *.**...*.*.*******
# ..*****..*......**
# .*......**.****.**
# ...*****...*K...**
# ******************
path="ddssaassdssassddwdddddwdwwwwwdwddsddwdddsssasaawaasassdddddssaaa"
path =path.replace("w","0")
path =path.replace("d","1")
path =path.replace("s","2")
path =path.replace("a","3")
s = [path[i:i+4] for i in range(0, len(path), 4)]
qua = [int(x, 4) for x in s]
for i in range(len(qua)):
qua[i]^=v8
v11=['0x05', '0x6e', '0x6b', '0x6d', '0x61', '0x6e']
for i in range(len(qua)):
v11.append(hex(qua[i]).zfill(4))#有0x0出现用zfill填满四位
flag = 'nkctf{'+''.join(v11).replace('0x','')+'}'
print(flag)
标签:NKCTF2023,...,..,esp,int,RE,ebp,PMKF,v8
From: https://www.cnblogs.com/Tree-24/p/17272143.html