Collection: Asm-Algorithms

Discussion in 'Реверсинг' started by hidden, 12 Dec 2006.

  1. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    [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] Если есть какието замечания, например по безопасности
    Вопрос: Для чего придерживаться формата?
    Ответ: В поиске по теме очень удобно отображается кажрый пост, попробуйте и сами убедитесь.
     
    #1 hidden, 12 Dec 2006
    Last edited: 30 Sep 2007
    5 people like this.
  2. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    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
     
    #2 hidden, 12 Dec 2006
    Last edited: 12 Dec 2006
  3. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    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
    *Сделаны исправления
     
    #3 hidden, 12 Dec 2006
    Last edited: 5 Mar 2007
    1 person likes this.
  4. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    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
     
    #4 hidden, 12 Dec 2006
    Last edited: 12 Dec 2006
    3 people like this.
  5. ProTeuS

    ProTeuS --

    Joined:
    26 Nov 2004
    Messages:
    1,239
    Likes Received:
    542
    Reputations:
    445
    Алгоритм: 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
    
     
    5 people like this.
  6. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    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 ниже в архиве, мучийте свой компилятор на здоровье :D

    Updates:
    - Добавлена относительность имён загружаемых библиотек
    - возможность импорта по ордилалу
    - исправле недочёт(по вине этих грёбаных писателей MSDN) с возможным не совпадением количества функций с количеством их имён.
     

    Attached Files:

    • imp.zip
      File size:
      48.9 KB
      Views:
      758
    #6 hidden, 4 Jan 2007
    Last edited: 21 Jan 2007
    1 person likes this.
  7. hidden

    hidden 7H3 0N3

    Joined:
    23 Apr 2006
    Messages:
    550
    Likes Received:
    332
    Reputations:
    386
    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: Теперь игнорирует повторяющиеся пробелы между аргументами
     
    #7 hidden, 7 Jan 2007
    Last edited: 12 Jan 2007
    2 people like this.
  8. ProTeuS

    ProTeuS --

    Joined:
    26 Nov 2004
    Messages:
    1,239
    Likes Received:
    542
    Reputations:
    445
    Алгоритм: 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;
    
     
    #8 ProTeuS, 29 Jan 2007
    Last edited: 29 Jan 2007
  9. ProTeuS

    ProTeuS --

    Joined:
    26 Nov 2004
    Messages:
    1,239
    Likes Received:
    542
    Reputations:
    445
    Алгоритм: 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
    
     
    KIR@PRO and hidden like this.
  10. !_filin_!

    !_filin_! Elder - Старейшина

    Joined:
    7 Jan 2007
    Messages:
    86
    Likes Received:
    40
    Reputations:
    16
    Алгоритм: Генератор случайных чисел
    Синтаксис: 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
    
     
    #10 !_filin_!, 25 May 2007
    Last edited: 24 Jun 2008
    1 person likes this.
  11. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Алгоритм: 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
    
    
     
    1 person likes this.
  12. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Алгоритм: Реализация агоритма 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