Os dejo algunas funciones en FASM que e ido haciendo desde que empece con asm.
Función que compara dos cadenas:
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:
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:
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:
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:
proc DGlobalAlloc,cantidad
sub esp,[cantidad]
mov eax,esp
ret
endp
Ejemplo de su uso:
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):
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:
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:
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:
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:
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.
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].
Ret Exe corruption
;///////////////////////////////////////////////////////////////////////////////
;//// 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