+ Reply to Thread
Results 1 to 1 of 1

Thread: Разбор crackserial_linux

  1. #1

    Default Разбор crackserial_linux

    По просьбе @petrucho выкладываю здесь свое решение крэкми с занятия в МТУ 25.10.

    1. Описание
    Дан файл crackserial_linux. При запуске запрашивает имя юзера и серийный номер, в случае верного ввода выводит Good Job, в противном случае - Try Again. Необходимо разобрать алгоритм проверки вводимых данных
    Для решения задачи будут использоваться:
    1. IDA 32-bit
      Для дизассемблирования
    2. g++
      Для компиляции кейгена

    Поскольку это исполнемый 32-х битный файл, запустим IDA и разберем его.


    2. Разбор
    IDA определяет формат данного файла как исполняемый файл как 32х битный ELF.
    Перед нами оказывается дизассемблированный код и найденные функции. Откроем окно со строками, обнаружим там уже известные значения User, Serial и тд и перейдем в функцию sub_8048A41, где они используются и начнем разбор.





    После беглого осмотра становится понятно, что функция sub_8048A41 выполняет всю логику работы программы и осуществляет обработку данных и выход из нее. Для удобства переименуем ее в main.

    Дале пойдем по порядку. Обратим внимание на метку loc_8048A61. По этому адресу у нас используется строка "User", далее вызываются оператор >> (вывода потока) с параметрами cout и этой строкой, что означает вывод на экран слова User. После этого вызывается функция getline, в результате работы которой введенные нами данные помещаются в [esp+10h] (строка 8048A89). После этого введенная нами строка перемещается в eax и вызывается функция length, возвращающая ее длину, которая помещается в [esp+1ch]. После этого полученная длина сравнивается с 2 и 30 и если она не попадает в этот диапазон, то происходит перемещение на метку loc_8048A61 и вся процедура повторяется.
    Из этого запутанного описания можно сделать один простой вывод - имя пользователя должно больше 2 и меньше 30 символов в длину.

    Далее, видим аналогичный вывод на экран строки Serial, вызовы операторов работы с потоками, о которых позднее, после чего видим вызов некоей функции(sub_80489CD), результат которой определяет, успешно ли наши данные прошли проверку или нет.

    N.B. В языке С++ - string - это класс, поэтому все функции работы со строками имеют подобный префикс - _zStl.

    Обратим внимание на строку 0848ACA. В ней вызывается функция sub_8048CC1 (адрес 8048ABB), имеющая сигнатуру istream& operator>> (ios_base& (*pf)(ios_base&)) - где pf - это так называемый манипулятор, то есть функция занимающаяся не извлечением данных из потока, а его изменением. Далее, в этот поток отправляется введенный нами серийный номер. После этого вызывается конструктор копирования (8048AF2) и вызывается функция sub_80489CD, которая в качестве параметров берет ссылку на введеный нами username и некое число, полученное в результате ввода нами серийного номера и обработанное функцией 8048СС1. Работа функции sub_80489CD определяет исход работы программы.
    Отсюда следует, что нам необходимо разобрать работу двух функций - sub_80489CD и sub_8048CC1.

    3. Функция sub_8048CC1
    Перейдем в эту функцию. Переименуем ее в strange_func
    Как мы видим, она добавляет в стэк числа 74 (4Ah), 8 и указатель на наш аргумент и вызывает функцию sub_8048C6C. Далее, кладем в eax указатель на наш аргумент и выходим из функции. Раз наш аргумент используется - идем в функцию sub_8048C6C.
    Как мы видим в строках 0848C72 - 0848C78 и 0848CBC, функция берет указатель на наш аргумент, берет 12й байт и начинает производить с ним манипуляции. Однако, в конце работы нам опять возвращается по указателю значение [ebp + var_C], из чего я сделал вывод о том, что функция не влияет на вводимый нами результат.
    N.B. Вывод довольно поспешный, но я немного схитрил и запустил все в динамике, после чего убедился, что вводимый нами серийный номер никаким образом не меняется после работы этой функции.

    Таким образом остается только одна функция
    4. Функция sub_80489CD

    На скриншоте уже переименованы переменный и описаны шаги работы алгоритма.
    На входе функция получает наш юзернейм и серийный номер. Далее, заводятся локальные переменные индекс, некое значение magic и значение для хранения промежуточного результата. После чего magic присваивается 0x4E504700, index/tmp_result - 0. Далее, по адресу 8048A21 происходит сравнение величины текущего значения индекса и длины строки-аргумента. Если индекс меньше - прыгаем на 80489EA. По этому адресу происходит взятие i-го элемента строки, xor со значением magic, умножение на 8 и вычитание (т.о. просто умножение на 7). Полученный результат записывается в magic, а потом прибавляется в tmp_result.

    Далее, когда проверка на длину не проходит, то есть когда размер индекса равен длине строки, происходит проверка условия равенства второго аргумента(нашего серийного номера) и полученного tmp_result. Если они равны, то далее в программе происходит прыжок на ветку кода, выводящую Good Job.

    Таким образом можно написать простой keygen, генерирующий правильный серийный номер по заданном имени пользователя:
    Code:
    #include <string>
    #include <inttypes.h>
    #include <iostream>
    #include <stdint.h>
    #include <stdio.h>
    
    
    void secretfunc(std::string* a1);
    
    using namespace std;
    
    
    
    int main() 
    {
        string username;
        for (int i=0; i < 2 || i > 30  ; i=username.length())
        {
            cout<<"User: ";
            cin>>username;
        }
        secretfunc(&username); 
        return 0;
    }
    
    
    
    
    void secretfunc(std::string* a1)
    {
        uint32_t tmp_result=0;
        uint32_t MAGIC = 0x4E504700;
    
        for (int i=0; (*a1).length()>i;i++)
        {
            MAGIC = 7*(((*a1).at(i))^MAGIC);
            tmp_result+=MAGIC;
        }
        printf("Serial for user %s is %x\n",(*a1).c_str(),tmp_result);
        return;
    }

    Спасибо за внимание!

    P.S. Разбором и подробным описанием занимаюсь впервые, огромная просьба, подскажите, на какие моменты следует обратить внимание, может, что то было сделано неверно, хотелось бы улучшать качество работы.

  2. 5 пользователя(ей) сказали cпасибо:
    Darwin (29-10-2017) korsader (30-10-2017) petrucho (29-10-2017) ximera (30-10-2017) yashechka (30-10-2017)
+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 01:21
vBulletin® Copyright ©2000 - 2018
www.reverse4you.org