So I'm trying to write a sequence of zeroes from a file offset until the end of the file, here is my code:
HANDLE hFile = CreateFileA((LPCSTR)"hello.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile < 0) return -1;
DWORD fileSize = GetFileSize(hFile, NULL);
DWORD offset = 0x13d4;
DWORD check = NULL;
DWORD pos = SetFilePointer(hFile, offset, 0, FILE_BEGIN);
BYTE* zeroes = new BYTE[fileSize-offset];
ZeroMemory((PVOID)zeroes, fileSize-offset);
WriteFile(hFile, (PVOID)&zeroes, fileSize-offset, &check, NULL);
printf("Wrote %d bytes at %x\n", check, pos);
if(check < fileSize-offset)
{
printf("[+] An error occured while trying to patch the file.");
return EXIT_FAILURE;
}
CloseHandle(hFile);
Now I checked my fileSize is correct, the file offset (pos) is the same as offset, my file Handle is valid, the number of bytes written stored in check is equal to the the zeroes buffer length and the last error is 0. However, when I check my file in hex mode it did not add any zeroes at the end.
Any ideas?
Thanks in advance
The line
WriteFile(hFile, (PVOID)&zeroes, fileSize-offset, &check, NULL);
is wrong. You are writing data in the pointer variable zeroes itself, not what is pointed at by the variable. Typically the pointer has only 4 or 8 bytes, so it may cause out-of-range access if the file is large enough.
Remove & before zeros to have it write contents of the buffer pointed at by zeroes.
WriteFile(hFile, (PVOID)zeroes, fileSize-offset, &check, NULL);
Related
I am trying to open a file and read its content using the Win32 API:
HANDLE hFileRead = CreateFileA(FilePath,
GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
LARGE_INTEGER fileSize = { 0 };
DWORD cbFileSize = GetFileSizeEx(hFileRead, &fileSize);
PBYTE buffer = (PBYTE)HeapAlloc(GetProcessHeap(), 0, fileSize.QuadPart);
DWORD dwBytesRead = 0;
NTSTATUS s = ReadFile(hFileRead,
buffer,
fileSize.QuadPart,
&dwBytesRead,
NULL);
std::cout << buffer << "\n"; // <<< expect to print "asdasd" but prints "asdasd"+random chars (1 or more each run)
What I want to get is the file content (.txt in this case).
What I get is the content of a .txt file + some more random chars (its different for each run).
I tried to write the buffer indexed, it seems that the buffer prints more than its size (?)
What am I doing wrong?
std::cout << buffer expects buffer to be null-terminated, but it is not. You need to allocate space for the terminator, eg:
PBYTE buffer = (PBYTE)HeapAlloc(GetProcessHeap(), 0, fileSize.QuadPart + 1);
...
buffer[dwBytesRead] = 0;
Alternatively, you can use cout.write() instead, then you don't need a terminator, eg:
std::cout.write(buffer,dwBytesRead);
Half of the buffer used with ReadFile is corrupt. Regardless of the size of the buffer, half of it has the same corrupted character. I have look for anything that could be causing the read to stop early, etc. If I increase the size of the buffer, I see more of the file so it is not failing on a particular part of the file.
Visual Studio 2019. Windows 10.
#define MAXBUFFERSIZE 1024
DWORD bufferSize = MAXBUFFERSIZE;
_int64 fileRemaining;
HANDLE hFile;
DWORD dwBytesRead = 0;
//OVERLAPPED ol = { 0 };
LARGE_INTEGER dwPosition;
TCHAR* buffer;
hFile = CreateFile(
inputFilePath, // file to open
GENERIC_READ, // open for reading
FILE_SHARE_READ, // share for reading
NULL, // default security
OPEN_EXISTING, // existing file only
FILE_ATTRIBUTE_NORMAL, // normal file | FILE_FLAG_OVERLAPPED
NULL); // no attr. template
if (hFile == INVALID_HANDLE_VALUE)
{
DisplayErrorBox((LPWSTR)L"CreateFile");
return 0;
}
LARGE_INTEGER size;
GetFileSizeEx(hFile, &size);
_int64 fileSize = (__int64)size.QuadPart;
double gigabytes = fileSize * 9.3132e-10;
sendToReportWindow(L"file size: %lld bytes \(%.1f gigabytes\)\n", fileSize, gigabytes);
if(fileSize > MAXBUFFERSIZE)
{
buffer = new TCHAR[MAXBUFFERSIZE];
}
else
{
buffer = new TCHAR[fileSize];
}
fileRemaining = fileSize;
sendToReportWindow(L"file remaining: %lld bytes\n", fileRemaining);
while (fileRemaining) // outer loop. while file remaining, read file chunk to buffer
{
sendToReportWindow(L"fileRemaining:%d\n", fileRemaining);
if (bufferSize > fileRemaining) // as fileremaining gets smaller as file is processed, it eventually is smaller than the buffer
bufferSize = fileRemaining;
if (FALSE == ReadFile(hFile, buffer, bufferSize, &dwBytesRead, NULL))
{
sendToReportWindow(L"file read failed\n");
CloseHandle(hFile);
return 0;
}
fileRemaining -= bufferSize;
// bunch of commented out code (verified that it does not cause the corruption)
}
delete [] buffer;
Debugger html view (512 byte buffer)
Debugger html view (1024 byte buffer). This shows that file is probably not the source of the corruption.
Misc notes: I have been told that memory mapping the file does not provide an advantage since I am sequentially processing the file. Another advantage to this method is that when I detect particular and reoccurring tags in the WARC file I can skip ahead ~500 bytes and resume processing. This improves speed.
The reason is that you use a buffer array of type TCHAR, and the size of TCHAR type is 2 bytes. So the bufferSize set when you call the ReadFile function is actually filled into the buffer array every 2 bytes.
But the actual size of the buffer is sizeof(TCHAR) * fileSize, so half of the buffer array you see is "corrupted"
I'm trying to write two PUNICODE_STRING structure to file, but the data written is invalid, any ideas?
(The data1 is 123 and data2 is 456 in this case)
DWORD dwBytesWritten = 0;
WCHAR buffer[1024];
HANDLE hFile = CreateFile(L"c:\\log.txt", FILE_APPEND_DATA, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
memset(buffer, 0, sizeof(buffer));
wsprintf(buffer, L"%s :: %s\r\n", Data1->Buffer, Data2->Buffer);
WriteFile(hFile, buffer, wcslen(buffer), &dwBytesWritten, NULL);
CloseHandle(hFile);
}
main error is
WriteFile(hFile, buffer, wcslen(buffer), &dwBytesWritten, NULL);
WriteFile always take The number of bytes to be written to the file. but wcslen return the number of characters which in case UINICODE in 2 time less - need * sizeof(WCHAR) or << 1
then for format UNICODE_STRING need use %wZ format - because in general case Buffer can be not 0 terminated. and better use swprintf or _snwprintf instead wsprintf.
at the last always better dynamic allocate needed buffer, then use hardcoded size, which can be overwritten
so i be use next code:
void test(PCUNICODE_STRING Data1, PCUNICODE_STRING Data2)
{
DWORD dwBytesWritten;
PWSTR buffer = (PWSTR)alloca(Data1->Length + Data2->Length + sizeof(L" :: \r\n"));
int n = swprintf(buffer, L"%wZ :: %wZ\r\n", Data1, Data2) * sizeof(WCHAR);
HANDLE hFile = CreateFile(L"c:\\log.txt", FILE_APPEND_DATA, 0, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
WriteFile(hFile, buffer, n, &dwBytesWritten, NULL);
CloseHandle(hFile);
}
}
So basically I wish to write a byte array to a file, however the program crashes.
Unhandled exception at 0x7766DEE1 (KernelBase.dll) in append.exe: 0xC0000005: Access violation writing location 0x00000000.
BYTE *image ;
BYTE *bigMem;
#define REASONABLY_LARGE_BUFFER 16777216
file = CreateFile(fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
fileSize = GetFileSize(file, NULL);
bigMem = (BYTE *)HeapCreate(NULL, REASONABLY_LARGE_BUFFER, 0);
image = (BYTE *)HeapAlloc(bigMem, HEAP_ZERO_MEMORY, fileSize);
if (bigMem == NULL || image == NULL){
printf("Allocation failed");
return EXIT_FAILURE;
}
printf("We are writing to the file %p, with data location %p, and filesize %d\n", file, image, fileSize);
LPDWORD at = 0;
WriteFile(file, image, fileSize, at, NULL);
That print says:
We are writing to the file 00000038, with data location 02451590, and filesize 161169
The argument passed to WriteFile used to store the number of bytes written (at) can only be null if the argument for the overlapped structure is not null. I suggest changing at to be a DWORD and pass a pointer to it.
DWORD at;
WriteFile(file, image, fileSize, &at, NULL);
How can I make the code below to read correct text. In my text file has Hello welcome to C++, however at the end of the text, it has a new line. With the code below, my readBuffer always contains extra characters.
DWORD byteWritten;
int fileSize = 0;
//Use CreateFile to check if the file exists or not.
HANDLE hFile = CreateFile(myFile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL readSuccess;
DWORD byteReading;
char readBuffer[256];
readSuccess = ReadFile(hFile, readBuffer, byteReading, &byteReading, NULL);
if(readSuccess == TRUE)
{
TCHAR myBuffer[256];
mbstowcs(myBuffer, readBuffer, 256);
if(_tcscmp(myBuffer, TEXT("Hello welcome to C++")) == 0)
{
FindClose(hFile);
CloseHandle(hFile);
WriteResultFile(TRUE, TEXT("success!"));
}
}
}
Thanks,
There are a few problems:
You're passing uninitialized data (byteReading) as the "# of bytes to read" parameter to ReadFile().
Depending on how you created the file, the file's contents may not have a terminating 0 byte. The code assumes that the terminator is present.
FindClose(hFile) doesn't make sense. CloseHandle(hFile) is all you need.
You need to call CloseHandle if CreateFile() succeeds. Currently, you call it only if you find the string you're looking for.
This isn't a bug, but it's helpful to zero-initialize your buffers. That makes it easier to see in the debugger exactly how much data is being read.
HANDLE hFile = CreateFile(myfile, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL readSuccess;
DWORD byteReading = 255;
char readBuffer[256];
readSuccess = ReadFile(hFile, readBuffer, byteReading, &byteReading, NULL);
readBuffer[byteReading] = 0;
if(readSuccess == TRUE)
{
TCHAR myBuffer[256];
mbstowcs(myBuffer, readBuffer, 256);
if(_tcscmp(myBuffer, TEXT("Hello welcome to C++")) == 0)
{
rv = 0;
}
}
CloseHandle(hFile);
}
I see two things:
byteReading isn't initialized
you are reading bytes so you have to terminate the string by 0.
CloseHandle is sufficient
Either remove the new line character from the file or use _tcsstr for checking the existence of the string "Hello Welcome to C++".