ANTICHAT.RU    AUDIT.ANTICHAT.RU    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  

ВКонтакте\Одноклассники - Цены самые дешевые ,не упустите. Качественное продвижение.



Партнерка для SEOшников by ViKing. +15-40% к конверсии сайта. 50р за каждого пользователя!

Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Получение базы kernel32.dll
  #1  
Старый 09.12.2006, 12:55
Аватара для _Great_
_Great_
Флудер
Регистрация: 27.12.2005
Сообщения: 2,365
Провел на форуме:
2 месяца 1 день

Репутация: 476 ±



Отправить сообщение для  _Great_ с помощью ICQ
По умолчанию Получение базы kernel32.dll

Article: Получение базы kernel32.dll
Author: Great
Date: 09.12.2006
Note: В этой мини-статье я опишу устройство структур TEB,PEB и способы получения базы kernel32.dll. Предполагается знание читателем языков программирования C/C++, Assembler
/************************************************** *********************************************/

Многие задачи системного мирного и не очень программирования сталкиваются напрямую с задачей получения адреса базы kernel32.dll, ведь в ней находится большинство апишек, а точнее переходников к native api из ntdll.dll, которые в свою очередь обращаются к сервисам ядра из ntoskrnl.exe, нужных для функционирования программы. Если у тебя PE-файл, то проблем нет - дописал kernel32.dll в импорт и загрузчик сам ее подгрузит и даже адреса апишек выставит (биндинг не в счет). А вот если ты пишешь шеллкод или (и того хуже =)) вирь, то тут уже придется туго без kernel'а.
Для нахождения заветной базы существует много способов. Я вспомню три из них:
1) разбор стека только что запустившегося потока (для этого нужно вирю внедрить свой код в самое начало, либо поставить EntryPoint на свой код) - в стеке будет адрес возврата в kernel32.dll (в цепочку функции BaseProcessStart)
Код:
push ss:[esp] ; удваиваем в стеке адрес возврата в kernel32.BaseProcessStart, чтобы дать его как аргумент к GetBase call GetBase ; получаем базу ; теперь в EAX искомая база

2) анализ последнего SEH-обработчика, который опять же указывает куда-то в kernel32.dll
Кратко опишу реализацию метода. В TIB есть поле ExceptionList с линейным односвязанным списоком обработчиков SEH. Последний обработчик обязательно укажет в kernel32.dll, т.к. если никто исключение не перехватит, то управление пойдет в этот обработчик и он выдаст до боли знакомое окно "someprog.exe has encountered a problem and needs to close. We are sorry for the inconvenience."
Элементы списка - структуры ERR:
Код:
// SEH Handler typedef struct _ERR { _ERR* lpNext; DWORD lpHandler; } ERR, *PERR;

