Интересное в инструкции Rdtsc

03.03.2010

Давно я что-то не касался (и не дотрагивался) темы ассемблера, пора исправить этот не большой баг. Сегодня поговорим о ассемблерной инструкции RDTSC. Собственно что это такое и зачем она нам нужна?Эта инструкция читает счётчик времени в процессоре(TSC) и возвращает 64-битный результат в регистры EDX:EAX количество тактов с момента последнего сброса процессора . Что это, мы поговорим немного позже. На этом функции rdtsc не заканчиваются. Так же она может применяться в антиотладочных приёмах и для генерации псевдослучайных чисел. Же она может работать с малыми временными интервалами.

Как собственно говоря работает RDTSC? Попробую попытаться объяснить.Она подсчитывает количество тактов начиная с включения, информация о количестве тактов записывается в регистры EDX:EAX. Старшие 32 бита MSR, загружаются в регистр EDX, а младшие 32 в EAX. До появления многоядерных процессоров(а так же с технологией Hyper-threaded) эта функция могла похвастаться точными результатами, но после их выхода, такого про неё уже сказать нельзя. Нет гарантии что счётчики со всех процессоров, будут синхронизированы, поэтому достоверные результаты можно было получить только с одного процессора. Но в современных решениях, Intel могут быть синхронизированы знания и на многоядерной системе. Также счётчик TSK, в таких системах, увеличивается на единицу вне зависимости от того, работал процессор или «спал». Раньше, если процессор переводился в спящий режим, счётчик TSC сбрасывался. Так же нельзя не заметить, что Microsoft не рекомендует использовать TSC для широкого временного разрешения. То есть много замерять нельзя. Вместо этого, корпорация предлагает заменить своими API-функциями. QueryPerformanceCounter и QueryPerformanceFrequency. Даже при использовании этого кода, Microsoft советует блокировать код на одном процессоре. Для Linux тоже самое можно повторить, если прочитать значение CLOCK_MONOTONIC функции clock_gettime.

Но теперь давайте перейдём непосредственно к примерам. Сначала будем используем TSC по его прямому назначению

Листинг 1.1


int clock;

_asm

{

RDTSC

MOV clock, eax

RDTSC

SUB clock,eax

}

cout << abs(clock);

Сначала читаем значение регистра времени, затем полученный результат перебрасываем в clock. Далее снова читаем rdtsc, и полученный снова результат, вычитаем из того что было.

И получим за сколько тактов выполняется этот код. У меня эта цифра была 63. Почему так много?Это уже тема для отдельного разговора.

Также и тоже можно получить если выполнив такой код:

Листинг 1.2


int clock;

_asm

{

RDTSC

MOV clock, EAX

RDTSC

SUB EAX, clock

}

Сначала очищается eax, далее вызывается функция cpuid(CPU Identection). Она используется для получения информации о процессоре. Но а дальше, код думаю должен быть понятен, потому что он уже был описан выше. Вот так советует поступать с RDTSC Intel.

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

Листинг 1.4

int clock;

_asm

{

RDTSC

MOV clock, eax

RDTSC

SUB clock,eax

}

if(clock > 63)

MessageBox(NULL,"Отладчик есть","Попался!",MB_OK);

else

MessageBox(NULL,"Отладчика нет","всё норм",MB_OK);

Как видно, мы просто дополнили слегка пример 1. И теперь если пройтись отладчиком поэтому месту, то появится табличка «Отладчик есть». Но примером в чистом таком виде, вряд ли сможет поймать кого-то его надо модифицировать, но это другая история.

И наконец, самое простое, что можно сделать с этой функцией. Это генератор псевдослучайных чисел. Что это такое, говорить не буду, потому что итак думаю ясно, а лучше перейду к примеру.

Листинг 1.5


int mm;

_asm

{

RDTSC

MOV mm, eax

}

cout << abs(mm);

Тут мы просто читаем из регистра EAX и отбрасываем минус, если он есть. Вот и готов генератор. Если надо число меньше, то просто делим на 10 или на 100 итд.

Мы сегодня разобрали функцию Rdtsc, что само по себе являлось очень интересным занятием. Конечно, это не все свойства этой замечательной функции, но на основных моментах, мы остановились. Удачи и успехов!

О руткитах.

03.03.2010

