Funciones en FASM

Iniciado por fary, 10 Julio 2011, 13:25 PM

0 Miembros y 1 Visitante están viendo este tema.

fary

Os dejo algunas funciones en FASM que e ido haciendo desde que empece con asm.

Función que compara dos cadenas:

Código (asm) [Seleccionar]
   proc Comparar,cadena1,cadena2
           ;Si son iguales  EAX = 1
           ;Si son diferentes EAX = 0
           mov esi,[cadena1]
           mov ecx,[cadena2]
           dec ecx
           bucle:
               inc ecx
               lodsb
               cmp byte[ecx],al
               jne diferentes
               cmp al,0
               je comprovar
               jmp bucle
           comprovar:
               cmp byte[ecx],0
               je iguales
               jne diferentes
           diferentes:
               mov eax,0
               ret
           iguales:
               mov eax,1
               ret
        endp


Ejemplo de su uso:

Código (asm) [Seleccionar]
   include 'win32ax.inc'
   
   .data
       palabra db 'Drinky94',0
       palabra2 db 'Drinky94',0
   
   .code
   start:
       stdcall Comparar,palabra,palabra2
       .if eax = 0
           invoke MessageBoxA,0,'Son Diferentes',0,0
       .else
           invoke MessageBoxA,0,'Son Iguales',0,0
       .endif
       ret
   
       proc Comparar,cadena1,cadena2
           ;Si son iguales  EAX = 1
           ;Si son diferentes EAX = 0
           mov esi,[cadena1]
           mov ecx,[cadena2]
           dec ecx
           bucle:
               inc ecx
               lodsb
               cmp byte[ecx],al
               jne diferentes
               cmp al,0
               je comprovar
               jmp bucle
           comprovar:
               cmp byte[ecx],0
               je iguales
               jne diferentes
           diferentes:
               mov eax,0
               ret
           iguales:
               mov eax,1
               ret
        endp
   .end start





Función que mide la longitud de una cadena:

Código (asm) [Seleccionar]
   proc Len,Cadena
           ;ECX = Longitud de la cadena.
           mov eax,[Cadena]
           mov ecx,-1
           bucle:
               inc ecx
               cmp byte[eax+ecx],0
               jne bucle
           ret
   endp


Ejemplo de su uso:

Código (asm) [Seleccionar]
   include 'win32ax.inc'
   
   .data
       palabra db 'Drinky94',0
       longitud dd ?
   .code
   start:
       stdcall Len,palabra
       mov [longitud],ecx
       invoke GlobalAlloc,GPTR,1024
       push eax
       invoke wsprintfA,eax,"%d",[longitud]
       pop eax
       invoke MessageBox,0,eax,0,MB_OK
       leave
       ret
   
       proc Len,Cadena
           ;ECX = Longitud de la cadena
           mov eax,[Cadena]
           mov ecx,-1
           bucle:
               inc ecx
               cmp byte[eax+ecx],0
               jne bucle
           ret
       endp
   .end start





Función que puede servir de remplazo a GlobalAlloc:

Código (asm) [Seleccionar]
   proc DGlobalAlloc,cantidad
           sub esp,[cantidad]
           mov eax,esp
           ret
   endp


Ejemplo de su uso:

Código (asm) [Seleccionar]
   include 'win32ax.inc'
   
   .data
       palabra db 'Drinky94',0
       longitud dd ?
   .code
   start:
   
       stdcall Len,palabra
       mov [longitud],ecx
       stdcall DGlobalAlloc,1024
       push eax
       invoke wsprintfA,eax,"%d",[longitud]
       pop eax
       invoke MessageBox,0,eax,0,MB_OK
       leave
       ret
   
       proc Len,Cadena
           mov eax,[Cadena]
           mov ecx,-1
           bucle:
               inc ecx
               cmp byte[eax+ecx],0
               jne bucle
           ret
       endp
   
       proc DGlobalAlloc,cantidad
           sub esp,[cantidad]
           mov eax,esp
           ret
       endp
   .end start





Código para saber si nos están debuggeando (usa el PEB):

