C++ WriteFile only writing 4 bytes - c++

Here's what I'm trying to achieve; I'm hooking onto the HttpSendRequest function (on Xbox it's XHttp) and trying dump the certificate that's in pcszHeaders which has the size of 0x1F0E.
Now the problem; it only seems to write 4 bytes, I've even tried allocating extra memory and setting each bit to 0 to see if it's the size of Headers and it continues to only write 4 bytes. I've been able to dump pcszHeaders remotely because I got the address whilst debugging but I need to dump it at run-time.
Something I notice whilst debugging - The address of pcszHeaders only shows in locals until it reaches;
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
Once it reaches the printf() above the address changes to 0x00000000 (bad ptr) but it still writes the first byte of correct data of pcszHeaders correctly but nothing more.
Here is the entire hook;
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if(pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//does file exist?
if(GetLastError()!=ERROR_ALREADY_EXISTS
||fileHandle!=INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: %s\n", "Writing to file...");
DWORD wfbr;
//write to our file
if(WriteFile(fileHandle, pcszHeaders, 0x2000, &wfbr, NULL))
{
printf("XHttpSendRequest: %s\n", "File written!");
printf("%s\n", "Request has ended.");
CloseHandle(fileHandle);
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}
}
}
}
EDIT: I've changed the code slightly and I've copied pcszHeaders data into another section of memory that I've created and my pointers seems to have all the correct data and I've tried Writing it to file and it still only writes 4 bytes. I've even used sizeof() instead of hard-coded 0x2000.

pcszHeaders is a char* pointer. sizeof(pcszHeaders) is 4 in a 32bit app (8 in a 64bit app). You need to use the dwHeadersLength parameter instead, which tells you how many characters are in pcszHeaders.
Also, your GetLastError() check after CreateFile() is wrong. If CreateFile() fails for any reason other than ERROR_ALREADY_EXISTS, you are entering the code block and thus writing data to an invalid file handle. When using CREATE_NEW, CreateFile() returns INVALID_HANDLE_VALUE if the file already exists. You don't need to check GetLastError() for that, checking for INVALID_HANDLE_VALUE by itself is enough. If you want to overwrite the existing file, use CREATE_ALWAYS instead.
You are also leaking the file handle if WriteFile() fails.
And you are calling the original HttpSendRequest() only if you successfully write headers to your file. If there are no headers, or the create/write fails, you are not allowing the request to proceed. Is that what you really want?
Try this instead:
BOOL XHTTP_SEND_REQUEST_HOOK(
HINTERNET hRequest,
const CHAR *pcszHeaders,
DWORD dwHeadersLength,
const VOID *lpOptional,
DWORD dwOptionalLength,
DWORD dwTotalLength,
DWORD_PTR dwContext)
{
if (pcszHeaders != XHTTP_NO_ADDITIONAL_HEADERS)
{
printf("XHttpSendRequest: Creating Certificate.bin...\n");
// Setup expansion
doMountPath("Hdd:", "\\Device\\Harddisk0\\Partition1");
//create our file
HANDLE fileHandle = CreateFile("Hdd:\\Certificate.bin", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
//is file open?
if (fileHandle != INVALID_HANDLE_VALUE)
{
printf("XHttpSendRequest: Writing to file...\n");
DWORD wfbr;
//write to our file
if (WriteFile(fileHandle, pcszHeaders, dwHeadersLength, &wfbr, NULL))
printf("XHttpSendRequest: File written!\n");
else
printf("XHttpSendRequest: Error writing to file: %u\n", GetLastError());
CloseHandle(fileHandle);
}
else
printf("XHttpSendRequest: Error creating file: %u\n", GetLastError());
}
printf("Request has ended.\n");
return XHttpSendRequest(hRequest, pcszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, dwTotalLength, dwContext);
}

Finally the problem has been solved!
First I created an empty array for the data to be stored.
CHAR xtoken[0x2000];
memset(xtoken, 0, 0x2000);
The first part of the hook is to store the header data.
DWORD bufferLength = dwHeadersLength;
memcpy(xtoken, pcszHeaders, bufferLength);
I then write the data to file
WriteFile(fileHandle, (void*)&xtoken, bufferLength, &wfbr, NULL))
Success! I guess the problem was that parameter 2 of WriteFile() was incorrect.

Related

Why the file could be written after changing the attribute to readonly under windows?

Given one normal file, it could be read and written. Then I change this file attribute to Read-only through
However, this file still could be written through file handler. Here are my codes
#define CREATE_FILE_OPT FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH | FILE_FLAG_RANDOM_ACCESS
std::string name("test.txt");
HANDLE hfile = ::CreateFile(name.c_str(),
GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, CREATE_FILE_OPT, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
hfile = ::CreateFile(name.c_str(),
GENERIC_READ | GENERIC_WRITE, NULL, NULL, CREATE_NEW, CREATE_FILE_OPT, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
printf("so sad, invalid file handler....");
return -1;
}
}
int i = 0;
char rbuf[] = "you are";
DWORD bytesWritten;
do {
Sleep(5000);
++i;
bytesWritten = 0;
BOOL bret = ::WriteFile(hfile, rbuf, strlen(rbuf), &bytesWritten, NULL);
if (bret == FALSE) {
printf("Cannot write bytes into file.....");
DWORD err = GetLastError();
printf("The error code is %d\n", err);
}
else
printf("write %d bytes to file\n", bytesWritten);
DWORD ret = GetFileAttributes(name.c_str());
printf("The file attribute is %d\n", ret);
} while (i < 10000);
The file attribute is 32 before I change it to Read-only, but it will be 33 after this file is Read-only.
I want to know why the file could be written after change it to Read-only? Is there any issue in my test codes?
PS: test it in VS2015 under windows 7.
Sorry, I get your meaning finally. I guess you are talking about creating a file first, setting it readonly without closing the program. The READONLY attribute check only happens in CreateFile routine.
In Windows kernel, every object is assigned a temporary access right list once created, unless explicitly refreshed, a thing seldom happens on actual files on fixed disks. So even if you deny all rights after CreateFile using NTFS access control, your program will behave just as when CreateFile is called.
In conclusion, it is natural your program can still write to the file, after your hot-changing it into READONLY, which only writes information onto disk, not changing kernel access table.

C++ Download File WinInet - 0kb written to file

Can someone tell me what is wrong with my code?
I am trying to download a file from the internet using WinInet. The function connects to the target site just fine, I don't understand why this code isn't working. Can anyone help me out?
Here is my code:
HANDLE hFile = CreateFileW(FilePath, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, NULL, NULL);
if (hFile != INVALID_HANDLE_VALUE || GetLastError() == ERROR_ALREADY_EXISTS)
{
CHAR Buffer[2048];
DWORD BytesRead=0, BytesToRead=0;
DWORD BytesWritten=0, BytesToWrite=0;
SetFilePointer(hFile, 0, 0, FILE_BEGIN);
do
{
if (BytesRead)
{
WriteFile(hFile, Buffer, BytesWritten, &BytesToWrite, FALSE);
}
}
while
(InternetReadFile(hRequest, (LPVOID)Buffer, BytesToRead, &BytesRead) != FALSE);
}
CloseHandle(hFile);
}
hRequest is passed to the function, it is the HINTERNET handle from HttpOpenRequestA.
Your code has some logic problems.
you are misusing GetLastError() when calling CreateFileW(). Regardless of whether the file already exists or not, CreateFileW() will not return INVALID_HANDLE if it successfully creates/opens the file. That is all you need to check for (call GetLastError() only if CreateFileW() fails and you want to find out why). also, there is no need to call SetFilePointer() at all, as CREATE_ALWAYS ensures the opened file is empty, truncating the file if it already exists and has data in it.
your do..while loop should be a while loop instead, so that InternetReadFile() is called first. There is no point in skipping WriteFile() on the first loop iteration. If you use a do..while loop, InternetReadFile() should not be used as the loop condition.
more importantly, you are breaking the loop only if InternetReadFile() fails with an error. You are expecting it to fail when it reaches the end of the response, but it actually returns TRUE and sets BytesRead to 0. This is documented behavior, which you are not handling at all:
InternetReadFile function
InternetReadFile operates much like the base ReadFile function, with a few exceptions. Typically, InternetReadFile retrieves data from an HINTERNET handle as a sequential stream of bytes. The amount of data to be read for each call to InternetReadFile is specified by the dwNumberOfBytesToRead parameter and the data is returned in the lpBuffer parameter. A normal read retrieves the specified dwNumberOfBytesToRead for each call to InternetReadFile until the end of the file is reached. To ensure all data is retrieved, an application must continue to call the InternetReadFile function until the function returns TRUE and the lpdwNumberOfBytesRead parameter equals zero. This is especially important if the requested data is written to the cache, because otherwise the cache will not be properly updated and the file downloaded will not be committed to the cache. Note that caching happens automatically unless the original request to open the data stream set the INTERNET_FLAG_NO_CACHE_WRITE flag.
ReadFile function
When a synchronous read operation reaches the end of a file, ReadFile returns TRUE and sets *lpNumberOfBytesRead to zero.
when calling WriteFile(), you are passing BytesWritten to the nNumberOfBytesToWrite parameter, but BytesWritten is never set to anything other than 0, so nothing gets written to the file. You need to pass BytesRead instead.
With that said, use something more like this:
HANDLE hFile = CreateFileW(FilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
// handle error as needed...
}
else
{
BYTE Buffer[2048];
DWORD BytesRead, BytesWritten;
do
{
if (!InternetReadFile(hRequest, Buffer, sizeof(Buffer), &BytesRead))
{
// handle error as needed...
break;
}
if (!BytesRead)
break;
if (!WriteFile(hFile, Buffer, BytesRead, &BytesWritten, FALSE))
{
// handle error as needed...
break;
}
}
while (true);
CloseHandle(hFile);
}
MSDN even has a full example of how to use InternetReadFile():
HOWTO: Using InternetReadFile To Get File
BOOL GetFile (HINTERNET IN hOpen, // Handle from InternetOpen()
CHAR *szUrl, // Full URL
CHAR *szFileName) // Local file name
{
DWORD dwSize;
CHAR szHead[] = "Accept: */*\r\n\r\n";
VOID * szTemp[25];
HINTERNET hConnect;
FILE * pFile;
if ( !(hConnect = InternetOpenUrl ( hOpen, szUrl, szHead,
lstrlen (szHead), INTERNET_FLAG_DONT_CACHE, 0)))
{
cerr << "Error !" << endl;
return 0;
}
if ( !(pFile = fopen (szFileName, "wb" ) ) )
{
cerr << "Error !" << endl;
return FALSE;
}
do
{
// Keep coping in 25 bytes chunks, while file has any data left.
// Note: bigger buffer will greatly improve performance.
if (!InternetReadFile (hConnect, szTemp, 50, &dwSize) )
{
fclose (pFile);
cerr << "Error !" << endl;
return FALSE;
}
if (!dwSize)
break; // Condition of dwSize=0 indicate EOF. Stop.
else
fwrite(szTemp, sizeof (char), dwSize , pFile);
} // do
while (TRUE);
fflush (pFile);
fclose (pFile);
return TRUE;
}

