ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Событие завершения процесса (https://forum.antichat.xyz/showthread.php?t=76643)

gevara 10.07.2008 16:24

Цитата:

Тут только перехватывать ZwExitProcess и ZwExitThread.
таких функций не сущесмтвует

Hellsp@wn 10.07.2008 17:23

вот такие функции есть:

ntdll.ZwTerminateProcess
ntdll.ZwTerminateThread

SlyBit 10.07.2008 17:43

Цитата:

таких функций не сущесмтвует
сорри, ошибся, имел ввиду:

ntdll.ZwTerminateProcess
ntdll.ZwTerminateThread

Цитата:

- есть вот какая тема - добавить свою запись в двусвязный список LDR_MODULE (или как его там...), указав адрес обработчика, которому и будут приходить сообщения DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH и прочие...
Вообщем ты себе все круто усложняешь. Лучше все же вернись к перехвату функций, можно подменой адреса в таблице ипорта (как советовал Jes), если не хочешь возиться со сплайзингом.

Если хуки тебя не в какую не устраивают, то можно вместо добавления новой структуры в двусвязный список загруженных библиотек (довольно палевно, т.к. такие программы как Process Explorer увидят странную библиотеку), изменить базу существующей библиотеку на свой обработчик. При вызове твоего обработчика проверяй 2-ой параметр Reason на равенство коду DLL_PROCESS_DETACH, пиши там свои логи и затем вызывай оригинальную точку входа библиотеки с такими же параметрами. Подменяй точку входа у невыгружаемых библиотеках, таких как user32.dll, kernel32.dll, ntdll.dll.

Теперь постараюсь объяснить как выйти на этот список и что нужно менять.

Для начала нужно получить адрес структуры PEB процесса. Указатель лежит по адресу fs:[30h], либо можно взять его из структуры PROCESS_BASIC_INFORMATION по смещению +4 байта. Указатель на саму струкуру PROCESS_BASIC_INFORMATION получаешь вызвав функцию NtQueryInformationProcess со вторым параметром равным 0 (ProcessBasicInformation). Указатель на PEB есть.

По смещению 0xC в PEB находится указатель на структуру PPEB_LDR_DATA. В этой структуре находятся 3 указателя на точки входа двусвязных списков, содержащих информацию о библиотеках на стадии загрузки, уже загруженных в память и на стадии инициализации. Нас интересует второй указатель.

Теперь нам нужно обойти список LDR_DATA_TABLE_ENTRY и сравнить имя BaseDllName с "ntdll.dll" например. Как находим, заменяем EntryPoint на наш обработчик.

Это все в теории, если что-то не так - поправьте.

NTDLL.h

gevara 10.07.2008 18:13

Что толку от перехвата таблицы импорта, если не знаешь какой именнго модуль завершит последний поток? вообще прога может завершить своё выполнение по рету и ExitProcess будет вызван из kernel32 - тут только сплайсинг. а вариант с изменением адреса входа действительно реальный, хотя, возможно, и не самый лучший. ведь адрес точки входа будет лежать за границами модуля, что может вызвать подозрения...

SlyBit 10.07.2008 18:26

да, я про таблицу экспорта kernel32 и ntdll конечно...какая нафиг импорта ;) мне кажется вариант со сплайзингом такой же палевный как и подмена адреса точки входа либы.

Цитата:

вообще прога может завершить своё выполнение по рету и ExitProcess будет вызван из kernel32
Подменяй тогда адрес возврата.

zl0y 10.07.2008 18:50

KiSystemFastRet+ZwTerminateProcess.

gevara 10.07.2008 20:16

Цитата:

Сообщение от SlyBit
да, я про таблицу экспорта kernel32 и ntdll конечно...какая нафиг импорта ;) мне кажется вариант со сплайзингом такой же палевный как и подмена адреса точки входа либы.


Подменяй тогда адрес возврата.

про адрес возврата я уже сказал - не катит на случай многопоточности

SlyBit 10.07.2008 20:19

А вот и пример подмены точки входа библиотеки подоспел (описание несколькими постами выше):

Код:

#include <windows.h>
#include "ntdll.h"
 
#pragma comment(linker, "/ENTRY:Main")
 
typedef DWORD (WINAPI *PTRUEENTRY)(HMODULE Module, DWORD Reason, LPVOID Reserved);
 
PVOID dwTrueAddr;
 
DWORD WINAPI CatchExit(HMODULE Module, DWORD Reason, LPVOID Reserved)
{
    if(Reason == DLL_PROCESS_DETACH) {
        // Событие перед завершение приложения
    }
    return ((PTRUEENTRY)dwTrueAddr)(Module, Reason, Reserved);
}
 
VOID WINAPI HookDllEntry(PWCHAR pDllName, PVOID pDummyEntry)
{
    PPEB pPeb;
    PPEB_LDR_DATA pPebLdrData;
    PLDR_DATA_TABLE_ENTRY pLdrDataTableEntry;
    DWORD dwBlink;
 
    __asm {
        mov eax, fs:[0x30]
        mov pPeb, eax
    }
   
    pPebLdrData = (PPEB_LDR_DATA)pPeb->Ldr;
   
    // Запоминаем адрес последнего элемента в двусвязном списке
    dwBlink = *(PDWORD)pPebLdrData->InMemoryOrderModuleList.Blink;

    // Получаем указатель на первую структуру в двусвязном списке
    pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pPebLdrData->InLoadOrderModuleList.Flink;
   
    // Обходим все структуры и как находим библиотеку с именем pDllName, изменяем её точку входа
    do {
        pLdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)pLdrDataTableEntry->InLoadOrderModuleList.Flink;
        if(!lstrcmpW(pLdrDataTableEntry->BaseDllName.Buffer, pDllName)) {
            dwTrueAddr = pLdrDataTableEntry->EntryPoint;
            pLdrDataTableEntry->EntryPoint = pDummyEntry;
        }
    } while(dwBlink != *(PDWORD)pLdrDataTableEntry->InMemoryOrderModuleList.Flink);
}
 
VOID WINAPI Main()

    HookDllEntry(L"ntdll.dll", CatchExit);
    ExitProcess(0);
}


gevara 10.07.2008 20:29

SlyBit, пасиб, конечно. но это вобщем-то понятно. у меня ситуация несколько другая - вот я и думаю что сделать лучше: перехват PEB или сплайсинг ExitThread или ExitProcess. Вообще-то мой код и так хучит кое-какие функции. В частности имеет доступ к оконным сообщениям. так что идеальный вариант - отслеживать сообщения (есали такие есть) о закрытии всех окон или что-то типа этого...

SlyBit 10.07.2008 21:18

gevara

Я думаю, что оконные сообщения отпадают по как минимум 2м причинам: не отслеживается самостоятельный вызов ExitProcess программой, не всегда они "правильно" обрабатываются программой. Пример Outpost, при посылке его главному окну сообщения WM_CLOSE (щелчек на крестик в правом верхнем углу), оно просто сворачивается, вместо того чтобы закрыться. На сообщения WM_DESTROY и WM_QUIT вообще нет никакой реакции. Калькулятор же спокойно закрывается получив WM_CLOSE.

Выбор между модификацией PEB и сплайзингом ExitProcess и ExitThread. В первом случае все просто. Во втором нужно считать количество потоков, приложение закроется как только закроют его последний поток. Для этого нужно будет перехватывать CreateThread и икрементировать счетчик кол-ва потоков и декрементировать при выхове ExitThread, либо подсчитывать количество потоков перед вызовом ExitThread.


Время: 02:30