Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   Реверсинг (https://forum.antichat.xyz/forumdisplay.php?f=94)
-   -   Collection: Asm-Algorithms (https://forum.antichat.xyz/showthread.php?t=28998)

hidden 12.12.2006 22:55

Collection: Asm-Algorithms
 
Asm-Алгоритмы

Описание: Этот thread представляет из себя сборник интересных, полезных, а также просто часто требующихся функций, написанных на ассемблере.
Условие: Сюда добавляете только те функции, которые использовались, были оптимизированы вами, или же очень вас заинтересовали.
Формат: Придерживайтесь формата, каждый новый алгоритм в новом посте, название алгоритма повторяйте в заголовке:
Код:

[b]Алгоритм:[/b] Название алгоритма
[b]Синтаксис:[/b] fasm/masm/nasm/...
[b]Описание:[/b] Что делает дынный алгоритм
[b]Коментарий:[/b] Что вы думаете о нём/его реализации
[b]Пример вызова:[/b]
[code]  Достаточный код, чтоб его проверить[/code]
[b]Код:[/b]
[code]  Код самой функции[/code]
[b]Внимание:[/b] Если есть какието замечания, например по безопасности

Вопрос: Для чего придерживаться формата?
Ответ: В поиске по теме очень удобно отображается кажрый пост, попробуйте и сами убедитесь.

hidden 12.12.2006 22:57

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='));"
Пример вызова:
Код:

format PE GUI 4.0
entry start

include 'win32a.inc'

data import
  library USER32,'USER32.DLL'
  import  USER32,MessageBoxA,'MessageBoxA'
end data

include 'utils.inc'

start:
        stdcall bin2base64, bin, bin.len, chrset, buf
        ret
 chrset        db 'ABCDEFGHIJKLMNOP'
                db 'QRSTUVWXYZabcdef'
                db 'ghijklmnopqrstuv'
                db 'wxyz0123456789+/'

 bin            db 'This is my data'
 .len          = $ - bin
 buf            rb 256

Внимание: Длина буфера должна быть больше длины кодируемых данных в 4/3 раза c округлением в большую сторону + pad символ + символ конца строки, мы ведь не хотим переполнения буфера ;)
Код:
Код:

proc bin2base64, data, len, chrset, base
        push    edx
        xchg    esi, [data]
        xchg    ecx, [len]
        xchg    ebx, [chrset]
        xchg    edi, [base]
        mov    eax, ecx
        xor    edx, edx
        lea    ecx, [edx+3]
        div    ecx
        mov    ecx, eax
        mov    al, dl
        ror    eax, 16
 .lop:  lodsb
        ror    ax, 2
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        stosb
        rol    ax, 10
        lodsb
        ror    ax, 4
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        stosb
        rol    ax, 12
        lodsb
        ror    ax, 6
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        stosb
        rol    ax, 6
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        stosb
        loop    .lop
        rol    eax, 16
        mov    cx, ax
        jcxz    .sz
        mov    eax, '==' shl 16
        lodsb
        ror    ax, 2
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        dec    cx
        jnz    @f
        shr    ah, 2
        mov    dl, ah
        mov    ah, [edx+ebx]
        stosd
        jmp    .sz
 @@:    stosb
        shr    eax, 8
        shl    ax, 2
        lodsb
        ror    ax, 4
        and    al, 63
        mov    dl, al
        and    dl, 63
        mov    al, [edx+ebx]
        shr    ah, 2
        mov    dl, ah
        mov    ah, [edx+ebx]
        stosd
 .sz:  xor    eax, eax
        stosb
 .lnd:  pop    edx
        mov    esi, [data]
        mov    ecx, [len]
        mov    ebx, [chrset]
        mov    edi, [base]
        ret
endp


hidden 12.12.2006 23:00

try except endt
 
Алгоритм: try except endt
Синтаксис: fasm
Описание: Обработка исключений в fasm
Коментарий: При переходе с делфи на ассемблер мне очень нехватало обработки исключений, вот я её и сделал, по образу и подобию стандартного макроса if else endif.
Пример вызова:
Код:

format PE GUI 4.0
entry start

include 'win32w.inc'

data import
  library USER32,'USER32.DLL'
  import  USER32,MessageBoxA,'MessageBoxA'
end data

include 'try.inc'

proc start
try
 try
  try
        push    eax
        push    eax
        push    eax
        xor    eax, eax
        push    eax
        push    eax
        push    eax
        push    dword[eax]
  except
        invoke  MessageBoxA, 0, err2, err2, 0
  endt
        int3
 endt
        int3
except
        invoke  MessageBoxA, 0, err1, err1, 0
endt
        ret
endp

TryProc

  err1          db 'Error in block 1',0
  err2          db 'Error in block 2',0

Код:
Код:

include 'macro/proc32.inc'

macro SetHandler
{ push TryHandler
  push dword[fs:0]
  mov [fs:0], esp
  push __EXCEPT
  push ebp }

macro UnsetHandler
{ pop dword[fs:0]
  add esp, 4 }

macro try
{ __TRY equ
  local ..endt
  __ENDT equ ..endt
  local ..except
  __EXCEPT equ ..except
  SetHandler }

macro except
{ add esp, 8
  UnsetHandler
  jmp __ENDT
  __EXCEPT:
  UnsetHandler
  restore __TRY
  __TRY equ , }

macro endt
{ if __TRY eq
    add esp, 8
    __EXCEPT:
    UnsetHandler
  end if
  __ENDT:
  restore __EXCEPT
  restore __ENDT
  restore __TRY }

macro TryProc
{ proc TryHandler, ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext
    push esi edi ebx
    mov esi, [EstablisherFrame]
    mov edi, [ContextRecord]
    mov ebx, esi
    sub esi, 8
    add edi, $B4
    movsd ; ebp
    lodsd
    xchg [edi], eax
    ;movsd ; eip
    mov [edi+12], ebx ; esp
    mov [edi-8], eax ; esp

    pop ebx edi esi
    xor eax, eax
    ret
  endp }

if noinit eq
else
  TryProc
end if

*Сделаны исправления

hidden 13.12.2006 00:10

fmem (Fill memory)
 
Алгоритм: fmem (Fill memory)
Синтаксис: fasm
Описание: Заполнение участка памяти байтом, указоным в третьем параметре
Коментарий: В общем, это альтернатива функции zeromem, если в третий параметор поместить 0, работоспособность ничуть не снизится, а даже повысется из-за придельной оптимизации, а так как в этот параметор можно помещять не только 1 байт, можно немного по импровизировать с форматом заполнения. Какие только извращённые алгоритмы я не встречал, для выполнения этой элементарнейшей задачи, бывали даже в пять раз длиннее представленного мной кода, больше вам не придётся извращятся над этим алгоритмом, он оптимизирован до примела. Кстати он не затирает не один регистр, даже eax.
Пример вызова:
Код:

format PE GUI 4.0
entry start

include 'win32a.inc'

start:
        stdcall fmem, buf, 11, 0
        stdcall fmem, buf, 21, 'aaaa' ; Нужно указывать 4 'a' !
        ret

buf    db '2yt2i3uy4t5234t5ywgejhfvjrvbxau4vufv3db4tgvrjwqyt4fvbejsdyqwtfvbeudrweq'

Код:
Код:

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


ProTeuS 13.12.2006 11:44

Алгоритм: md5 hashing algo
Синтаксис: masm
Описание: "экономи4еская" реализация алгоритма хэширования md5

Код:
Код:

.686
.model flat,stdcall
option casemap:none

.data?
MD5HashBuf db 64 dup(?)
MD5Digest dd 4 dup(?)
MD5Len dd ?
MD5Index dd ?
 
.code
MD5FF macro dwA, dwB, dwC, dwD, locX, rolS, constAC
        mov        edi,dwC
        xor        edi,dwD
        and        edi,dwB
        xor        edi,dwD
        add        dwA,[locX]
        lea        dwA,[edi+dwA+constAC]
        rol        dwA,rolS
        add        dwA,dwB
endm

MD5GG macro dwA, dwB, dwC, dwD, locX, rolS, constAC
        mov        edi,dwC
        xor        edi,dwB
        and        edi,dwD
        xor        edi,dwC
        add dwA,[locX]
        lea        dwA,[edi+dwA+constAC]
        rol        dwA,rolS
        add        dwA,dwB
endm

MD5HH macro dwA, dwB, dwC, dwD, locX, rolS, constAC
        mov        edi,dwC
        xor        edi,dwD
        xor        edi,dwB
        add dwA,[locX]
        lea        dwA,[dwA+edi+constAC]
        rol        dwA,rolS
        add        dwA,dwB
endm

MD5II macro dwA, dwB, dwC, dwD, locX, rolS, constAC
        mov edi,dwD
        xor edi,-1
        or edi,dwB
        xor edi,dwC
        add dwA,[locX]
        lea dwA,[edi+dwA+constAC]
        rol dwA,rolS
        add dwA,dwB
endm

align dword
MD5Transform proc
        pushad
        mov esi,offset MD5Digest
        mov edi,offset MD5HashBuf       
        mov eax,[esi+0*4]
        mov ebx,[esi+1*4]
        mov ecx,[esi+2*4]
        mov ebp,edi
        mov edx,[esi+3*4]
        ;==============================================================
        MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 0*4],  7, 0D76AA478H
        MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 1*4], 12, 0E8C7B756H
        MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 17, 0242070DBH
        MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 3*4], 22, 0C1BDCEEEH
        MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 4*4],  7, 0F57C0FAFH
        MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 5*4], 12, 04787C62AH
        MD5FF ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 17, 0A8304613H
        MD5FF ebx, ecx, edx, eax, dword ptr [ebp+ 7*4], 22, 0FD469501H
        MD5FF eax, ebx, ecx, edx, dword ptr [ebp+ 8*4],  7, 0698098D8H
        MD5FF edx, eax, ebx, ecx, dword ptr [ebp+ 9*4], 12, 08B44F7AFH
        MD5FF ecx, edx, eax, ebx, dword ptr [ebp+10*4], 17, 0FFFF5BB1H
        MD5FF ebx, ecx, edx, eax, dword ptr [ebp+11*4], 22, 0895CD7BEH
        MD5FF eax, ebx, ecx, edx, dword ptr [ebp+12*4],  7, 06B901122H
        MD5FF edx, eax, ebx, ecx, dword ptr [ebp+13*4], 12, 0FD987193H
        MD5FF ecx, edx, eax, ebx, dword ptr [ebp+14*4], 17, 0A679438EH
        MD5FF ebx, ecx, edx, eax, dword ptr [ebp+15*4], 22, 049B40821H
        ;==============================================================
        MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 1*4],  5, 0F61E2562H
        MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 6*4],  9, 0C040B340H
        MD5GG ecx, edx, eax, ebx, dword ptr [ebp+11*4], 14, 0265E5A51H
        MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 0*4], 20, 0E9B6C7AAH
        MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 5*4],  5, 0D62F105DH
        MD5GG edx, eax, ebx, ecx, dword ptr [ebp+10*4],  9, 002441453H
        MD5GG ecx, edx, eax, ebx, dword ptr [ebp+15*4], 14, 0D8A1E681H
        MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 4*4], 20, 0E7D3FBC8H
        MD5GG eax, ebx, ecx, edx, dword ptr [ebp+ 9*4],  5, 021E1CDE6H
        MD5GG edx, eax, ebx, ecx, dword ptr [ebp+14*4],  9, 0C33707D6H
        MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 14, 0F4D50D87H
        MD5GG ebx, ecx, edx, eax, dword ptr [ebp+ 8*4], 20, 0455A14EDH
        MD5GG eax, ebx, ecx, edx, dword ptr [ebp+13*4],  5, 0A9E3E905H
        MD5GG edx, eax, ebx, ecx, dword ptr [ebp+ 2*4],  9, 0FCEFA3F8H
        MD5GG ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 14, 0676F02D9H
        MD5GG ebx, ecx, edx, eax, dword ptr [ebp+12*4], 20, 08D2A4C8AH
        ;==============================================================
        MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 5*4],  4, 0FFFA3942H
        MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 8*4], 11, 08771F681H
        MD5HH ecx, edx, eax, ebx, dword ptr [ebp+11*4], 16, 06D9D6122H
        MD5HH ebx, ecx, edx, eax, dword ptr [ebp+14*4], 23, 0FDE5380CH
        MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 1*4],  4, 0A4BEEA44H
        MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 4*4], 11, 04BDECFA9H
        MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 7*4], 16, 0F6BB4B60H
        MD5HH ebx, ecx, edx, eax, dword ptr [ebp+10*4], 23, 0BEBFBC70H
        MD5HH eax, ebx, ecx, edx, dword ptr [ebp+13*4],  4, 0289B7EC6H
        MD5HH edx, eax, ebx, ecx, dword ptr [ebp+ 0*4], 11, 0EAA127FAH
        MD5HH ecx, edx, eax, ebx, dword ptr [ebp+ 3*4], 16, 0D4EF3085H
        MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 6*4], 23, 004881D05H
        MD5HH eax, ebx, ecx, edx, dword ptr [ebp+ 9*4],  4, 0D9D4D039H
        MD5HH edx, eax, ebx, ecx, dword ptr [ebp+12*4], 11, 0E6DB99E5H
        MD5HH ecx, edx, eax, ebx, dword ptr [ebp+15*4], 16, 01FA27CF8H
        MD5HH ebx, ecx, edx, eax, dword ptr [ebp+ 2*4], 23, 0C4AC5665H
        ;==============================================================
        MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 0*4],  6, 0F4292244H
        MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 7*4], 10, 0432AFF97H
        MD5II ecx, edx, eax, ebx, dword ptr [ebp+14*4], 15, 0AB9423A7H
        MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 5*4], 21, 0FC93A039H
        MD5II eax, ebx, ecx, edx, dword ptr [ebp+12*4],  6, 0655B59C3H
        MD5II edx, eax, ebx, ecx, dword ptr [ebp+ 3*4], 10, 08F0CCC92H
        MD5II ecx, edx, eax, ebx, dword ptr [ebp+10*4], 15, 0FFEFF47DH
        MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 1*4], 21, 085845DD1H
        MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 8*4],  6, 06FA87E4FH
        MD5II edx, eax, ebx, ecx, dword ptr [ebp+15*4], 10, 0FE2CE6E0H
        MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 6*4], 15, 0A3014314H
        MD5II ebx, ecx, edx, eax, dword ptr [ebp+13*4], 21, 04E0811A1H
        MD5II eax, ebx, ecx, edx, dword ptr [ebp+ 4*4],  6, 0F7537E82H
        MD5II edx, eax, ebx, ecx, dword ptr [ebp+11*4], 10, 0BD3AF235H
        MD5II ecx, edx, eax, ebx, dword ptr [ebp+ 2*4], 15, 02AD7D2BBH
        MD5II ebx, ecx, edx, eax, dword ptr [ebp+ 9*4], 21, 0EB86D391H
        ;==============================================================
        add [esi+0*4],eax        ; update digest
        add [esi+1*4],ebx
        add [esi+2*4],ecx
        add [esi+3*4],edx
        popad
        retn
MD5Transform endp

MD5BURN macro
        xor eax,eax
        mov MD5Index,eax
        mov edi,Offset MD5HashBuf
        mov ecx,(sizeof MD5HashBuf)/4
        rep stosd
endm

align dword
MD5Init proc uses edi
        xor eax, eax
        mov MD5Len,eax
        MD5BURN
        mov eax,offset MD5Digest
        mov dword ptr [eax+0*4],067452301h
        mov dword ptr [eax+1*4],0EFCDAB89h
        mov dword ptr [eax+2*4],098BADCFEh
        mov dword ptr [eax+3*4],010325476h
        ret
MD5Init endp

align dword
MD5Update proc uses esi edi ebx lpBuffer:dword, dwBufLen:dword
        mov ebx,dwBufLen
        mov esi,lpBuffer
        add MD5Len,ebx
        .while ebx
                mov eax,MD5Index
                mov ecx,64
                sub ecx,eax
                lea edi,[MD5HashBuf+eax]       
                .if ecx <= ebx
                        sub ebx,ecx
                        rep movsb
                        call MD5Transform
                        MD5BURN
                .else
                        mov ecx,ebx
                        rep movsb
                        add MD5Index,ebx
                        .break
                .endif
        .endw
        ret
MD5Update endp

align dword
MD5Final proc uses esi edi
        mov ecx, MD5Index
        mov byte ptr [MD5HashBuf+ecx],80h
        .if ecx >= 56
                call MD5Transform
                MD5BURN
        .endif
        mov eax,MD5Len
        xor edx,edx
        shld edx,eax,3
        shl eax,3
        mov dword ptr [MD5HashBuf+56],eax
        mov dword ptr [MD5HashBuf+60],edx
        call MD5Transform
        mov eax,offset MD5Digest       
        ret
