Х-конкурс GpCH (www.dotfix.net) Хакер, номер #082, стр. 082-074-2 00406116 85 DB 85 00406117 68 DB 68 ;CHAR 'h' 00406118 FD DB FD 00406119 FF DB FF 0040611A FF DB FF Олька после распаковки программы не смогла автоматически опознать код, поэтому нажми Ctrl+A. Начало кода теперь примет вид: 0040610E . 8D85 58FDFFFF LEA EAX,DWORD PTR SS:[EBP-2A8] пролистни код чуток вверх и ты увидишь: 004060EB . 8D85 A8F6FFFF LEA EAX,DWORD PTR SS:[EBP-958] 004060F1 . 50 PUSH EAX 004060F2 . 8D85 B8F6FFFF LEA EAX,DWORD PTR SS:[EBP-948] 004060F8 . 50 PUSH EAX 004060F9 . 8D85 C8F6FFFF LEA EAX,DWORD PTR SS:[EBP-938] 004060FF . 50 PUSH EAX 00406100 . 6A 40 PUSH 40 00406102 . 8D85 D8F6FFFF LEA EAX,DWORD PTR SS:[EBP-928] 00406108 . 50 PUSH EAX 00406109 . E8 2EB2FFFF CALL CrackMe.0040133C Выше расположена процедура проверки серийника. Она большая из-за того, что я специально замусорил код при написании CrackMe для усложнения его анализа. Пройдя несколько экранов вверх, мы найдем проверку длины имени пользователя: 00404286 . E8 CFD0FFFF CALL CrackMe.0040135A 0040428B . 33C9 XOR ECX,ECX 0040428D . 83F8 04 CMP EAX,4 Ниже расположена процедура проверки длины пароля: 00404A7E . E8 D7C8FFFF CALL CrackMe.0040135A 00404A83 . 33C9 XOR ECX,ECX 00404A85 . 83F8 0A CMP EAX,0A Несмотря на то, что пароль должен быть не менее 10 символов, немного проанализировав программу, мы поймем, что больше 10 символов он также не может быть. Потому условимся: имя - более трех символов, пароль - ровно 10 символов. После проверок идет процедура преобразования имени пользователя и пароля. Этот код на PHP выглядел бы так: так выглядит преобразование имени и пароля на php //преобразуем имя пользователя $strName for ($i=0;$i for ($j=strlen($strName)-1;$j>gt;-1;$j--) { $sText .= (ord(substr($strName, $i, 1)) ^ ord(substr($strName, $j, 1))); } } //делаем полученный хэш от имени кратным 10 $sTXT = $sText.substr("0000000000", 1, ((floor(strlen($sText) / 10) * 10) + 10) - strlen($sText)); $sPass = substr($sTXT, 0, 10); $sText = ""; //криптуем хэш имени первыми 10 символами хэша имени for ($i=9;$i for($j=0;$j $sXOR = (substr($sPass, $j, 1) ^ substr($sTXT, $i + $j + 1, 1)); if (strlen($sXOR) >gt; 1) $sXOR = substr($sXOR,0,1); $sText .= $sXOR; } $sPass = $sText; sText = ""; } //получаем имя функции регистрации из пароля $strPass for($i=0;$i $code = $code.chr(substr($sPass, $i, 1) ^ ord(substr($strPass, $i, 1))); } После этого $code вызывается как функция. Для этого в VB есть функция CallByName. В нашем крэкми ее вызов мы найдем тут: 0040568A . E8 65BCFFFF CALL CrackMe.004012F4 0040568F . 50 PUSH EAX 00405690 . FF35 10304100 PUSH DWORD PTR DS:[413010] 00405696 . 8D85 38FFFFFF LEA EAX,DWORD PTR SS:[EBP-C8] 0040569C . 50 PUSH EAX 0040569D . E8 ECBBFFFF CALL CrackMe.0040128E 004056A2 . 50 PUSH EAX 004056A3 . 8D85 28FFFFFF LEA EAX,DWORD PTR SS:[EBP-D8] 004056A9 . 50 PUSH EAX 004056AA . E8 EBBBFFFF CALL CrackMe.0040129A 004056AF . 8D85 A4F6FFFF LEA EAX,DWORD PTR SS:[EBP-95C] После вызова функции по адресу 0040568A в регистре eax мы получаем адрес на $code, то есть на функцию, которую нужно вызывать. Еще одна уязвимость данного крэкми состоит в обратимом алгоритме шифровки. Если в качестве пароля ввести имя функции, то в eax уже будет адрес на пароль. То есть наша задача определить имя функции длиной 10 символов, которую нужно вызывать, затем ввести ее вместо пароля, и по адресу 0040568F получить пароль на наше имя. Так как программа запакована, то чтобы в ней рыться, нам нужно сделать ее дамп. Для этого в Olly жмем правой кнопкой по листингу и выбираем в появившемся меню Dump debugged process. Нам не нужен рабочий дамп, поэтому просто жмем в появившемся диалоге Dump и вводим имя файла. Теперь открываем файл в фаре по F3 или в hiew'е и начинаем искать в нем 10-символьные строки среди функций. Листать долго не придется: Picture1 lblPass lblText тNн3Щf? |