Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Сканирование памяти


Автор: Canore 18.7.2015, 13:47
Есть рабочий код, но он напрочь отказывается работать в игре ArcheAge хотя скажем в CS:Source работает.
Код

struct MemoryBlock
{
    // По какому адресу находился блок в оригинале
    LPBYTE startAddressOld;
    // Указатель на скопированную память
    void *p;
    // Размер блока
    SIZE_T size;
};

void CopyVA(vector<MemoryBlock> &valList, bool first = true)
{
    LPBYTE buffer = NULL;
    vector<MemoryBlock> a;
    DWORD address = NULL;
    int flagg = 0;
 
    int counter = 0;
 
    #define NEEDED (memInf.State==MEM_COMMIT) && (memInf.Protect==PAGE_READWRITE)
 
    for (LPBYTE startAppAddress = (LPBYTE)sysInf.lpMinimumApplicationAddress; startAppAddress <= (LPBYTE)sysInf.lpMaximumApplicationAddress; startAppAddress += memInf.RegionSize)
    {
        if (VirtualQueryEx(hProc, startAppAddress, &memInf, sizeof(memInf))) // Дальше этого отказывается проходить в ArcheAge
        {
            if (NEEDED)
            {
                buffer = new BYTE[memInf.RegionSize];
                
                if (ReadProcessMemory(hProc, startAppAddress, buffer, memInf.RegionSize, NULL))
                {
                    MemoryBlock temp;
                    temp.startAddressOld = startAppAddress;
                    temp.p = VirtualAlloc ( NULL, memInf.RegionSize, MEM_COMMIT, PAGE_READWRITE );
                    temp.size = memInf.RegionSize;
                    
                    if (WriteProcessMemory(hProcHormiX1, temp.p, buffer, temp.size, NULL))
                    {
                        if (!first && flagg == 0)
                        {
                            FreeVA(valList);
                            valList.clear();
                            flagg = 1;
                        }
                        valList.push_back(temp);
                        //cout << temp.p << " " << temp.size << endl;
                    }
                    else
                    {
                        VirtualFree(temp.p, NULL, MEM_RELEASE);
                    }
                }
            }
        }
    }
}


Как решить данную проблему? Я пытался уже запускать свою программу от имени админа.

Автор: Canore 18.7.2015, 18:14
Никто не знает ?!

Автор: feodorv 18.7.2015, 20:20
Код, использующий WriteProcessMemory() лично у меня вызывает большие подозрения. 

Я понимаю, что код урезан для публикации в этом форуме, но этот никак не способствует его пониманию. Почему VirtualAlloc делается в своём процессе, а по выделенному адресу происходит запись уже в какой-то иной процесс? Почему не высвобождается buffer? 

Я так понимаю, что VirtualQueryEx вернул ноль? В https://msdn.microsoft.com/en-us/library/windows/desktop/aa366907%28v=vs.85%29.aspx на сайте Microsoft сказано, что в этом случае можно вызвать GetLastError(), Вы вызывали?

В моём древнем описании этой функции упоминания о GetLastError() нет, но сказано так:
Цитата
Passing a kernel-mode pointer to this function can result in no information being returned, due to security issues. In this case, the return value is zero. 

Автор: Canore 18.7.2015, 21:03
feodorv, hProcHormiX1 - это handle моего окна, hProc - handle ArcheAge, ну и собственно здесь происходит по блочное чтение из ArcheAge в мой процесс предварительно выделяя память. Но до VirtualAlloc даже не доходит.

Добавлено через 9 минут и 58 секунд
При каждом проходе цикла:

VirtualQueryEx(...) = 0
GetLastError() = 5 (Ошибка доступа)

Как решить ? Собственно в моём коде нет ничего особенного, но раз ошибка доступа то думаю вам пригодится функция с помощью которой я получаю handle.
Код

