|
Постоянный
Регистрация: 23.04.2006
Сообщений: 622
Провел на форуме: 5887054
Репутация:
1292
|
|
Hash Importer
Алгоритм: Hash Importer
Синтаксис: fasm
Описание: Импортирует функции из модулей по ихним хэшам или номерам, при первом варианте они хешируются без учёта регистра макроинструкцией iprc, абсолютная вероятность неповторимости хэша сохраняется, только при условии, что длина имени не превышает 6 символов, не включает цифр и не зависит от регистра, тем не менее, количество вариантов настолько велико, что вероятность того что в одном модуле будут две функции одной и той-же длины и с одной и той-же хешью стремится к 0. Во время импортирования вычисляется дельта функций относительно мест, куда они будут сохранены, и сохраняются в виде относительных переходов(инструкция E9), также сохраняются и нэнделы проанализированных модулей. Всё это сохранённое добро доступно по указанным ссылкам. Установка флага AntiDebug включает проверку, если первая инструкция в импортированной функции mov edi, edi знацит пропустить эту инструкцию, что очень запутывает отладчик.
Комментарий: Макроинструкция istr содержит имена библиотек, её можно вынести в ReadOnly секцию. Да и готовые функции ProcIdByHash, ProcAddrById и BaseByAddr тоже иногда бывают полезны.
Змечания: В примере используется не invoke, a stdcall, т.к. invoke proc компилируется как call dword[proc] (вызов функции, адрес которой записан в переменной proc), а stdcall как call proc (вызов инструкции, по адресу proc), что позволяет использовать этот алгоритм в базонезависимых программах, так как call proc - relative call(Относительный вызов). Если используется подгрузка дополнительных модулей, то должна присутствовать функция LoadLibraryA, она может импортироваться из первого модуля(до подгрузки остальных) или же создана статически. Также можно создать функцию ImportErrProc, программа будет попадать на неё, при вызове функции которой не нашел импортер.
Результат работы:
Код:
до:
LoadLibraryA db $0C ; Длина LoadLibraryA
dd $9224447C ; Хэшь LoadLibraryA
db $FF ; Команда загрузить модуль
user dd $004010FC ; Адрес строки user.str содержащий имя модуля
db $0B ; Длина MessageBoxA
MessageBoxA dd $1E1EC3BC ; Хэшь MessageBoxA
db $FE ; Конец структуры
user.str db 'user32',0
после:
LoadLibraryA jmp kernel.LoadLibraryA ; E9 860C407C
db $FF ; Команда загрузить модуль
user dd user32.77D40000 ; 0000D477 - База user32
MessageBoxA jmp user32.MessageBoxA ; E9 EFF39777
db $FE ; Конец структуры
user.str db 'user32',0
Пример вызова:
Код:
format PE GUI 4.0
entry start
AntiDebug equ
include 'win32a.inc'
include 'utils.inc'
myi:
iprc LoadLibraryA, 'LoadLibraryA'
imod user, 'user32'
iprc MessageBoxA, 'MessageBoxA'
endi
istr user
tit db 'Message',0;
txt db 'Example of Hash importer',0
start:
stdcall BaseByAddr, [esp+4] ; or stdcall GetKernel without parametrs
stdcall importer, eax, myi
stdcall MessageBoxA, 0, txt, tit, 0
ret
Код:
macro iprc [proc, name]
{ forward
if used proc | proc eq LoadLibraryA
if name eqtype ''
local ch
local hash
local length
virtual at 0
db name
length = $
hash = 0
repeat length
load ch byte from length-%
hash = ((hash shl 5) or (hash shr (32 - 5))) and $FFFFFFFF ; hash = hash rol 5
hash = hash xor (ch and 11111b)
end repeat
end virtual
virtual at $
proc dd ?
end virtual
db length ; Length, if $ff then load lib, if $fe then end, if $fd then by id
dd hash
else
db $fd
dd name+1
end if
end if }
macro imod [module, str]
{ forward
db $fe
module dd module#.str - $
module#.text equ str }
macro istr [module]
{ forward
module#.str db module#.text, 0 }
macro endi ierrproc
{ db $ff }
struct IED
Characteristics dd ? ;This field appears to be unused and is always set to 0.
TimeDateStamp dd ? ;The time/date stamp indicating when this file was created.
Version dd ? ;These fields appear to be unused and are set to 0.
Name dd ? ;The RVA of an ASCIIZ string with the name of this DLL.
Base dd ? ;The starting ordinal number for exported functions. For example, if the file exports functions with ordinal values of 10, 11, and 12, this field contains 10. To obtain the exported ordinal for a function, you need to add this value to the appropriate element of the AddressOfNameOrdinals array.
NumberOfFunctions dd ? ;The number of elements in the AddressOfFunctions array. This value is also the number of functions exported by this module. Theoretically, this value could be different than the NumberOfNames field (next), but actually they're always the same.
NumberOfNames dd ? ;The number of elements in the AddressOfNames array. This value seems always to be identical to the NumberOfFunctions field, and so is the number of exported functions.
AddressOfFunctions dd ? ;This field is an RVA and points to an array of function addresses. The function addresses are the entry points (RVAs) for each exported function in this module.
AddressOfNames dd ? ;This field is an RVA and points to an array of string pointers. The strings are the names of the exported functions in this module.
AddressOfNameOrdinals dd ? ;This field is an RVA and points to an array of WORDs. The WORDs are the export ordinals of all the exported functions in this module. However, don't forget to add in the starting ordinal number specified in the Base field.
ends
proc ProcIdByHash, base, hash, len:byte
xchg edi, [base]
push ebx ecx edx esi
mov ebx, [edi+$3C] ; OffSet to PE Header
mov ebx, [edi+ebx+$78] ; Offset to Export section
push ebx
mov ecx, [edi+ebx+IED.NumberOfNames] ; NumberOfFunctions - Stupid MSDN writers, who have trying to import from ws2_32 that understend
mov ebx, [edi+ebx+IED.AddressOfNames]
add ebx, edi
.next:mov esi, [ebx+ecx*4-4]
add esi, edi
mov edx, [hash]
movzx eax, [len]
cmp byte[esi+eax], 0
jne .wrng
@@: lodsb
or al, al
jz @f
and al, 11111b
xor dl, al
ror edx, 5
jmp @b
@@: or edx, edx
jz .ret ; @f
.wrng:loop .next
xor eax, eax
jmp .end
.ret: pop ebx
mov eax, [edi+ebx+IED.AddressOfNameOrdinals]
add eax, edi
movzx eax, word[eax+ecx*2-2]
add eax, [edi+ebx+IED.Base]
.end: pop esi edx ecx ebx
mov edi, [base]
ret
endp
proc ProcAddrById, base, id
xchg edi, [base]
xchg ebx, [id]
mov eax, [edi+$3C] ; OffSet to PE Header
mov eax, [edi+eax+$78] ; Offset to Export section
sub ebx, [edi+eax+IED.Base]
mov eax, [edi+eax+IED.AddressOfFunctions]
add eax, edi
mov eax, [eax+ebx*4]
add eax, edi
mov ebx, [id]
mov edi, [base]
ret
endp
proc GetKernel
xor eax, eax
mov eax, [fs:eax+30h]
test eax, eax
js ngk
mov eax, [eax+0Ch]
mov esi, [eax+1Ch]
lodsd
mov eax, [eax+8]
jmp egk
ngk: mov eax, [eax+34h]
add eax, 7Ch
mov eax, [eax+3Ch]
egk: ret
endp
proc BaseByAddr, addr
mov eax, [addr]
xor ax, ax
@@: cmp word[eax], 'MZ'
jz @f
sub eax, $10000
jmp @b
@@: ret
endp
proc importer, kernel, imports
xchg esi, [imports]
xchg edi, [kernel]
;stdcall BaseByAddr, edi
;mov edi, eax
.loop:lodsb
cmp al, $fd
ja .more
je .byid
mov ah, al
or edi, edi
jz .xxx
stdcall ProcIdByHash, edi, [esi], [esi-1]
or eax, eax
if defined ImportErrProc
jnz @f
lea eax, [esi-ImportErrProc]
mov eax, errfunc
lodsd
jmp .stor
@@: else
jz .stor
display 'ImportErrProc is undefined',13,10
end if
.gbi: stdcall ProcAddrById, edi, eax
.stor:if AntiDebug eq
cmp word[eax], $FF8B
jnz @f
add eax, 2
@@: end if
sub eax, 4
@@: sub eax, esi
mov byte[esi-1], $E9
mov dword[esi], eax
.xxx: lodsd
jmp .loop
.byid:mov eax, [esi]
jmp .gbi
.more:cmp al, $ff
je .endi
lodsd
if defined LoadLibraryA
lea eax, [eax+esi-4]
stdcall LoadLibraryA, eax
mov edi, eax
mov [esi-4], eax
else
display 'LoadLibraryA is undefined',13,10
end if
jmp .loop
.endi:mov edi, [kernel]
mov esi, [imports]
ret
endp
Особые извращенцы над компилятором(шутка), могут воспользоваться таким способом импортирования функций, как приведён ниже. В некоторых случаях очень удобно, потому что, находит почти любую функцию которая может понадобится, хотя придётся немного(на моём примерно 0,9 seconds) подождать. Он не включает неиспользуемые функции, но он не проверяет, используется ли модуль, так что все модули включать не стоит, а-то он их все загрузит.
Код:
myi:
include '\imp\kernel32.inc'
include '\imp\ntdll.inc'
include '\imp\advapi32.inc'
include '\imp\comdlg32.inc'
include '\imp\gdi32.inc'
include '\imp\ole32.inc'
include '\imp\oleaut32.inc'
include '\imp\shell32.inc'
include '\imp\shlwapi.inc'
include '\imp\user32.inc'
endi
istr ntdll, advapi, comdlg, gdi, ole, oleaut, shell, shlwapi, user
А также все эти файлы, с выдранными функциями из данных модулей WindowsXP ниже в архиве, мучийте свой компилятор на здоровье
Updates:
- Добавлена относительность имён загружаемых библиотек
- возможность импорта по ордилалу
- исправле недочёт(по вине этих грёбаных писателей MSDN) с возможным не совпадением количества функций с количеством их имён.
Последний раз редактировалось hidden; 21.01.2007 в 19:31..
|