Исследование простого crackme

Здравствуйте Хабралюди. В этом топике я расскажу как я исследовал простой crackme. Этот крякмис предназначен, в первую очередь, для новичков, желающих попрактиковаться в реверсинге. Я планирую продолжать цикл статей этой тематики, двигаясь постепенно от простого к сложному.

Начало


Итак, приступим.
Необходимые инструменты:
  • 1. Сам crackme (с crackmes.de)
  • 2. Отладчик (лично я использую Olly)

Для начала запустим крякми. Видим простую форму с двумя полями для ввода имени и регистрационного кода. Вводим фейковые данные и видим ругательное сообщение о том, что серийник неправилный.
Ситуация проясняется когда видим мы сообщение, вызванное функцией MessageBoxA, а сам текст из полей заносится в буффер функцией GetDlgItemTextA.

План действий


Итак дальнейший алгоритм действий:
1. Загружаем крякми в отладчик.
2. Ставим бряки на все вызовы функции MessageBoxA и GetDlgItemTextA (в Olly это делается нажатием сочитания клавиш Alt + F1 и вводом, в появившуюся форму, команды bpx %имя_функции% ).
3. Выполняем программу до бряка и: а) ищем место перехода на ветку с ругательным сообщением и меняем условный переход так, что бы мы переходили на ветку с «правильным» сообщением;
б) ищем место модификации имени в серийник, выясняем алгоритм шифровки и пишем кейген.
Мы пойдём по плану б, так как основная моя цель-это исследовать.

Антиотладочный код


Расставив бряки и запустив программу, мы видим то, что бряк на MessageBoxA сработал. Но какой ещё МесаджБокс, ведь запустив программу в первый раз без отладчика, мы не видели никакого мессаджа? Протрассировав программу на шаг вперёд(в Олли нажав F8), лицезреем следующее:
image
Выходит в нашем крякмисе есть антиотладочный код. Придётся его обойти. Прокручиваем код немного вверх и выясняем откуда был прыжок на наш «антиотладочный мессадж бокс». Вот кусок кода с этого места:

004027DA . 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
004027E0 . 8B40 30 MOV EAX,DWORD PTR DS:[EAX+30]
004027E3 . 8B40 18 MOV EAX,DWORD PTR DS:[EAX+18]
004027E6 . 8378 10 00 CMP DWORD PTR DS:[EAX+10],0
004027EA 75 01 JNZ SHORT crackme_.004027ED //вот отсюда и совершается прыжок


Придётся патчить. Изменяем команду JNZ (опкод 75) на JE (опкод 74). Применяем патч, перезапускаем прогу под отладчиком и не видим ругательного мессадж бокса.

Алгоритм


Вводим в поля фейковые данные (я вводил someuser:somepassword), и нажимаем на Check. И тут же срабатывает бряк на вызове функции GetDlgItemTextA. Вот этот участок кода:

00401D3E . E8 CD0D0000 CALL <JMP.&user32.GetDlgItemTextA> //вызов самой функции GetDlgItemTextA
00401D43 . BE 64404000 MOV ESI,crackme_.00404064 //помещаем в ESI указатель на полученное слово
00401D48 > 8006 01 ADD BYTE PTR DS:[ESI],1 //добавляем 1 байт к первому байту слова находящемуся по адресу расположенному в ESI
00401D4B . 83C6 02 ADD ESI,2 // добавляем в ESI 2, тем самым указатель в ESI теперь указывает на то же слово, но без первых двух символов
00401D4E . 803E 00 CMP BYTE PTR DS:[ESI],0 //указывает ли ESI на пустую строку
00401D51 .^75 F5 JNZ SHORT crackme_.00401D48 //если нет то "прыгаем" на 00401D48
00401D53 . E9 BB010000 JMP crackme_.00401F13 //если да то "прыгаем" на 00401F13

Таким образом, мы видим алгоритм шифровки Username.
Трассируя дальше, мы попадаем на следующий участок:

00401F1D . 81F9 00500000 CMP ECX,5000
00401F23 -7F FE JG SHORT crackme_.00401F23