// Поиск нужного нам процесса
// flag true - поиск по титулу
// flag false - имя исполняемого файла (name.exe)
// HWND hWndHormiX1 - если я ищу свой handle ( просто лень было это убирать )
HANDLE Attach(char* lpWindowName, bool flag = true, HWND hWndHormiX1 = NULL)
{
 
    if (flag)
    {
        HWND hWnd;
        if (hWndHormiX1 != NULL)
            hWnd = hWndHormiX1;
        else
            hWnd= FindWindow(NULL, lpWindowName);
    if (hWnd != 0)
    {
        DWORD pId;
        GetWindowThreadProcessId(hWnd, &pId);
        if (pId != NULL)
        {
            HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pId);
            if (hProc)
            {
                return hProc;
            }
        }
    }
    } else
    {
        PROCESSENTRY32 entry;
        entry.dwSize = sizeof(PROCESSENTRY32);
        HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
        if (Process32First(snapshot, &entry) == TRUE)
        {
            while (Process32Next(snapshot, &entry) == TRUE)
            {
                if (stricmp(entry.szExeFile, lpWindowName) == 0)
                {  
                    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
                    
                    CloseHandle(snapshot);
 
                    if (hProcess)
                        return hProcess;
                }
            }
        }
    }
 
    return NULL;
}


Добавлено через 12 минут и 55 секунд
Цитата

Почему не высвобождается buffer? 

Потому что я слоупок ^_^

Автор: feodorv 18.7.2015, 22:39
Цитата(Canore @  18.7.2015,  21:03 Найти цитируемый пост)
Как решить ?

Не знаю. Причина возникновения ERROR_ACCESS_DENIED может быть затейливой. Например, исследуемый процесс является 64-битным (вроде, это не Ваш случай). Или исследуемый процесс может выполняться с более высоким уровнем привилегий.


