Просмотр полной версии : Получение базы kernel32.dll [Asm]
Вот решил провести эксперимент и написал (не без помощи сайтов) прогу (masm32), которая определяет адрес базы kernel32.dll:
.386
option casemap:none
.model flat, stdcall
;----------------------------include---------------------
includelib \masm32\lib\kernel32.lib
include \masm32\include\kernel32.inc
;--------------------------------------------------------
.data
db 0
.code
start:
mov esi, [esp]
call GetBase; после вызова в eax база kernel32.dll
invoke ExitProcess, 0
;#####################################GetBase##### ##########################
;
; Получение базы kernel32.dll
;
;################################################# ##########################
GetBase:
push esi;сохраняем все регистры, которые используются
push ecx
pushf;сохраняем регистр флагов
and esi,0FFFF0000H;гранулярность выделения памяти
mov ecx,6;счетчик страниц
_@1: ;проверка очередной страницы
cmp word ptr [esi], "ZM"
jz WeGotBase
_@2:
sub esi, 10000h
loop _@1
WeFailed:
mov eax, 00000000h ;база не найдена
jmp EndGetBase
WeGotBase:
xchg eax, esi
EndGetBase:
popf;восстанавливаем значения флагов
pop ecx
pop esi;восстанавливаем значения регистров
ret
;################################################# ########################
;Конец процедуры GetBase
;################################################# ########################
end start
В Windows XP SP3 я получил адрес базы 7C800000h в Windows 7 77140000h
Hiro Protagonist
20.01.2010, 23:30
cmp word ptr [esi], "ZM"
jz WeGotBase
после этого чекай на PE. А вообще байан редкостный. Тем более для dll не подходит.
cmp word ptr [esi], "ZM" - разве это не есть проверка на PE
спрашивается а нафига её искать методом поиска?
Если же можно тупо взять из PEB
Вариант с подмененным и неправильным PEB'ом можно расценивать как манию приследывания и последюю стадию шизофрении. Так что лучше юзать через PEB
Под 2k, XP, 2k3 ты получишь адрес kernel32.dll а под w7 - адрес KERNELBASE
KERNELBASE - это считай жалкий аналог kernel32.dll
Но есть хитрость. В них в обоих есть функции GetProcAddress и LoadLibraryExA
через который можно загрузить любую либу (хотябы туже kernel32 для w7)
Для всякого малвара своего юзаю примерно такую схему:
__declspec(naked) HMODULE GetKernel32(void)
{
__asm
{
push esi
xor eax,eax
mov eax,fs:[0x30]
js find_kernel_9x
mov eax,[eax+0x0c]
mov esi,[eax+0x1c]
lodsd
mov eax,[eax+0x8]
jmp find_kernel_end
find_kernel_9x:
mov eax,[eax+0x34]
lea eax,[eax+0x7c]
mov eax,[eax+0x3c]
find_kernel_end:
pop esi
ret
}
}
KERNELBASE = GetKernel32();
*(void* *)&_LoadLibraryExA = HideGetProcAddress(KERNELBASE, "LoadLibraryExA");
*(void* *)&_GetProcAddress = HideGetProcAddress(KERNELBASE, "GetProcAddress");
if (!_LoadLibraryExA || !_GetProcAddress) return 0;
kernel32_dll = _LoadLibraryExA("kernel32.dll", 0, 0);
итд итп.
HideGetProcAddress - самописная функция поиска адреса функции (когдато выкладывал тут её)
И пашет идеально на всей линейке NT начиная от 2k
Другое дело в ядре искать адрес загрузки ядра, Там это уже нужно осуществлять перебор.
Вот пример
mov esi, dword ptr ds:[0ffdff038h]; адрес обработчика для IDLE
lodsd
cdq
lodsd
base_loop:
dec eax
cmp dword ptr [eax], 00905a4dh ; сигнатура для файла ядра MZ+P+0x00
jnz base_loop
mov lib, eax
Но этот код очень удобно юзать под ядром. Вернее под ядром его тока и можно заюзать )
>>>> cmp word ptr [esi], "ZM" - разве это не есть проверка на PE
это проверка на дос заголовок. В досовских exe файлах и в старом LE нету PE заголовка )
Проверка на PE делается так
1) находится ImageBase и проверяется сигнатура MZ
2) ImageBase + 0x3С - по этому офсету хранится DWORD указывающий смещение (относительно ImageBase) на PE заголовок
3) ImageBase + офсет на PE и по этому адресу проверяется двойное слово
на сигнатуру 'P' 'E' 0x00 0x00
Hiro Protagonist
21.01.2010, 07:39
2slesh
жесть, зачем это делать ассемблерной вставкой? али влом структуры описывать и пользоваться макросами для LIST_ENTRY?
по старинке юзаю из шелкодов )
Но вообще некоторые операции без асм вставки будут некрасиво выглядеть. Допустим та же mov eax,fs:[0x30], которую придется заменить на соотвествующую апишку
Hiro Protagonist
21.01.2010, 12:51
дык понятно, я это тоже вставкой делаю. Но доступ то к полям пеба )))
mov esi,[eax+0x1c]
lodsd
mov eax,[eax+0x8]
зачем тут еsi?)
А ещё сравнил бы на всякий случай имя библиотеки
Hiro Protagonist
21.01.2010, 17:21
2desTiny
как зачем, а указать lodsd откуда грузить значение? Мы ж обращаемся ко второму LDR_MODULE_ENTRY в цепочке.
а проверять не нужно, там постоянно ntdll->kernel32->[user32]->...
mov esi,[eax+0x1c]
lodsd
~
mov eax, [eax+0x1c]
mov eax, [eax]
и нафиг не нужны эти первый пуш и последний поп
>> там постоянно
никто ничего не обещает. Вот если ты так уверен в порядке - ну-ка сходу скажи, где в цепочке будет kernelbase.dll?
как получать API? Сколько кода просмотрел нигде не нашел рабочего
почитай например http://www.phrack.com/issues.html?issue=62&id=7
Таких пару статей прочитьтать и на дурку )))
Hiro Protagonist
21.01.2010, 19:59
2desTiny
а зачем мне kernelbase.dll?
главное я чотко уверен, что под всей линейкой ntdll->kernel32. Остальное в принципе не интересно ) в данном случае. Поэтому проверять не надо.
>>главное я чотко уверен
А вот семёрке плевать на твою уверенность.
Hiro Protagonist
21.01.2010, 21:38
ладно, пойду семерку ставить на виртуалку и смотреть )
Для самоуверенных читать мой пост где я кинул кусок кода и там описал что и как.
И То что нужно искать там LoadLibraryExA/W потому что других подобных нету.
Это пришлось сделать именно из-за W7 потому как именно kernelbase там получалась а не kernel32.
Верно ли написан код получения GetProcAddress ? Вроде все как в туториале
.386
.model flat, stdcall
option casemap:none
includelib \masm32\lib\kernel32.lib
ExitProcess PROTO : DWORD
.data
db 0
ProcAd db "GetProcAddress",0h
Counter db 0h
OrdinalTableVA db 0h
AddressTableVA db 0h
Kernel db 0h
.code
start:
;считаем дельта смещение
call VirDelta
VirDelta:
sub dword ptr [esp], offset VirDelta
push dword ptr [esp]
;jmp ReadSEH
; Читаем SEH
ReadSEH:
xor edx, edx ; edx = 0
assume fs:flat
mov eax, fs:[edx] ; читаем элемент SEH
dec edx ; edx = 0FFFFFFFFh
; Ищем элемент со значением 0FFFFFFFFh
SearchKernel32:
cmp [eax], edx ; сравниваем очередной с 0FFFFFFFFh
je CheckKernel32 ; прыгаем, если нашли
mov eax, [eax] ; получаем следующее значение
jmp SearchKernel32 ; если не нашли - ищем дальше
; Определяем адрес Kernel32
CheckKernel32:
mov eax, [eax + 4] ; получаем адрес ГДЕ-ТО в
; kernel32.dll
xor ax, ax ; выравниваем полученный адрес
; Ищем сигнатуру MZ
SearchKernelMZ:
cmp word ptr [eax], 5A4Dh ; сверяем сигнатуру MZ
je CheckKernelMZ ; сигнатура верна, переходим на
; проверку сигнатуры PE
sub eax, 10000h ; если не равна MZ, то ищем дальше
jmp SearchKernelMZ
; Проверяем сигнатуру PE
CheckKernelMZ:
mov edx, [eax + 3Ch] ; переходим на PE-заголовок
cmp word ptr [eax + edx], 4550h ; сверяем сигнатуру
jne _Exit ; неверная сигнатура, поэтому
; выходим
call GetAPI
_Exit:
invoke ExitProcess, 0h
;поиск адреса GetProcessAddress
GetAPI:
mov edx, offset Kernel
mov [edx], eax
mov esi, offset ProcAd
mov edx, esi
@_1:
cmp byte ptr [esi], 0; конец строки?
jz @_2
inc esi
jmp @_1
@_2:
inc esi
sub esi, edx
mov ecx, esi
;;теперь в ecx и esi находится размер имени функции GetProcessAddress (12h символов)
mov ebx, eax
xor eax, eax
mov esi, ebx
add esi, 3Ch ;заголовок PE
lodsw
add eax, ebx
mov esi, [eax + 78h] ;RVA таблицы экспортов
add esi, ebx ;указатель на RVA таблицы адресов
add esi, 1ch
lodsd ;eax = RVA таблицы адресов
add eax, ebx ;eax VA таблицы адресов
mov edx, offset AddressTableVA
mov[edx], eax
;push eax ;сохраняем
lodsd ;eax = RVA таблицы указателей на имена
add eax, ebx ; eax = VA таблицы указателей на имена
push eax ;сохраняем
lodsd ;eax = RVA таблицы ординалов
add eax, ebx
mov edx, offset OrdinalTableVA
mov [edx], eax
;push eax
pop esi
@_3: push esi ;сохраняем VA таблицы указателей на имена
lodsd
add eax, ebx
mov esi, eax
mov edi, offset ProcAd
push ecx
cld
repe cmpsb
pop ecx
jz @_4
pop esi
add esi, 4
mov edx, [offset Counter]
inc edx
push ecx
mov ecx, offset Counter
mov [ecx], edx
pop ecx
jmp @_3
@_4:
pop esi
mov edx, offset Counter
mov eax, [edx]
shl eax, 1
mov edx, offset OrdinalTableVA
add eax, [edx]
shl eax, 2
mov edx, offset AddressTableVA
add eax, [edx]
mov edx, offset Kernel
add eax, [edx]
ret
end start
по идее в EAX должен остаться адрес этой функции...Сильно не ругайте за корявый код я только начал учить асму
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot