пятница, 11 февраля 2011 г.

Исследование файлов сохранения Doom 2

   Некоторым из нас хочется заглянуть под капот и выяснить суть работы того или иного механизма(и не только механизма). Те, кому это нравится — великие люди, ведь именно любопытство является двигателем прогресса, а не любимая всеми лень.
Любопытство иногда заставляет делать совершенно безумные и бессмысленные поступки и об одном из них, как раз сегодня и пойдёт речь.
   Как-то ожидая загрузки уровня в Сталкере, мне показалось любопытным узнать, а как именно устроен файл сохранения в играх? Конечно, мы все знаем что там содержится информация о текстурах, статических, динамических и прочих объектах. Но вот какой рисунок это имеет в байтовом представлении - это и есть цель выяснить.
К сожалению, от идеи исследования save-файлов непосредственно Сталкера, мне пришлось довольно быстро отказаться, потому что те кто играл — знают насколько невыносимо долгими там сделаны загрузки(а если ещё и машина не быстрая, то это вообще ад). Следующим вариантом была GTA: Vice City(порядок игр не случайный, именно они были у меня на тот момент на жёстком диске). С загрузками там был полный порядок, но вот копаться в почти 200 килобайтном файле(а это кто забыл, 200000 символов), мне было абсолютно не в кайф.
Остался всего лишь один вариант. Он же самый древний и самый заслуженный. Это всем известная(и пока не всеми забытая) игра DOOM 2. Это идеальный вариант для реализации сегодняшней нашей цели. Во первых, быстрая загрузка(наверное все уже проапгрейдились со своих 486-х), во-вторых, размер файла всего лишь 16 килобайт, да и его структура не очень сложная(но это уже небольшое опережение).
  Но довольно лирики, почти все действующие лица, которые будут участвовать в сегодняшнем исследовании уже были представлены ранее то есть HEX-редактор и игра Doom 2. Кроме этого, нам понадобится ещё DOSBOX, которая является довольно примитивным эмулятором операционной системы DOS. Но нам и этого хватит.