Более того, запрос VirtualQueryEx() может выдавать ERROR_ACCESS_DENIED не на все страницы исследуемого процесса. А у вас в коде есть неоднозначность:
Цитата(Canore @  18.7.2015,  13:47 Найти цитируемый пост)
    for (LPBYTE startAppAddress = (LPBYTE)sysInf.lpMinimumApplicationAddress; startAppAddress <= (LPBYTE)sysInf.lpMaximumApplicationAddress; startAppAddress += memInf.RegionSize)
    {
        if (VirtualQueryEx(hProc, startAppAddress, &memInf, sizeof(memInf))) // Дальше этого отказывается проходить в ArcheAge

Если VirtualQueryEx вернёт 0, то какое значение будет у memInf.RegionSize, на величину которого должна увеличиваться переменная цикла? Неизвестно. Делайте хотя бы
Код

if( VirtualQueryEx() )
   ...
else
   memInf.RegionSize = sysInf.dwPageSize;

Автор: Canore 19.7.2015, 04:26
feodorv, хорошо сейчас попытаюсь. Я вроде проверял процесс не использует не каких драйверов и других скрытых процессов и ещё одно очень странное наблюдение процесс подключает один модуль и после него уже становится не возможным воздействие на процесс, то есть до определённого момента при загрузке я могу делать с процессом что угодно. После загрузки(тогда когда подргузился уже этот модуль) я пытался что-то сделать с процессом с помощью программы AnVir Task Manager, но мне пишет что в доступе отказано. Как выдать себе максимальные привилегии драйвер писать? Или можно более простыми путями обойтись?

Автор: Canore 19.7.2015, 04:43
Процесс вроде x32 user posted image

Добавлено через 11 минут и 58 секунд
При добавлении счётчиков и исправленном коде результат таков:
user posted image
Попытка считалась успешной если зашло дальше VirtualQueryEx(), как видите похоже тут все регионы имеют максимальные привилегии.

Автор: Canore 19.7.2015, 07:46
Цитата

 Я вроде проверял процесс не использует не каких драйверов

Проверял программой AnVir Task Manager и не могу ручаться что она находит все загруженные драйвера, а не только те что прописаны в рестре или где там ещё.

Автор: Canore 19.7.2015, 18:31
Где-то на просторах интернета наткнулся:
Цитата

Причины ERROR_ACCESS_DENIED:
    STATUS_THREAD_IS_TERMINATING
    STATUS_PROCESS_IS_TERMINATING
    STATUS_INVALID_LOCK_SEQUENCE
    STATUS_INVALID_VIEW_SIZE
    STATUS_ALREADY_COMMITTED
    STATUS_ACCESS_DENIED
    STATUS_FILE_IS_A_DIRECTORY
    STATUS_CANNOT_DELETE
    STATUS_INVALID_COMPUTER_NAME
    STATUS_FILE_DELETED
    STATUS_FILE_RENAMED
    STATUS_DELETE_PENDING
    STATUS_PORT_CONNECTION_REFUSED
    STATUS_ENCRYPTION_FAILED
    STATUS_ENCRYPTION_FAILED
    STATUS_DECRYPTION_FAILED
    STATUS_NO_RECOVERY_POLICY
    STATUS_NO_EFS
    STATUS_WRONG_EFS
    STATUS_NO_USER_KEYS

Можно ли как-то отследить какая именно из этого списка ? Хотя вангану это STATUS_ACCESS_DENIED процентов так на 99.9%

Автор: feodorv 19.7.2015, 19:42
Попробуйте https://technet.microsoft.com/en-US/bb896653.aspx. Дважды щёлкните мышкой на исследуемом процессе, в открывшемся окне перейдите на вкладку "Security", посмотрите привилегии процесса. Наверняка SeDebugPrivilege поднята.

Автор: Canore 20.7.2015, 01:31
user posted image

Собственно показал всё что на той страницу. И да пытался заморозить процесс этой программой ошибка доступа снова smile 

Мне уже начинает казаться что они наняли шаманов с бубнами и наложили чары на этот процесс.

Добавлено через 9 минут и 44 секунды
Провёл сравнение с той же CS:Source различия в двух привилегиях: SeRestorePrivilege, SeManageVolumePrivilege.

Автор: DarthTon 20.7.2015, 13:24
У ArcheAge есть античит EasyAntiCheat, драйвер которого при помощи ObCallback убирает у всех открываемых хендлов на процесс права доступа к памяти.

Автор: Canore 20.7.2015, 13:58
DarthTon, можно обойти ? Хочу написать такую читалку памяти которую нельзя залочить.

Автор: DarthTon 20.7.2015, 14:07
Более-менее нормальный вариант: 
- Написать свой драйвер который будет вручную обходить VAD-дерево и возвращать инфу юзермодному клиенту. Только придется залочить память процесса на время работы.

Нестабильные решения:
- Изменить права доступа у хендла, добавив нужные
- Найти место где хранится хендл ObCallback в драйвере и снять его

Автор: Canore 20.7.2015, 14:26
DarthTon, 
Цитата

Изменить права доступа у хендла, добавив нужные

Меня устраивает вполне этот вариант так как не придётся лочить память. Как осуществить? Ссылки на msdn если можно или код пожалуйста.

Автор: Canore 20.7.2015, 15:04
DarthTon, 
Цитата

У ArcheAge есть античит EasyAntiCheat,

Если честно не нашёл не чего такого в интернете наверное потому что у ArcheAge HackShield(античит)  smile 

Автор: DarthTon 20.7.2015, 15:39
Цитата

Если честно не нашёл не чего такого в интернете наверное потому что у ArcheAge HackShield(античит)

Да, перепутал слегка smile 
Пример кода:
https://github.com/DarthTon/Blackbone/blob/master/src/BlackBoneDrv/Routines.c#L139-182

Автор: Canore 20.7.2015, 16:01
DarthTon, такой вопрос какие include надо для данного участка кода?

Автор: DarthTon 20.7.2015, 16:06
Посмотри там по проекту в целом на гитхабе. Я не помню точно.

Автор: Canore 20.7.2015, 16:16
DarthTon, я так понимаю это исходники драйвера? я надеялся обойтись без написания драйвера.

Автор: DarthTon 20.7.2015, 16:34
Без драйвера не выйдет в любом случае.  

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)