SPAGHETTI HACKER

  1. CRACKED - HCF

    Tags
    re
    By HCF il 25 April 2024
     
    0 Comments   16 Views
    .
    Au8tLPx%202-17020512346063-17055769137546-17062097000480

    [0x00001275]> pdf
    CheckPassword_std::__cxx11::basic_string_char__std::char_traits_char___std::allocator_char____ (int64_t arg1);

    ;arg int64_t arg1 @ rdi
    ;var uint32_t var_14h @ rbp-0x14
    ;var int64_t var_18h @ rbp-0x18
    ;var signed int64_t var_1ch @ rbp-0x1c
    ;var int64_t var_1dh @ rbp-0x1d
    ;var int64_t var_40h @ rbp-0x40
    ;var int64_t var_60h @ rbp-0x60
    ;var int64_t var_68h @ rbp-0x68

    push rbp
    mov rbp, rsp
    push r12
    push rbx
    sub rsp, 0x60

    ;il prologo della funzione prepara lo stack e i registri per l'esecuzione della funzione stessa, salvando i registri necessari e allocando spazio per le variabili locali nello stack.

    mov qword [var_68h], rdi ; arg1
    lea rax, [var_1dh]
    mov rdi, rax
    call sym std::allocator<char>::allocator()

    ;call sym std::allocator<char>::allocator(): Questa istruzione effettua una chiamata alla funzione std::allocator<char>::allocator(), che è il costruttore della classe std::allocator<char>. Questo costruttore è tipicamente responsabile dell'inizializzazione dell'allocator, che gestisce l'allocazione e la deallocazione della memoria per gli oggetti della classe std::allocator.

    lea rdx, [var_1dh]
    lea rax, [var_40h]
    lea rsi, [0x00002005] ; "dec"
    mov rdi, rax
    call method std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)

    ;questo codice crea un oggetto std::string contenente la stringa "dec" utilizzando un costruttore specifico che accetta una stringa costante di caratteri come input. Nella memoria puntata da var_40h viene copiata la stringa "dec"

    lea rax, [var_1dh]
    mov rdi, rax
    call fcn.000010f0
    mov dword [var_18h], 0xfffffff9 ; 4294967289

    ;in var_18h viene caricato il valore -7, che verrà utilizzato, dopo il cambio di segno, per il confronto con la lunghezza della password passata come parametro alla funzione CheckPassword.

    lea rax, [var_40h]
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const

    ;questo blocco serve per calcolare la lunghezza della stringa "dec", che viene poi immagazzinata in var_1ch.

    mov dword [var_1ch], eax
    mov rax, qword [var_68h]
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const

    ;viene calcolata la lunghezza della stringa passata come parametro alla funzione CheckPassword; lunghezza che viene immagazzinata nel registro rdx.

    mov rdx, rax
    mov eax, dword [var_18h]
    neg eax
    cdqe
    cmp rdx, rax
    sete al
    test al, al
    je 0x13c8

    ;il valore -7 viene convertito in 7 e poi comparato alla lunghezza della stringa in input; se la password passata alla funzione CheckPassword non ha una lunghezza di 7 caratteri, la funzione ritorna con un esito negativo.

    lea rax, [var_60h]
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()

    ;viene allocata memoria per una stringa puntata dalla variabile var_60h.

    mov dword [var_14h], 0
    mov eax, dword [var_14h]
    cmp eax, dword [var_1ch]
    jge 0x1368

    ;questo è il check del loop, viene prima inizializzato l'indice var_14h a zero poi confrontato con la lunghezza della stringa "dec" che è 3; quindi ci saranno 3 iterazioni, l'iterazione relativa all'indice 0, quella relativa all'indice 1 e quella relativa all'indice 2; quando eax diventerà maggiore o uguale a 3, il loop sarà terminato.

    mov eax, dword [var_1ch]
    sub eax, 1
    cmp dword [var_14h], eax
    jne 0x1339

    ;controlla se l'indice contenuto in var_14h è uguale alla lunghezza di "dec"-1, quindi è uguale a 2; in questo caso si entra in un branch che concatena al buffer var_60h, prima la lettera "k" e poi la stringa "car".

    lea rax, [var_60h]
    lea rsi, [0x00002009] ; "k"
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char const*)

    lea rax, [var_60h]
    lea rsi, [0x0000200b] ; "car"
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char const*)
    ;ha effettuato l'append delle stringhe "k" e "car" nel buffer var_60h

    mov eax, dword [var_14h]
    movsxd rdx, eax
    lea rax, [var_40h]
    mov rsi, rdx
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::at(unsigned long)

    ;metodo at(unsigned long): questo metodo è utilizzato per accedere al carattere all'indice specificato all'interno della stringa. Prende un parametro unsigned long che rappresenta l'indice del carattere che si desidera ottenere. Ad esempio, string.at(0) restituirà il primo carattere della stringa.

    movzx eax, byte [rax]
    movsx edx, al
    lea rax, [var_60h]
    mov esi, edx
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char)
    add dword [var_14h], 1
    jmp 0x1300

    ;se l'indicè è zero viene aggiunta la "d" di "dec" a var_60h, se è 1 la "e", se è 2 vengono aggiunti prima "k" e poi "car" e infine la c; quindi terminato il loop nella memoria puntata da var_60h troveremo la stringa "dekcarc"

    mov rax, qword [var_68h]
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::end()

    mov rbx, rax
    mov rax, qword [var_68h]
    mov rdi, rax
    call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::begin()

    mov rsi, rbx
    mov rdi, rax
    call method void std::reverse<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >)

    lea rdx, [var_60h]
    mov rax, qword [var_68h]
    mov rsi, rdx
    mov rdi, rax
    call method __gnu_cxx::__enable_if<std::__is_char<char>::__value, bool>::__type std::operator==<char>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)

    ;questi tre blocchi servono a calcolare gli iteratori di inizio e fine stringa della password, che vengono poi passati con parametri alla funzione reverse che inverte la stringa di input per poi confrontarla con la stringa creata precedentemente "dekcarc"; quindi la password passata in input alla funzione CheckPassword deve essere lunga 7 caratteri e deve corrispondere a "cracked" che invertita diventa proprio "dekcarc"

    test al, al
    je 0x13b2
    mov r12d, 1
    mov ebx, 0
    jmp 0x13b7
    mov ebx, 1

    ;a seconda che le due stringhe siano uguali o meno viene settato il registro r12d a 0 o a 1, il cui valore viene poi immagazzinato in rax che è il valore di uscita della funzione CheckPassword.

    lea rax, [var_60h]
    mov rdi, rax
    call fcn.00001070
    cmp ebx, 1
    jne 0x13ce

    mov r12d, 0

    lea rax, [var_40h]
    mov rdi, rax
    call fcn.00001070
    mov eax, r12d
    jmp 0x141f

    add rsp, 0x60
    pop rbx
    pop r12
    pop rbp
    ret

    ./crackme
    Enter the password:
    cracked
    Login successful

    #include <iostream>
    #include <string>
    #include <algorithm> // Per std::reverse

    bool checkPassword(std::string input) {
    std::string dec = "dec";

    if (input.length() == 7) {
    std::string buffer = "";
    for (size_t i = 0; i < dec.length(); i++) {
    if (i == dec.length() - 1) {
    buffer += "k";
    buffer += "car";
    }
    buffer += dec.at(i);
    }
    std::reverse(buffer.begin(), buffer.end());
    if (input == buffer) {
    return true;
    }
    }
    return false;
    }

    int main(void) {
    std::string input;
    std::cout << "Enter the password:" << std::endl;
    std::cin >> input;
    if (!checkPassword(input)) {
    std::cout << "Login failed" << std::endl;
    } else {
    std::cout << "Login successful" << std::endl;
    }
    return 0;
    }

    [0x00001275]> pds
    0x00001275 checkPassword(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
    0x00001280 arg1
    0x0000128b call sym std::allocator<char>::allocator()
    0x00001298 "dec"
    0x000012a2 call method std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)
    0x000012ae call fcn.000010f0 fcn.000010f0
    0x000012c1 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const
    0x000012d0 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::length() const
    0x000012f4 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string()
    0x00001321 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char const*)
    0x0000132a "car"
    0x00001334 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char const*)
    0x00001349 call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::at(unsigned long)
    0x0000135d call sym std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::operator+=(char)


    Edited by HCF - 27/4/2024, 19:54
      Share  
     
    .