Руткит – вредоносная программа, маскирующаяся сама в системе компьютера и прячащая другое вредоносное программное обеспечение.Цель – незаметно захватить Ваш ПК.После проникновения руткит открывает «черный ход» в Интернет, через который мошенники получают данные с зараженного компьютера и внедряют разные вирусы-трояны-черви.В результате из миллионов таких компьютеров создаются «зомби-сети» для рассылки спама и хакерских атак.
К счастью, руткитов пока немного.Но конструкторы для их создания уже есть в Интернете.
Проникают на компьютер руткиты разными путями : через почтовые вложения, через открытие страниц «зараженных» сайтов.
Как они скрываются?
Чтобы антивирусы не опознали их, некоторые руткиты манипулируют процессами обмена данными компьютерных приложений, удаляя сведения о себе и других вредителях.В результате антивирусные программы молчат.Другие руткиты перехватывают потоки данных между программами.Третьи «лезут» в компоненты Windows или системный реестр, откуда посылают антивирусу дезинформацию.
Что делать?
Остановить руткит на входе в Ваш компьютер популярные антивирусы могут.Но не стопроцентно.Поэтому довольно эффективно воспользоваться специальными антируткитными программами.Рекомендуется удалять руткиты с помощью бесплатной программы GMER, оставшихся вредителей добить так же бесплатной утилитой AVG Anti-Rootkit, а потом проверить систему надежным антивирусом.
Время почистить свой компьютер!

Разработка ПО. Начало проектирования. Рассмотрение ТЗ.

03.03.2010

Проектирование программного обеспечения является достаточно серьёзной дисциплиной, которая изучает все аспекты создания и продвижения ПО. Специалисты, которые занимаются проектированием архитектуры ПО, имеет за своими плечами опыт не одного года написания того или иного «живого» кода. Они прошли через огромные препятствия всевозможных ошибок функционала их приложений, а так же повстречали достаточное количество различных технологий и платформ разработки. Эти люди настоящие профи своего дела, которые по праву заслуживают название для своей профессии как Архитекторы ПО. Сегодня мы попробуем узнать, чего же требует специализация архитектора от подобного работника компании, ведь они есть в каждой себя уважающей организации, если, конечно, она занимается разработкой программного обеспечения.

Под началом проектирования подразумевается рассмотрение технического задания (ТЗ), предоставляемого заказчиком и дальнейшее составление, на базе полученного задания, модели бизнес-логики приложения, структуры данных и их отображения. В основном, главными вопросами разбора ТЗ являются выборы моделей предметных областей, в которых будет работать запрошенных функционал. Данный вопрос о функциональных возможностях упирается, непосредственно, в требования к ПО. Они определяются внешними характеристиками программы, которые являются «видимыми» для конечного пользователя. К примеру, это структурированное отображение некоторых текстовых документов. Здесь для пользователя будут показаны лишь структуры каталогов документов, в то время как способ реализации данной возможности будет для него скрыт в исходном коде. Собственно, проектирование этого исходного кода и есть одна из задач архитектора ПО.

Если рассматривать структуру ТЗ подробнее, то можно выявить следующие ключевые пункты:

1. Функциональные назначения (либо область применения).
2. Функциональные требования к самой программе.
3. Необходимые требования к составу и параметрам внутренней среды, а так же их надёжность и безопасность.
4. Необходимые требования к совместимости.
5. Документация.

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

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

Под третьим пунктом подразумевается наличие определённых составляющих всего ПО и то, каким они должны удовлетворять нормам безопасности и надёжности. Пусть то, к примеру, метал или пластик, операционная система Linux или Windows, язык программирования Java или PHP. Ну и так далее.

Четвёртый пункт указывает на учёт необходимых совместимостей ПО с другими сферами работы. Данные параметры должны быть учтены при этапе проектирования и разработки.

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

Выполнение этих и других пунктов подчиняются определённым стандартам, по которым, в свою, очередь, созданы соответствующие спецификации. В двух словах, спецификация – это набор требований и параметров, которым должна удовлетворять рассматриваемая сущность (предмет, область, сфера). Так же спецификация представляется собой некий список перечисленных условий, удовлетворяющие производственный заказ.

После разбора ТЗ, происходит этап учёта анализа всех затрат на выполнение необходимых требований. Рассматриваются все подходящие инструменты и платформы для реализации пунктов из ТЗ. После принятия решения о том или ином выборе, даётся задание архитектору на планирование организации построения архитектуры всего исходного кода ПО. Здесь можно выделить понятие «чёрного ящика», которое подразумевает под собой анализ внешних характеристик программы, без вмешательства в её структуру. Далее начинается подробное рассмотрение внутренней начинки проектируемой системы с детализация всех её внешних свойств.

