Как може да се получи името на начален адрес на процес, както се прави в Process Explorer?

Добре, пиша приложение, предназначено да изброява нишки в даден процес, точно както прави Process Explorer. Наясно съм, че това потенциално ще се счупи между различните версии на Windows, тъй като разчита на "неофициални" API като NtQuerySystemInformation, и аз съм напълно добре с това.

Вече имам кода за получаване на основния адрес на дадена нишка. Сега бих искал да превърна това в нещо като това, което прави Process Explorer, т.е. "ntdll.dll!EtwDeliverDataBlock+0x453". Всъщност не се нуждая от името на функцията или отместването, а само от името на модула.

Как мога да направя това?


person Billy ONeal    schedule 11.12.2010    source източник


Отговори (3)


Ако всичко, от което се нуждаете, е името на модула, най-лесният начин е да използвате EnumProcessModules за да получите списък с всички заредени модули, след това използвайте GetModuleInformation на всяка от тях. Едно от нещата, които GetModuleInformation връща, е основният адрес, където е зареден този модул. Технически, целочислената стойност на самия HMODULE е същата като основния адрес, но това ми се струва малко крехко...

След това е просто въпрос на намиране на модула с базов адрес точно под текущия (или началния) адрес на нишката.

О, и за да получите действителното име на модула, има GetModuleBaseName.

person Dean Harding    schedule 11.12.2010
comment
Хм.. това може да свърши работа. Има ли някакъв начин да го направя така, че да не се налага всъщност да отварям манипулатор на целевия процес? (не мога да направя това със системния процес, например) - person Billy ONeal; 13.12.2010
comment
@Billy: Не съм сигурен. Вярвам, че Process Explorer всъщност използва драйвер за режим на ядрото за някои от функциите си, така че може би това е един от тези моменти..? - person Dean Harding; 14.12.2010
comment
Заобикаляйки го, като извикате NtQuerySystemInformation с класа SystemModuleInformation -- ще се свържа с вас с това, което измислих. - person Billy ONeal; 15.12.2010

Можете да използвате GetModuleHandleEx с флага GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS за да получите манипулатор на модул с даден адрес. След това можете да използвате GetModuleBaseName, за да получите име на модула.

Редактиране: Вероятно ще искате да използвате и флага GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, така че да не увеличавате броя на препратките на модула.

person Paul    schedule 11.12.2010
comment
GetModuleHandleEx не работи за отдалечени процеси. Поради това вашето предложение за използване на флага UNCHANGED_REFCOUNT също е неуместно... - person wj32; 11.12.2010

Можете да използвате този код, за да получите манипулатор на модула (по-бърз е от GetModuleHandleEx< /strong>) и след това извикайте GetModuleBaseName .

HMODULE GetCallingModule( LPCVOID pCaller ) const
{
    HMODULE hModule = NULL;
    MEMORY_BASIC_INFORMATION mbi;
    if ( VirtualQuery(pCaller, &mbi, sizeof(MEMORY_BASIC_INFORMATION)) == sizeof(MEMORY_BASIC_INFORMATION) )
    {
        // the allocation base is the beginning of a PE file 
        hModule = (HMODULE) mbi.AllocationBase;
    }
    return hModule;
}
person KindDragon    schedule 07.03.2011
comment
@KindDragon: изисква VirtualQueryEx да работи между процеси и дори тогава изисква съответния манипулатор на процеса. Добър трик е обаче да получите HINSTANCE hInstance, като потърсите MEMORY_BASIC_INFORMATION::AllocationBase на статична променлива във вашия собствен процес. Но това е необходимо само ако избягвате шаблонен CRT код или така... - person 0xC0000022L; 27.03.2016