-1

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.

Corona
  • 375
  • 5
  • 21

2 Answers2

0

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);
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I tried the code you have shown and it still only write 4 bytes to the file. – Corona Oct 17 '14 at 20:40
  • `HttpSendRequest()` has both Ansi and Unicode versions. Is it possible that you hooked the Unicode version using an Ansi function? Can you show your code that is actually doing the hooking? – Remy Lebeau Oct 17 '14 at 21:33
  • This is Xbox 360 not Windows. Here is the difference shown in the SDK - http://gyazo.com/98bf25a6365ad0170e088cac555e2a7a – Corona Oct 17 '14 at 21:45
  • I decided to print out the number of Bytes Written `DWORD wfbr;` and it prints '8192' (0x2000) even though the file is 4 bytes in size. – Corona Oct 17 '14 at 22:13
  • There is no way that `WriteFile()` can write 8192 bytes and only 4 appear in the file. Something else has to be manipulating your file outside of your code. And what are the contents of the actual bytes in the file? – Remy Lebeau Oct 17 '14 at 22:26
  • The text is `xtok` like I said I've been able to dump the entire certificate remotely and that is the correct first 4 bytes. It is a strange phenomenon that has been frying my head all day. I've tried every impractical/practical solution and nothing forces it to output more than 4 bytes. – Corona Oct 17 '14 at 22:29
  • What does the entire `pcszHeaders` content look like? It should not even have a certificate in it, as certificates are not used in HTTP, they are used in SSL/TLS instead. – Remy Lebeau Oct 17 '14 at 23:16
  • That data does not begin with `xtok`, and it is not even a valid HTTP header that should ever be appearing in `pcszHeaders` to begin with. I don't think your code is writing to the same file that you are looking at. That is the only thing that makes sense given the symptoms you have described so far. – Remy Lebeau Oct 17 '14 at 23:46
  • "xtoken" is the header name, I removed the name as that's not what I was interested in. Trust me, it's the data that's being pointed to. – Corona Oct 17 '14 at 23:50
  • You have not shown that to be the case, though. I asked you to show EXACTLY what is in `pcszHeaders`, byte for byte. If it starts with `xtoken`, you did not show that. If it really does, then it should be something like `xtoken: ...`, but that is not what you showed. And what you showed does not appear to be 8192 bytes in size. – Remy Lebeau Oct 18 '14 at 00:57
0

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.

Corona
  • 375
  • 5
  • 21
  • 1
    You don't need the cast, or the address-of operator. – Ben Voigt Oct 18 '14 at 00:48
  • You DO NOT need to copy the bytes to a local array. If you can read from the source memory to make your copy, `WriteFile()` can read from the source memory as well. – Remy Lebeau Oct 18 '14 at 00:58
  • The cast and address-of operator is how I got it to work. The local storage is for personal use when another hooked function is called. – Corona Oct 18 '14 at 02:30