На мой взгляд, это ещё один антиотладочный приём, поэтому заменяем JG на JE и спокойно трассируем дальше. И опять мы натыкаемся на бряк функции GetDlgItemTextA. В этот раз она считывает рег. код:

00401FE6 > E8 250B0000 CALL <JMP.&user32.GetDlgItemTextA> //снова вызов функции GetDlgItemTextA
00401FEB . BE 64404000 MOV ESI,crackme_.00404064 //помещаем в ESI указатель на шифрованное имя пользователя (читай на валидный рег. ключ)
00401FF0 . BF 64484000 MOV EDI,crackme_.00404864 //помещаем в EDI указатель на рег. ключ, который мы ввели
00401FF5 . 8B07 MOV EAX,DWORD PTR DS:[EDI] //помещаем в EAX первые четыре байта рег. ключа, который мы ввели
00401FF7 . 8B1E MOV EBX,DWORD PTR DS:[ESI] //помещаем в EBX первые четыре байта валидного рег. ключа
00401FF9 . 3BC3 CMP EAX,EBX //сравниваем их
00401FFB 0F85 C4020000 JNZ crackme_.004022C5 //если они не равны, то прыгаем на 004022C5
00402001 . 83C6 04 ADD ESI,4
00402004 . 83C7 04 ADD EDI,4
00402007 . 8B1E MOV EBX,DWORD PTR DS:[ESI] //помещаем в EBX первые четыре байта валидного рег. ключа
00402009 . 8B07 MOV EAX,DWORD PTR DS:[EDI] //помещаем в EAX следующие четыре байта рег. ключа, который мы ввели
0040200B . 3BC3 CMP EAX,EBX //сравниваем их
0040200D 0F85 B2020000 JNZ crackme_.004022C5 //если они не равны то прыгаем на 004022C5
00402013 . E9 5C000000 JMP crackme_.00402074 //если они равны то прыгаем на "правильную" ветку программы


Вывод

Таким образом, получается, что весь алгоритм шифрования — это замена каждого второго символа имени на символ, следующий в таблице ASCII.
Плюс к тому, программа проверяет только первые 8 символов серийника, что, соостветственно, является недостатком.

Кейген


А вот и кейген:
var
s:string;
i:integer;
c:char;
begin
readln(s);
while i<= length(s) do begin
Inc(s[i]);
i:=i+2;
end;
writeln(s);
end.

Спасибо за внимание.
P.S. Извините за Паскаль, другого компилятора не нашёл.
P.P.S. И извините за простоту.
+105
20 июля 2010, 10:24
94
ryadzori 23,0

комментарии (57)

+11
1amer #
такой кейгенми можно было ломать без трассировки вообще. также статья для начинающих но вы не описали как работает антиотладочный механизм.
Просто камент для читателей:
патчить JNZ было не обязательно т.к. цель — написание кейгена. можно было поправить ZF в момент перед прыжком. если бы цель была пропатчить программу то надежнее всего JNZ(и аргумент) заменить нопами — опкод 90h
+27
1amer #
И плюс вам в карму и в топик. за попытку вернуть хабру звание торта
+1
ryadzori #
согласен
«Этот крякмис предназначен в первую очередь для новичков...»
Конечно ZF можно было перевести это как один из вариантов, но я выбрал другой.
Спасибо вам за комментарий.
0
aceventura #
Автор топика мошенническим путем получил у меня инвайт, после получения извинившись за обман. Все ради того, чтобы опубликовать этот и я полагаю подобные материалы.
Видимо я уже старенький и чего-то в этой жизни не понимаю.
+3
borisko #
Расскажите, а как можно мошенническим путём получить инвайт?
+5
aceventura #
Было заключено соглашение об обмене инвайтами, но после выполнения моей части юзер сказал, что без хабра не мог жить и дышать и у него не было другого выхода кроме как кого-нибудь обмануть.
+3
hellomax #
Это юмор такой?
+2
aceventura #
Нет, все правда. Небольшие мои художественные украшения, в реальности это звучало так:

«простите конечно что вас обманул, но мне необходимо было попасть на хабр и это был мой единственный шанс. инвайта на [вырезано] у меня не было.»
НЛО прилетело и опубликовало эту надпись здесь
0
marcus #
Там же FS:[18] считывается, совсем по-пацански было бы подключить к Олли патчер IsDebuggerPresent :)
+6
DedalX #
JE, JNE… Вспомнились старые добрые времена и softice. Эх настольгия!
0
MARDEN #
Любопытно, кому-нибудь удалось завести софтайс на WinXP? Помню бился с ним, но так и не удалось заставить его должным образом работать. После перешел на Олли и забыл об айсе как о страшном сне :)
+1
DedalX #
А он там и не должен работать, он же на уровне ядра запускается и в XP он понятия не имеет как туда влезть там же все совсем по другом, службы и т.д. Странно что такая программа как softice перестала развиваться под новые версии ОС. Видимо с защитами и брандмауэрами, дефендерами и прочим появившимися с XP softice уже просто никак не сможет влезть к ядру не поломав всю систему.
+2
Aux #
Нет, дебаггер продолжил своё существование в виде DriverStudio. Просто в каждом новом релизе винды немножко меняется ядро и его API. Дебаггер работает как обычный драйвер. Дрова от 2K обычно не подходят к XP. Однако если они не используют меняющиеся API, то впихнуть можно руками. Собсно ниже даны ссылки, как впихнуть SoftICE.

Никаких защит нет. Если у пользователя есть права ставить Native Apps (Win32 лишь оболочка поверх NT, у NT свои собственные программы с Win32 несовместимые, дрова — один из типов Native Apps), то в ядро можно сунуть что угодно.
0
ryadzori #
да, куча статей по запуску сайса под хр
0
MARDEN #
Я многое перепробовал, но нормально работать с ним не получалось: то он клавиатуру не видел, то на бряки не срабатывал, то просто вешал комп.
НЛО прилетело и опубликовало эту надпись здесь
0
ryadzori #
+3
vilgeforce #
А зачем там Sice? Если нужна kernel-mode отладка — WinDBG, а еще лучше — IDA+WinDBG. Для юзермода хватает Olly.
НЛО прилетело и опубликовало эту надпись здесь
+2
MARDEN #
Истинные кейгены пишутся на асме :)
Для кейгена порой удобно копировать участки кода прямо из отладчика. Вот за что люблю Олли, так это за его удобство работы и плагины.

Кстати, было бы интересно почитать также про исследование протекторов (ASProtect, Armadillo и прочее).
0
Iwamoto #
вам на cracklab.ru
0
MARDEN #
На крэклабе уже давно не публикуется ничего нового. Теперь там рулит только форум.
+1
s1im #
Ох, сколько подобного прочел раньше на страницах ][акер-а, одной из первых статей была эта: www.xakep.ru/magazine/xa/080/070/1.asp
Кому интересно, со всеми статьями более подробно можно познакомиться здесь: www.xakep.ru/local/search/search.asp?text=crackme
+2
Scratch #
ждем статью о взломе VMProtect )
+2
Meliborn #
Кому интересна данная тема, советую добавить в закладки данный сайт, в свое время учился по нему, достаточно хорошие статьи.
+1
1amer #
ещё есть cracklab.ru
0
ValdikSS #
На Cracklab DVD 2007, вроде, есть мое видео по взлому какой-то программки, уже даже и не помню какой.
0
vallkor #
И штук двадцать моих статей :)
0
art_linux #
Эх, ностальгия :)
+1
Shark #
Почему ностальгия? Реверс инжиниринг и сейчас достаточно популярен и современен :)
0
art_linux #
я три года назад этим развлекался, да потом забросил :)
0
Shark #
На Windows 7 прога сразу пишет Debugger Found, причём никакой дебаггер я даже запустить не успел ;)
0
ryadzori #
интересно)
сам крякмис из раздела windows xp. Я подумал что юзеры семёрки, если захотят, заюзают режим совместимости
0
Levsha100 #
Совутую:
www.wasm.ru/ ==> Курс Рикардо Нарваха(к сожалению не знаю как правильно склонить) «Введение в крэкинг с нуля, используя OllyDbg»
+2
alienff #
Эээ. Я крякнул это с первой попытки, просто запустив прогу и вписав значения в поля…
0
alienff #
*вписав удачные значения в поля
0
Imposeren #
Шутите?(= Ну либо какой-то кусок вашего мозга находится в спутанном состоянии с куском мозга разработчика данного кракми
+3
alienff #
Нет, не шучу. Я вписал 1 и 2. Потом сообразил, что ответ — верхнее поле +1 =)
0
Imposeren #
И это для новичков? Что-то совсем для яслей )=
+3
nicosha #
Когда-то погрузился в вопросы кряков программ. На 3 дня полностью выпал из привычного ритма жизни. Но на 3-й день мне удалось взломать очень специфичный плагин для ms word, кряков на который не было вообще. Хочу сказать, что взлом программ очень увлекательный процесс, требующий терпения, концентрации и знаний.
НЛО прилетело и опубликовало эту надпись здесь
+4
degratnik #
Побольше таких статей.
+3
ryadzori #
будут. обещаю
0
allein #
>00401D48 > 8006 01 ADD BYTE PTR DS:[ESI],1 //добавляем 1 байт к первому байту слова находящемуся по адресу расположенному в ESI
Может быть 1 _бит_ добавляется к первому байту? Чтобы в итоге получить следующий символ в ASCII таблице?
0
Shark #
Наверное «прибавляем байт-единицу» имелось в виду.
0
nsinreal #
Вроде-бы прибавляем единицу к байту (не первый байт, а просто байт)
–1
barboss #
Статья заинтересовала, только с ассемблером совсем не знаком. Подскажите где познакомиться?

