PDA

Просмотр полной версии : Исследование программ. Урок 0.


Ivan_32
27.03.2009, 00:57
Что в этом уроке:
В данном коротком но думаю полезном уроке мы ознакомимся с инструментарием и взломаем первую программу 2 способами.
Необходимый инструментарий:
Нам понадобится только OllyDBG - на мой взгляд лучший User-Mode отладчик. Версия 1.1. Скачать ее можно с оффсайта. OllyDBG ([Ссылки могут видеть только зарегистрированные и активированные пользователи])
А так же вам понадобится сама тестовая программа ([Ссылки могут видеть только зарегистрированные и активированные пользователи]).
Практическая часть:
Для начала откройте OllyDBG. Устанавливать ее кстати не нужно - просто распакуйте архив в удобную вам папку. Откройте файл SimpleApp.exe (Нажминет в OllyDBG File->Open). На экране вы должны увидеть что то вроде такого:
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

В куче этого кода нас интересует фрагмент по адресу 402082 - 402091.
MOV ECX,8
MOV ESI,401008
MOV EDI,401208
REPE CMPS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
Это как ни странно цикл сравнения двух строк - серийников введенных и того что зашит в программу. Комментарий отображает один из аргументов этой инструкции - зашитый в программу сейриник. Это логично так как до запуска программы, дизассемблер может отобразить только один аргумент, так как пользователь не ввел второй.
Вот сосбтвенно и все - переписываем в блокнотик серийник и вводим его в программе. На этом первый способ кряка завершен.


Теперь давайте проанализируем что же происходит после сравнения строк.
JNZ SHORT 004020C3
А происходит у нас условный переход - JNZ - если флаг ZF не установлен. Он не установится только если результат последнего сравнения отрицательный. Т.е эта команда почти тоже самое что и JNE.
Кликаем два раза по строке с этой инструкцией, ставим галочку Fill with NOPs и вводим в текстовое поле команду NOP и нажимаем assemble.
Теперь нам осталось только сохранить эти изменения:
1. Выделите обе инструкции NOP(у нас их получилось две, так как команда JNZ+Аргумент = 2 байта. А инструкция NOP однобайтовая - 90h) зажав клавишу Shift. Кликните по выделенным инструкциям правой кнопкой мыши. И в выпадающем меню выберите Copy to Executable -> Selection.
После этих манипуляций перед вами появится окно дизассембла файла(Значок - Буква D на голубом фоне.). Наши инструкции как раз отобраажены в нем(и выбраны) Нажимаем по выделение правой кнопкой мыши и выбираем Save File. Все - указывайте путь куда сохранять взломанный файл.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

В заключение:
Вот и все - поздравляю вы взломали свою первую программу. Эти знания помогут вам в ислледовани экзешек клиентов игр на предмет защит и проверок. В них все реализовано по такому же принципу:)
Урок этот первый но не последний.

Leo_ня
27.03.2009, 11:06
Спасибо :)

Но вот одна проблемка вышла... серийник не вмещается О_О

Я, как понял, сначала сравниваются строки, если результат отрицательный, значит флаг ZF не установлен, и джамп будет идти на "Wrong serial number" :)

А если убрать этот джамп (хотя можно сменить на переход на "Correct serial" :)), то следующая команда будет вывод текста "Correct serial" и далее команды соответственно)

П.С: вторым способом получилось :)

Ivan_32
27.03.2009, 16:22
Не вмещается? о_О А скрин можно?) Кажется у Висты теперь несовместимость с XP на уровне UI X_X Я могу сделать конечно больше или скроллбар прикрутить...
Да кстати, вот что хочу добавить. Эта прога она на асме написана - а значит дизассембл будет очень похож на исходник. Ну вот тут разве что есть один косяк. Я ставил в коде не JNZ а JNE, но видимо компиль решил что JNZ предпочтительней...

Leo_ня
27.03.2009, 16:46
[Ссылки могут видеть только зарегистрированные и активированные пользователи]******.net/out.php/i160169_1234567.PNG
Вмещается только AFuguw931t7hwghasfuhuqw8hf2[
Не хватает места для 2333

Да, кстати, я так и не нашёл, как из оли копировать текст о_О пришлось открывать хекс редактором, ибо перепечатывать лень %)))

Глюконатор
27.03.2009, 18:14
Все конечно замечательно... И я благодарен Ивану за статью. Но чет я тут самого главного не увидел. Как же все таки всю эту хрень искать. Тут нам сразу сказали, что интересуеют такие-то строчки. Это конечно хорошо, когда прога мелкая и ее можно просмотреть за полминутки...
Короч мой вариант прохождения этой мелкой радости:

Открываем прогу в оле. Т.е. можно File->Open или F3 (надо начать привыкать к горячим клавишам - в дальнейшем будут спасать время) и выбираем нужный файл.
По началу оля проводит анализ, встает на предпологаему точку входа и впадает в состояние задумчивости aka Pause
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Далее запускаем прогу - Debug->Run (F9). Появляется милое окошечко проги. Веря нашему интуитивному мышлению мы понимаем, что прога ждет ввода серийника. Но мы его не знаем.... =( Но это не беда! =) Вводим любую фигню. Либо не вводим вообще ничего =) Ага.. прога выдала надпись:"Wrong serial number."
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Нам это на руку. Переключаемся на олю и выполняем следующие махинации:

ПКМ на экране CPU (окно с буквой С в синем квадрате) -> Search for -> All referenced text strings.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
В появившемся окошке пробегаемся по надписям и радуемся при виде знакомой нам "Wrong serial number." Выделяем ее, ПКМ -> Follow in Disassembler (можно просто Enter)

[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Добрая оля отсылает нас к коду где эта строка употребялется. Смотрим в окно дополнительной инфы (оч полезная штука кстати), где нам сообщают, что прыжок сюда есть на оффсете 402093. Выделяем эту строку, ПКМ -> Go to...

[Ссылки могут видеть только зарегистрированные и активированные пользователи]
И...оля перекидывает нас как раз на те строки сравнения о которых нам любезно рассказал Иван. Далее следуем его интсрукциям и пускаем сопли от взломанной проги.
Спасибо за внимание ^_^

Leo_ня Можно выделить строку с пассом и в окне доп инфы ПКМ -> Copy pane to clipboard. Скопирует конечно все что там будет написано... но имхо эт этого избавится гораздо быстрее чем се-то еще в хекс-редакторе открывать...

Добавлено через 32 минуты
ЗЫ Я пожалуй дополню варианты поиска... Если знаем API, то можно химичить с ними... К примеру у нас алгоритм будет таков:

Открываем прогу.
ПКМ в окне ЦПУ (или дизассемблера другими словами) -> Search for -> Name (label) in current module (Ctrl+N).
Перед нашими глазами появляется список импортируемых/экспортируемых функций данной проги. Ищем там глазами GetDlgItemTextA. В относительно простых прогах этой функцией часто считывается пароль из окна ввода пароля.
ПКМ по нему -> Set breakpoint on every reference (это мы поставили бряк на каждый вызов этой функции)
Далее запускаем прогу, вводим фигню, жмем Check и... оля тормозит прогу ибо была вызвана наша функция на которую мы поставили бряк.

За ней следует код проверки валидности пасса. Это в самом простом случае.
Посложнее - далее может идти вызов проверяющей функции (так что надо будет трассировать прогу с вхождением) или джамп куданить... а за ним еще джамп и еще джамп =) Дабы "усложнить" реверсеру жизнь =) Но мы же таких трудностей не испугаемся, прально? =)

ZeLiK
07.08.2009, 23:20
Выделить пароль можно было ещё проще, в "С", под-окно внизу слева, я так понял hex-редактор, в нём ПКМ, Text, ASCII (64 chars). Идём на адрес 401200, выделяем пароль, ПКМ, copy, To clipboard, получится:
00401200 AFuguw931t7hwghasfuhuqw8hf2[2333
Отсюда вытянуть пасс тем же способом: выделить, copy =)
з.ы. по дефолту вид hex 4 byte.

Ещё хочу добавить, чтоб без знания процедур/функций (JNZ, JNE), того же флага (ZF)... трудненько разобраться, я, к примеру, не знаю ассемблера, пока не понял какая аббривиатура, за что отвечает. Но всё же что-то понять удалось :)

schurik
18.10.2009, 20:24
привет! а можно с помощью ваших hex-редакторов справиться с pw-protector-ом,служащий для защиты игры PerfectWorld ?

Если да,то подскажите как,если не трудно конечно))
Заранее очень признателен!спасибо!

koduru
18.10.2009, 22:37
статьи крутые, а реально кто-нить мне может dll распаковать или сорцы компильнуть?

Глюконатор
19.10.2009, 19:13
Сорцы компильнуть может каждый чоткий пацык с компилятором.. А вот длл распаковать... Сначала находишь пакер которым она запакована, а потом анпакер к нему =) Так что тут проблем тож нет)

koduru
20.10.2009, 12:49
Сорцы компильнуть может каждый чоткий пацык с компилятором.
здесь на форуме такие чёткие пацаны есть?

Сначала находишь пакер которым она запакована, а потом анпакер к нему =) Так что тут проблем тож нет)
я имею ввиду навыки ручной распаковки, в случае, когда статический анпакер не помогает

Leo_ня
20.10.2009, 13:32
Это тебе скорее на кряклаб, чем на жук.ру х_Х

здесь на форуме такие чёткие пацаны есть?
В чём проблема, мы не знаем. Но обычно всё компилируется нажатием одной кнопки в компиляторе.

koduru
21.10.2009, 00:33
жестокая шутка... на кряклабе от одного упоминания слова "бот" у них идиосинкразия

В чём проблема, мы не знаем. Но обычно всё компилируется нажатием одной кнопки в компиляторе. теория, мой друг, суха, но древо жизни вечно зеленеет

исходники могут быть не совсем полными, содержать ошибки, иногда есть необходимость заменить некоторые куски

пару чёткий пацанов я заметил тута: Ivan_32, shagart, возможно ещё Глюконатор... никого не пропустил?

Leo_ня
22.10.2009, 19:51
FFForever, может быть. Но даже если это так, он вряд ли будет этим заниматься.

mars2107
03.05.2012, 21:17
Попробовал по уроку взятому отсюда Ссылка ([Ссылки могут видеть только зарегистрированные и активированные пользователи]) проделать с тестовым примером, все получилось.

Решил взяться за свою программу, но тут не так все просто. В программе имеются "Логин" и "Пароль" которые можно получить, зарегистрировавшись на сайте*. Программа состоит из одного исполняемого файла. Можно ли как то отвязать ее от сайта или вообще от авторизации с помощью OLLYDBG, я пробовал, но уже в самом начале застрял на том, что никак не могу поймать нужный шаг и он все время меняется. Можете объяснить, помочь и научить. Хочу расширить границы "читерского" мастерства.


skype: mars2107
vk: [Ссылки могут видеть только зарегистрированные и активированные пользователи]

*за регистрацию нужно платить

object
05.05.2012, 22:36
mars2107, не легче ли проснифить пакеты(при успешной авторизации), поднять небольшой прокси сервер и при запросе на сайт авторизации заменять его ответ на "исправленный".Уверен программа не отличит фейк от валидного :)
(если конечно Вы не писали защиты (хеши, токены, кукисы))

Ninazu
08.06.2013, 20:14
Вот решил попытать счастья и вытащить базу из справочника. Опыта особого нет, но механизм в целом понятен.

Собственно жертва!
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Увидев файлы базы, подумал что всё пройдёт гладко. Но после тщетных попыток понять с чем же мы имеем дело, оказалось что это не стандартная база, а какое-то извращение своё.
Прога написана на Делфи. Был скачан DeDe, но жизни он не облегчил особо. Запустив под Олькой обнаружил, что с базой работают три библиотеки

dread.dll
xfind.dll
udata.dll

С первой проще! Быстренько написал софтинку (PureBasic) для чтения .dat файлыов с её помощью, и получить даже количество записей в каждой из БД.
Но вот дошел до функции dreadrecord, а она возвращает два загадочных параметра. Которые как я подозреваю являются адресом и размером для чтения. Вот только адресом чего и откуда читать потом

EnableExplicit
;{

DataSection
DB_KEY:
Data.b $44,$65,$43,$35,$31,$36,$37,$35,$30,$33,$32,$37,$3 7,$64,$56,$66,$0B,$01,$00
EndDataSection

Prototype p_dloadfile(Fname$,*File)
Prototype p_drecordcount(File,*Count)
Prototype p_dreadrecord(File,Index,*Addr,*Count)
Prototype p_drcsetmasterkey(*Key)
Prototype p_dunloadfile(File)
Prototype p_xloadfile(Fname$)
Prototype p_xfind_cb(*FirstP,Flag,*EP,*NextP)

Define FLib=OpenLibrary(#PB_Any, "dread.dll")
If FLib
Global dloadfile.p_dloadfile = GetFunction(FLib, "dloadfile")
Global drecordcount.p_drecordcount = GetFunction(FLib, "drecordcount")
Global dreadrecord.p_dreadrecord = GetFunction(FLib, "dreadrecord")
Global drcsetmasterkey.p_drcsetmasterkey = GetFunction(FLib, "drcsetmasterkey")
Global dunloadfile.p_dunloadfile = GetFunction(FLib, "dunloadfile")
EndIf

Define FLib=OpenLibrary(#PB_Any, "xfind.dll")
If FLib
Global xloadfile.p_xloadfile = GetFunction(FLib, "xloadfile")
Global xfind_cb.p_xfind_cb = GetFunction(FLib, "xfind_cb")
EndIf

Structure REC
RID.i
Count.i
EndStructure

Structure DBF
File.i
Count.i
Array Record.REC(0)
EndStructure

;}

Global NewList DBF.DBF()

Procedure ReadFileDB(FName$)
Protected File,Count,I,RID,RCount
Protected *lBuff,*wBuff
If dloadfile(FName$,@File)=#S_OK
AddElement(DBF())
DBF()\File=File
If drecordcount(File,@Count)=#S_OK
DBF()\Count=Count
ReDim DBF()\Record(Count)
For I= 1 To Count
If dreadrecord(File,I,@RID,@RCount)=#S_OK
With DBF()\Record(I-1)
\RID=RID
\Count=RCount
EndWith
EndIf
Next
EndIf
ProcedureReturn File
EndIf
EndProcedure

#FPath="C:\Program Files\Kontakt! 2012\Products\Kontakt! 2012\"

ReadFileDB(#FPath+"prod.dat")
ReadFileDB(#FPath+"prod.dat")
ReadFileDB(#FPath+"Kontakt\init.dat")
drcsetmasterkey(?DB_KEY)
ReadFileDB(#FPath+"Kontakt\comp1.dat")
ReadFileDB(#FPath+"Kontakt\comf1.dat")
ReadFileDB(#FPath+"Kontakt\head1.dat")
ReadFileDB(#FPath+"Kontakt\regi1.dat")
ReadFileDB(#FPath+"Kontakt\sadd1.dat")
ReadFileDB(#FPath+"Kontakt\banner1.dat")
ReadFileDB(#FPath+"Kontakt\reno1.dat")
ReadFileDB(#FPath+"Kontakt\ext01.dat")
ReadFileDB(#FPath+"Kontakt\ext11.dat")
ReadFileDB(#FPath+"Kontakt\ext21.dat")

Дальше веселее. По размеру файла idxs1.idx, понял что вся вкусность храниться в нём, а dat - это лишь заглавные файлы хранящие инфо о полях в нём. И для работы с ним есть либа xfind.dll, эта гадость линкуется в процессе уже.
На ней и застрял. Если правильно уловил параметры в ольке, то вызывается изначально

xloadfile(#FPath+"Kontakt\idxs1.idx")

Но что за щятафака? Возвращает она S_OK, если файл норм, и код ошибки если нет, а где же указатель на прочтённый файл или что-то в этом роде? Выделения памяти библиотекой тоже не заметил.

Поиск по БД если снова таки правильно понял, то осуществляется с помощью xfind_cb. Пока, это всё, что удалось нарыть.

Помогите совместить полезное с приятным. Решить проблему и за одно освоить сие направление, чтобы в дальнейшем я не задавал такие вопросы а смог сам пройти этот путь