【问题标题】:C++ WriteFile only writing 4 bytesC++ WriteFile 只写 4 个字节
【发布时间】:2014-10-17 17:58:57
【问题描述】:

这就是我想要实现的目标;我正在连接 HttpSendRequest 函数(在 Xbox 上是 XHttp)并尝试转储 pcszHeaders 中大小为 0x1F0E 的证书。

现在的问题;它似乎只写了 4 个字节,我什至尝试分配额外的内存并将每个位设置为 0 以查看它是否是 Headers 的大小,并且它继续只写 4 个字节。我已经能够远程转储 pcszHeaders,因为我在调试时获得了地址,但我需要在运行时转储它。

我在调试时注意到的一点 - pcszHeaders 的地址只在本地显示,直到它到达;

 printf("XHttpSendRequest: %s\n", "Creating Certificate.bin...");

一旦它到达上面的 printf(),地址将更改为 0x00000000(坏 ptr),但它仍然正确写入 pcszHeaders 正确数据的第一个字节,但仅此而已。

这是整个钩子;

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);
      }
    }
  }
}

编辑:我稍微更改了代码,并将 pcszHeaders 数据复制到我创建的另一段内存中,并且我的指针似乎具有所有正确的数据,我尝试将其写入文件和它仍然只写 4 个字节。我什至使用 sizeof() 而不是硬编码的 0x2000。

【问题讨论】:

  • TL;DR;您是否在某处使用sizeof(<pointer>),而不是指针指向的数据大小?!?
  • πάντα ῥεῖ - 是的,我试过了。
  • @Corona:这就是重点——不要使用sizeof(<pointer>),这是错误的。

标签: c++ http io xbox writefile


【解决方案1】:

pcszHeaders 是一个char* 指针。 sizeof(pcszHeaders) 在 32 位应用程序中为 4(在 64 位应用程序中为 8)。您需要改用dwHeadersLength 参数,它告诉您pcszHeaders 中有多少个字符。

另外,您在CreateFile() 之后的GetLastError() 检查是错误的。如果CreateFile() 因ERROR_ALREADY_EXISTS 以外的任何原因而失败,则您正在输入代码块,从而将数据写入无效的文件句柄。当使用CREATE_NEW 时,如果文件已经存在,CreateFile() 返回INVALID_HANDLE_VALUE。您无需为此检查GetLastError(),仅检查INVALID_HANDLE_VALUE 就足够了。如果要覆盖现有文件,请改用CREATE_ALWAYS。

如果WriteFile() 失败,您也会泄露文件句柄。

如果您成功将标头写入文件,您将调用原始HttpSendRequest() 。如果没有标头,或者创建/写入失败,则您不允许请求继续进行。这真的是你想要的吗?

试试这个:

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);
}

【讨论】:

  • 我尝试了您显示的代码,但它仍然只向文件写入 4 个字节。
  • HttpSendRequest() 有 Ansi 和 Unicode 版本。您是否有可能使用 Ansi 函数挂钩 Unicode 版本?你能展示你的代码实际上是在做钩子吗?
  • 这是 Xbox 360 而不是 Windows。这是 SDK 中显示的差异 - gyazo.com/98bf25a6365ad0170e088cac555e2a7a
  • 我决定打印出 DWORD wfbr; 写入的字节数,即使文件大小为 4 个字节,它也会打印出 '8192' (0x2000)。
  • WriteFile()不可能写入8192字节,文件中只出现4个。必须有其他东西在您的代码之外操纵您的文件。文件中实际字节的内容是什么?
【解决方案2】:

问题终于解决了!

首先我为要存储的数据创建了一个空数组。

CHAR xtoken[0x2000];
memset(xtoken, 0, 0x2000);

钩子的第一部分是存储头部数据。

DWORD bufferLength = dwHeadersLength;
memcpy(xtoken, pcszHeaders, bufferLength);

然后我将数据写入文件

WriteFile(fileHandle, (void*)&xtoken, bufferLength, &wfbr, NULL))

成功!我猜问题是WriteFile() 的参数2 不正确。

【讨论】:

  • 您不需要演员表或地址运算符。
  • 您不需要将字节复制到本地数组。如果您可以从源内存中读取来制作副本,WriteFile() 也可以从源内存中读取。
  • 演员表和地址操作符是我让它工作的方式。当调用另一个挂钩函数时,本地存储供个人使用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-13
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多