一题引发的关于WriteFile的思考
引言:今天在buu上看见了个水题

题目为 [FlareOn3]Challenge1

main

这个main逻辑清晰

先printf再scanf 然后sub_401260最后strcmp

这个sub_401260是一个换表base64,主要注意力不是这里所以我就不用它了

不过他实现printf和scanf的方法我觉得挺有意思

所以我也打算实现一下

mymain

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
#include<windows.h>
#include<defs.h>//这个文件在ida的plugins里

int __cdecl main(int argc, const char **argv, const char **envp)
{
char Buffer[128]; // [esp+0h] [ebp-94h] BYREF
char *Str1; // [esp+80h] [ebp-14h]
char *Str2; // [esp+84h] [ebp-10h]
HANDLE Input;// [esp+88h] [ebp-Ch]
HANDLE Output;// [esp+8Ch] [ebp-8h]
DWORD NumberOfBytesWritten; // [esp+90h] [ebp-4h] BYREF

Output = GetStdHandle(STD_OUTPUT_HANDLE);//STD_OUTPUT_HANDLE==0xFFFFFFF5
Input = GetStdHandle(STD_INPUT_HANDLE );//STD_INPUT_HANDLE ==0xFFFFFFF6
Str2 = (char*)"x2dtJEOmyjacxDemx2eczT5cVS9fVUGvWTuZWjuexjRqy24rV29q";
WriteFile(Output, "Enter password:\r\n", 0x12u, &NumberOfBytesWritten, 0);
ReadFile(Input, Buffer, 0x80u, &NumberOfBytesWritten, 0);
for(int i=NumberOfBytesWritten-2;i<NumberOfBytesWritten;i++)
Buffer[i]=0;//将输入末尾的/r/n清除
Str1=Buffer;
if ( !strcmp(Str1, Str2) )
WriteFile(Output, "Correct!\r\n", 0xBu, &NumberOfBytesWritten, 0);
else
WriteFile(Output, "Wrong password\r\n", 0x11u, &NumberOfBytesWritten, 0);
return 0;
}

看看WriteFile的声明

1
2
3
4
5
6
7
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);

hFile是一个句柄,

文件或I / O设备的句柄(例如,文件,文件流,物理磁盘,卷,控制台缓冲区,磁带驱动器,套接字,通信资源,邮槽或管道)。

代码里用的是Output句柄也就是STD_OUTPUT_HANDLE,就是标准输出句柄,是从GetStdHandle里面来的

GetStdHandle百度百科如下

1
2
WriteFile(Output, "Enter password:\r\n", 0x12u, &NumberOfBytesWritten, 0);
ReadFile(Input, Buffer, 0x80u, &NumberOfBytesWritten, 0);

那么这两句代码就好理解了

在标准输出句柄写”Enter password:\r\n”,长度18,把写了的长度记录在变量NumberOfBytesWritten里,最后的null暂且不管

在标准输入句柄读,把读到的0x80个字节写到Buffer里,把写了的长度记录在变量NumberOfBytesWritten里,最后的null暂且不管

虽然不是很懂为什么用这两个句柄就可以操作控制台输入输出,其中原理应该与printf和scanf有相同之处吧,不过因为没有去读源码,所以还是以后再说吧

另一个例子

之前那篇用管道爆破控制台程序里面也用了WriteFile,也一起看看吧

1
2
3
4
5
6
7
8
9
10
CreatePipe(&hReadPipe1, &hWritePipe1, &sa, 0);
CreatePipe(&hReadPipe2, &hWritePipe2, &sa, 0);

si.hStdInput = hReadPipe2;
si.hStdError = si.hStdOutput = hWritePipe1;

CreateProcess(NULL, pCommandLine, NULL, NULL, TRUE, NULL, NULL, NULL, &si, &pi);

WriteFile(hWritePipe2, flag.c_str(), flag.length() + 1, &dwWrite, NULL);
ReadFile(hReadPipe1, cbBuf, BUFSIZE, &dwRead, NULL);

这里是获取了新开程序的标准输入输出流,再进行指定的输入以及获取输出进行处理分析,分析满足条件则爆破到正确的flag

有兴趣的小伙伴可以翻翻前面的文章

文章作者: Usher
文章链接: https://usher2008.github.io/2021/01/13/%E4%B8%80%E9%A2%98%E5%BC%95%E5%8F%91%E7%9A%84%E5%85%B3%E4%BA%8EWriteFile%E7%9A%84%E6%80%9D%E8%80%83/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Usher