Функция получения TEB:
Код:
TEB * GetTEB() { __asm mov eax, fs:[18h]; #pragma warning(disable:4035) }


Ну а код для получения базы будет таким:
Код:
ERR* err = (ERR*)GetTEB()->Tib.ExceptionList; // Получаем список SEH while(err->lpNext!=(ERR*)-1) // ищем последний элемент списка err = err->lpNext; DWORD dwKernel32Base = GetBase( (void*)err->lpHandler ); // Получаем базу его обработчика - базу kernel32.dll


В этих двух случаях дальше пишется небольшая функция GetBase, которая берет адрес где-то в kernel32.dll, листает страницы назад, пока не наткнется на MZ и PE-заголовки, что будет означать, что она, наконец, дошла до базового адреса загрузки kernel32.dll.
Код:
void* GetBase(DWORD lpAddr) { for(lpAddr &= 0xFFFF0000 /* гранулярность выделения памяти */ ; ; lpAddr -= 0x10000 /* листаем назад страницами */) { if( ( ((IMAGE_DOS_HEADER*)lpAddr)->e_magic == 0x5a4d ) // MZ && ( ((IMAGE_NT_HEADERS*) ((DWORD)lpAddr + ((IMAGE_DOS_HEADER*)lpAddr)->e_lfanew) )->Signature == 0x00004550 ) // PE ) return (void*)lpAddr; // это заветная база } // Ни фига =( return NULL; }


Третий способ основан на том факте, что подавляющее большинство программ импортируют kernel32.dll и ее базу можно найти в списке модулей текущего процесса, который можно взять из Process Environment Block (PEB), адрес которого, в свою очередь, можно узнать из структуры Thread Environment Block (TEB), расположенной по адресу FS:[0]. Этот способ мы и рассмотрим детально, т.к. он представляет особый интерес и затраты на поиск базы у него существенно ниже.
В исходниках вирей можно найти следующий код для получения базы, реализующий этот способ:
Код:
void* asmGetKernelBase() {_asm{ xor eax, eax mov eax, fs:[eax+30h] test eax, eax js win9x push esi mov eax, [eax+0Ch] mov esi, [eax+1Ch] lodsd mov eax, [eax+8] pop esi leave ret win9x: mov eax, [eax+34h] add eax, 7Ch mov eax, [eax+3Ch] }}

С первого взгляда даже непонятно, что он делает. Если присмотреться, можно обнаружить, что сперва он обращается по адресу FS:[30] и берет оттуда двойное слово.
А что же там должно лежать? Ответ дает описание пользовательских структур - насчиная с FS:[0] располагается структура TEB, в которой есть указатель на PEB, а в ней есть указатель на структуры загрузчика.
В хидерах Windows Platform SDK структуры не документированы и большинство их полей обозваны обычно как BYTE Reserved[A];
Поэтому мы обратимся к хидерам React OS
TEB имеет много полей, и все они нам не понадобятся. Нас интересует эта часть структуры:
Код:
typedef struct _TEB { NT_TIB Tib; /* 00h */ PVOID EnvironmentPointer; /* 1Ch */ DWORD Cid[2]; /* 20h */ PVOID ActiveRpcInfo; /* 28h */ PVOID ThreadLocalStoragePointer; /* 2Ch */ PPEB Peb; /* 30h */ ULONG LastErrorValue; /* 34h */

Подструктура TIB досталась ей в наследство от Windows 9x, а вот поле PPEB Peb нам очень интересно - к нему то и обращается наша функция по команде mov eax, fs:[eax+30]. Тут лежит адрес структуры PEB в памяти.
Смотрим, как устроена PEB:
Код:
typedef struct _PEB { UCHAR InheritedAddressSpace; /* 00h */ UCHAR ReadImageFileExecOptions; /* 01h */ UCHAR BeingDebugged; /* 02h */ BOOLEAN SpareBool; /* 03h */ HANDLE Mutant; /* 04h */ PVOID ImageBaseAddress; /* 08h */ PPEB_LDR_DATA Ldr; /* 0Ch */

Остальные поля не представляют для нас интереса. Функция обращается к полю со смещением 0c - Ldr (в некоторых других вариантах оно называется LoaderData, в том числе и я буду использовать такое определение PEB). Это адрес структуры PEB_LDR_DATA:
Код:
typedef struct _PEB_LDR_DATA { ULONG Length; BOOLEAN Initialized; PVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, *PPEB_LDR_DATA;

В ней есть три кольцевых двусвязанных списка структур LDR_MODULE (иногда они называются LDR_DATA_TABLE_ENTRY):
InLoadOrderModuleList - список модулей в порядке загрузки
InMemoryOrderModuleList - список модулей в порядке расположения в памяти
InInitializationOrderModuleList - список модулей в порядке инициализации. Он-то нам и нужен, т.к. первые два элемента в нем ntdll и kernel32
Код:
typedef struct _LDR_MODULE { LIST_ENTRY ModuleList; PVOID BaseAddress; PVOID EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; ULONG Flags; SHORT LoadCount; SHORT TlsIndex; LIST_ENTRY HashTableEntry; ULONG TimeDateStamp; } LDR_MODULE, *PLDR_MODULE;

Поле BaseAddress нас как раз интересует.
В списке первой будет стоять ntdll.dll, а за ней будет kernel32.dll
Поэтому мы получаем голову списка через PEB_LDR_DATA.InInitializationOrderModuleList.Flink и делаем еще раз переход по Flink в следующему элементу списка.
Преобразовав указатель к типу LDR_MODULE*, мы получим указатель структуру описания kernel32.dll, где и будет ее база.

Сокращенная реализация на Си выглядит предельно просто:
Код:
void* GetKernel32Base() { TEB* teb; _asm { mov eax, fs:[18h] mov teb, eax } return ((PLDR_MODULE)teb->Peb->LoaderData->InInitializationOrderModuleList.Flink->Flink)->BaseAddress; }

Расскажу еще немного про устройство двусвязанных списков в Windows.
В файле winnt.h описана структура
Код:
typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, *PLIST_ENTRY, *RESTRICTED_POINTER PRLIST_ENTRY;

Это как бы абстрактное звено списка, т.к. структура содержит только указатели вперед и назад и никаких данных.
Список модулей на самом деле содержит структуры
Код:
typedef struct _LDR_MODULE { LIST_ENTRY ModuleList;

где ModuleList - два указателя вперед и назад, но в структуре еще есть и данные. Поэтому мы приводим указатель, полученный из Flink, к типу PLDR_MODULE.

Вот функция на С++, которая поможет лучше усвоить эти структуры - она проходит по всему списку модулей, выводя попутно на консоль его элементы (имя длл и база) и ищет kernel32.dll по имени (хоть она и всегда будет второй).
Код:
void* ListModules() { // Get TEB TEB* teb = GetTEB(); // Get PEB PEB* peb = teb->Peb; // Get PEB_LDR_DATA PPEB_LDR_DATA pldr = peb->LoaderData; // Get double-linked list of the modules // View in right direction PLDR_MODULE pentry; pentry = (PLDR_MODULE) pldr->InInitializationOrderModuleList.Flink; VOID* dwBase = 0; char buffer[1024]; // Walk the list do { // Print the name WideCharToMultiByte(CP_ACP, 0, pentry->BaseDllName.Buffer, -1, buffer, sizeof(buffer), 0, 0); printf("%s\t[0x%08x]\n", buffer, pentry->BaseAddress); // kernel32.dll found if(lstrcmpi(buffer, "kernel32.dll")==0) dwBase = pentry->BaseAddress; // Next pentry = (PLDR_MODULE)pentry->ModuleList.Flink; } while(pentry->ModuleList.Flink != pldr->InInitializationOrderModuleList.Flink); return dwBase; }


Скачать все описания структур: structures.h
NT_TIB входит в стандартные виндовые хидеры
*************

Я собрал несколько способов получения базы kernel32.dll вместе и один из них подробно расписал

Последний раз редактировалось _Great_, 09.12.2006 в 13:03.
 
Ответить с цитированием

  #2  
Старый 09.07.2008, 17:23
Аватара для gevara
gevara
Познающий
Регистрация: 30.11.2006
Сообщения: 49
Провел на форуме:
10 часов 7 минут 14 секунд

Репутация: 3 ±

По умолчанию

Искал в инете описание PEB, вот наткнулся на твой топик. хочу сказать, надеяться на то, что LDR_MODULE of kernel32 в связном списке будет вторым не стоит. сам столкнулся с этой проблемой.
 
Ответить с цитированием
Ответ


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Базы данных мобильных операторов. GaR1k[Sp] Сотовый фрикинг 7 27.03.2010 08:56
7 причин не напрягаться насчет базы данных МТС novichok Сотовый фрикинг 1 02.03.2006 15:32
Взломай базы данных и сделай популярный сайт Zaratustra Мировые новости. Обсуждения. 1 24.01.2006 15:03


Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра


Быстрый переход


Powered by: vBulletin Version 3.0.x
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.

ANTICHAT.RU