Файл чтения неправильно считывает байты

#c #winapi

#c #winapi

Вопрос:

Я пытаюсь прочитать файл с помощью readfile, сохранить его в широком массиве, затем записать в другой файл. Проблема в том, что когда я помещаю их рядом в формате HxD, некоторые байты верны (например, текст), но все остальное совершенно другое. Я тоже не могу его запустить

 struct a
{
    BYTE* buff;
    long siz;
};

int main()
{
    HANDLE hFile;
    a struct_a;

    if (hFile = CreateFileW(L"C:\Windows\System32\notepad.exe", GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr))
    {
        long lFileSize = GetFileSize(hFile, nullptr);

        if (lFileSize)
        {
            struct_a.siz = lFileSize;
            struct_a.buff = new BYTE[struct_a.siz];

            if (ReadFile(hFile, struct_a.buff, struct_a.siz,
                nullptr, nullptr))
            {
                CloseHandle(hFile);
            }

        }
    }

    HANDLE h = CreateFileA("C:\Users\USER\Desktop\notepad_new.exe", GENERIC_WRITE, FILE_SHARE_WRITE, nullptr,
        CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr);

    WriteFile(h, struct_a.buff, struct_a.siz, nullptr, nullptr);

return 0;
}
  

Я хочу, чтобы он мог правильно прочитать файл, а затем записать его, чтобы я мог его запустить.


В качестве бонуса я также попытался записать несколько байтов в конце файла после того, как прочитал его, выполнив

 struct_a.buff[struct_a.siz - 5] = L'A';
  

но это нигде не отображалось. Но когда я попытался записать это в начале (убрав скобки), он записал это нормально.

РЕДАКТИРОВАТЬ: я попытался прочитать его впоследствии, и он, как ни странно, прочитал правильную букву

ПРАВКА 2: Описание проблемы: введите описание изображения здесь

Комментарии:

1. Похоже, вы не хотите работать с файлом как с текстовым файлом и должны вместо этого обрабатывать его как двоичные данные.

2. Объясните дальнейший помощник

3. Можете ли вы, ребята, сказать мне, в чем мои проблемы, вместо того, чтобы голосовать против меня? Я не эксперт, но я изо всех сил старался сделать все сам, поэтому я подумал, что могут возникнуть некоторые ошибки

4. Еще не проголосовал. Но, вероятно, избиратели обескуражены тем, что в вашем примере кода не хватает информации. Возможно, это неверное представление вашей реальной программы. Примечательно, что мы не видим, происходят ли эти чтения и записи в одной и той же функции или именно там, где struct_a определено. Что касается вашего «бонусного» теста, это вызывает тревогу. Если вы не видите никаких изменений, то, возможно, вы на самом деле никогда не записывали (возможно, файл уже открыт?) — проверьте, действителен ли дескриптор после открытия файла, и выдайте ошибку, если нет. Что касается двоичного режима, это необходимо, чтобы избежать перевода новой строки.

5. На самом деле проблема с «бонусом» заключается в том, что вы выделили wchar_t массив. Не считывайте ваш файл как wchar_t значения!! Размер файла указан в байтах . Когда вы обращаетесь к size-5 элементу в wchar_t массиве, это далеко от конца файла.

Ответ №1:

Левый файл на скриншоте является 32-разрядным EXE-файлом. Выделенный вами байт, который отличается, является адресом структуры IMAGE_NT_HEADERS в файле.

По адресу 0xFC, 4 байта в этой структуре, 2 байта равны 4C 01. Это поле Machine в IMAGE_FILE_HEADERS, и это значение указывает, что на компьютере установлен «i386» (т. е. 32-разрядная программа).

В нужном файле вместо адреса указан 0xEC, а байты равны 64 86, что означает «AMD64» (т. е. это 64-разрядная программа).

Вероятно, ваша программа является 32-разрядной программой, и поэтому она обращается к 32-разрядной версии System32 из-за функции Windows, называемой перенаправлением файловой системы (спасибо Полу Сандерсу за ссылку). В 64-разрядной Windows 32-разрядные программы перенаправляют System32 в другую папку (которая на самом деле называется SysWOW64) — согласно этой таблице:

                    32-bit System32        64-bit System32

32-bit program   C:WindowsSystem32    C:Windowssysnative
64-bit program   C:WindowsSysWOW64    C:WindowsSystem32
  

Вы можете решить эту проблему, либо прочитав notepad.exe из sysnative, или сравнивая его с файлом в SysWOW64 вместо файла в System32, или компилируя вашу программу как 64-разрядную.

Комментарии:

1. Вы очень правы, я не могу поверить, что я этого не видел. У меня даже вызов ReadProcessMemory возвращал несоответствующую длину, потому что я пытался получить доступ к процессу x64 из скомпилированного exe-файла x86. Большое спасибо