how to append text to a file in windows?

Everytime this function is called the old text data is lost?? Tell me how to maintain previous data and appending new data.
This function is called 10 times:
void WriteEvent(LPWSTR pRenderedContent)
{
HANDLE hFile;
DWORD dwBytesToWrite = ((DWORD)wcslen(pRenderedContent)*2);
DWORD dwBytesWritten = 0;
BOOL bErrorFlag = FALSE;
printf("\n");
hFile = CreateFile(L"D:\\EventsLog.txt", FILE_ALL_ACCESS, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Terminal failure: Unable to open file \"EventsLog.txt\" for write.\n");
return;
}
printf("Writing %d bytes to EventsLog.txt.\n", dwBytesToWrite);
bErrorFlag = WriteFile(
hFile, // open file handle
pRenderedContent, // start of data to write
dwBytesToWrite, // number of bytes to write
&dwBytesWritten, // number of bytes that were written
NULL); // no overlapped structure
if (FALSE == bErrorFlag)
{
printf("Terminal failure: Unable to write to file.\n");
}
else
{
if (dwBytesWritten != dwBytesToWrite)
{
printf("Error: dwBytesWritten != dwBytesToWrite\n");
}
else
{
printf("Wrote %d bytes to EventsLog.txt successfully.\n",dwBytesWritten);
}
}
CloseHandle(hFile);
}
You should pass FILE_APPEND_DATA as the dwDesiredAccess to CreateFile, as documented under File Access Rights Constants (see sample code at Appending One File to Another File). While this opens the file using the correct access rights, your code is still responsible for setting the file pointer. This is necessary, because:
Each time a file is opened, the system places the file pointer at the beginning of the file, which is offset zero.
The file pointer can be set using the SetFilePointer API after opening the file:
hFile = CreateFile( L"D:\\EventsLog.txt", FILE_APPEND_DATA, 0x0, nullptr,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr );
if ( hFile == INVALID_HANDLE_VALUE ) {
printf( "Terminal failure: Unable to open file \"EventsLog.txt\" for write.\n" );
return;
}
// Set the file pointer to the end-of-file:
DWORD dwMoved = ::SetFilePointer( hFile, 0l, nullptr, FILE_END );
if ( dwMoved == INVALID_SET_FILE_POINTER ) {
printf( "Terminal failure: Unable to set file pointer to end-of-file.\n" );
return;
}
printf("Writing %d bytes to EventsLog.txt.\n", dwBytesToWrite);
bErrorFlag = WriteFile( // ...
Unrelated to your question, the calculation of dwBytesToWrite should not use magic numbers. Instead of * 2 you should probably write * sizeof(*pRenderedContent). The parameter to WriteEvent should be constant as well:
WriteEvent(LPCWSTR pRenderedContent)
The parameter for appending data to a file is FILE_APPEND_DATA instead of FILE_ALL_ACCESS in the CreateFile function.
Here is an example: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363778(v=vs.85).aspx

Win 32 Writefile: Access Viloation and Error 1784

Two problems with the below code. To begin, I have been scouring this and various other forums for answers to my 1784 error code and everything I've tried has failed. Two of the threads I've checked on stackoverflow are WriteFile returning error 1784 and BlockWrite I/O Error 1784. I've checked some others on this forum but I'm not remembering exactly what the are right now.
I'm trying to save an array of structs to an empty binary file. The first problem is that I get an access violation if my size variable (nNumberOfBytesToWrite parameter) is anything less about 99000 bytes. That number jumps around. For awhile when I was testing it would have the access violation if it was 99,999 bytes but not 100,000 bytes. Of course, what I eventually want to do is set the size to the size of the entire array. The original code to handle that is now commented out so I can test with various sizes.
The second thing that happens (if I don't get an access violation) is I get error code 1784 and WriteFile fails every time. As other threads on this topic have stated, this is defined on MSDN as ERROR_INVALID_USER_BUFFER and the description is "The supplied user buffer is not valid for the requested operation." I've looked at MSDN's own example for opening files like this (http://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx) and have tried some variations based on their code, but nothing seems to work.
This problem is probably massively noob and I'm sure I'm overlooking something ridiculously simple, but if anyone has suggestions they'd be greatly appreciated.
case IDM_SAVE1:
{
HANDLE hFile = CreateFile("MineSave.mss", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
int test_buffer[] = {1,2,3,4,5,6,7,8,9,10};
if(hFile != INVALID_HANDLE_VALUE)
{
BOOL bSuccess;
DWORD size = 100000; //DWORD size = (((sizeof(tile)) * tiles_total));
LPDWORD bytes_written = 0;
bSuccess = WriteFile(hFile, test_buffer, size, bytes_written, NULL);
if(bSuccess)
{
MessageBox(hwnd, "File saved successfully.", "Great Job!", MB_OK);
}
else
{
DWORD error = GetLastError();
MessageBox(hwnd, "Could not write to file.", "Error", MB_OK);
}
CloseHandle(hFile);
}
else
{
MessageBox(hwnd, "Could not create file.", "Error", MB_OK);
}
}
break;
Your buffer is the size of 10 ints, which is 40 bytes on Windows. You are trying to write 100,000 bytes from that buffer. That is undefined behaviour, a buffer overrun. Hence the access violation.
You must not pass a value greater than sizeof(test_buffer), i.e. 40, to the nNumberOfBytesToWrite parameter of WriteFile.
You'll need to write this file in a loop, writing 40 bytes at a time, until you have written as much as you need. Perhaps something like this:
BOOL bSuccess = TRUE;
DWORD bytesRemaining = 100000;
while (bSuccess && bytesRemaining>0)
{
DWORD bytesToWrite = std::min(sizeof(test_buffer), bytesRemaining);
DWORD bytesWritten;
bSuccess = WriteFile(hFile, test_buffer, bytesToWrite, &bytesWritten, NULL);
bytesRemaining -= bytesToWrite;
}
if (!bSuccess)
{
//handle error;
}
Writing 40 bytes at a time is pretty slow. You'll find it more efficient to write a few KB with each call to WriteFile.
Note that you aren't allowed to pass NULL to the lpNumberOfBytesWritten parameter if you also pass NULL to lpOverlapped, as you do here. From the documentation:
lpNumberOfBytesWritten [out, optional]
......
This parameter can be NULL only when the lpOverlapped parameter is not NULL.
You must provide a buffer to receive the number of bytes written, either the lpNumberOfBytesWritten parameter must be non-NULL, or the lpOverlapped parameter must be non-NULL.
You are passing NULL for both, which is illegal and causes the access violation.

getting error code 998 Invalid access to memory location when trying to read from named pipe

I created a named pipe using WCF and C#, and a client to connect to it so that I know that it is working correctly. Now I'm trying to create a c++ client. So far I have been able to get the name of the pipe, connect to it, and write some data to it. When I try to read from it I'm getting error code 998 Invalid access to memory location. Here is the code I'm using:
HANDLE hPipe = CreateFile(pipeName.c_str(), GENERIC_WRITE | GENERIC_READ, 2, NULL, OPEN_EXISTING, NULL, NULL);
BOOL bWrite = WriteFile(hPipe, &message, size, &bytesWritten, NULL);
LPVOID buffer = 0;
DWORD bytesRead;
BOOL bRead = ReadFile(hPipe, buffer, 10, &bytesRead, NULL);
I'm not sure what I'm doing wrong.
No memory has been allocated for buffer, it is currently a null pointer, and the code is requesting that 10 bytes of data be read into an array that does not exist. From ReadFile():
lpBuffer [out]
A pointer to the buffer that receives the data read from a file or device.
To rectify:
char buffer[10];