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.
    1. 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
      1. 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.
        1. 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.
          1. 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.
            1. 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:
                764
              #6 hidden, 4 Jan 2007
              Last edited: 21 Jan 2007
              1 person likes this.
              1. 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.
                1. 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
                  1. 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.
                    1. !_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.
                      1. 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.
                        1. 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