Código (asm) [Seleccionar]
   format PE GUI 4.0
   entry start
   
   include 'win32ax.inc'
   
       SiDbg db 'Hay Debugger',0
       NoDbg db 'No hay Debugger',0
   
   start:
           mov eax,dword[fs:18h]
           mov eax,dword[eax+30h]
           mov bl,byte[eax+2]  ; si bl = 1 Nos estan debujeando.
   
           .if bl = 1
               invoke MessageBoxA,0,SiDbg,0,0
           .else
               invoke MessageBoxA,0,NoDbg,0,0
           .endif
           ret
   
   data import
           library user32,'user32.dll'
   
           import user32,MessageBoxA,'MessageBoxA'
   
   end data            





Simple cifrado Xor:

Código (asm) [Seleccionar]
   proc Cifrar,Cadena
               xor ecx,ecx
               mov eax,[Cadena]
               .bucle:
                   .if byte[eax+ecx] = 0
                       jmp .salir
                   .endif
                   xor byte[eax+ecx],7
                   inc ecx
                   jmp .bucle
               .salir:
               ret
            endp


Ejemplo de su uso:

Código (asm) [Seleccionar]
   include 'win32ax.inc'
   
   .data
           hola db 'hola',0
   
   .code
   start:
            stdcall Cifrar,hola
            invoke MessageBoxA,0,eax,0,0
            ret
   
            proc Cifrar,Cadena
               xor ecx,ecx
               mov eax,[Cadena]
               .bucle:
                   .if byte[eax+ecx] = 0
                       jmp .salir
                   .endif
                   xor byte[eax+ecx],7
                   inc ecx
                   jmp .bucle
               .salir:
               ret
            endp
   .end start    





Función que pasa un número entero a cadena:

Código (asm) [Seleccionar]
proc NumToString,Numero
               ;Función creada por Drinky94. Agradecimientos a Jep.
               locals
                       divisor dw ?
                       ; buffer rb 20  Agregar esta variable en la sección data
                       ; El numero 20 es la longitud que tendra la cadena
                       ;si nuestro numero tiene 4 cifras tendremos que poner 4
                       ; CadenaFinal rb 20  ; lo mismo que con la variable buffer.
               endl

               mov [divisor],10
               xor eax,eax
               xor ebx,ebx
               mov eax,[Numero]
               bucle:
                       xor edx,edx
                       div [divisor]
                       add dl,0x30
                       mov byte[buffer+ebx],dl
                       inc ebx
                       cmp eax,0
                           jne bucle
               inc ebx
               mov byte[buffer+ebx],0x0
               mov eax,buffer
               mov ecx,-1
               buclelen:
                       inc ecx
                       cmp byte[eax+ecx],0
                           jne buclelen
               xor ebx,ebx
               dec ecx
               reverse:
                       xor edx,edx
                       mov dl,byte[eax+ecx]
                       mov byte[CadenaFinal+ebx],dl
                       inc ebx
                       sub ecx,1
                       cmp ecx,-1
                           jne reverse
               mov eax,CadenaFinal
               ret
       endp  


Ejemplo de su uso:

Código (asm) [Seleccionar]
include 'win32ax.inc'

.data
       buffer rb 4
       CadenaFinal rb 4
.code
start:
       stdcall NumToString,1994
       invoke MessageBoxA,0,eax,0,0
       ret

       proc NumToString,Numero
               ;Función creada por Drinky94. Agradecimientos a Jep.
               locals
                       divisor dw ?
                       ; buffer rb 20  Agregar esta variable en la sección data
                       ; El numero 20 es la longitud que tendra la cadena
                       ;si nuestro numero tiene 4 cifras tendremos que poner 4
                       ; CadenaFinal rb 20  ; lo mismo que con la variable buffer.
               endl

               mov [divisor],10
               xor eax,eax
               xor ebx,ebx
               mov eax,[Numero]
               bucle:
                       xor edx,edx
                       div [divisor]
                       add dl,0x30
                       mov byte[buffer+ebx],dl
                       inc ebx
                       cmp eax,0
                           jne bucle
               inc ebx
               mov byte[buffer+ebx],0x0
               mov eax,buffer
               mov ecx,-1
               buclelen:
                       inc ecx
                       cmp byte[eax+ecx],0
                           jne buclelen
               xor ebx,ebx
               dec ecx
               reverse:
                       xor edx,edx
                       mov dl,byte[eax+ecx]
                       mov byte[CadenaFinal+ebx],dl
                       inc ebx
                       sub ecx,1
                       cmp ecx,-1
                           jne reverse
               mov eax,CadenaFinal
               ret
       endp
.end start      



Cuando valla haciendo mas las voi posteando :P

saludos.
Un byte a la izquierda.

hosuko

#1
Muy buen post. Yo también tengo una función para pasar de Hex a ASCII:


proc Conversor_ASCII2 uses ebx esi edi, datos
  mov   ecx, 3                   ;Pongo el contador a 3

  mov   eax, [datos]          ;Pongo en EAX el número a convertir
  mov   ebx, 0ah               ;Se tendrá que dividir entre 10 = 0Ah
.repetir:
  div   bl                           ;AL = Resultado, AH =resto = número que importa.
  mov   [Buffer+ecx], ah   ;Guardo aquí el resultado (AH).
  add   [Buffer+ecx],30h   ;Le sumamos 30 para que quede el código en ascii
  and   eax, 0ffh               ;Hacemos un filtro para dejar sólo AL (el resto)

  dec   ecx                       ;Restamos 1 al contador
  cmp   ecx, 0                  ;Lo comparamos con 0
  jl    .fuera                     ;Si es inferior se sale

jmp .repetir                     ;Repetimos la operación, solo que ECX ahora vale menos.

.fuera:
  mov   eax, dword [Buffer]   ;Ponemos en EAX el resultado.
  ret                                    ;Devolvemos el flujo del programa donde fue llamado
endp


La variable buffer la tengo definida asi:
Buffer   db 1

y para usar la función:
stdcall Conversor_ASCII2 , eax

donde EAX es el valor Hex a pasar. La función retorna en EAX el número en ASCII.

Ya os habreis dado cuenta que esta función está pensada para números de 4 dígitos solamente, el motivo es que la uso para visualizar las coordenadas del ratón asi como otros datos que no requieren números grandes.

   Se podría modificar para usar números más grandes, solamente que el valor no se devolvería en EAX sino en [Buffer].


fary

Ret Exe corruption

Código (asm) [Seleccionar]
;///////////////////////////////////////////////////////////////////////////////
;////  Ret Exe Corruption: corrompe los exe poniendo un 0xC3 (ret) en el    ////
;////  entry point. Este código no funciona con algunos ejecutables para    ////
;////  ello habría que hacer algunos modificaciones.                        ////
;////  Programado por Drinky94 a 13 - Septiembre - 2011                     ////
;///////////////////////////////////////////////////////////////////////////////

include 'win32ax.inc'

.data
        manija dd ?
        larchivo dd ?
        espacio dd ?
        bleidos dd ?

        PE dd ? ; puntero a NT

        EP dd ? ; EntryPoint
        wb dd ?
.code
start:
        invoke CreateFileA,'g:\bowser.exe', GENERIC_READ, FILE_SHARE_READ, 0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0
        mov [manija],eax

        invoke GetFileSize,[manija],0
        mov [larchivo],eax

        invoke GlobalAlloc,GPTR,[larchivo]
        mov [espacio],eax

        invoke ReadFile,[manija],[espacio],[larchivo],addr bleidos,0
        invoke CloseHandle,[manija]
        leave

        mov eax,[espacio]


        cmp word[eax],'MZ'
        jne salir

        mov ecx,eax

        add eax,dword[eax+0x3C] ; EAX = PE
        mov [PE],eax

        cmp word[eax],'PE'
        jne salir

        add eax,0x28

        mov ebx,dword[eax]
        mov [EP],ebx ;EP = EntryPoint

        mov ebx,ecx ; EAX = puntero inicio

        add ecx,[EP]
        mov word[ecx],0xC3

        ;// Aquí tendríamos que eliminar el viejo archivo y generar nuestro Exe modificado con el mismo nombre.

        invoke CreateFile,"g:\NuevoRET.exe",GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,0
        push eax
        invoke WriteFile,eax,ebx,[larchivo],wb,NULL
        pop eax
        invoke CloseHandle,eax

        invoke MessageBoxA,0,"FIN",0,0

        salir:
        leave
        ret
.end start
Un byte a la izquierda.