Загружаем и сразу сохраням игру. Это нужно для того, чтобы размер файла был как можно меньше(соответственно проще). В папке с игрой, тут же материализуется файл DOOMSAV0.DSG(радует глаз, что первое сохранение начинается с нуля, а не с единицы).
Теперь самое время его открыть и посмотреть какие байты он нам сможет предложить.
Как не трудно догадаться, первой строчкой идёт само название файла. Оно может быть не более 22 байт, хотя на деле и того меньше. Следом за именем файла идёт фраза «version 106», которая может и является номером версии, но на деле выполняет больше роль сигнатуры, по которой игра узнаёт свой родной файл. В противном случае, загрузка сохранения просто не состоится. Хотя кроме неё, подобных сигнатур, есть ещё несколько.
По этому результату, уже не сложно получить первое представление о стуктуре .DSG(Doom Save Game) файла, которая начинается с заголовка, но что будет дальше? Для этого за NOP`им следующую строчку которая включает в себя адреса 0x30 – 0x3f. То есть вместо нулей пищем 90. Запускаем игру и видим, что чем дальше мы двигаемся, тем больше «проваливаемся» под текстуры пола. В итоге играть становится просто невозможно. Значит в файле сохранения, хранятся также данные и о текстурах. Довольно неожиданно было встретить их уже в самом начале. Не уходим далеко от этой строки, находим значение по адресу 0x38, которое должно быть равно 00. Если изменить его на 01, то при загрузке вы не сможете не только сдвинуться с места, но и повернуться в разные стороны.
Приведу ещё несколько интересных возможностей:

Адрес Старое значение Новое значение Результат
0x54-0x56 В зависимости от игры FF FF FF Управление уровнем здоровья(может не работать)
0x58 - 0x5A В зависимости от игры FF FF FF Управление уровнем брони(может не работать)
0x60-0x62 00 00 00 FF Таблетка неуязвимости
0x64 0 0 FF Убийтво кулаком с одного удара
0x67 0 0 FF Всё в красном цвете
0x78,0x7C,0x80 0 0 FF,FF,FF Появление синего, красного и жёлтого жетонов
0xd0 В зависимости от игры FF 255 патронов на пистолет
0x128 0x0A FF Игра без оружия( War is Over)

   Как уже наверное стало понятно, всё в итоге свелось к тупому перебору значений и просмотру поведения игры. И это так и есть, только что делать, когда надо изменить, например положение игрока? На перебор всех значений уйдёт ни один день, что само по себе не может радовать(лучше эти несколько дней потратить на более интересные вещи). Для таких случаев, на помощь приходит побайтовое сравнение. Копируем файл со старым сохранением, в какую-нибудь папку, загружаемся, делаем какое-нибудь действие , сохраняемся снова и сравниваем эти два файла. Таким образом, можно довольно быстро узнать о изменениях, которым предшествовали ваши действия. Сравнивать файлы можно в любом приличном HEX-редакторе, которым несомненно является WinHex. Даже при небольшом перемещении, оказалось, что найдено 87 изменений. Значит на те места, надо обратить бОльшее внимание.
Возможно кому-то покажется бессмысленной, сегодняшнее действо. Отчасти это так и есть, но возможно это натолкнёт кого-нибудь на более правильные мысли. Удачи!
   P.S. Напоминаю, что целью данной заметки, была не научить, а вдохновить на какие-нибудь собственные исследования или эксперименты.

суббота, 29 января 2011 г.

Блокировщик сайтов для Хрома

Сегодня мы с вами будем писать блокировщик сайтов для Хрома. Как известно, нужен он в том случае, если вы или кто-то ещё, не хотят знакомится с содержимым сайта. Это может быть по разным причинам. Например во время рабочего дня, нет времени заходить на сайты различных социальный сетей и при попытки нарушить данный запрет, программа будет перебрасывать нас например на сайт www.google.ru. Ну и конечно, данная программа будет полезна при блокировки контента эротического содержания, который нежелателен для просмотра детям.
Теперь разбирёмся с регламентом. Логичнее всего, данную идею оформить в виде расширения для Google Chrome. Но, как мне кажется, и на C++, программа будет выглядеть тоже достойно. А расширение мы ещё напишем. Если говорить о внешнем виде, то лично я буду писать консольное приложение, а кому надо, могут прикрутить GUI, ну и дописать ещё что-нибудь. Ведь наша цель больше образовательная и не претендует на полноценное решение.
Ну пора начинать. Создаём новый файл в Visual Studio и после этого, думаем что будем писать. Очевидно, что сначала надо получить дескриптор окна, который принадлежит Хрому, потом получить данные которые находятся в URL и если этот адрес находится в чёрном списке, то переходим на www.google.ru. Всё это выглядит примерно так:

Листинг 1.1

#include < windows.h >
#include < tchar.h >

#pragma comment(lib, "user32.lib")

const TCHAR wqq[] = L"www.google.ru";
BOOL __stdcall GetChromeEditText(HWND hWnd,LPARAM)
{
char szbuff[500];
if( GetWindowTextA(hWnd, szbuff, sizeof(szbuff)/sizeof(szbuff[0]))!= 0 ) //Получаем адрес
{
if(!strstr(szbuff,"Chrome")) //Если там нет слова Chrome, то выходим
false;
HWND hw = FindWindowExA(hWnd,NULL,"Chrome_AutocompleteEditView",NULL); //Ищем дескриптор //адресной строки
if(hw != NULL) //Если дескриптор найден
{
TCHAR buff[1000];
char szdisplay[1000];
SendMessage(hw,WM_GETTEXT,100,(LPARAM)buff); //считываем URL
wcstombs(szdisplay,buff,lstrlen(buff)); //приводим его к виду
if(strstr(szdisplay,"sex")) //если он содержит слово
{
//то посылаем текст Google
SendMessage(hw,WM_SETTEXT,100,(LPARAM)wqq);
//нажимаем Enter
PostMessage(hw, WM_KEYDOWN, VK_RETURN, VK_RETURN);
}
}
}
return true;
}

void main() {EnumWindows(GetChromeEditText,0);}

Тут надо сделать несколько пояснений. Наверное сразу у многих появился вопрос: Откуда взялся “Chrome_AutocompleteEditView”? Имя этого класса, удалось получить с помощью утилиты Spy++. Далее, у нас блокируется только одно слово, а если мы хотим несколько? Для этого, поместим все ненужные нам слова в отдельный массив и при проверки, с помощью цикла, будем проверять соответствия. То есть сделаем как-то так:

Листинг 1.2

const int len = 2;
const char* badwords[len] = {"sex","porno"};

…..
for(int i = 0;i if(strstr(szdisplay,badwords[i])) //Это у нас уже было
{
SendMessage(hw,WM_SETTEXT,100,(LPARAM)wqq);
PostMessage(hw, WM_KEYDOWN, VK_RETURN, VK_RETURN);
PostMessage(hw, WM_KEYUP, 0, VK_RETURN);
}

….......

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

void main() {
while(1)
{
Sleep(1000);
EnumWindows(GetChromeEditText,0);
}

}

Вы можете всё доработать и переработать по своему вкусу.
Мы рассмотрели способ доступа к адресной строки браузера Google Chrome. Аналогично, тоже самое можно сделать и для других браузеров, но это уже на ваш выбор. А пока, удачи во всех ваших начинаниях!

четверг, 27 января 2011 г.

Ещё раз о распаковки AsPack 2.XX



О распаковке протектора AsPack 2.XX, написано уже столько, что до конца жизни хватит. Правда это чтиво, будет не всегда полезным, потому что большинство приёмов, по понятным причинам - не работает. А дело всё в том, что команда разработчиков, даром не просиживает штаны, а чуть ли не в каждом новом билде, преподносит хоть небольшое, но новое. Вот из-за этого, и происходят непонятки.  Поэтому не будет лишним, снова поднять эту тему.
  Почему именно ручная распаковка, когда давным давно написаны распаковщики и скрипты, позволяющие обойти данную проблему в пол счёта? Да потому, что на автомате может и осёл распаковывать, а нам ведь главное процесс, а не результат.
  Теперь перейдём непосредственно к действию. Примером программы запакованной данным протектором, будет USDownloader, которая(как это не сложно догадаться по названию), является менеджером загрузок. Открываем её в OllyDBG и видим стандартную картину, для AsPack`а

00579100 > $ 60             PUSHAD
00579101   . BE 00804F00    MOV ESI,USDownlo.004F8000
00579106   . 8DBE 0090F0FF  LEA EDI,DWORD PTR DS:[ESI+FFF09000]
0057910C   . C787 D4941300 >MOV DWORD PTR DS:[EDI+1394D4],7F107FD1
00579116   . 57             PUSH EDI
00579117   . 83CD FF        OR EBP,FFFFFFFF
0057911A   . EB 0E          JMP SHORT USDownlo.0057912A

Как обычно доходим до сюда и дампим с помощью плагина OllyDump. Естественно, программа не запустится, потому что у неё нарушена таблица импорта, котрую нам и предстоит восстановить. Открываем распакованное приложение в дизассемблере HIEW, давим F8, а потом F10. Это минишаманство нужно для того, чтобы перейти в начало таблицы импорта. Сразу как только мы перенесёмся в это место, становится понятно, почему программа не запускалась. Начало таблицы, заехало прямо на функцию LoadLibraryA, что естественно является аномальным. Настоящий старт таблицы, начинается чуть-чуть ниже, а именно на строке 00576FB8. После этого, надо занести изменения в раздел NT_HEADER. Далее запускаем и видим что программа вроде загрузилась, но всё-равно выдаёт ошибку. Значит это ещё не всё. Открываем PE Tools и смотрим есть ли что-то странное в библиотеках, которые обеспечивают работу программы. В самом конце списка библиотек, мы замечаем  oleaut32.dll в которой первая функция выглядит довольно странно. То есть у неё нет ни Thunk RVA, ни Thunk Value. В таком случае, давайте удалим эту функцию, чтобы она не смущала загрузчик. Перезапускаем и видим, что теперь программа успешно запускается. Теперь можно радоваться и праздновать) Вот так вот не сложно, можно восстановить таблицу импорта. Конечно, в полевых условиях лучше всего юзать ImpRec, но знать как восстанавливается эта таблица, думаю не помешает. Удачи!

понедельник, 24 января 2011 г.

Неизвестные хакеры взломали личную страницу Николя Саркози в Facebook

Хакеры разместили на страничке Саркози сообщение об отказе участвовать в президентских выборах 2012 года. "Учитывая исключительные обстоятельства, в которых оказалась наша страна, я, находясь в здравом рассудке, и от чистого сердца решил не выставлять свою кандидатуру на выборах в 2012 году", - говорилось в сообщении, составленном с орфографическими ошибками.

Также всем желающим было предложено вступить в группу, посвященное уходу Саркози со своего поста в мае 2012 года.
Сам президент Франции поспешил успокоить своих сторонников, несколько часов спустя опровергнув сообщение об уходе из большой политики. "Мой аккаунт на Facebook был взломан сегодня, еще раз подтвердив тот факт, что ни одна система не может быть надежной на сто процентов. Я получил хороший урок письма и правописания, однако вынужден не согласиться с выводами, предложенными в этом несколько поспешном сообщении. Спасибо тем, кто вовремя обнаружил ошибку, и всем, кто меня поддерживает", - написал Саркози. 

http://www.securitylab.ru/news/404433.php


  Меня всегда удивляло, насколько мы беззащитны перед взломами наших аккаунтов в Twitter, Facebook, Вконтакте и других сервисах. Можно конечно поставить длинный пароль и не переходить по ссылкам, но если наш аккаунт действительно кому-нибудь понадобится, то увы, атакующие скорее всего добьются своей цели. И тут уже сделать что-то довольно сложно. Всем известно, что любой более-менее серьёзный программный код, содержит ошибки. Чем более популярный программный продукт, тем больше людей ищут там ошибки. Следовательно и успешных результатов, тоже больше. Конечно, все найденные ошибки закрываются, но на их месте, с довольно большой долей вероятности, вырастают новые.
 Хотя может не всё так плохо? Давайте посмотрим. Руководители социальных сетей тоже не сидят сложа руки. Например Вконтакте, если взломали ваш почтовый ящик, и хотят получить доступ к аккаунту с помощью восстановления пароля, то вы получите сообщение о вводе вашего номера мобильного телефона на который будет выслан секретный номер. Если конечно вы позаботились о подключении этой опции. Также в Facebook недавно была введена система безопасности, которая позволяет добавить к своему аккаунту сразу несколько барьеров на пути взломщика. начиная от ответа на секретный вопрос и заканчивая номером мобильного телефона(к сожалению на территории России, воспользоваться этой фишкой можно, только если вы абонент Билайна).  
  В завершении, можно отметить, что социальные сети делают определённые шаги к обеспеченю безопасности для пользователей(дело теперь за пользователями), но до идеала, пока всё-таки далеко. Но, дорогу осилит идущий..

Написание программы интернет-радио


