我正在尝试在Windows上打开文件,并检查魔术字节是否与Windows PE32匹配。如果我运行下面的代码并在函数ReadFile
中的problemFunction
调用之前返回,则该代码可以正常工作,并且在主函数的末尾显示5a4d
。但是,如果在ReadFile
中的problemFunction
调用之后返回,则在dos->e_magic != PIMAGE_DOS_HEADER
检查中退出。
#include <Windows.h>
#include <winternl.h>
void problemFunction(HANDLE *fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(*fh, pByte, fileSize, &dw, NULL);
// could be wrong but i think i need to run SetFilePointer here but not sure on what to do.
return;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(fh == INVALID_HANDLE_VALUE) { CloseHandle(fh); exit(1); }
problemFunction(&fh);
DWORD fileSize = GetFileSize(fh, NULL);
if (!fileSize) { CloseHandle(fh); exit(1); }
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
ReadFile(fh, pByte, fileSize, &dw, NULL);
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) { CloseHandle(fh); exit(1); }
// dos->e_magic should be 5a4d for MZ, windows PE
}
我想在problemFunction
读调用后需要用类似的东西来重置文件指针
LONG reset = -sizeof(DWORD);
SetFilePointer(*fh, reset, NULL, FILE_END);
但是我无法使它正常工作。
谢谢
您的代码有很多问题。
problemFunction()
将HANDLE*
指针作为输入,但是在将其传递给GetFileSize()
或CloseHandle()
时未取消引用该指针。但这是在将指针传递给ReadFile()
时取消对指针的引用。
您必须在STRICT Type Checking关闭的情况下编译代码,否则您的代码将无法编译。您应该始终启用STRICT进行编译。
HANDLE
是指针类型,因此不需要通过指针传递它,除非您要修改它的值,而此代码不会这样做。因此,您应该更改problemFunction()
使其原样使用HANDLE
而不是使用HANDLE*
指针。
此外,GetFileSize()
不会在失败时返回0,就像您的代码所假定的那样。它实际上返回为[-1]的INVALID_FILE_SIZE
,即0XFFFFFFFF
作为DWORD
。 documentation中明确指出:
如果函数失败并且lpFileSizeHigh为NULL,则返回值为INVALID_FILE_SIZE。要获取扩展的错误信息,请调用GetLastError。
但是,最重要的是,您对ReadFile()
内部的main()
的第二次调用未读取您的期望,因为对ReadFile()
内部的problemFunction()
的第一次调用已经读取了数据(并且泄漏了!) ,但是在读取之后您没有将HANDLE
找回文件的开头,因此对ReadFile()
的第二次调用可以再次读取它。您是正确的,您需要使用SetFilePointer()
。
话虽如此,请尝试更多类似这样的事情:
#include <Windows.h>
#include <winternl.h>
bool test(HANDLE fh) {
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
return false;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL)) {
delete[] pByte;
return false;
}
// use pByte as needed...
delete[] pByte;
if (SetFilePointer(fh, 0, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) {
return false;
}
return true;
}
int main() {
const char* filepath = "C:\\windows\\file\\path\\to\\exe";
HANDLE fh = CreateFileA(filepath, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (fh == INVALID_HANDLE_VALUE) {
return 1;
}
if (!test(fh)) {
CloseHandle(fh);
return 1;
}
DWORD fileSize = GetFileSize(fh, NULL);
if (fileSize == INVALID_FILE_SIZE) {
CloseHandle(fh);
return 1;
}
BYTE* pByte = new BYTE[fileSize];
DWORD dw;
if (!ReadFile(fh, pByte, fileSize, &dw, NULL) || dw < sizeof(IMAGE_DOS_HEADER)) {
CloseHandle(fh);
return 1;
}
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER)pByte;
if (dos->e_magic != IMAGE_DOS_SIGNATURE) {
delete[] pByte;
CloseHandle(fh);
return 1;
}
...
delete[] pByte;
CloseHandle(fh);
return 0;
}