Вот кейген на C#:

  1. private string GeneratePassword()
  2.     {
  3.       string userName = txtUserName.Text;
  4.  
  5.       if (!String.IsNullOrEmpty(userName))
  6.       {
  7.         int i = 0;
  8.         StringBuilder pass = new StringBuilder();
  9.  
  10.         pass.Append(userName);
  11.  
  12.         while (i < userName.Length)
  13.         {
  14.           pass[i] = GetNextASCIISymbol(userName[i]);
  15.           i += 2;
  16.         }
  17.  
  18.         return pass.ToString();
  19.       }
  20.  
  21.       else
  22.       {
  23.         return String.Empty;
  24.       }
  25.     }
  26.  
  27.     private char GetNextASCIISymbol(char symbol)
  28.     {
  29.       int index = (int)symbol;
  30.       char result = Char.MinValue;
  31.  
  32.       index++;
  33.       result = Convert.ToChar(index);
  34.  
  35.       return result;
  36.     }
* This source code was highlighted with Source Code Highlighter.

0
ryadzori #
уже писали
wasm.ru
cracklab.ru
0
barboss #
Спасибо. Буду повнимательней в следующий раз.
0
Nitrogen #
если уж для новичков, то начинать надо с объяснения, что такое WinAPI, и почему getdlgitemtexta, messageboxa… а так да — слишком все просто.

удивительно, как меняется человек — несколько лет назад думал, что никогда это не брошу, а теперь изредка запускаю ida и то только, что бы пропатчить что ни будь, типа utorrent :-)

p.s. первые кейгены тоже писал на паскале, а потом понял, что гораздо проще рипнуть асм-код и использовать его в кейгене на асме :)
0
madflux #
А ну признавайтесь кто в 0DAY командах успел поучаствовать? :) Я каюсь, ломал, не корысти ради, ради количества :)
0
MARDEN #
Отдел К внимательно следит за постом :)
0
madflux #
Было бы желание… Проще внедриться в группу и взять всех, чем выискивать подозрительные комментарии на хабре, у человека которй в стороне давно. Да и смысла нет, были бы от правообладателей жалобы, типа 1С или Microsoft, а в 0DAY как раз этим этим никто не занимается.
0
zenden2k #
Есть некоторые программы, которые «крякнуть» даже проще, чем этот crackme.
Например, WinRAR, чтобы убрать надоедливое окошко, можно отлавливать таймер + функцию DialogBoxParam. Или можно просто удалить окошко из ресурсов с помощью ResHacker-a.
0
AndrewTishkin #
Автору: после слов «лицезреем следующее» не хватает цитирования куска кода
+1
ryadzori #
та картинка должна быть ;)
поправил спасибо

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.