Исключение при создании потока

Мне нужно сохранить некую информацию по базовому адресу загрузки приложения. Но как только я что то записываю по первым двум байтам, у меня происходит необработанное исключение при создании потока стандартными средствами c++.

#include <Windows.h>
#include <iostream>
#include <thread>
#include <TlHelp32.h>


void Thr()
{
    while (true)
    {
        Sleep(1);
    }
}

int main()
{
    void* image_base = reinterpret_cast<void*>(GetModuleHandleA(NULL));

    DWORD oldProtect;
    if (!VirtualProtect(image_base, 2, PAGE_READWRITE, &oldProtect))
        return false;

    ((PCHAR)image_base)[1] = 4;

    if (!VirtualProtect(image_base, 2, oldProtect, &oldProtect))
        return false;

    std::thread _thr(Thr); //вот тут происходит исключение
    _thr.detach();

    system("pause");
    return 1;
}

Я даже предположить не могу почему так может происходить. Но очень странно, ведь первые 2 байта приложения - это MZ сигнатура. Неужели она проверяется перед созданием потока?...


Ответы (1 шт):

Автор решения: KoVadim

Ох. ну почему люди никогда не проверяют нормально коды возврата? там сколько полезной информации бывает. Давайте перепишем немного приложение, что бы оно нам помогло.

#include <Windows.h>
#include <iostream>
#include <thread>
#include <TlHelp32.h>


void Thr()
{
    while (true)
    {
        Sleep(1);
    }
}

int main()
{
    void* image_base = reinterpret_cast<void*>(GetModuleHandleA(NULL));

    DWORD oldProtect;
    if (!VirtualProtect(image_base, 2, PAGE_READWRITE, &oldProtect))
        return false;

    ((PCHAR)image_base)[1] = 4;

    if (!VirtualProtect(image_base, 2, oldProtect, &oldProtect))
        return false;

    try {
    std::thread _thr(Thr); //вот тут происходит исключение
    _thr.detach();
    }
    catch(...) { puts("да, случилось, но и так знаем"); }
    printf("error = %d\n", GetLastError()); // Вот это нас и интересует!
    system("pause");
    return 1;
}

запускаем и что видим? выдает error = 193. Открываем Error Lookup (стандартная утилита, идет с студией, даже с меню Tools можно открыть), вбиваем туда и получаем "%1 is not a valid Win32 application.".

Ну да, логично. Мы же повредили самый базовый заголовок. Но почему это так важно? Скорее всего, потому что когда создается новый поток, операционная система должна создать для него "инфраструктуру" - стек, какие то внутренние записи, таблицу импорта подгрузить. А вот это все как раз можно прочитать в заголовке файла. Не хранить же его в десяти местах. Там же можно найти адреса таблиц импорта. Да, все это уже находится в значительно дальше, чем MZ, но код, который читает это все должен быть уверен, что он читает то, что нужно.

→ Ссылка