MD5Final endp

end


hidden 04.01.2007 10:09

Hash Importer
 
Вложений: 1
Алгоритм: Hash Importer
Синтаксис: fasm
Описание: Импортирует функции из модулей по ихним хэшам или номерам, при первом варианте они хешируются без учёта регистра макроинструкцией iprc, абсолютная вероятность неповторимости хэша сохраняется, только при условии, что длина имени не превышает 6 символов, не включает цифр и не зависит от регистра, тем не менее, количество вариантов настолько велико, что вероятность того что в одном модуле будут две функции одной и той-же длины и с одной и той-же хешью стремится к 0. Во время импортирования вычисляется дельта функций относительно мест, куда они будут сохранены, и сохраняются в виде относительных переходов(инструкция E9), также сохраняются и нэнделы проанализированных модулей. Всё это сохранённое добро доступно по указанным ссылкам. Установка флага AntiDebug включает проверку, если первая инструкция в импортированной функции mov edi, edi знацит пропустить эту инструкцию, что очень запутывает отладчик.
Комментарий: Макроинструкция istr содержит имена библиотек, её можно вынести в ReadOnly секцию. Да и готовые функции ProcIdByHash, ProcAddrById и BaseByAddr тоже иногда бывают полезны.
Змечания: В примере используется не invoke, a stdcall, т.к. invoke proc компилируется как call dword[proc] (вызов функции, адрес которой записан в переменной proc), а stdcall как call proc (вызов инструкции, по адресу proc), что позволяет использовать этот алгоритм в базонезависимых программах, так как call proc - relative call(Относительный вызов). Если используется подгрузка дополнительных модулей, то должна присутствовать функция LoadLibraryA, она может импортироваться из первого модуля(до подгрузки остальных) или же создана статически. Также можно создать функцию ImportErrProc, программа будет попадать на неё, при вызове функции которой не нашел импортер.
Результат работы:
Код:

до:
LoadLibraryA db        $0C                    ; Длина LoadLibraryA
            dd        $9224447C              ; Хэшь LoadLibraryA
            db        $FF                    ; Команда загрузить модуль
user        dd        $004010FC              ; Адрес строки user.str содержащий имя модуля
            db        $0B                    ; Длина MessageBoxA
MessageBoxA  dd        $1E1EC3BC              ; Хэшь MessageBoxA
            db        $FE                    ; Конец структуры
user.str    db        'user32',0

после:
LoadLibraryA jmp        kernel.LoadLibraryA    ; E9 860C407C
            db        $FF                    ; Команда загрузить модуль
user        dd        user32.77D40000        ; 0000D477 - База user32
MessageBoxA  jmp        user32.MessageBoxA      ; E9 EFF39777
            db        $FE                    ; Конец структуры
user.str    db        'user32',0

Пример вызова:
Код:

format PE GUI 4.0
entry start

AntiDebug equ

include 'win32a.inc'
include 'utils.inc'

myi:
  iprc LoadLibraryA, 'LoadLibraryA'
  imod user, 'user32'
  iprc MessageBoxA, 'MessageBoxA'
  endi
  istr user

tit    db 'Message',0;
txt    db 'Example of Hash importer',0

start:
        stdcall BaseByAddr, [esp+4] ; or stdcall GetKernel without parametrs
        stdcall importer, eax, myi
        stdcall MessageBoxA, 0, txt, tit, 0
        ret

