[size=+2]Asm-Алгоритмы[/size] Описание: Этот thread представляет из себя сборник интересных, полезных, а также просто часто требующихся функций, написанных на ассемблере. Условие: Сюда добавляете только те функции, которые использовались, были оптимизированы вами, или же очень вас заинтересовали. Формат: Придерживайтесь формата, каждый новый алгоритм в новом посте, название алгоритма повторяйте в заголовке: Code: [b[size=2]][/size]Алгоритм:[/b[size=2]][/size] Название алгоритма [b[size=2]][/size]Синтаксис:[/b[size=2]][/size] fasm/masm/nasm/... [b[size=2]][/size]Описание:[/b[size=2]][/size] Что делает дынный алгоритм [b[size=2]][/size]Коментарий:[/b[size=2]][/size] Что вы думаете о нём/его реализации [b[size=2]][/size]Пример вызова:[/b[size=2]][/size] [size=2][[/size]code] Достаточный код, чтоб его проверить[size=2][[/size]/code[size=2]][/size] [b[size=2]][/size]Код:[/b[size=2]][/size] [code[size=2]][/size] Код самой функции[size=2][[/size]/code[size=2]][/size] [b[size=2]][/size]Внимание:[/b[size=2]][/size] Если есть какието замечания, например по безопасности Вопрос: Для чего придерживаться формата? Ответ: В поиске по теме очень удобно отображается кажрый пост, попробуйте и сами убедитесь.
Base64 Encode Алгоритм: Base64 Encode Синтаксис: fasm Описание: rfc2045.txt Коментарий: Вот решил переписать алгоритм по своему, оптимизировать и т.д. после этого у меня сложилось впечатление что автор разработавший его смутно представлял основы написания програм на ассемблере, можно было сделать его намного быстрее, кстати кто нибудь задумывался что результат кодирования участка данных длиной пропорциональной выражению x*2 имеет 3 синонима, а x*2+1 целых 15, для примера выполни эту команду perl -e "print'OK'if(decode_base64('bWU=')eq decode_base64('bWX='));" Пример вызова: Code: 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 символ + символ конца строки, мы ведь не хотим переполнения буфера Код: Code: 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 Алгоритм: try except endt Синтаксис: fasm Описание: Обработка исключений в fasm Коментарий: При переходе с делфи на ассемблер мне очень нехватало обработки исключений, вот я её и сделал, по образу и подобию стандартного макроса if else endif. Пример вызова: Code: 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 Код: Code: 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) Алгоритм: fmem (Fill memory) Синтаксис: fasm Описание: Заполнение участка памяти байтом, указоным в третьем параметре Коментарий: В общем, это альтернатива функции zeromem, если в третий параметор поместить 0, работоспособность ничуть не снизится, а даже повысется из-за придельной оптимизации, а так как в этот параметор можно помещять не только 1 байт, можно немного по импровизировать с форматом заполнения. Какие только извращённые алгоритмы я не встречал, для выполнения этой элементарнейшей задачи, бывали даже в пять раз длиннее представленного мной кода, больше вам не придётся извращятся над этим алгоритмом, он оптимизирован до примела. Кстати он не затирает не один регистр, даже eax. Пример вызова: Code: 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 '2yt2i3uy4t5234t5ywgejhfvjrvbxau4vufv3db4tgvrjwqyt4fvbejsdyqwtfvbeudrweq' Код: Code: 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 Код: Code: .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 Алгоритм: 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, программа будет попадать на неё, при вызове функции которой не нашел импортер. Результат работы: Code: до: 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 Пример вызова: Code: 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 Code: 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) подождать. Он не включает неиспользуемые функции, но он не проверяет, используется ли модуль, так что все модули включать не стоит, а-то он их все загрузит. Code: 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) с возможным не совпадением количества функций с количеством их имён.
Get Command Line Arguments Алгоритм: Get Command Line Arguments Синтаксис: fasm Описание: Самая частоиспользуемая функция после импортера. При написании какой нибудь маленькой консольной(и не только) утилиты, бывает очень нужно получить аргументы коммандной строки. Змечания: Данная функция защищена от переполнения, указываемая в последним аргументе длина указывается включая нулевой окончательный символ. Если длина 4, в буффер поместятся только 3 символа аргумента и 1 конца строки. В eax возвращается длина полученого аргумента, если его не нашлось, возвращасется 0, при этом в буффер ничего не записывается, так что можно предопределять аргументы. Пример вызова: Code: 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(?) Code: 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ную вводить утомительно. Пример вызова: Code: 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 Описание: потоковое шифрование\дешифрование Код: В Code: 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
Алгоритм: Генератор случайных чисел Синтаксис: fasm/masm Описание: Генератор случайных чисел, достаточно быстрый основан на сдвигах. Пример вызова: Code: 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. Код: Code: .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 Комментарий: самая вменяемая реализация из всех мне встречавшихся. Код: Code: .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