Просмотр полной версии : Collection: Asm-Algorithms
Asm-Алгоритмы
Описание: Этот thread представляет из себя сборник интересных, полезных, а также просто часто требующихся функций, написанных на ассемблере.
Условие: Сюда добавляете только те функции, которые использовались, были оптимизированы вами, или же очень вас заинтересовали.
Формат: Придерживайтесь формата, каждый новый алгоритм в новом посте, название алгоритма повторяйте в заголовке:
Алгоритм: Название алгоритма
Синтаксис: fasm/masm/nasm/...
Описание: Что делает дынный алгоритм
Коментарий: Что вы думаете о нём/его реализации
Пример вызова:
Достаточный код, чтоб его проверить
Код:
Код самой функции
Внимание: Если есть какието замечания, например по безопасности
Вопрос: Для чего придерживаться формата?
Ответ: В поиске по теме очень удобно отображается кажрый пост, попробуйте и сами убедитесь.
Алгоритм: Base64 Encode
Синтаксис: fasm
Описание: rfc2045.txt
Коментарий: Вот решил переписать алгоритм по своему, оптимизировать и т.д. после этого у меня сложилось впечатление что автор разработавший его смутно представлял основы написания програм на ассемблере, можно было сделать его намного быстрее, кстати кто нибудь задумывался что результат кодирования участка данных длиной пропорциональной выражению x*2 имеет 3 синонима, а x*2+1 целых 15, для примера выполни эту команду perl -e "print'OK'if(decode_base64('bWU=')eq decode_base64('bWX='));"
Пример вызова:
format PE GUI 4.0
entry start
include 'win32a.inc'
data import
library USER32,'USER32.DLL'
import USER32,MessageBoxA,'MessageBoxA'
end data
include 'utils.inc'
start:
stdcall bin2base64, bin, bin.len, chrset, buf
ret
chrset db 'ABCDEFGHIJKLMNOP'
db 'QRSTUVWXYZabcdef'
db 'ghijklmnopqrstuv'
db 'wxyz0123456789+/'
bin db 'This is my data'
.len = $ - bin
buf rb 256
Внимание: Длина буфера должна быть больше длины кодируемых данных в 4/3 раза c округлением в большую сторону + pad символ + символ конца строки, мы ведь не хотим переполнения буфера ;)
Код:
proc bin2base64, data, len, chrset, base
push edx
xchg esi, [data]
xchg ecx, [len]
xchg ebx, [chrset]
xchg edi, [base]
mov eax, ecx
xor edx, edx
lea ecx, [edx+3]
div ecx
mov ecx, eax
mov al, dl
ror eax, 16
.lop: lodsb
ror ax, 2
mov dl, al
and dl, 63
mov al, [edx+ebx]
stosb
rol ax, 10
lodsb
ror ax, 4
mov dl, al
and dl, 63
mov al, [edx+ebx]
stosb
rol ax, 12
lodsb
ror ax, 6
mov dl, al
and dl, 63
mov al, [edx+ebx]
stosb
rol ax, 6
mov dl, al
and dl, 63
mov al, [edx+ebx]
stosb
loop .lop
rol eax, 16
mov cx, ax
jcxz .sz
mov eax, '==' shl 16
lodsb
ror ax, 2
mov dl, al
and dl, 63
mov al, [edx+ebx]
dec cx
jnz @f
shr ah, 2
mov dl, ah
mov ah, [edx+ebx]
stosd
jmp .sz
@@: stosb
shr eax, 8
shl ax, 2
lodsb
ror ax, 4
and al, 63
mov dl, al
and dl, 63
mov al, [edx+ebx]
shr ah, 2
mov dl, ah
mov ah, [edx+ebx]
stosd
.sz: xor eax, eax
stosb
.lnd: pop edx
mov esi, [data]
mov ecx, [len]
mov ebx, [chrset]
mov edi, [base]
ret
endp
Алгоритм: try except endt
Синтаксис: fasm
Описание: Обработка исключений в fasm
Коментарий: При переходе с делфи на ассемблер мне очень нехватало обработки исключений, вот я её и сделал, по образу и подобию стандартного макроса if else endif.
Пример вызова:
format PE GUI 4.0
entry start
include 'win32w.inc'
data import
library USER32,'USER32.DLL'
import USER32,MessageBoxA,'MessageBoxA'
end data
include 'try.inc'
proc start
try
try
try
push eax
push eax
push eax
xor eax, eax
push eax
push eax
push eax
push dword[eax]
except
invoke MessageBoxA, 0, err2, err2, 0
endt
int3
endt
int3
except
invoke MessageBoxA, 0, err1, err1, 0
endt
ret
endp
TryProc
err1 db 'Error in block 1',0
err2 db 'Error in block 2',0
Код:
include 'macro/proc32.inc'
macro SetHandler
{ push TryHandler
push dword[fs:0]
mov [fs:0], esp
push __EXCEPT
push ebp }
macro UnsetHandler
{ pop dword[fs:0]
add esp, 4 }
macro try
{ __TRY equ
local ..endt
__ENDT equ ..endt
local ..except
__EXCEPT equ ..except
SetHandler }
macro except
{ add esp, 8
UnsetHandler
jmp __ENDT
__EXCEPT:
UnsetHandler
restore __TRY
__TRY equ , }
macro endt
{ if __TRY eq
add esp, 8
__EXCEPT:
UnsetHandler
end if
__ENDT:
restore __EXCEPT
restore __ENDT
restore __TRY }
macro TryProc
{ proc TryHandler, ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext
push esi edi ebx
mov esi, [EstablisherFrame]
mov edi, [ContextRecord]
mov ebx, esi
sub esi, 8
add edi, $B4
movsd ; ebp
lodsd
xchg [edi], eax
;movsd ; eip
mov [edi+12], ebx ; esp
mov [edi-8], eax ; esp
pop ebx edi esi
xor eax, eax
ret
endp }
if noinit eq
else
TryProc
end if
*Сделаны исправления
Алгоритм: fmem (Fill memory)
Синтаксис: fasm
Описание: Заполнение участка памяти байтом, указоным в третьем параметре
Коментарий: В общем, это альтернатива функции zeromem, если в третий параметор поместить 0, работоспособность ничуть не снизится, а даже повысется из-за придельной оптимизации, а так как в этот параметор можно помещять не только 1 байт, можно немного по импровизировать с форматом заполнения. Какие только извращённые алгоритмы я не встречал, для выполнения этой элементарнейшей задачи, бывали даже в пять раз длиннее представленного мной кода, больше вам не придётся извращятся над этим алгоритмом, он оптимизирован до примела. Кстати он не затирает не один регистр, даже eax.
Пример вызова:
format PE GUI 4.0
entry start
include 'win32a.inc'
start:
stdcall fmem, buf, 11, 0
stdcall fmem, buf, 21, 'aaaa' ; Нужно указывать 4 'a' !
ret
buf db '2yt2i3uy4t5234t5ywgejhfvjrvbxau4vufv3db4tgvrjwqyt 4fvbejsdyqwtfvbeudrweq'
Код:
proc fmem, mem, len, byte
xchg edi, [mem]
xchg ecx, [len]
xchg eax, [byte]
shr ecx, 1
jnc @f
stosb
@@: shr ecx, 1
jnc @f
stosw
@@: rep stosd
xchg edi, [mem]
xchg ecx, [len]
xchg eax, [byte]
ret
endp
Алгоритм: md5 hashing algo
Синтаксис: masm
Описание: "экономи4еская" реализация алгоритма хэширования md5
Код:
.686
.model flat,stdcall
option casemap:none
.data?
MD5HashBuf db 64 dup(?)
MD5Digest dd 4 dup(?)
MD5Len dd ?
MD5Index dd ?
.code
MD5FF macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwD
and edi,dwB
xor edi,dwD
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm
MD5GG macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwB
and edi,dwD
xor edi,dwC
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm
MD5HH macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwC
xor edi,dwD
xor edi,dwB
add dwA,[locX]
lea dwA,[dwA+edi+constAC]
rol dwA,rolS
add dwA,dwB
endm
MD5II macro dwA, dwB, dwC, dwD, locX, rolS, constAC
mov edi,dwD
xor edi,-1
or edi,dwB
xor edi,dwC
add dwA,[locX]
lea dwA,[edi+dwA+constAC]
rol dwA,rolS
add dwA,dwB
endm
align dword
MD5Transform proc
pushad
mov esi,offset MD5Digest
mov edi,offset MD5HashBuf
mov eax,[esi+0*4]
mov ebx,[esi+1*4]
mov ecx,[esi+2*4]
mov ebp,edi
mov edx,[esi+3*4]
;================================================= =============
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 0*4], 7, 0D76AA478H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 1*4], 12, 0E8C7B756H
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 17, 0242070DBH
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 3*4], 22, 0C1BDCEEEH
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 4*4], 7, 0F57C0FAFH
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 5*4], 12, 04787C62AH
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 17, 0A8304613H
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 7*4], 22, 0FD469501H
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 8*4], 7, 0698098D8H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 9*4], 12, 08B44F7AFH
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+10*4], 17, 0FFFF5BB1H
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+11*4], 22, 0895CD7BEH
MD5FF eax, ebx, ecx, edx, dword ptr [ebp+12*4], 7, 06B901122H
MD5FF edx, eax, ebx, ecx, dword ptr [ebp+13*4], 12, 0FD987193H
MD5FF ecx, edx, eax, ebx, dword ptr [ebp+14*4], 17, 0A679438EH
MD5FF ebx, ecx, edx, eax, dword ptr [ebp+15*4], 22, 049B40821H
;================================================= =============
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 1*4], 5, 0F61E2562H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 6*4], 9, 0C040B340H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+11*4], 14, 0265E5A51H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 0*4], 20, 0E9B6C7AAH
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 5*4], 5, 0D62F105DH
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+10*4], 9, 002441453H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+15*4], 14, 0D8A1E681H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 4*4], 20, 0E7D3FBC8H
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 9*4], 5, 021E1CDE6H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+14*4], 9, 0C33707D6H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 14, 0F4D50D87H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 8*4], 20, 0455A14EDH
MD5GG eax, ebx, ecx, edx, dword ptr [ebp+13*4], 5, 0A9E3E905H
MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 2*4], 9, 0FCEFA3F8H
MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 14, 0676F02D9H
MD5GG ebx, ecx, edx, eax, dword ptr [ebp+12*4], 20, 08D2A4C8AH
;================================================= =============
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 5*4], 4, 0FFFA3942H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 8*4], 11, 08771F681H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+11*4], 16, 06D9D6122H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+14*4], 23, 0FDE5380CH
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 1*4], 4, 0A4BEEA44H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 4*4], 11, 04BDECFA9H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 16, 0F6BB4B60H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+10*4], 23, 0BEBFBC70H
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+13*4], 4, 0289B7EC6H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 0*4], 11, 0EAA127FAH
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 16, 0D4EF3085H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 6*4], 23, 004881D05H
MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 9*4], 4, 0D9D4D039H
MD5HH edx, eax, ebx, ecx, dword ptr [ebp+12*4], 11, 0E6DB99E5H
MD5HH ecx, edx, eax, ebx, dword ptr [ebp+15*4], 16, 01FA27CF8H
MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 2*4], 23, 0C4AC5665H
;================================================= =============
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 0*4], 6, 0F4292244H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 7*4], 10, 0432AFF97H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+14*4], 15, 0AB9423A7H
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 5*4], 21, 0FC93A039H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+12*4], 6, 0655B59C3H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 3*4], 10, 08F0CCC92H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+10*4], 15, 0FFEFF47DH
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 1*4], 21, 085845DD1H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 8*4], 6, 06FA87E4FH
MD5II edx, eax, ebx, ecx, dword ptr [ebp+15*4], 10, 0FE2CE6E0H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 15, 0A3014314H
MD5II ebx, ecx, edx, eax, dword ptr [ebp+13*4], 21, 04E0811A1H
MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 4*4], 6, 0F7537E82H
MD5II edx, eax, ebx, ecx, dword ptr [ebp+11*4], 10, 0BD3AF235H
MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 15, 02AD7D2BBH
MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 9*4], 21, 0EB86D391H
;================================================= =============
add [esi+0*4],eax ; update digest
add [esi+1*4],ebx
add [esi+2*4],ecx
add [esi+3*4],edx
popad
retn
MD5Transform endp
MD5BURN macro
xor eax,eax
mov MD5Index,eax
mov edi,Offset MD5HashBuf
mov ecx,(sizeof MD5HashBuf)/4
rep stosd
endm
align dword
MD5Init proc uses edi
xor eax, eax
mov MD5Len,eax
MD5BURN
mov eax,offset MD5Digest
mov dword ptr [eax+0*4],067452301h
mov dword ptr [eax+1*4],0EFCDAB89h
mov dword ptr [eax+2*4],098BADCFEh
mov dword ptr [eax+3*4],010325476h
ret
MD5Init endp
align dword
MD5Update proc uses esi edi ebx lpBuffer:dword, dwBufLen:dword
mov ebx,dwBufLen
mov esi,lpBuffer
add MD5Len,ebx
.while ebx
mov eax,MD5Index
mov ecx,64
sub ecx,eax
lea edi,[MD5HashBuf+eax]
.if ecx <= ebx
sub ebx,ecx
rep movsb
call MD5Transform
MD5BURN
.else
mov ecx,ebx
rep movsb
add MD5Index,ebx
.break
.endif
.endw
ret
MD5Update endp
align dword
MD5Final proc uses esi edi
mov ecx, MD5Index
mov byte ptr [MD5HashBuf+ecx],80h
.if ecx >= 56
call MD5Transform
MD5BURN
.endif
mov eax,MD5Len
xor edx,edx
shld edx,eax,3
shl eax,3
mov dword ptr [MD5HashBuf+56],eax
mov dword ptr [MD5HashBuf+60],edx
call MD5Transform
mov eax,offset MD5Digest
ret
MD5Final endp
end
Алгоритм: 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 ниже в архиве, мучийте свой компилятор на здоровье :D
Updates:
- Добавлена относительность имён загружаемых библиотек
- возможность импорта по ордилалу
- исправле недочёт(по вине этих грёбаных писателей MSDN) с возможным не совпадением количества функций с количеством их имён.
Алгоритм: Get Command Line Arguments
Синтаксис: fasm
Описание: Самая частоиспользуемая функция после импортера. При написании какой нибудь маленькой консольной(и не только) утилиты, бывает очень нужно получить аргументы коммандной строки.
Змечания: Данная функция защищена от переполнения, указываемая в последним аргументе длина указывается включая нулевой окончательный символ. Если длина 4, в буффер поместятся только 3 символа аргумента и 1 конца строки. В eax возвращается длина полученого аргумента, если его не нашлось, возвращасется 0, при этом в буффер ничего не записывается, так что можно предопределять аргументы.
Пример вызова:
format PE GUI 4.0
entry start
include 'win32a.inc'
include 'ulils.inc'
myi:
iprc LoadLibraryA, 'LoadLibraryA',\
GetCommandLineA,'GetCommandLineA'
imod user, 'user32'
iprc MessageBoxA, 'MessageBoxA'
endi
istr user
start:
stdcall importer, [esp+4], myi
stdcall GetCommandLineA
mov [arg], eax
stdcall GetArg, [arg], 1, Message, 64
stdcall MessageBoxA, 0, Message, tit1, 0
stdcall GetArg, [arg], 2, Message, 64
stdcall MessageBoxA, 0, Message, tit2, 0
ret
arg dd ?
tit1 db 'Arg number 1',0
tit2 db 'Arg number 2',0
Message db 64 dup(?)
proc GetArg, line, num, buf, len
xchg esi, [line]
xchg edi, [buf]
xchg ecx, [num]
dec [len]
jecxz .cur
.lp1: lodsb
or al, al
jz .ret
cmp al, '"'
jne .nq1
.lp2: lodsb
or al, al
jz .ret
cmp al, '"'
jne .lp2
lodsb
or al, al
jz .ret
cmp al, '"'
je .lp2
.nq1: cmp al, ' '
jne .lp1
@@: lodsb
cmp al, ' '
je @b
dec esi
loop .lp1
.cur: mov ecx, [len]
.lp3: lodsb
or al, al
jz .end
.chs: cmp al, ' '
je .end
cmp al, '"'
jne .nq2
.gq2: lodsb
or al, al
jz .ret
cmp al, '"'
jne .gq1
.nq2: stosb
loop .lp3
.end: mov eax, [len]
sub eax, ecx
jz .ret
mov byte[edi], 0
inc edi
.ret: mov esi, [line]
mov edi, [buf]
mov ecx, [num]
ret
.lp4: lodsb
or al, al
jz .ret
cmp al, '"'
jne .gq1
lodsb
or al, al
jz .ret
cmp al, '"'
jne .chs
.gq1: stosb
loop .lp4
jmp .end
.err: xor eax, eax
jmp .ret
endp
Updates: Теперь игнорирует повторяющиеся пробелы между аргументами
Алгоритм: dup export file to fasm dd table
Синтаксис: delphi -> fasm
Описание:
данная процедурка(delphi) генерит таблицу смещений и пат4ей по экспортируемому DUPом файлу такого вида:
RAW Offset | Old Byte | New Byte
-----------------+----------+----------
00000149 20 30
000001F6 00 12
00000217 60 E0
0000023C 40 20
0000023F 40 E0
00000246 00 12
00000264 40 20
и сохраняет в удобном для использования в fasm'е
Offsets dd 0x00000149, 0x000001F6, 0x00000217, 0x0000023C, 0x0000023F
dd 0x00000246, 0x00000264
Patch db 0x30, 0x12, 0xE0, 0x20, 0xE0, 0x12, 0x20
Очень полезно при создании пат4ей, лоадеров с большим коли4естов байт для пат4а, которые вру4ную вводить утомительно.
Пример вызова:
procedure make_fasm_patch_table(dup_filename, offsets, pat4es: string);
var
f, offs, patches: textfile;
s, temp: string;
i: integer;
begin
assignfile(f, dup_filename);
assignfile(offs, offsets);
assignfile(patches, pat4es);
rewrite(offs);
rewrite(patches);
reset(f);
readln(f, s); //skip dup banner
readln(f, s);
i :=0;
write(offs, 'Offsets dd ');
write(patches, 'Patch db ');
while not eof(f) do
begin
readln(f, s);
inc(i);
temp := '0x' + copy(s, 6, 8)+', ';
if i mod 7 <> 0 then
write(offs, temp) else
begin
writeln(offs, copy(temp, 1, length(temp)-2));
write(offs, ' dd ');
end;
temp := '0x' + copy(s, 34, 2)+', ';
if i mod 15 <> 0 then
write(patches, temp) else
begin
writeln(patches, copy(temp, 1, length(temp)-2));
write(patches, ' db ');
end;
end;
closefile(f);
closefile(offs);
closefile(patches);
end;
Алгоритм: RC4 cipher
Описание: потоковое шифрование\дешифрование
Код: В
INCLUDE MISC.INC
MODULE RC4
PUBLIC _rc4expandKey, _rc4crypt
DATA
; The RC4 keying information
rc4key DB 256 DUP (?)
rc4x DB 0
rc4y DB 0
CODE
; void rc4ExpandKey( unsigned char const *key, int keylen )
_rc4expandKey PROCEDURE
push bp
mov bp, sp
push si
push di ; Save register vars
les si, [bp+4] ; ES:SI = key
mov dx, [bp+8] ; DX = keylen
mov dh, dl ; keylenTmp = keylen
; rc4word y = 0;
xor ax, ax ; y = 0
sub di, di ; DI = AX as an index register
; for( x = 0; x < 256; x++ )
; rc4key[ x ] = x;
xor bx, bx ; x = 0
@@initLoop:
mov rc4key[bx], bl ; rc4key[ x ] = x
inc bl ; x++
jnz SHORT @@initLoop
; for( x = 0; x < 256; x++ )
; {
; sx = rc4key[ x ];
; y += sx + key[ keypos ];
; rc4key[ x ] = rc4key[ y ];
; rc4key[ y ] = sx;
;
; if( ++keypos == keylen )
; keypos = 0;
; }
@@keyLoop:
mov cl, rc4key[bx] ; sx = rc4key[ x ]
add al, es:[si] ; y += key[ keypos ]
add al, cl ; y += sx
mov di, ax
mov ch, rc4key[di] ; temp = rc4key[ y ]
mov rc4key[bx], ch ; rc4key[ x ] = temp
mov rc4key[di], cl ; rc4key[ y ] = sx
inc si ; ++keypos
dec dh ; keylenTmp--
jnz SHORT @@noResetKeypos ; if( !keylenTmp )
sub si, dx ; keypos = 0
mov dh, dl ; keylenTmp = keylen
@@noResetKeypos:
inc bl ; x++
jnz SHORT @@keyLoop
; rc4->x = rc4->y = 0;
mov rc4x, bl ; rc4->x = 0
mov rc4y, bl ; rc4->y = 0
pop di
pop si ; Restore register vars
pop bp
ret
_rc4expandKey ENDP
; void rc4Crypt( unsigned char *data, int len )
_rc4crypt PROCEDURE
push bp
mov bp, sp
push si
push di ; Save register vars
les si, [bp+4] ; ES:SI = data
mov dx, [bp+8] ; DX = len
test dx, dx ; Check that len != 0
jz SHORT @@exit ; Yes, exit now
xor bx, bx
mov bl, rc4x ; BX = rc4x
xor ax, ax
mov al, rc4y ; AX = rc4y
xor di, di ; DI = AX as an index register
; while( len-- )
; {
; x++;
; sx = rc4key[ x ];
; y += sx;
; sy = rc4key[ y ];
; rc4key[ y ] = sx;
; rc4key[ x ] = sy;
; *data++ ^= rc4key[ ( sx + sy ) & 0xFF ];
; }
@@rc4loop:
inc bl ; x++
mov cl, rc4key[bx] ; sx = rc4key[ x ]
add al, cl ; y += sx
mov di, ax
mov ch, rc4key[di] ; sy = rc4key[ y ]
mov rc4key[di], cl ; rc4key[ y ] = sx
mov rc4key[bx], ch ; rc4key[ x ] = sy
add cl, ch
xor ch, ch
mov di, cx ; temp = ( sx + sy ) & 0xFF
mov cl, rc4key[di]
xor es:[si], cl ; *data ^= rc4key[ temp ]
inc si ; data++
dec dx ; len--
jnz SHORT @@rc4loop
mov rc4x, bl
mov rc4y, al ; Remember x and y values
@@exit:
pop di
pop si ; Restore register vars
pop bp
ret
_rc4crypt ENDP
ENDMODULE
!_filin_!
25.05.2007, 16:47
Алгоритм: Генератор случайных чисел
Синтаксис: fasm/masm
Описание: Генератор случайных чисел, достаточно быстрый основан на сдвигах.
Пример вызова:
srand_init proc near; инициализирует кольцевой буфер для генератора, ВХОД:EAX начальное значение например из области данных BIOS
push bx
push si
push edx
mov edx,1
; засеять кольцевой буфер
mov bx, 216
do_0: mov word ptr ablex[bx], dx
sub eax,edx
xchg eax, edx
sub bx,4
jge do_0
;разогреть генератор
mov bx,216
do_1: push bx
do_2: mov si,bx
add si,120
cmp si,216
jbe skip
sub si, 216
skip: mov eax, dword ptr tablex[bx]
sub eax dword ptr tablex[si]
mov dword ptr tablex[bx], eax
sub bx,4
jge do_2
pop bx
sub bx,4
jge do_1
; инициализировать индексы
sub ax,ax
mov word ptr index0,ax
mov ax,124
mov index1, ax
pop edx
pop si
pop bx
ret
srand_init endp
Алгоритм: adler32
Синтаксис: masm
Описание: оптимизированный алгоритм вычисления контрольных сумм adler32.
Код:
.686
.model flat,stdcall
option casemap:none
.const
ADLER32_BASE equ 65521
ADLER32_NMAX equ 5552
.code
align dword
Adler32 proc uses edi esi ebx lpBuffer:DWORD, dwBufLen:DWORD, dwAdler:DWORD
mov eax,dwAdler
mov ecx,dwBufLen
mov ebx,dwAdler
and eax,0FFFFh
shr ebx,16
mov esi,lpBuffer
jmp @F
.repeat
mov edi,ADLER32_NMAX
.if ecx<edi
mov edi,ecx
.endif
sub ecx,edi
.repeat
movzx edx,byte ptr [esi]
add eax,edx
inc esi
add ebx,eax
dec edi
.until ZERO?
mov edi,ADLER32_BASE
xor edx,edx
div edi
push edx
mov eax,ebx
sub edx,edx
div edi
mov ebx,edx
pop eax
@@:
test ecx,ecx
.until ZERO?
shl ebx,16
add eax,ebx
ret
Adler32 endp
end
Алгоритм: Реализация агоритма sha-1
Синтаксис: masm
Описание: оптимизированный алгоритм sha-1
Комментарий: самая вменяемая реализация из всех мне встречавшихся.
Код:
.686
.model flat,stdcall
option casemap:none
.data?
SHA1HashBuf db 64 dup(?)
SHA1Len dd ?
SHA1Index dd ?
SHA1Digest dd 5 dup(?)
.code
SHA1F0 macro dwA, dwB, dwC, dwD, dwE, locX, constAC
mov edi, dwC
xor edi, dwD
and edi, dwB
xor edi, dwD
lea dwE, [dwE + constAC + edi]
rol dwB, 30
mov edi, dwA
rol edi, 05
add dwE, [locX]
add dwE, edi
ENDM
SHA1F1 macro dwA, dwB, dwC, dwD, dwE, locX, constAC
mov edi, dwC
xor edi, dwD
xor edi, dwB
lea dwE, [dwE + constAC + edi]
rol dwB, 30
mov edi, dwA
rol edi, 05
add dwE, [locX]
add dwE, edi
ENDM
SHA1F2 macro dwA, dwB, dwC, dwD, dwE, locX, constAC
mov edi,dwB
or edi,dwC
and edi,dwD
mov ebp,edi
mov edi,dwB
and edi,dwC
or edi,ebp
lea dwE,[dwE + constAC + edi]
rol dwB,30
mov edi,dwA
rol edi,05
add dwE,[locX]
add dwE,edi
ENDM
SHA1F3 macro dwA, dwB, dwC, dwD, dwE, locX, constAC
mov edi,dwC
xor edi,dwD
xor edi,dwB
lea dwE,[dwE + constAC + edi]
rol dwB,30
mov edi,dwA
rol edi,05
add dwE,[locX]
add dwE,edi
endm
align dword
SHA1Transform proc
pushad
SHA1locals equ 80*4
sub esp,SHA1locals
SHA1W equ dword ptr [esp]
mov edi,offset SHA1HashBuf
xor ebx,ebx
.repeat
mov eax,[edi+ebx*4]
mov ecx,[edi+ebx*4+4]
mov edx,[edi+ebx*4+32]
mov esi,[edi+ebx*4+32+4]
bswap eax
bswap edx
bswap ecx
bswap esi
mov SHA1W[ebx*4],eax
mov SHA1W[ebx*4+4],ecx
mov SHA1W[ebx*4+32],edx
mov SHA1W[ebx*4+32+4],esi
inc ebx
inc ebx
.until ebx==8
shl ebx,1
.repeat
mov eax,SHA1W[(4*ebx)-03*4]
mov edx,SHA1W[(4*ebx+4)-03*4]
xor eax,SHA1W[(4*ebx)-08*4]
xor edx,SHA1W[(4*ebx+4)-08*4]
xor eax,SHA1W[(4*ebx)-14*4]
xor edx,SHA1W[(4*ebx+4)-14*4]
xor eax,SHA1W[(4*ebx)-16*4]
xor edx,SHA1W[(4*ebx+4)-16*4]
rol eax,1
mov SHA1W[4*ebx],eax
rol edx,1
mov SHA1W[4*ebx+4],edx
inc ebx
inc ebx
.until ebx==80
mov edi,offset SHA1Digest
mov eax,[edi+0*4]
mov ebx,[edi+1*4]
mov ecx,[edi+2*4]
mov edx,[edi+3*4]
mov esi,[edi+4*4]
;================================================= =======
SHA1F0 eax, ebx, ecx, edx, esi, SHA1W[00*4], 05a827999h
SHA1F0 esi, eax, ebx, ecx, edx, SHA1W[01*4], 05a827999h
SHA1F0 edx, esi, eax, ebx, ecx, SHA1W[02*4], 05a827999h
SHA1F0 ecx, edx, esi, eax, ebx, SHA1W[03*4], 05a827999h
SHA1F0 ebx, ecx, edx, esi, eax, SHA1W[04*4], 05a827999h
SHA1F0 eax, ebx, ecx, edx, esi, SHA1W[05*4], 05a827999h
SHA1F0 esi, eax, ebx, ecx, edx, SHA1W[06*4], 05a827999h
SHA1F0 edx, esi, eax, ebx, ecx, SHA1W[07*4], 05a827999h
SHA1F0 ecx, edx, esi, eax, ebx, SHA1W[08*4], 05a827999h
SHA1F0 ebx, ecx, edx, esi, eax, SHA1W[09*4], 05a827999h
SHA1F0 eax, ebx, ecx, edx, esi, SHA1W[10*4], 05a827999h
SHA1F0 esi, eax, ebx, ecx, edx, SHA1W[11*4], 05a827999h
SHA1F0 edx, esi, eax, ebx, ecx, SHA1W[12*4], 05a827999h
SHA1F0 ecx, edx, esi, eax, ebx, SHA1W[13*4], 05a827999h
SHA1F0 ebx, ecx, edx, esi, eax, SHA1W[14*4], 05a827999h
SHA1F0 eax, ebx, ecx, edx, esi, SHA1W[15*4], 05a827999h
SHA1F0 esi, eax, ebx, ecx, edx, SHA1W[16*4], 05a827999h
SHA1F0 edx, esi, eax, ebx, ecx, SHA1W[17*4], 05a827999h
SHA1F0 ecx, edx, esi, eax, ebx, SHA1W[18*4], 05a827999h
SHA1F0 ebx, ecx, edx, esi, eax, SHA1W[19*4], 05a827999h
;================================================= =======
SHA1F1 eax, ebx, ecx, edx, esi, SHA1W[20*4], 06ed9eba1h
SHA1F1 esi, eax, ebx, ecx, edx, SHA1W[21*4], 06ed9eba1h
SHA1F1 edx, esi, eax, ebx, ecx, SHA1W[22*4], 06ed9eba1h
SHA1F1 ecx, edx, esi, eax, ebx, SHA1W[23*4], 06ed9eba1h
SHA1F1 ebx, ecx, edx, esi, eax, SHA1W[24*4], 06ed9eba1h
SHA1F1 eax, ebx, ecx, edx, esi, SHA1W[25*4], 06ed9eba1h
SHA1F1 esi, eax, ebx, ecx, edx, SHA1W[26*4], 06ed9eba1h
SHA1F1 edx, esi, eax, ebx, ecx, SHA1W[27*4], 06ed9eba1h
SHA1F1 ecx, edx, esi, eax, ebx, SHA1W[28*4], 06ed9eba1h
SHA1F1 ebx, ecx, edx, esi, eax, SHA1W[29*4], 06ed9eba1h
SHA1F1 eax, ebx, ecx, edx, esi, SHA1W[30*4], 06ed9eba1h
SHA1F1 esi, eax, ebx, ecx, edx, SHA1W[31*4], 06ed9eba1h
SHA1F1 edx, esi, eax, ebx, ecx, SHA1W[32*4], 06ed9eba1h
SHA1F1 ecx, edx, esi, eax, ebx, SHA1W[33*4], 06ed9eba1h
SHA1F1 ebx, ecx, edx, esi, eax, SHA1W[34*4], 06ed9eba1h
SHA1F1 eax, ebx, ecx, edx, esi, SHA1W[35*4], 06ed9eba1h
SHA1F1 esi, eax, ebx, ecx, edx, SHA1W[36*4], 06ed9eba1h
SHA1F1 edx, esi, eax, ebx, ecx, SHA1W[37*4], 06ed9eba1h
SHA1F1 ecx, edx, esi, eax, ebx, SHA1W[38*4], 06ed9eba1h
SHA1F1 ebx, ecx, edx, esi, eax, SHA1W[39*4], 06ed9eba1h
;================================================= =======
SHA1F2 eax, ebx, ecx, edx, esi, SHA1W[40*4], 08f1bbcdch
SHA1F2 esi, eax, ebx, ecx, edx, SHA1W[41*4], 08f1bbcdch
SHA1F2 edx, esi, eax, ebx, ecx, SHA1W[42*4], 08f1bbcdch
SHA1F2 ecx, edx, esi, eax, ebx, SHA1W[43*4], 08f1bbcdch
SHA1F2 ebx, ecx, edx, esi, eax, SHA1W[44*4], 08f1bbcdch
SHA1F2 eax, ebx, ecx, edx, esi, SHA1W[45*4], 08f1bbcdch
SHA1F2 esi, eax, ebx, ecx, edx, SHA1W[46*4], 08f1bbcdch
SHA1F2 edx, esi, eax, ebx, ecx, SHA1W[47*4], 08f1bbcdch
SHA1F2 ecx, edx, esi, eax, ebx, SHA1W[48*4], 08f1bbcdch
SHA1F2 ebx, ecx, edx, esi, eax, SHA1W[49*4], 08f1bbcdch
SHA1F2 eax, ebx, ecx, edx, esi, SHA1W[50*4], 08f1bbcdch
SHA1F2 esi, eax, ebx, ecx, edx, SHA1W[51*4], 08f1bbcdch
SHA1F2 edx, esi, eax, ebx, ecx, SHA1W[52*4], 08f1bbcdch
SHA1F2 ecx, edx, esi, eax, ebx, SHA1W[53*4], 08f1bbcdch
SHA1F2 ebx, ecx, edx, esi, eax, SHA1W[54*4], 08f1bbcdch
SHA1F2 eax, ebx, ecx, edx, esi, SHA1W[55*4], 08f1bbcdch
SHA1F2 esi, eax, ebx, ecx, edx, SHA1W[56*4], 08f1bbcdch
SHA1F2 edx, esi, eax, ebx, ecx, SHA1W[57*4], 08f1bbcdch
SHA1F2 ecx, edx, esi, eax, ebx, SHA1W[58*4], 08f1bbcdch
SHA1F2 ebx, ecx, edx, esi, eax, SHA1W[59*4], 08f1bbcdch
;================================================= =======
SHA1F3 eax, ebx, ecx, edx, esi, SHA1W[60*4], 0ca62c1d6h
SHA1F3 esi, eax, ebx, ecx, edx, SHA1W[61*4], 0ca62c1d6h
SHA1F3 edx, esi, eax, ebx, ecx, SHA1W[62*4], 0ca62c1d6h
SHA1F3 ecx, edx, esi, eax, ebx, SHA1W[63*4], 0ca62c1d6h
SHA1F3 ebx, ecx, edx, esi, eax, SHA1W[64*4], 0ca62c1d6h
SHA1F3 eax, ebx, ecx, edx, esi, SHA1W[65*4], 0ca62c1d6h
SHA1F3 esi, eax, ebx, ecx, edx, SHA1W[66*4], 0ca62c1d6h
SHA1F3 edx, esi, eax, ebx, ecx, SHA1W[67*4], 0ca62c1d6h
SHA1F3 ecx, edx, esi, eax, ebx, SHA1W[68*4], 0ca62c1d6h
SHA1F3 ebx, ecx, edx, esi, eax, SHA1W[69*4], 0ca62c1d6h
SHA1F3 eax, ebx, ecx, edx, esi, SHA1W[70*4], 0ca62c1d6h
SHA1F3 esi, eax, ebx, ecx, edx, SHA1W[71*4], 0ca62c1d6h
SHA1F3 edx, esi, eax, ebx, ecx, SHA1W[72*4], 0ca62c1d6h
SHA1F3 ecx, edx, esi, eax, ebx, SHA1W[73*4], 0ca62c1d6h
SHA1F3 ebx, ecx, edx, esi, eax, SHA1W[74*4], 0ca62c1d6h
SHA1F3 eax, ebx, ecx, edx, esi, SHA1W[75*4], 0ca62c1d6h
SHA1F3 esi, eax, ebx, ecx, edx, SHA1W[76*4], 0ca62c1d6h
SHA1F3 edx, esi, eax, ebx, ecx, SHA1W[77*4], 0ca62c1d6h
SHA1F3 ecx, edx, esi, eax, ebx, SHA1W[78*4], 0ca62c1d6h
SHA1F3 ebx, ecx, edx, esi, eax, SHA1W[79*4], 0ca62c1d6h
;================================================= =======
mov edi,offset SHA1Digest
add [edi+0*4],eax
add [edi+1*4],ebx
add [edi+2*4],ecx
add [edi+3*4],edx
add [edi+4*4],esi
add esp,SHA1locals
popad
ret
SHA1Transform endp
SHA1BURN macro
xor eax,eax
mov SHA1Index,eax
mov edi,Offset SHA1HashBuf
mov ecx,(sizeof SHA1HashBuf)/4
rep stosd
endm
align dword
SHA1Init proc uses edi
xor eax, eax
mov SHA1Len,eax
SHA1BURN
mov eax,offset SHA1Digest
mov dword ptr [eax+00],067452301h
mov dword ptr [eax+04],0efcdab89h
mov dword ptr [eax+08],098badcfeh
mov dword ptr [eax+12],010325476h
mov dword ptr [eax+16],0c3d2e1f0h
ret
SHA1Init endp
align dword
SHA1Update proc uses esi edi ebx lpBuffer:dword, dwBufLen:dword
mov ebx,dwBufLen
add SHA1Len,ebx
.while ebx
mov eax,SHA1Index
mov edx,64
sub edx,eax
.if edx <= ebx
lea edi, [SHA1HashBuf+eax]
mov esi, lpBuffer
mov ecx, edx
rep movsb
sub ebx, edx
add lpBuffer, edx
call SHA1Transform
SHA1BURN
.else
lea edi, [SHA1HashBuf+eax]
mov esi, lpBuffer
mov ecx, ebx
rep movsb
mov eax, SHA1Index
add eax, ebx
mov SHA1Index,eax
.break
.endif
.endw
ret
SHA1Update endp
align dword
SHA1Final proc uses esi edi
mov ecx, SHA1Index
mov byte ptr [SHA1HashBuf+ecx],80h
.if ecx >= 56
call SHA1Transform
SHA1BURN
.endif
mov eax,SHA1Len
xor edx,edx
shld edx,eax,3
shl eax,3
bswap edx; \
bswap eax; /
mov dword ptr [SHA1HashBuf+56],edx
mov dword ptr [SHA1HashBuf+60],eax
call SHA1Transform
mov eax,offset SHA1Digest
mov edx,[eax+0*4]
mov ecx,[eax+1*4]
mov esi,[eax+2*4]
mov edi,[eax+3*4]
bswap edx
bswap ecx
bswap edi
bswap esi
mov [eax+0*4],edx
mov [eax+1*4],ecx
mov [eax+2*4],esi
mov [eax+3*4],edi
mov edx,[eax+4*4]
bswap edx
mov [eax+4*4],edx
ret
SHA1Final endp
end
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot