SPAGHETTI HACKER

  1. WE BELEAF - bash
    log.016

    Tags
    re
    By AKIRA BASHO il 11 April 2023
     
    0 Comments   57 Views
    .
    nhkgvoN

    Arch: amd64-64-little
    RELRO: Full RELRO
    Stack: Canary found
    NX: NX enabled
    PIE: PIE enabled

    [0x000008a1]> pdf
    ;arg int argc @ rdi
    ;arg char **argv @ rsi
    ;var int64_t canary @ rbp-0x8
    ;var char *s @ rbp-0x90
    ;var uint32_t var_98h @ rbp-0x98
    ;var size_t var_a0h @ rbp-0xa0
    ;var int64_t var_a8h @ rbp-0xa8
    ;var int64_t var_b4h @ rbp-0xb4
    ;var char **var_c0h @ rbp-0xc0

    0x000008a1 push rbp
    0x000008a2 mov rbp, rsp
    0x000008a5 sub rsp, 0xc0
    0x000008ac mov dword [var_b4h], edi ;argc
    0x000008b2 mov qword [var_c0h], rsi ;argv
    0x000008b9 mov rax, qword fs:[0x28]
    0x000008c2 mov qword [canary], rax

    ;inizializzazione stack frame e stack canary

    0x000008c6 xor eax, eax
    0x000008c8 lea rdi, str.Enter_the_flag_n____ ;"Enter the flag\n>>> " ;const char *format
    0x000008cf mov eax, 0
    0x000008d4 call sym.imp.printf ;int printf(const char *format)

    ;printf

    0x000008d9 lea rax, [s]
    0x000008e0 mov rsi, rax
    0x000008e3 lea rdi, [0x00000a78] ;"%s" ;const char *format
    0x000008ea mov eax, 0
    0x000008ef call sym.imp.__isoc99_scanf ;int scanf(const char *format)

    ;scanf

    0x000008f4 lea rax, [s]
    0x000008fb mov rdi, rax ;const char *s
    0x000008fe call sym.imp.strlen ;size_t strlen(const char *s)

    ;strlen

    0x00000903 mov qword [var_a0h], rax
    0x0000090a cmp qword [var_a0h], 0x20
    0x00000912 ja 0x92a
    0x00000914 lea rdi, str.Incorrect_ ;"Incorrect!" ;const char *s
    0x0000091b call sym.imp.puts ;int puts(const char *s)

    ;se la stringa inserita è inferiore a 32 caratteri stampa la stringa "Incorrect!" ed esce

    0x00000920 mov edi, 1 ;int status
    0x00000925 call sym.imp.exit ;void exit(int status)

    ;exit

    0x0000092a mov qword [var_a8h], 0
    0x00000935 jmp 0x99d

    ;inizializza la variabile contatore var_a8h a 0 e salta

    0x00000937 lea rdx, [s]
    0x0000093e mov rax, qword [var_a8h]
    0x00000945 add rax, rdx
    0x00000948 movzx eax, byte [rax]
    0x0000094b movsx eax, al
    0x0000094e mov edi, eax ;int64_t arg1
    0x00000950 call fcn.000007fa

    ;prende il carattere iesimo della stringa inserita in input e lo passa alla funzione di trasformazione che ritorna un indice

    0x00000955 mov qword [var_98h], rax
    0x0000095c mov rax, qword [var_a8h]
    0x00000963 lea rdx, [rax*8]
    0x0000096b lea rax, [0x002014e0]
    0x00000972 mov rax, qword [rdx + rax]

    ;questo indice viene memorizzato nella variabile var_98h, poi in rax viene caricato il valore del contatore var_a8h, che viene moltiplicato per 8 e va a fungere da indice per l'array di indici che si trova in memoria all'indirizzo 0x002014e0; questo perchè i vari elementi dell'array a partire da quell'indirizzo sono separati da un offset di 8 byte;
    in rax viene calcolato con il mov rax, qword [rdx+rax] un altro indice che viene poi confrontato con quello ritornato dalla funzione di trasformazione

    0x00000976 cmp qword [var_98h], rax
    0x0000097d je 0x995

    ;i due indici vengono confrontati e se sono uguali il processo continua altrimenti, viene stampata la stringa "Incorrect!" e il processo esce

    0x0000097f lea rdi, str.Incorrect_ ;"Incorrect!" ; const char *s
    0x00000986 call sym.imp.puts ;int puts(const char *s)
    0x0000098b mov edi, 1 ;int status
    0x00000990 call sym.imp.exit ;void exit(int status)
    0x00000995 add qword [var_a8h], 1
    0x0000099d mov rax, qword [var_a8h]
    0x000009a4 cmp rax, qword [var_a0h]
    0x000009ab jb 0x937

    ;questo viene fatto per tutti i caratteri della stringa, man mano che il contatore in var_a8h viene incrementato; se viene raggiunto l'ultimo carattere della stringa senza che ci sia stata un'exit dovuta a una comparazione fallita, viene stampata la stringa "Correct!", poi viene fatto un controllo sul canarino nello stack e successivamente il processo termina

    0x000009ad lea rdi, str.Correct_ ; 0xa86 ; "Correct!" ; const char *s
    0x000009b4 call sym.imp.puts ;int puts(const char *s)
    0x000009b9 mov eax, 0
    0x000009be mov rcx, qword [canary]
    0x000009c2 xor rcx, qword fs:[0x28]
    0x000009cb je 0x9d2
    0x000009cd call sym.imp.__stack_chk_fail ;void __stack_chk_fail(void)
    0x000009d2 leave
    0x000009d3 ret

    ;la funzione di trasformazione, va a cercare il carattere in ingresso nell'insieme di caratteri presente in memoria e ritorna un indice per l'altro insieme di dati presenti a partire dall'altra locazione di memoria; inizia a cercare il carattere calcolando un nuovo indice a seconda se il carattere in ingresso è maggiore o minore del carattere iesimo, fino a quando non lo trova o fino a quando diventa troppo grande e cambia di segno essendo un long con segno;

    [0x000008a1]> s fcn.000007fa
    [0x000007fa]> pdf

    ; arg int64_t arg1 @ rdi
    ; var uint32_t var_8h @ rbp-0x8
    ; var int64_t var_14h @ rbp-0x14
    0x000007fa push rbp
    0x000007fb mov rbp, rsp
    0x000007fe mov eax, edi ;arg1
    0x00000800 mov byte [var_14h], al
    0x00000803 mov qword [var_8h], 0
    0x0000080b jmp 0x890

    ;carica in var_14h l'argomento passato alla funzione, il carattere iesimo della stringa di input, e in var_8h il valore 0 e salta a 0x890

    0x00000810 movsx edx, byte [var_14h]
    0x00000814 mov rax, qword [var_8h]
    0x00000818 lea rcx, [rax*4]
    0x00000820 lea rax, str.wf_ny ;0x201020

    ;0x00201020 7 32 .data utf32le wf{_ny}
    ;rax funge da indice per l'array di caratteri che si trovano a partire dall'indirizzo 0x201020; ogni carattere è separato dal successivo da 4 byte, per questo rax viene moltiplicato per 4;

    0x00000827 mov eax, dword [rcx + rax]
    0x0000082a cmp edx, eax
    0x0000082c jne 0x834

    ;c'è una comparazione tra il carattere in input e eax, se non sono uguali salta, altrimenti mette in rax l'indice ed esce

    0x0000082e mov rax, qword [var_8h]
    0x00000832 jmp 0x89f

    ;mette in rax il contatore e salta a 0x89f per uscire

    0x00000834 movsx edx, byte [var_14h]
    0x00000838 mov rax, qword [var_8h]
    0x0000083c lea rcx, [rax*4]
    0x00000844 lea rax, str.wf_ny ;0x201020
    0x0000084b mov eax, dword [rcx + rax]
    0x0000084e cmp edx, eax
    0x00000850 jge 0x863

    ;qui controlla se il valore del byte in ingresso è maggiore o uguale al carattere in ingresso, in caso salta a 0x863; altrimenti calcola l'indice di ritorno in questo modo :
    ;i = (i*2)+1

    0x00000852 mov rax, qword [var_8h]
    0x00000856 add rax, rax
    0x00000859 add rax, 1
    0x0000085d mov qword [var_8h], rax
    0x00000861 jmp 0x890

    ;incrementa il contatore e poi salta alla condizione del loop

    0x00000863 movsx edx, byte [var_14h]
    0x00000867 mov rax, qword [var_8h]
    0x0000086b lea rcx, [rax*4]
    0x00000873 lea rax, str.wf_ny ;0x201020
    0x0000087a mov eax, dword [rcx + rax]
    0x0000087d cmp edx, eax
    0x0000087f jle 0x890

    ;qui va a comparare il carattere in ingresso con quello calcolato dall'indice e controlla se è minore o uguale al carattere e salta in caso

    0x00000881 mov rax, qword [var_8h]
    0x00000885 add rax, 1
    0x00000889 add rax, rax
    0x0000088c mov qword [var_8h], rax

    ;altrimenti calcola il indice di ritorno in questo modo :
    ;i = (i+1)*2
    ;incrementa il contatore

    0x00000890 cmp qword [var_8h], 0xffffffffffffffff
    0x00000895 jne 0x810

    ;fa la comparazione tra var_8h e -1 e torna indietro in caso i due valori non siano uguali

    0x0000089b mov rax, qword [var_8h]
    0x0000089f pop rbp
    0x000008a0 ret

    ;esce dopo aver inserito il nuovo indice in rax; la funzione di trasformazione per ogni carattere in ingresso va a trovare un indice, il suo valore di ritorno, che confronta successivamente con i vari indici presenti nell'altra locazione di memoria che rappresentano la flag;

    [0x000007fa]> iz
    [Strings]
    nth paddr vaddr len size section type string
    ――――――――――――――――――――――――――――――――――――――――――――――
    0 0x00000a64 0x00000a64 19 20 .rodata ascii Enter the flag\n>>>
    1 0x00000a7b 0x00000a7b 10 11 .rodata ascii Incorrect!
    2 0x00000a86 0x00000a86 8 9 .rodata ascii Correct!
    0 0x00001020 0x00201020 7 32 .data utf32le wf{_ny}

    undefined8 main(void)

    {
    size_t inputLen;
    long transformedInput;
    long in_FS_OFFSET;
    ulong i;
    char input [136];
    long stackCanary;

    stackCanary = *(long *)(in_FS_OFFSET + 0x28);
    printf("Enter the flag\n>>> ");
    __isoc99_scanf(&DAT_00100a78,input);
    inputLen = strlen(input);

    if (inputLen < 0x21) {
    puts("Incorrect!");
    /* WARNING: Subroutine does not return */
    exit(1);
    }

    i = 0;
    while (i < inputLen) {
    transformedInput = transformFunc(input[i]);
    if (transformedInput != *(long *)(&desiredOutput + i * 8)) {
    puts("Incorrect!");
    /* WARNING: Subroutine does not return */
    exit(1);
    }
    i = i + 1;
    }
    puts("Correct!");
    if (stackCanary != *(long *)(in_FS_OFFSET + 0x28)) {
    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
    }
    return 0;
    }

    long transformFunc(char input)

    {
    long i;

    i = 0;
    while ((i != -1 && ((int)input != *(int *)(&lookup + i * 4)))) {
    if ((int)input < *(int *)(&lookup + i * 4)) {
    i = i * 2 + 1;
    }
    else {
    if (*(int *)(&lookup + i * 4) < (int)input) {
    i = (i + 1) * 2;
    }
    }
    }
    return i;
    }
    V8mXM3L
    ;01 09 11 27 02 00 12 03 08 12 09 12 11 01
    ;f l a g
    ;flag{we_beleaf_in_your_re_future}


    Edited by HCF - 27/4/2024, 20:16
      Share  
     
    .