Всем привет! Сегодня мы попробуем написать небольшое приложение на языке C#, которое позволяло бы нам прослушивать радиостанции. Сразу хочется сказать, что предстоящее действо, будет нести только образовательный характер, ведь средств для прослушивания интернет радио, написано уже не мало.
 Наверное не надо никому объяснять что такое интернет радио, поэтому обойдёмся без прелюдий и перейдём прямо к делу, поэтому открываем Visual Studio(некоторые могут открыть и Mono) и создаём новый проект. Для простоты, будем использовать стандартный компонент Media Player потому, что в самом начале договорились, что приложение будет небольшим. Но его надо ещё добавить, потому что в стандартной комплектации, на панеле инструментов его нет. Поэтому после создания проекта, жмём правой кнопкой мыши на “Панель элементов”, выбираем “Выбрать элементы” и переходим во вкладку “COM - компоненты”. После этого, находим компонент Windows Media Player, подключаем и кидаем на форму в её нижнюю часть. Также нам понадобится один ListView, два textbox`а и один Button. В результате должно получиться что-то вроде этого:



Теперь перейдём к внутреннему наполнению кодом. Но перед этим, сразу определимся что все данные( т.е названия радиостанция, URL и др) ,будем хранить в формате XML, который очень удобно использовать как раз для таких вещей. Далее пишем обработчик события для нажатия кнопки. Тут надо сразу условится, что в первое поле будем вводить название для радиостанции, а во вторую её URL. Чтобы был корректным адрес, нужно не допустить некоторые символы. Запишем их в отдельный массив.


private char []symb = {'!','@','&','#','%','*','"'};



И теперь можно писать функцию, которая проверяет корректность символов в полях
                                            Листинг 1.1


public bool CheckFields()
       {
           string t1 = textBox1.Text; string t2 = textBox2.Text;
           if ( (t1.Length == 0 || t2.Length == 0)
               || (t1.Length > 100 || t2.Length > 100) )
               return false;
           if ( t1.IndexOfAny(symb) != -1 || t2.IndexOfAny(symb) != -1 )
               return false;
           return true;
       }


Думаю всё понятно,а если не всё , то в конце заметки, будет архив с исходниками и с подробными комментариями. Скажу только, что в лучшем случае функция вернёт true, а в худшем false. Если функция вернула true, то можно переходить непосредственно к заполнению ListView

Листинг 1.2


private void button1_Click(object sender, EventArgs e)
       {
                   if (CheckFields())
                   {
                          string[] items = { textBox1.Text, textBox2.Text, "Отключено" };
                          ListViewItem lv = new ListViewItem(items);
                          listView1.Items.Add(lv);
                   }

       }


В массив записывается {имя,ссылка, и текущий статус}, который добавляется в наш список. Давайте попробуем добавить первую радиостанцию, например
Эхо-Москвы, http://radio.echo.msk.ru:8000/listen.pls . После нажатия кнопки добавить, мы видим, что радиостанция успешно добавилась. Теперь неплохо бы и послушать. Для этого, пишем обработчик события для двойного клика для ListView. Пишем слудующее.
  
                                               Листинг 1.3


//Проверяем в что мы в онлайне
if (axWindowsMediaPlayer1.isOnline)
           {
                //URL
               axWindowsMediaPlayer1.URL = listView1.SelectedItems[0].SubItems[1].Text;
               axWindowsMediaPlayer1.Ctlcontrols.play();  //Запускаем проигрывание
                //Изменяем параметры включено и отключено
               foreach (ListViewItem it in listView1.SelectedItems)
               {
                   if (ll == -1)
                       it.SubItems[2].Text = "Работает";
                   else
                   {
                       listView1.Items[ll].SubItems[2].Text = "Отключено";
                       it.SubItems[2].Text = "Работает";
                   }
                   ll = listView1.SelectedItems[0].Index;
               }
           }


Вот собственно и весь запуск. Теперь можно включать радиостанцию и наслаждаться звуком, который выдаёт Windows Media Player:) Кстати таким же образом можно слушать и подкасты. Для них можно также, придумать дополнительные фишки типа выбора выпуска итд, но данная тема уже выходит за рамки нашего сегодняшнего обсуждения. Теперь, когда все радиостанции добавлены, надо их сохранить в файл. Как было уже сказано, данные будем хранить в XML файле. Для записи, воспользуемся интерфейсом Linq to XML, который обеспечивает более простую работу с XML файлами.

                                    Листинг 1.4


try
           {
               XDocument doc = new XDocument();
               XElement library = new XElement("radio");
               doc.Add(library);

               foreach (ListViewItem lv in listView1.Items)
               {
                   XElement name = new XElement(lv.Text);
                   name.Value = lv.SubItems[1].Text;
                   library.Add(name);
               }
               doc.Save("test.xml");
           }
           catch (Exception ex)
           {
               MessageBox.Show(ex.Message);
           }


Сначала создаём объект XDocument, после этого создаём элементы в нашей базе, которые будут носит имя радиостанций. Опять же, более подробные комментарии, ищите в архиве с исходниками.
 Вот вроде бы и всё. Сегодня мы написали небольшое приложения для прослушивания радио. Надеюсь, эта заметка была вам полезна. В архиве вы найдёте готовую программу и исходные тексты, которые вы сможете править по собственному желанию. Удачи!

Дополнение.

1. Архив и исходниками
http://zalil.ru/30393243

2. Полезные ссылки