Решение ksydfius - Ksydfius Crackit I

Сложность: 2 – Needs a little brain (or luck)
Платформа: Windows
Язык: Assembler
Дано: Ksydfius Crackit I

Небольшой crackme, который можно решить за 1 секунду
(если знать, что делать…)
Не очень сложно, всего лишь чуточку ASM кода и битовых операций
-ksydfius-

Решение (автор freesoul)
опубликовано 14.09.2012

~~~~~~~~~~~~ ИНТРО

Здравствуйте. В этом crackme есть действительно забавная хитрость, которая может сбить вас с толку. Но об этом чуть позже. Кратко. Программа не имеет интерфейса. Пароль «зашит» по адресу 0x403000. Как туда внести пароль – проблема для пользователя. Можно написать загрузчик (что сделал автор решения), а можно внести в exe-файл через блокнот (благо, пароль как выяснится - текстовой). Длина пароля – 12 символов, т.е. 12 байт = три значения DWORD.
Задачка состоит из двух частей, одна - проверяет ваш пароль, а другая – раскодирует текст сообщения тем же самым паролем. В первой части, программа проверяет три жестко заданных двойных слова (DWORDS) с нашими тремя DWORDS.
Вся логика crackme умещается буквально в 100 байтах. Именно, реверс этого алгоритма нам и нужен.

~~~~~~~~~~~~ НАБРОСОК АЛГОРИТМА

image00.jpg

Приведенный алгоритм полностью обратим. Что мы и сделаем в следующей секции.

~~~~~~~~~~~~ РАЗБОР ПОЛЕТОВ

1. Итак, у нас два цикла. Внутренний цикл находится в функции 0040107C. Разберем его.
Функция 0040107C.

image01.jpg

Как видите, в обратном алгоритме отсутствует цикл. Тут все просто. Первое, значение в eax каждые 32 раза возвращает к исходному значению (циклический сдвиг вправо на 1 бит – ROR – «вращает» eax по кругу). Второе, результат цикла – это значение ecx, которое возвращает функция reverse(eax) на крайнем проходе цикла. Найдем чему равно eax перед вызовом reverse(eax) на последней итерации цикла:

(4096 – 1) % 32 = 31-я итерация цикла.
Тогда eax = ROR eax, 31 или eax = ROL eax, 1

Осталось разобраться с самой reverse(eax). Она на входе получает 32-хбитное значение, а на выходе – получаем ее обратное значение. Например, для 0x80000000 получим 0х00000001. Но! Так должно быть. На самом деле смотрим на код внимательно.

image02.jpg

Вывод немного удивительный. Последние 2 бита накладываются друг на друга (операция XOR) и записываются в 1-й бит. А 0-й бит всегда будет равен нулю.
Например, реверсим 0x80000000:
0x80000000 = 1000 0000 0000 0000 0000 0000 0000 0000
Должно получиться
0x00000001 = 0000 0000 0000 0000 0000 0000 0000 0001
А на самом деле

image032.jpg

Таким образом, обратным значение для 0x80000000 является 0x00000002.

2. Внешний цикл.

image04.jpg
~~~~~~~~~~~~ КЕЙГЕН

Функции циклического сдвига ROL и ROR я вынес в отдельный модуль bitop

# -*- coding: cp1251 -*-
import bitop
 
def int32tostr(eax):
    tostr = ""
    for i in range(4):
        tostr += chr(eax & 0xFF)
        eax >>= 8
    return tostr
 
def reverse(num, sizeop):
    res = 0
    curnum = num
    cnt = sizeop - 1
    while cnt >= 0:
        res ^= (curnum & 1) << cnt
        curnum = (curnum >> 1) & ((1 << sizeop) - 1)
        cnt -= 1
    return res
 
def decode(eax):
    ebx = 0xC0DEC0DE
    # ROL ebx, 7
    ebx = bitop.rol(ebx, 7, 32)
    for i in range(8):
        # eax = eax XOR ebx
        eax ^= ebx
        # ROR ebx, 1
        ebx = bitop.ror(ebx, 1, 32)
 
        # ROL eax, 1
        eax = bitop.rol(eax, 1, 32)
        # NOT eax
        eax = eax ^ 0xFFFFFFFF
 
        # получить реверс значения
        eax = reverse(eax, 32)
        # колдуем с последними битами
        lastbit_1 = eax & 1
        lastbit_2 = (eax & 2) >> 1
        eax = (eax & 0xFFFFFFFC) | ((lastbit_1 ^ lastbit_2) << 1)
    return eax
 
# Ищем пароль
password = ""
eax = 0x19496E48
password += int32tostr(decode(eax))
eax = 0x394A0F4E
password += int32tostr(decode(eax))
eax = 0x320D4F6E
password += int32tostr(decode(eax))
print ("Password: "+password)


Password: tRuEr3veRs1n
Пароль у нас на руках. Осталось совсем чуть-чуть. Т.к. программа не имеет интерфейса, то пароль надо добавить в exe-файл руками. Ручной вариант – самый простой. Открываем exe-файл в блокноте (я использую Notepad++). Находим строку passwordhere и заменяем на tRuEr3veRs1n. Сохраняем файл и запускаем.

image05.jpg
Пока не указано иное, содержимое этой страницы распространяется по лицензии Creative Commons Attribution-ShareAlike 3.0 License