Это всё и есть начальный этап проектирования, где очень важно грамотно продумать все цепочки действий по выполнению ТЗ. При ошибке в одном звене, рушится вся структурная цепочка, а это повлечёт за собой пересмотр многих важных вопросов.

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

Антиотладочные приёмы. Часть 5. Усложняем анализ кода.

03.03.2010

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

Какие приходят на ум мысли, когда мы хотим защититься от дизассемблера?Конечно, это затруднение анализа кода. Это и будет являться основной темой статьи. Правда от таких корифеев типа IDA-pro различные трюки не помогут(а может и помогут), главным в этом дела остаётся человек, которому мы и будем сегодня пусть мозги.

Теперь поговорим для чего всё это и где лучше размещать код. Для чего, вроде понятно. Мы будем скрывать ключевые участки кода программы. Будь это защитный механизм для регистрации или вы просто не хотите раскрывать работу кода в данном участке, да и другие причины тоже могут тут присутствовать. Я довольно много говорю, что «опытных взломщикам это не остановит»(ну или примерно так), это фразу я хочу произнести и тут, но вы можете выиграть время пока вашу программу не взломают, а это уже хорошо.

Вообще кода должно быть довольно много, чтобы прятать эти участки. Потому что если написать просто “Hello world”, и кода в 10 раз больше, то конечно, всё сразу выйдет наружу, надо использовать дурман для дизассемблера, как бы между делом, как так и должно быть. Вот тогда защита будет довольно грозной.

Ещё хочется сказать о тех, кто разбирается в программах, исключительно отладчиком. Данные трюки их вряд ли остановят, потому что ваших шаманств, они просто не заметят и не оценят(даже новички), но дополнительная защита, ещё никому не вредила, поэтому смысл её подключать, несомненно есть.

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

Первым делом, заменим вот так обычный JMP

Листинг 1.1

int _tmain(int argc, _TCHAR* argv[])

{

_asm

{
mov eax,esp

ret

}
return 0;
}

Заносим в регистр EAX,стек(так конечно делать не рекомендуется) и потом делаем возврат.

Ещё способ, сделать тоже самое

Листинг 1.2


_asm

{

push[esp]

call [esp]

}

Производим в ручную вызов адреса стека.

А теперь напишем небольшую программку, которая сравнивает два числа, если прогнать её через дизассемблер, то код будет довольно простой, но после наших преобразований, уже не так просто будет понять что к чему.

Листинг 1.3

int _tmain(int argc, _TCHAR* argv[])

{

int number;

cin >> number;

if(number == 12)

MessageBoxA(NULL,"YES","YES",MB_OK);

else

MessageBoxA(NULL,"NO","NO",MB_OK);

return 0;

}

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

Листинг 1.4


00401011 833C240c cmp dword ptr[esp],0000000C
00401015 6A00 push 00000000
00401017 7516 jne 0040102F

Теперь попробуем немного усложнить этот код для понимания, потому что тут всё предельно просто, число, которая находится по адресу в стеке, сравнивается с Ch(12)и если они не равны, то прыжок на MessageBox, одни, а если равны, то на другой. Вот другой вариант этого кода:

Листинг 1.5


int number;

cin >> number;

_asm

{

xor eax,eax

mov eax,[number]

push eax

cmp[number],0xC

jne pt

tr: push 0x00000000L

push n1

push n1

push 0

call ds:[MessageBoxA] ; косвенный вызов API-функции MessageBox

jmp ex;

pt:

push 0x00000000L

push n2

push n2

push 0

call ds:[MessageBoxA] ; косвенный вызов API-функции MessageBox

ex:

}

Сей код, является интерпретацией того что было написано в листинге 1.3, теперь посмотрим, как это выглядит в дизассемблере:

Листинг 1.6


0040103C 33C0 xor eax,eax
0040103E 8B45FC mov eax,[ebp-04]
00401041 50 push eax
00401042 837DFC0C cmp dword ptr[ebp-04],0000000C
00401046 7513 jne 0040105B

Согласитесь, немного, да, но и этого может быть достаточно, чтобы дезориентировать крякера, конечно очень не опытного. Желательно этот код, помещать куда нибудь в середину основного кода, чтобы он не вызывал никаких подозрений.

Как мы видим, можно обложить подобными командами любой код, главное желание, умение и терпение. Естественно, это только поверхность работы по сокрытию кода в дизассемблере, но для начала достаточно. Удачи!

Антиотладочные приёмы. Часть 4. Взгляд на процесс.

03.03.2010

Сегодня я расскажу о довольно простом и довольно понятном антиотладочном приёме. Суть его крутится около OpenProcess. А точнее вокруг дескриптора, который возвращает эта функция. Дело в том, что при нормальном запуске программы, она возвращает что-то типа

000007D4. А при отладке, это значение может варироваться. Это вызвано, если этой функции передать значение PROCESS_QUERY_INFORMATION, то есть получить информацию о процессе. Именно из-за этого, дескриптор и ответственен за нужный нам возврат функции.

Но говорить больше не будем, а будем делать. Этот код будет героем дня сегодня

Листинг 1.1


#include "stdafx.h"

#include

#include

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

HANDLE han;

han = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, GetCurrentProcessId());

if (han == (HANDLE)2004) {

MessageBox(NULL, L"OK,OK, you win", L"Good", MB_OK);

} else {

MessageBox(NULL, L"Ha-ha, i know, you useing debugger", L"Debugger Detected", MB_OK);

}

return 0;

}

В принципе, всё было описано выше, код предельно прост и понятен. Кто не знает как выглядит скелет функции OpenProcess, то в MSDN. Остальным, удачи и терпения!

Антиотладочные приёмы. Чаcть 3. Имитируем вызов IsDebuggerPresent

03.03.2010

В самом начале, мы рассматривали функцию IsDebuggerPresent(подробности в Части 0), но я говорил о недостатках этой функции(недостатков больше чем приемуществ). Самое простое это через дизассемблер посмотреть где находится вызов этой функции и просто заNOPить это место. Да и обойти проблем нет. Сегодня мы будем использовать те же байты что и эта функция. Только делать это будем мы без палива. Чем хорошо данный метод?Его довольно сложно увидеть не вооружённым глазом, потому что тут не вызываются функции. Есть конечно переход, только этот переход ещё надо найти! На это раз будем кодить на Ассемблере, но я лично буду делать проект на c++ с ассемблерными вставками.

Листинг 1.1


#include "stdafx.h"

#include

#include

using namespace std;

int _tmain(int argc, _TCHAR* argv[])

{

int all;

__asm

{

mov eax,fs:[30h]

mov eax,[eax+2]

mov all,eax

}

if (all != -65536)

MessageBoxA(GetForegroundWindow(),"Hello,hacker","Message",MB_OK);

return 0;

}

Помните, чтобы обезвредить IsDebuggerPresent, мы шли в fs:[30] и меняли 1 на 0. Тут мы считываем информацию из fs:[30], затем переходим загружаем данные, которые находятся по адресу [eax+2], там и есть то что нам надо, а именно отлаживается программа или нет. Теперь загружаем в переменную то что у нас есть в eax(Этот способ немного другой, мы могли конечно и не выходя из ассемблера всё это провернуть, но для оригенальности поступим так:))

Если прога не отлаживается, то в регистре eax, должно быть число -65536(Этот способ проверял на OllyDbg и на стандартном отладчике в Студии). А если там другое число, то программа выдаст то что и должна – «Hello,hacker».

Но этот приём можно снова убрать заменой байтика в fs:[30]. В дальнейшем будем рассматривать трюки, которые нельзя так просто обойти.

Антиотладочные приёмы. Часть 2. Возвращение джедая.

03.03.2010

Сегодня, мы возвратимся к истокам, То есть к тому, от чего начали. Героем дня, будет функция CheckRemoteDebuggerPresent, которая похожа на IsDebuggerPresent, но так сказать, более усовершенствованная. Впервые она появилась только в Windows XP SP1, поэтому как говориться, делайте выводы сами. Эта функция считает из структуры EPROCESS, значение ProcessDebugPort , которое в случае отладки равно семи. Так чем же она отличается от функции IsDebuggerPrestent, кроме как то что принимает два параметра?Главное отличие то, что можно так «контролировать» не только текущий процесс программы, но и любой другой. И это может кому — то показаться удобней. Да и стандартным обходом(см. Обход IsDebuggerPresent)её не обойти. Да и вообще, внутренности у этих функций разные. Поэтому, эта функция с точки зрения безопасности, надёжнее чем IsDebuggerPresent(хотя на самом деле, тут нет никакой безопасности). Ну теперь напишем небольшую программку, которая будет использовать эту функцию:

Листинг 1.1

#include "stdafx.h"

#include

#include

int _tmain(int argc, _TCHAR* argv[])

{

BOOL po = FALSE;//Отладка дебаггера не активна

CheckRemoteDebuggerPresent(GetCurrentProcess(),&po);//Загружаем текущий процесс

if (po)//Если 1, значит идёт отладка

MessageBoxA(GetForegroundWindow(),"Hello, hacker","Message",MB_OK);

else //Если 0, значит нет отладки:)

MessageBoxA(GetForegroundWindow(),"Hello, good people","Message",MB_OK);

return 0;

}

Запускаем прогу и видим, что нас назвали «Хорошим человеком», но теперь попробуем запустить под отладчиком, и на это раз программа уже не так к нам приветлива. Ну что ж попробуем изменить эту ситуацию. Конечно, можно просто поймать эту функцию через дизассемблер и изменить в ней, хотя бы один байт. Но мы пойдём по другому пути, мы заменим переход в функции ZwQueryInformationProcess, котрую вызывают многие противоотладочные функции. И внутри видим такой код:

Листинг 1.2

7C85AB18 85C0 TEST EAX,EAX

7C85AB1A 7D 08 JGE SHORT kernel32.7C85AB24

Как раз в регистре eax, хранится информация о том отлаживается приложение или нет. Для того мы не будем запариваться в том что в EAX, а просто изменим JGE на JNZ. Загружаем и смотрим, что нас опять поминают добрым словом «Hello, good people». При желании можно и пропатчить эту функцию, таким образом отфутболить довольно многие антиотладочные функции.

Жизнь без Луны реальность или фантастика.

31.01.2010

Луна не просто спутник Земли. Кроме того что ученые до сих пор спорят о ее происхождении, так поверьте научно уже доказано о том, что при отсутствии нашего естественного спутника Земля не была бы такой какой она есть.

Луна

В чем же заключается важность Луны?

Многие на данный вопрос скажут что практически ни чем, еще часть признается в том что на Земле исчезнут приливы и отливы, некоторые вспомнив истории о оборотнях скажут, что при отсутствии луны не будет полнолуний. Но все это лишь детский лепет, верите или нет, но если бы мы не дружили с нашим естественным спутником, нас ожидали бы серьезные проблемы, вот некоторые из них.

Ведущие астрономы и астрофизики в частности Жак Ласкар занимаются изучением данного вопроса. В компьютерной модели выходит, что без Луны либо другого спутника такого размера жизнь на Земле в том виде, в котором она развивается сейчас, была бы не возможна. Причина кроется в гравитационном взаимодействии Земли и Луны.

Известный факт, что солнце удерживает нашу планету на орбите, но за счет воздействия планет на солнце, оно тоже колеблется относительно центра солнечной системы. Аналогично и с Луной не только Земля удерживает Луну на орбите, но и Луна заставляет Землю колебаться. Эти колебания выглядят так: если мы возьмем Землю и повернем вокруг своей оси то над полюсами ось опишет окружность, то есть как бы Земля вращаясь колеблется из стороны в сторону как волчок. И все это благодаря Луне. Она своим гравитационным воздействием удерживает колебания Земли в строгих рамках (приблизительно 23 градуса), теперь представьте, что Луны нет. Ось вращения Земли в таком случае будет вращаться в произвольных плоскостях. Что это значит, а то, что климат на Земле будет хаотичным, типа сегодня северный полюс на своем месте, а завтра он находится в районе экваториальной Африки, или в районе тихого океана. Хорошая перспектива, еще бы.

А хотите супер весть? По данным ученых Луна медленно, но уверено нас покидает где-то на 3 сантиметра каждый год. Ерунда скажете вы, на наш век хватит. Но чем дальше Луна, тем разболтанней ось вращения Земли тем больше климатический хаос, сутки будут увеличиваться за счет замедления вращения Земли. Но не стоит отчаиваться ученые работают над проектами, которые помогут сохранить нашу Луну будь это дамбы через океаны (для уменьшения приливно-отливного трения), либо мы найдем способ притащить к нам еще один спутник от каких ни будь других планет типа Юпитер или Сатурн.

Антиотладочные приёмы. Часть1. Самое главное в ECX

23.01.2010

Ну что, будем расти в наших познаниях и продолжать познавать антиотладочные приёмы. Сегодня на очереди будет функция GetThreadContext. Но сегодня не будет того что, просто вызываешь функцию и отладчик палится. Нет, сегодня будет всё сложнее. Но не так, чтобы свесить уши и другие части тела. Для начала идём в MSDN и читаем что пишут про эту функции. Если вкратце, то эта функция нужна для получения потока в контексте указанного потока. Звучит довольно мутно, но я думаю мы скоро со всем разберёмся. Если функция завершиться удачно, то нам возвратится значение всё что угодно, только не ноль. А если наоборот, то ноль. Что-то придумывать сегодня не будем, просто тупо возьмём пример из MSDN (А может и не тупо).

Листинг 1.1

#include "stdafx.h"
#include 
#include 
#include


void newthread(void *data)
{
          // Завершаем текущей поток
          TerminateThread(GetCurrentThread(),1);
}

void changeThreadState()
{
          // Запускаем новый поток
          HANDLE thread = (HANDLE)_beginthread(newthread, 0, NULL );

          //Объявляем структуру CONTEXT
          CONTEXT context;

          BOOL success;

          SuspendThread(thread);

          // Устанавливаем флаги
          context.ContextFlags = (CONTEXT_FULL | CONTEXT_CONTROL);

          success = GetThreadContext(thread, &context);

          // Проверяем поток на ошибки
          assert(success);

          //Выводим инфу
          printf( "eax=%09X, ebx=%09X, ecx=%09Xn",context.Eax, context.Ebx, context.Ecx );

          // Присваиваем значение EAX
          context.Eax = 0x1234BBBB;

          // Присваиваем значение ECX
          context.Ecx = 0x2468ABCD;

          // Применяем изменения
          success = SetThreadContext(thread, &context);

          // Снова проверка
          assert(success);

          // Останавливаем поток
          ResumeThread(thread);
}

int _tmain(int argc, _TCHAR* argv[])
{
          // Вызываем функцию
          changeThreadState();

          // Если нет отладчика, то вы видите это сообщение
          MessageBoxA(GetForegroundWindow(), "Отладчика в системе нет", "Хорошая новость", MB_OK);

          return 0;
}

Если программа отлаживается, то отладчик просто падает в процессе работы. Если отладчик не найден, то программа выполняет свою работу. Этот способ хорош тем, что в нем нет ни одного перехода и это теоретически может остановить крякеров (новичков). На более опытных это не работает.

Антиотладочные приёмы. Часть 0. Детсад.

23.01.2010

Это даже не первая, это нулевая часть. Потому что об этом антиотладочном трюке (если можно так сказать), знают не просто все, а больше чем все. Речь пойдёт сегодня о IsDebuggerPresent. Если кто-то даже просто подходил к отладчику, то и они знают об этом приёме. Эта функция живёт (экспортируется) в Kernel32.dll. Как уже понятно, эта функция позволяет определить, отлаживается приложение или нет. Если текущий процесс, запущен в контексте отладчика, то возвращается 1, а если нет, то 0. Просто вызвать эту функцию их любого участка вашего кода. И Microsoft всё сделает за вас:) Рассмотрим классический пример

Листинг 1.1


#include "stdafx.h"
#include

int _tmain(int argc, _TCHAR* argv[])
{
if(IsDebuggerPresent())
MessageBoxA(NULL,"Hello,hacker","Message",MB_OK);

else
MessageBoxA(NULL,"Hello,good people","Message",MB_OK);

return 0;
}

Всё просто, если попался дебаггер, то нашему взору предстаёт надпись «Hello,hacker», а если мы честно запускаем просто экзэшник, то вываливается табличка со словами « Hello,good people».

Этот трюк работает со многими отладчиками, но например Soft-ice, он не берёт. Оно и понятно, на Айсе сидят профессионалы, а против профов нет приёмов:)

Теперь о том как его обойти. Тут ещё всё элементарнее. Открываем допустим OllyDbg (Олечка) и загружаем подопытную программу. Затем жмём . Нашим взорам, предстаёт следующая примерно следующая картина:

Лисинг 1.2


7FFD8000 0000 ADD BYTE PTR DS:[EAX], AL
7FFD8002 0100 ADD DWORD PTR DS:[EAX], EAX

Единичка — это как раз то что нас засекли. Ну что ж,меняем единичку на ноль. Теперь жмём и видим, что на это раз нам более приветливы «Hello,good people».

Это было уж слишком просто, но дальше будем усложняться