Код:

macro iprc [proc, name]
 { forward
    if used proc | proc eq LoadLibraryA
    if name eqtype ''
      local ch
      local hash
      local length
      virtual at 0
      db name
      length = $
      hash = 0
      repeat length
        load ch byte from length-%
        hash = ((hash shl 5) or (hash shr (32 - 5))) and $FFFFFFFF ; hash = hash rol 5
        hash = hash xor (ch and 11111b)
      end repeat
      end virtual
      virtual at $
      proc dd ?
      end virtual
      db length ; Length, if $ff then load lib, if $fe then end, if $fd then by id
      dd hash
    else
      db $fd
      dd name+1
    end if
    end if }

macro imod [module, str]
 { forward
    db $fe
    module dd module#.str - $
    module#.text equ str }

macro istr [module]
 { forward
    module#.str db module#.text, 0 }

macro endi ierrproc
 { db $ff }

struct IED
 Characteristics        dd ? ;This field appears to be unused and is always set to 0.
 TimeDateStamp          dd ? ;The time/date stamp indicating when this file was created.
 Version                dd ? ;These fields appear to be unused and are set to 0.
 Name                  dd ? ;The RVA of an ASCIIZ string with the name of this DLL.
 Base                  dd ? ;The starting ordinal number for exported functions. For example, if the file exports functions with ordinal values of 10, 11, and 12, this field contains 10. To obtain the exported ordinal for a function, you need to add this value to the appropriate element of the AddressOfNameOrdinals array.
 NumberOfFunctions      dd ? ;The number of elements in the AddressOfFunctions array. This value is also the number of functions exported by this module. Theoretically, this value could be different than the NumberOfNames field (next), but actually they're always the same.
 NumberOfNames          dd ? ;The number of elements in the AddressOfNames array. This value seems always to be identical to the NumberOfFunctions field, and so is the number of exported functions.
 AddressOfFunctions    dd ? ;This field is an RVA and points to an array of function addresses. The function addresses are the entry points (RVAs) for each exported function in this module.
 AddressOfNames        dd ? ;This field is an RVA and points to an array of string pointers. The strings are the names of the exported functions in this module.
 AddressOfNameOrdinals  dd ? ;This field is an RVA and points to an array of WORDs. The WORDs are the export ordinals of all the exported functions in this module. However, don't forget to add in the starting ordinal number specified in the Base field.
ends

proc ProcIdByHash, base, hash, len:byte
        xchg    edi, [base]
        push    ebx ecx edx esi

        mov    ebx, [edi+$3C] ; OffSet to PE Header
        mov    ebx, [edi+ebx+$78] ; Offset to Export section

        push    ebx
        mov    ecx, [edi+ebx+IED.NumberOfNames] ; NumberOfFunctions - Stupid MSDN writers, who have trying to import from ws2_32 that understend
        mov    ebx, [edi+ebx+IED.AddressOfNames]
        add    ebx, edi

  .next:mov    esi, [ebx+ecx*4-4]
        add    esi, edi
        mov    edx, [hash]
        movzx  eax, [len]
        cmp    byte[esi+eax], 0
        jne    .wrng
  @@:  lodsb
        or      al, al
        jz      @f
        and    al, 11111b
        xor    dl, al
        ror    edx, 5
        jmp    @b
  @@:  or      edx, edx
        jz      .ret ; @f
  .wrng:loop    .next
        xor    eax, eax
        jmp    .end
  .ret: pop    ebx
        mov    eax, [edi+ebx+IED.AddressOfNameOrdinals]
        add    eax, edi
        movzx  eax, word[eax+ecx*2-2]
        add    eax, [edi+ebx+IED.Base]

  .end: pop    esi edx ecx ebx
        mov    edi, [base]
        ret
endp

proc ProcAddrById, base, id
        xchg    edi, [base]
        xchg    ebx, [id]

        mov    eax, [edi+$3C] ; OffSet to PE Header
        mov    eax, [edi+eax+$78] ; Offset to Export section
        sub    ebx, [edi+eax+IED.Base]
        mov    eax, [edi+eax+IED.AddressOfFunctions]

        add    eax, edi

        mov    eax, [eax+ebx*4]
        add    eax, edi

        mov    ebx, [id]
        mov    edi, [base]
        ret
endp

proc GetKernel
        xor    eax, eax
        mov    eax, [fs:eax+30h]
        test    eax, eax
        js      ngk
        mov    eax, [eax+0Ch]
        mov    esi, [eax+1Ch]
        lodsd
        mov    eax, [eax+8]
        jmp    egk
ngk:    mov    eax, [eax+34h]
        add    eax, 7Ch
        mov    eax, [eax+3Ch]
egk:    ret
endp

proc BaseByAddr, addr
        mov    eax, [addr]

        xor    ax, ax
  @@:  cmp    word[eax], 'MZ'
        jz      @f
        sub    eax, $10000
        jmp    @b
  @@:  ret
endp

proc importer, kernel, imports
        xchg    esi, [imports]
        xchg    edi, [kernel]

        ;stdcall BaseByAddr, edi
        ;mov    edi, eax

  .loop:lodsb
        cmp    al, $fd
        ja      .more
        je      .byid
        mov    ah, al

        or      edi, edi
        jz      .xxx

        stdcall ProcIdByHash, edi, [esi], [esi-1]

        or      eax, eax
        if      defined ImportErrProc
        jnz      @f
        lea    eax, [esi-ImportErrProc]
        mov    eax, errfunc
        lodsd
        jmp    .stor
  @@:  else
        jz    .stor
        display 'ImportErrProc is undefined',13,10
        end    if

  .gbi: stdcall ProcAddrById, edi, eax

  .stor:if      AntiDebug eq
        cmp    word[eax], $FF8B
        jnz    @f
        add    eax, 2
  @@:  end    if
        sub    eax, 4

  @@:  sub    eax, esi
        mov    byte[esi-1], $E9
        mov    dword[esi], eax
  .xxx: lodsd
        jmp    .loop

  .byid:mov    eax, [esi]
        jmp    .gbi

  .more:cmp    al, $ff
        je      .endi
        lodsd

        if      defined LoadLibraryA
        lea    eax, [eax+esi-4]
        stdcall LoadLibraryA, eax
        mov    edi, eax
        mov    [esi-4], eax
        else
        display 'LoadLibraryA is undefined',13,10
        end    if

        jmp    .loop

  .endi:mov    edi, [kernel]
        mov    esi, [imports]
        ret
endp

Особые извращенцы над компилятором(шутка), могут воспользоваться таким способом импортирования функций, как приведён ниже. В некоторых случаях очень удобно, потому что, находит почти любую функцию которая может понадобится, хотя придётся немного(на моём примерно 0,9 seconds) подождать. Он не включает неиспользуемые функции, но он не проверяет, используется ли модуль, так что все модули включать не стоит, а-то он их все загрузит.
Код:

myi:
  include '\imp\kernel32.inc'
  include '\imp\ntdll.inc'
  include '\imp\advapi32.inc'
  include '\imp\comdlg32.inc'
  include '\imp\gdi32.inc'
  include '\imp\ole32.inc'
  include '\imp\oleaut32.inc'
  include '\imp\shell32.inc'
  include '\imp\shlwapi.inc'
  include '\imp\user32.inc'
  endi
  istr ntdll, advapi, comdlg, gdi, ole, oleaut, shell, shlwapi, user

А также все эти файлы, с выдранными функциями из данных модулей WindowsXP ниже в архиве, мучийте свой компилятор на здоровье :D

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

hidden 07.01.2007 20:37

Get Command Line Arguments
 
Алгоритм: Get Command Line Arguments
Синтаксис: fasm
Описание: Самая частоиспользуемая функция после импортера. При написании какой нибудь маленькой консольной(и не только) утилиты, бывает очень нужно получить аргументы коммандной строки.
Змечания: Данная функция защищена от переполнения, указываемая в последним аргументе длина указывается включая нулевой окончательный символ. Если длина 4, в буффер поместятся только 3 символа аргумента и 1 конца строки. В eax возвращается длина полученого аргумента, если его не нашлось, возвращасется 0, при этом в буффер ничего не записывается, так что можно предопределять аргументы.
Пример вызова:
Код:

format PE GUI 4.0
entry start

include 'win32a.inc'
include 'ulils.inc'

myi:
  iprc LoadLibraryA, 'LoadLibraryA',\
  GetCommandLineA,'GetCommandLineA'
  imod user, 'user32'
  iprc MessageBoxA, 'MessageBoxA'
  endi
  istr user

start:
        stdcall importer, [esp+4], myi
       
        stdcall GetCommandLineA
        mov    [arg], eax

        stdcall GetArg, [arg], 1, Message, 64
        stdcall MessageBoxA, 0, Message, tit1, 0

        stdcall GetArg, [arg], 2, Message, 64
        stdcall MessageBoxA, 0, Message, tit2, 0

        ret

 arg            dd ?
 tit1          db 'Arg number 1',0
 tit2          db 'Arg number 2',0
 Message        db 64 dup(?)

Код:

proc GetArg, line, num, buf, len
        xchg    esi, [line]
        xchg    edi, [buf]
        xchg    ecx, [num]
        dec    [len]

        jecxz  .cur

 .lp1:  lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        jne    .nq1

 .lp2:  lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        jne    .lp2
        lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        je      .lp2

 .nq1:  cmp    al, ' '
        jne    .lp1

 @@:    lodsb
        cmp    al, ' '
        je      @b
        dec    esi

        loop    .lp1

 .cur:  mov    ecx, [len]
 .lp3:  lodsb
        or      al, al
        jz      .end
 .chs:  cmp    al, ' '
        je      .end
        cmp    al, '"'
        jne    .nq2

 .gq2:  lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        jne    .gq1

 .nq2:  stosb
        loop    .lp3

 .end:  mov    eax, [len]
        sub    eax, ecx
        jz      .ret
        mov    byte[edi], 0
        inc    edi
 .ret:  mov    esi, [line]
        mov    edi, [buf]
        mov    ecx, [num]
        ret

 .lp4:  lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        jne    .gq1

        lodsb
        or      al, al
        jz      .ret
        cmp    al, '"'
        jne    .chs

 .gq1:  stosb
        loop    .lp4
        jmp    .end

 .err:  xor    eax, eax
        jmp    .ret
endp

Updates: Теперь игнорирует повторяющиеся пробелы между аргументами

ProTeuS 29.01.2007 19:27

Алгоритм: dup export file to fasm dd table
Синтаксис: delphi -> fasm
Описание:

данная процедурка(delphi) генерит таблицу смещений и пат4ей по экспортируемому DUPом файлу такого вида:

RAW Offset | Old Byte | New Byte
-----------------+----------+----------
00000149 20 30
000001F6 00 12
00000217 60 E0
0000023C 40 20
0000023F 40 E0
00000246 00 12
00000264 40 20


и сохраняет в удобном для использования в fasm'е

Offsets dd 0x00000149, 0x000001F6, 0x00000217, 0x0000023C, 0x0000023F
dd 0x00000246, 0x00000264

Patch db 0x30, 0x12, 0xE0, 0x20, 0xE0, 0x12, 0x20


Очень полезно при создании пат4ей, лоадеров с большим коли4естов байт для пат4а, которые вру4ную вводить утомительно.

Пример вызова:

Код:

procedure make_fasm_patch_table(dup_filename, offsets, pat4es: string);
var
f, offs, patches: textfile;
s, temp: string;
i: integer;
begin
  assignfile(f, dup_filename);
  assignfile(offs, offsets);
  assignfile(patches, pat4es);
  rewrite(offs);
  rewrite(patches);
  reset(f);
  readln(f, s); //skip dup banner
  readln(f, s);
  i :=0;
  write(offs, 'Offsets        dd  ');
  write(patches, 'Patch          db  ');
    while not eof(f) do
      begin
        readln(f, s);
        inc(i);
        temp := '0x' + copy(s, 6, 8)+', ';
        if i mod 7 <> 0 then
        write(offs, temp) else
          begin
            writeln(offs, copy(temp, 1, length(temp)-2));
            write(offs, '              dd  ');
          end;
        temp := '0x' + copy(s, 34, 2)+', ';
        if i mod 15 <> 0 then
        write(patches, temp) else
          begin
            writeln(patches, copy(temp, 1, length(temp)-2));
            write(patches, '              db  ');
          end;
      end;
  closefile(f);
  closefile(offs);
  closefile(patches);
end;


ProTeuS 31.03.2007 15:16

Алгоритм: RC4 cipher
Описание: потоковое шифрование\дешифрование
Код: В

Код:

                INCLUDE MISC.INC
                MODULE RC4
 
                PUBLIC _rc4expandKey, _rc4crypt
 
                DATA
 
; The RC4 keying information
 
rc4key  DB              256 DUP (?)
rc4x    DB              0
rc4y    DB              0
 
                CODE
 
; void rc4ExpandKey( unsigned char const *key, int keylen )
 
_rc4expandKey PROCEDURE
        push bp
        mov bp, sp
        push si
        push di                                                ; Save register vars
        les si, [bp+4]                                  ; ES:SI = key
        mov dx, [bp+8]                                  ; DX = keylen
        mov dh, dl                                              ; keylenTmp = keylen
 
        ; rc4word y = 0;
        xor ax, ax                                              ; y = 0
        sub di, di                                              ; DI = AX as an index register
 
        ; for( x = 0; x < 256; x++ )
        ;      rc4key[ x ] = x;
        xor bx, bx                                              ; x = 0
@@initLoop:
        mov rc4key[bx], bl                              ; rc4key[ x ] = x
        inc bl                                                  ; x++
        jnz SHORT @@initLoop
 
        ; for( x = 0; x < 256; x++ )
        ;      {
        ;      sx = rc4key[ x ];
        ;      y += sx + key[ keypos ];
        ;      rc4key[ x ] = rc4key[ y ];
        ;      rc4key[ y ] = sx;
        ;
        ;      if( ++keypos == keylen )
        ;              keypos = 0;
        ;      }
@@keyLoop:
        mov cl, rc4key[bx]                              ; sx = rc4key[ x ]
        add al, es:[si]                                ; y += key[ keypos ]
        add al, cl                                              ; y += sx
        mov di, ax
        mov ch, rc4key[di]                              ; temp = rc4key[ y ]
        mov rc4key[bx], ch                              ; rc4key[ x ] = temp
        mov rc4key[di], cl                              ; rc4key[ y ] = sx
        inc si                                                  ; ++keypos
        dec dh                                                  ; keylenTmp--
        jnz SHORT @@noResetKeypos              ; if( !keylenTmp )
        sub si, dx                                              ; keypos = 0
        mov dh, dl                                              ; keylenTmp = keylen
@@noResetKeypos:
        inc bl                                                  ; x++
        jnz SHORT @@keyLoop
 
        ; rc4->x = rc4->y = 0;
        mov rc4x, bl                                    ; rc4->x = 0
        mov rc4y, bl                                    ; rc4->y = 0
 
        pop di
        pop si                                                  ; Restore register vars
        pop bp
        ret
_rc4expandKey ENDP
 
; void rc4Crypt( unsigned char *data, int len )
 
_rc4crypt PROCEDURE
        push bp
        mov bp, sp
        push si
        push di                                                ; Save register vars
        les si, [bp+4]                                  ; ES:SI = data
        mov dx, [bp+8]                                  ; DX = len
        test dx, dx                                            ; Check that len != 0
        jz SHORT @@exit                                ; Yes, exit now
 
        xor bx, bx
        mov bl, rc4x                                    ; BX = rc4x
        xor ax, ax
        mov al, rc4y                                    ; AX = rc4y
        xor di, di                                              ; DI = AX as an index register
 
        ; while( len-- )
        ;      {
        ;      x++;
        ;      sx = rc4key[ x ];
        ;      y += sx;
        ;      sy = rc4key[ y ];
        ;      rc4key[ y ] = sx;
        ;      rc4key[ x ] = sy;
        ;      *data++ ^= rc4key[ ( sx + sy ) & 0xFF ];
        ;      }
@@rc4loop:
        inc bl                                                  ; x++
        mov cl, rc4key[bx]                              ; sx = rc4key[ x ]
        add al, cl                                              ; y += sx
        mov di, ax
        mov ch, rc4key[di]                              ; sy = rc4key[ y ]
        mov rc4key[di], cl                              ; rc4key[ y ] = sx
        mov rc4key[bx], ch                              ; rc4key[ x ] = sy
        add cl, ch
        xor ch, ch
        mov di, cx                                              ; temp = ( sx + sy ) & 0xFF
        mov cl, rc4key[di]
        xor es:[si], cl                                ; *data ^= rc4key[ temp ]
        inc si                                                  ; data++
        dec dx                                                  ; len--
        jnz SHORT @@rc4loop
 
        mov rc4x, bl
        mov rc4y, al                                    ; Remember x and y values
 
@@exit:
        pop di
        pop si                                                  ; Restore register vars
        pop bp
        ret
_rc4crypt ENDP
ENDMODULE


!_filin_! 25.05.2007 16:47

Алгоритм: Генератор случайных чисел
Синтаксис: fasm/masm
Описание: Генератор случайных чисел, достаточно быстрый основан на сдвигах.
Пример вызова:
Код:

srand_init proc near; инициализирует кольцевой буфер для генератора, ВХОД:EAX начальное значение например из области данных BIOS
push bx
push si
push edx
mov edx,1
; засеять кольцевой буфер
mov bx, 216
do_0: mov word ptr ablex[bx], dx
sub eax,edx
xchg eax, edx
sub bx,4
jge do_0
;разогреть генератор
mov bx,216
do_1: push bx
do_2: mov si,bx
add si,120
cmp si,216
jbe skip
sub si, 216
skip: mov eax, dword ptr tablex[bx]
sub eax dword ptr tablex[si]
mov dword ptr tablex[bx], eax
sub bx,4
jge do_2
pop bx
sub bx,4
jge do_1
; инициализировать индексы
sub ax,ax
mov word ptr index0,ax
mov ax,124
mov index1, ax
pop edx
pop si
pop bx
ret
srand_init endp



Время: 13:43