Esecuzione di un breve script asm in linea per l'analisi dinamica

3

C'è qualche buona ragione per non eseguire un breve script di assemblaggio sconosciuto (30 righe) in linea in un programma usermode c per l'analisi dinamica direttamente sul mio portatile?

C'è solo una chiamata di sistema al tempo, e a questo punto posso dire che è una funzione che accetta una stringa e la sua lunghezza, ed esegue una sorta di crittografia su di essa in un ciclo, che scorre solo attraverso la stringa finché come dice l'argomento della lunghezza.

So che lo script è (supposto essere) da un codice malevolo, ma per la vita di me non riesco a pensare ad alcun modo in cui possa bloccare il mio computer escludendo una sorta di bug hardware (che sembra improbabile dato che il ciclo è lungo ~ 7 istruzioni e le istruzioni più strane dell'intero copione sono uno shr).

So che suona male eseguendo un pezzo sconosciuto di codice assembly direttamente sul metallo, ma vista la mia analisi fino a questo punto non riesco a pensare a nessun modo in cui potrebbe mordermi o fuggire.

    
posta comp.sci.intern 02.11.2018 - 18:11
fonte

1 risposta

3

C'è una ragione per cui non puoi studiare il codice? 30 linee di ASM dovrebbero essere facili da capire. Aggiungi solo commenti che spiegano cosa fa ogni linea e la capirai in pochissimo tempo. Ciò sarà ancora più semplice se si considera con quanta rapidità esattamente ciò che fa una singola istruzione.

Anche se sarei d'accordo sul fatto che è improbabile che sia in grado di fare qualcosa di pericoloso da solo con un solo syscall, non dovresti mai sottovalutare l'ingegno che alcuni sviluppatori possono avere. È perfettamente possibile progettare shellcode per ingannare un disassemblatore nel mostrare il codice che in realtà non è presente, come sottolineato da DEF CON alcuni anni fa. 30 linee di assemblaggio x86 sono sufficienti per un payload di stage 1.

È probabile che sia completamente innocuo. Non ci scommetterei la vita, comunque.

Puoi usare seccomp su Linux per isolarlo. Seccomp è una funzionalità Linux che filtra le chiamate di sistema. Esistono due modalità per seccomp, modalità 1 e modalità 2. La modalità Seccomp 1 è la modalità più rigida. Quando un programma attiva questa modalità, è limitato all'utilizzo di solo quattro syscalls codificate : read() , write() , exit() e rt_sigreturn() . La modalità 2 è più complessa e utilizza un filtro eBPF generato dallo spazio utente per specificare una whitelist personalizzata di syscall e argomenti syscall. Per un pezzo di shellcode molto semplice, avresti solo bisogno della modalità 1.

La modalità di attivazione 1 seccomp è semplice. Tratto da un'altra risposta ho scritto su un altro sito StackExchange, un programma di esempio che esegue in modo sicuro una funzione che restituisce 42 in bytecode:

#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <linux/seccomp.h>

/* "mov al,42; ret" aka "return 42" */
static const unsigned char code[] = "\xb0\x2a\xc3";

void main(void)
{
    int fd[2], ret;

    /* spawn child process, connected by a pipe */
    pipe(fd);
    if (fork() == 0) {
        close(fd[0]);

        /* enter mode 1 seccomp and execute untrusted bytecode */
        prctl(PR_SET_SECCOMP, SECCOMP_MODE_STRICT);
        ret = (*(uint8_t(*)())code)();

        /* send result over pipe, and exit */
        write(fd[1], &ret, sizeof(ret));
        syscall(SYS_exit, 0);
    } else {
        close(fd[1]);

        /* read the result from the pipe, and print it */
        read(fd[0], &ret, sizeof(ret));
        printf("untrusted bytecode returned %d\n", ret);
    }
}

Dovresti sostituire code[] con lo shellcode che vuoi testare.

Hai detto che c'è un syscall in time() . Sulla maggior parte dei sistemi Linux, questo non è un vero syscall, ma un vDSO . Se è in realtà un syscall diretto, è necessario utilizzare la modalità 2 seccomp e autorizzarla esplicitamente in whitelist. Per questo, vorresti usare libseccomp per astrarre la complessità.

    
risposta data 03.11.2018 - 05:11
fonte