Как только я нашел OEP и начал трассировать то увидел кол,на котором меня крашит
(для того что бы обойти этот прием достаточно его занопить)
Так же,в OEP,я заметил инструкции,которые рандомизируют некоторые регистры
Дальше идут ненужные сисколы,большинство из которых просто аллоцируют память(каюсь,я не уделял им должного внимания)
После этого идет некая "преинициализация" адресов и значений,с которыми мне,в последующем,пришлось работать
Далее,после всех сисколов,идет инструкция call eax,зайдя в который мы попадем в сам "алгоритм".
Первые строки,а если быть точнее,первые строки до прыжка,который разделял программу на несколько блоков - и есть инициализация адреса со строками :
1)пароль (записывался как : 1 байт = его длинна +1,дальше шли аски символы)
for example : Я вводил 1111,получал на выходе байты 05 31 31 31 31
2)строка .good в том же формате,что и пароль (1 байт - длинна +1,аски символы)
3)строка .bad в том же формате,что и предыдущие.
Кол,который как раз таки разделял программу в зависимости от значения регистра EAX у меня помечен как "enumeration".
Возвращал он значение,от которого зависело,в какой блок программы мы сейчас попадем для примера :
,
1 блок.
В нем не было ничего примечательного,он просто возвращал значение,которое потом было задействовано в коле "enumeration". Прикреплю скрин с IDA
,
2 блок.
В нем уже был задействован пароль,правда,никаких данных для решения данного крякми не было.
Был цикл,который к значению ASCII символа текущего индекса пароля прибавлялось 2.
Помимо этого,он как и первый блок возвращал значение,которое потом было задействовано в коле "enumeration". Прикреплю скрин с IDA
,
3 блок.
В этом блоке выполнялась операция,обратная операции что была ранее(если до этого к значению ASCII символа прибавлялось 2,то в тут все вставало на свои места)
Помимо этого,он как и первый блок возвращал значение,которое потом было задействовано в коле "enumeration".
4 блок.
В нем как раз таки и перебирался в цикле наш пароль.
В чем суть?
второй по счету кол в этой функции возвращал нам в EAX значение 0x75 (ascii "u"),дальше помещал результат в R11.
В цикле происходило деление ascii значения НАШЕГО символа и 0x75,соответственно,если 75 : 75 мы получаем 1,и у нас в наш некий "счетчик"(зачение R8) прибавлялось по одному
На выходе из цикла перебора результат помещался в EAX(помещалась разыменованная переменная(в иде будет видно. Как выйти в дампе на разименованную переменную я думаю объяснять не надо))
Собственно,при вводе пароля "1234" я получил там вот такое значение
5 блок.
Здесь мое внимание упало на предпоследнюю строку,которая означало то,что в значение по адресу RSI+38 кидалось значение нашего "счетчика",отнятое от 7(т.к первый байт это всегда длинна пароля + 1),и больше нигде не перезаписывалось
,
6 блок.
в нем уже было сравнение полученного значения в 5 блоке и 0.
,
дальше нас кидало в цикл вывода результата проверки двумя путями,в зависимости от :
1)если проверка пройдена успешно,то в EDI кидалось значение,которое было в EAX(оно помечено как temporary_dynamical_counter).
2)если проверка не пройдена(пароль неверный) то в temporary_dynamical_counter просто прибавлялась единичка.
Итог.
Таким образом,если мы получали максимальное число temporary_dynamical_counter's,то значение,которое высчитывалось путем сложения EAX + RCX * 4 - возвращало - 14FD29
В противном случае - это было 14FD2A
и ксорилось с RSI (14FE80) в функции enumeration
.
Кстати,вот так она выглядит при последнем ее взаимодействии с программой перед выводом результата(good\bad)
Вот и все!
Если полученный результат был равен 1,а потом прибавлялся к самому себе,то на выходе мы получали 2 и выводилась "вторая строка"
,в которой было слово "good",в противном случае,выводилось bad.
result :