вторник, 28 декабря 2010 г.

Чем отличаются опции с одним дефисом от опций с двумя в консольных приложениях?

Сегодня как будто заново родился в прямом смысле слова.

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


c:\tools\grep_>grep --help
Usage: grep [OPTION]... PATTERN [FILE] ...
Search for PATTERN in each FILE or standard input.
Example: grep -i 'hello world' menu.h main.c

Regexp selection and interpretation:
-E, --extended-regexp PATTERN is an extended regular expression
-F, --fixed-strings PATTERN is a set of newline-separated strings


Возможно у Вас также как и у меня возникали вопросы:
  1. А чем отличаются опции с одним дифисом, от опций с двумя дефисами?
  2. Если обе опции ведут к одному и тому же, то зачем вводить две?
Введем терминологию(не моя, услышал от коллеги):
  1. Короткие опции, помечаемые одним дефисом;
  2. Длинные опции, помечаемые двумя дефисами.

Для того чтобы понять эту разницу, нужно осознавать, что существуют два случая применения программ консольного типа:
  1. В визуальной среде позволяющей интерактивно работать с програмами консольного типа(К примеру: для MS Windows это "cmd.exe", либо FAR с горячей клавишей "ctrl+O");
  2. В командных сценариях(*.bat, *.cmd, *.sh, etc). 


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

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

Осталось пояснить еще один нюанс, который весьма важен и который нужно знать!
Значения в коротких опциях, следуют через пробел, а в длинных через символ "=" , который в языке программирования в "С" означает "присвоить".

четверг, 18 ноября 2010 г.

Screencast making

Уже давным давно столкнулся с разнообразными обучающами видео-роликами. Ищи как правило на youtube.com. Все что поднимает бунт в моей душе, к примеру драйвер-девелопмент, разработка и проектирование приложений, написание грамотного кода, да много чего. Однако только недавно решился на создание своих скринкастов, так сказать до рос ))) Встал вопрос, на чем остановиться?

Ответ гугла вывел меня на обзор программ приведенный на хабре, благодаря которумы узнал об этой фриварной проге. Умеет как раз то что надо:
  • Пишет полноэкранный видос с микрофоном;
  • Позволяет также на видосе уставливать разнообразные стрелочки, заметки и др. Причем разными цветами!!
Может, как нить начну толкать свои мысли через скринкасты, пока все это будет направлено на корпоративный документатион, по причине того, что информация нужна, а писать много букав влом!;)

воскресенье, 3 октября 2010 г.

Бъярн Страуструп

Очень многие из нас хотят знать, а что собственно думает о С++ сам автор? Об этом можно получить представление, но только англо-понимающих. К сожалению у меня не такой уровень владения языком,чтобы легко понимать его,однако замечу что говорит Бъярн члено-раздельно!!!
Предлагаю практикующимся в С++ и английском, слушать чаще подобных людей. Приведу ссылки на ютуб, где можно послушать Бъярна:
Успеха вам в понимании! ;)

среда, 29 сентября 2010 г.

Получить десятичное число, перевести и вывести в двоичной системе счисления

Задачка уровня 1-курсника ВУЗа:

Введенное десятичное число в диапазоне от 0 до INT_MAX(константа из climit-инклуда) преобразовать в двоичную систему счисления и вывести на экран. Для вывода и ввода юзать std::cout, std::cin.

Запрещено:
  1. Использовать любые массивы;
  2. Вызывать printf;
  3. Создавать функции, кроме одной main();
  4. Использовать манипуляторы пространства std::
  5. Логические сдвиги чисел, т.е. операции '<<', '>>'
  6. Рекурсия запрещена.
  7. Логическое умножение; 
Ответ(http://www.base64.ru/):
ICAgIGludCBudW1iZXIgPSBpOwogICAgaW50IHBvd2VyICA9IDE7CiAgICB3aGlsZShwb3dlcioyPD1udW1iZXIgJiYgcG93ZXIqMiA+IHBvd2VyKQogICAgICBwb3dlcio9MjsKICAgIAogICAgd2hpbGUocG93ZXIgPiAwKSB7CiAgICAgIGNvdXQgICA8PCBudW1iZXIgLyBwb3dlcjsKICAgICAgbnVtYmVyICU9IHBvd2VyOwogICAgICBwb3dlciAgLz0gMjsKICAgIH0=

понедельник, 13 сентября 2010 г.

Забавное нововведение в использовании реестра MS Windows

Вобщем, теперь можно менять способ поиска DLL-ок, но об этом лучше почитать тут. Фактически означает еще одну "возможность" ;)

среда, 8 сентября 2010 г.

Меня догнал Python

Итак, как дикая смесь ленивого + системаного программиста + реверсера мне всегда было любопытны технологиии автоматизирующие реверс и поиск чего-либо для решения моих задач в кратчейшее время или чтобы само искалось ))) Но в этот раз технологии, а точнее язык, сам меня догнал и четко сказал мне "Я Python! Меня надо учить!" и сколько бы не убегал от его эгоцентричности, что мол он сказал и ... не убежал. Он твердо сегодня мне заявил: "А теперь я еще и в WinDbg"

О чем это я ? О том что скриптовый язык Python теперь почти в любом в более-менее значимом реверс-инструменте:

суббота, 4 сентября 2010 г.

Создание нового SVN-проекта на кряклаб

Ввиду того что команда cracklab.ru подняли SVN сервак, то я тут же воспользовался этой возможностью ) Поэтому теперь, все мои публичные исходники будут только тут .

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

Пока еще все конечно сырое, но в последствии будет куда лучше ;)

четверг, 2 сентября 2010 г.

Детект машинной инструкции PUSH/POP reg

Приведу одну из задачек, которые встречаются в практике написания кодо-анализитаторов. Есть код приведенный ниже, нужно оптимизировать и получить более эффективный по выполнению код:

 switch(Opc)
 {
 case 0x50: case 0x51: case 0x52: case 0x53:
 case 0x54: case 0x55: case 0x56: case 0x57:
 {
  std::cout << "This is PUSH reg instruction" << std::endl;
  break;
 }
 case 0x58: case 0x59: case 0x5A: case 0x5B:
 case 0x5C: case 0x5D: case 0x5E: case 0x5F:
 {
  std::cout << "This is POP reg instruction"  << std::endl;
  break;
 }
 default:
  std::cout << "This isn't PUSH/POP reg instruction" << std::endl;
 }
Ответ (http://www.base64.ru/):

CS8vINCe0LTQvdC+INC40Lcg0LLQvtC30LzQvtC20L3Ri9GFINGA0LXRiNC10L3QuNC5CglpZigoT3BjICYgMHhGOCk9PTB4NTApCgkJc3RkOjpjb3V0IDw8ICJUaGlzIGlzIFBVU0ggcmVnIGluc3RydWN0aW9uIiA8PCBzdGQ6OmVuZGw7CgllbHNlIGlmKChPcGMgJiAweEY4KT09MHg1OCkKCQlzdGQ6OmNvdXQgPDwgIlRoaXMgaXMgUE9QIHJlZyBpbnN0cnVjdGlvbiIgIDw8IHN0ZDo6ZW5kbDsKCWVsc2UKCQlzdGQ6OmNvdXQgPDwgIlRoaXMgaXNuJ3QgUFVTSC9QT1AgcmVnIGluc3RydWN0aW9uIiA8PCBzdGQ6OmVuZGw7

среда, 1 сентября 2010 г.

Упаковщики, крипторы, протекторы

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

Забыл пароль от Win 7 x64, чего делать?

Задумался тут, что если у человека не стоит пароля на BIOS и как тогда мне стать админом на его компе,. если там семерка? ;) Порыскав по инэту наткнулся на:
Change your password with sticky keys

Приведу цитату:

To reset a forgotten administrator password, follow these steps:
  1. Boot from Windows PE or Windows RE and access the command prompt.
  2. Find the drive letter of the partition where Windows is installed. In Vista and Windows XP, it is usually C:, in Windows 7, it is D: in most cases because the first partition contains Startup Repair. To find the drive letter, type C: (or D:, respectively) and search for the Windows folder. Note that Windows PE (RE) usually resides on X:.
  3. Type the following command (replace “c:” with the correct drive letter if Windows is not located on C:):
    copy c:\windows\system32\sethc.exe c:\
    This creates a copy of sethc.exe to restore later.
  4. Type this command to replace sethc.exe with cmd.exe:
    copy /y c:\windows\system32\cmd.exe c:\windows\system32\sethc.exe
  5. Reboot your computer and start the Windows installation where you forgot the administrator password.
  6. After you see the logon screen, press the SHIFT key five times.
  7. You should see a command prompt where you can enter the following command to reset the Windows password (see screenshot above):
    net user you_user_name new_password
    If you don’t know your user name, just type net user to list the available user names.
  8. You can now log on with the new password.
     

четверг, 26 августа 2010 г.

Плагины к Hiew

 Итак, новости которые меня весьма поразили ;)
  1. Hiewplus, ссылка на hiewplus
  2. PyHiew, ссылка на pyhiew 
  Первый представляет собой приложение win32 и позволяет попытаться открыть процессы в стандартном Hiew-шном интерфейсе.
  Второй же служит для добавления возможности написания скриптов на Python и использовать их к открытому в Hiew файле.

среда, 18 августа 2010 г.

Реализация идиомы Pointer to Implementation с применением std::auto_ptr

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

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

Условия: имеется небольшой файл-хидер header1.hpp:

#include 

class CMain1 {
  class     CAddon;
  typedef   std::auto_ptr< CAddon >  AddonPtr_t;
public:
  CMain1();
private:
  AddonPtr_t m_Addon;
};
а также есть файл-реализации impl1.cpp:

#include "header1.h"

class CMain1::CAddon {
};

CMain1::CMain1()
: m_Addon(new CAddon) 
{}

Ответ (  http://www.base64.ru/ ):
----
 0JTQtdGB0YLRgNGD0LrRgtC+0YAg0LrQu9Cw0YHRgdCwIENNYWluMSDQstGL0LfRi9Cy0LDQtdGCINC00LXRgdGC0YDRg9C60YLQvtGAIHN0ZDo6YXV0b19wdHIsINC90L4g0L/RgNC4INGN0YLQvtC8IH5DTWFpbigpINC/0L7QvdGP0YLQuNGPINC90LUg0LjQvNC10LXRgiDQviDRgtC+0Lwg0LrQsNC6INGD0YHRgtGA0L7QtdC9IENBZGRvbi4g0KfRgtC+INCx0Ysg0LjQt9Cx0LDQstC40YLRjNGB0Y8g0L7RgiDQvtGI0LjQsdC60Lgg0L3Rg9C20L3QviAg0L3QsNC/0LjRgdCw0YLRjCDRgNC10LDQu9C40LfQsNGG0LjRjiB+Q01haW4oKSDQsiDRgtC+0Lwg0LbQtSDRhNCw0LnQu9C1INCz0LTQtSDQuCDQtNC10LrQu9Cw0YDQsNGG0LjRjyBDQWRkb24=
----

пятница, 13 августа 2010 г.

Небезопасные типы в закрытых базовых классах

Наверняка многие сталкивались с готовым кодом, который менять нельзя, хоть ты тресни. А в нем используются небозопасные типы, к примеру метод класса принимает указатель на void, а по нему не зная типа или размера нельзя корректно освободить память!
Читая Джеффа Элджера увидел интересный прием:

class UnsafeNode {
public:
  UnsafeNode(UnsafeNode * next_, void * data_);
  virtual ~UnsafeNode();
  UnsafeNode * Next();
  void * Data();
private:
  UnsafeNode * m_Next;
  void       * m_Data;
};

template < typename T>
class SafeNode : private UnsafeNode {
public:
  SafeNode(SafeNode * next_, T * data_) : UnsafeNode(next_, data_) {}
  virtual ~SafeNode() { delete( (T*)Data() ); }
  SafeNode * Next()   { return( (SafeNode*)UnsafeNode::Next() ); }
  T *  Data()         { return( (T *)UnsafeNode::Data()); } 
};

1) Потомки не видят безобразия в базовом классе, т.к. применяется закрытое наследование
2) Можно применить любой тип, т.к. шаблон
3) Коректно удалится в деструкторе, т.к. задана привязка к типу

Некомпилируется код применением указателя:

Имеется код, приведенный ниже. Почему в случае №1 компилятор не может скомпилировать код, а в случае №2 пусть и громоздко, но все отлично компилируется?


class CUnk {
public:
  void SuperMethod() { std::cout << "CUnk::SuperMethod()" << std::endl; }
};

class CUnkPointer {
public:
  CUnkPointer() : m_UnkPtr(0) {}
  CUnkPointer(CUnk * UnkPtr) : m_UnkPtr(UnkPtr) {}
  ~CUnkPointer()     { if(m_UnkPtr) delete(m_UnkPtr); m_UnkPtr=0;  }
  operator CUnk *()  { return(m_UnkPtr); }
private:
  CUnk * m_UnkPtr;
};

  CUnkPointer UnkPtr( new CUnk);
  UnkPtr->SuperMethod();            // (Случай №1)
  ((CUnk*)UnkPtr)->SuperMethod();   // (Случай №2)

Ответ( http://www.base64.ru/ ):

----
0J/QvtGC0L7QvNGDINGH0YLQviDQsiDRgdC70YPRh9Cw0LUg4oSWMiDRgdGD0YnQtdGB0YLQstGD0LXRgiDQvtC/0LXRgNCw0YLQvtGAINC/0YDQtdC+0LHRgNCw0LfQvtCy0LDQvdC40Y8sINCwINCyINGB0LvRg9GH0LDQtSDihJYxINC90LXRgiDQv9C10YDQtdCz0YDRg9C30LrQuCDQvtC/0LXRgNCw0YLQvtGA0LAgIi0+Ig==
----

четверг, 12 августа 2010 г.

Перевод "%UPX_SOURCE%\upx-3.05-src\doc\filter.txt"

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

среда, 11 августа 2010 г.

понедельник, 9 августа 2010 г.

Моя первая статья

На прошлой неделе вышла моя статья с названием "Некоторые приёмы статического анализа кода из арсенала вирусного аналитика" в журнале "No bunkum". Статья посвящена некоторым полезным приемам использования реверс-тулзы Hiew, которые помогают повысить эффективность и качество работы при анализе исполнимых файлов.
Прошу не судить строго и учесть, что это мой первый опыт написания чего-либо на паблику. Хотя нет, вру,  второй ))) Но между первым и вторым был слишком большой промежуток и можно считать эту статью условно первым моим опытом )

Статью можно  найти тут .

P.S.:
Для справки, первой была статья "Алгоритм шифрования ГОСТ 28147-89. Метод простой замены."  на  wasm.ru , по этой ссылке можно перейти к статье

Операторы преобразования

Сегодня после прочтения подраздела "Операторы преобразования" на стр. 48 книги Джеффа Элджера "Библиотека программиста. C++" пришел к тому, что тот велосипед, что я сконструировал для работы с параметрами можно упростить, вот его текущий код:


  class CParameter {
  public:
    CParameter() : m_Exist(false) { }
    CParameter(std::string & val, bool exist)
      : m_Exist(exist), m_Value(val) {};

    bool        Exist()   { return( m_Exist );                            }
    int         AsInt()   { return( atoi(str::Trim(m_Value).c_str()) );   }
    double      AsFloat() { return( atof(str::Trim(m_Value).c_str()) );   }
    std::string AsString(){ return( m_Value.c_str() );                    }

    bool        AsBool()  {
      std::string s(str::Trim(m_Value));
      if(s.empty())
        return(false);

      std::transform(s.begin(),s.end(),s.begin(),tolower);
      return(1 == strcmp( s.c_str(), "true"));
    }
  private:
    std::string m_Value;
    bool        m_Exist;
  };


его текущее использование выглядит таким:

std::string driver = m_Ini["driver"]["filepath"].AsString();

что является не совсем наглядным. После прочтения этого подраздела, пришел к выводу, что куда удобней будет перегрузить:
  • operator std::string()
  • opertator int() 
  • operator double()
  • operator bool()
Тогда работа с параметрами будет уже более наглядной:

 std::string driver ( m_Ini["driver"]["filepath"] );

т.е. компилятор зная тип, куда присваивается сам определяет нужную версию функции возврата и тем самым избавляет меня от необходимости писать эти громоздкие AsString() , AsInt() , etc

воскресенье, 8 августа 2010 г.

Забывая о методах класса создаваемых по умолчанию

Весьма забавный феномен, если не знать тонкости ;)

class CStr {
public:
  CStr(char * str) {
    if(!str) {
      m_Ch  = new char[1];
      *m_Ch = 0x0;
    }
    else {
      m_Ch = new char[strlen(str)+1];
      strcpy(m_Ch,str);
    }
  }
  ~CStr() { delete(m_Ch); }
  void dump(std::ostream & strm) {
    strm << "\"" << m_Ch << "\"\n";
  }
private:
  char * m_Ch;
};

CStr * s1 = new CStr("First String !!!");
CStr * s2 = new CStr("Second String !!!");

s1->dump(std::cout);
s2->dump(std::cout);

s2 = s1;

s1->dump(std::cout);
s2->dump(std::cout);

delete(s1);

s2->dump(std::cout);
delete(s2);

Думаю этот пример убедил, что нужно быть внимательней при разработке класса ;)

вторник, 27 июля 2010 г.

Знакомство с итараторами

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

Ссылка: http://www.hostmake.ru/articles/c/324/
Название: Итераторы библиотеки STL
Автор: Дмитрий Рамодин

Рекомендую к прочтению любому, кто осваивает язык

понедельник, 26 июля 2010 г.

Подмена dll зная CLSID КоСервера

Исследуя недавно Windows Messenger, задался вопросом: "а как внедрить в его адресное пространство процесса свою dll ?". Именно об этом эта заметка:

Значение параметра в ini-файле

В виду того,что иногда программистам хочется размять свой мозг и сделать какие-либо упражнения, то они начинают их искать :). Приведу пример подобной задачки и я.

Цель задачи: Написать реализацию функции, которая возвращает значение параметра в виде std::string.

Вот прототип итоговой функции и используемого ею типа итератора:

typedef std::string::iterator StrItr_t;
std::string ExtractValue(StrItr_t & p, std::string & s)

Значением считать:

1) Одну и более строк, с возможным выделением значения в ковычки;
2) Символом переноса на новую строку считать '\', находящийся в конце строки, до привычного нам '\n', т.е. байта 0x0A и предваренный пробелом или табуляцией;
3) Строка начатая ковычкой, при перенесении на новую строку не выделяется повторно в ковычки на новой перенесенной строке;
4) Символами коментария считать ';', '#' и только если значение не выделено в ковычки;
5) Если значение взято в ковычки и встретилось s.end() значит все что успели прочитать считать результатом;

В результат не попадают:

1) Ковычки, которые выделяют значение;
2) Символы коментариев;
3) Привычный нам символ новой строк '\n', т.е. байт равный значению 0x0A, который физически делит строки;
4) Символ переноса '\' на следующую строку;
5) Символ вертикальной табуляции '\t'.

пятница, 16 июля 2010 г.

Понимание устройства INI-файлов

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

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

Строение:
1) Могут иметься глобальные параметры, это параметры не принадлежащие какой-либо секции, т.е. описаны до первой секции
2) Секции определяются названием заключенным в квадратные скобки и их значением, состоящим из параметров и их значений
3) Параметры задаются именем и значением. Значение и имя разделяется символом '='
4) Значения могут быть очень большими и тогда очень удобно внедрить поддержку символа '\' означающего перенос на новую строку
5) Также для удобства сопровождения файлов существуют коментарии, как правило, это символы ';', '#'
6) Может возникнуть ситуация, когда символы относящиеся к специальным ';', '#', '\' нужно включить поддержку ковычек. Другими словами, если значение начинается с ковычек, то считать значением все пока не найдена закрывающая, т.е. самая последняя, после которой только пробелы, табуляци или конец строки, ну или пока не закончилась строка

Какие могут быть нюансы?

1) В файле могут быть две секции с одинаковыми названиями?
2) Стоит ли обрамлять в ковычки каждую новую перенесенную строку в ковычки?

Рекомендуемые ссылки:
1) ".ini"
2) "Cloanto Implementation of INI File Format"

понедельник, 12 июля 2010 г.

Создание заготовки распакованного файла

Заметка для тех кто по каким-либо причинам заинтересовался разработкой статических распаковщиков.

воскресенье, 20 июня 2010 г.

Организация работы приложения соглассно настройкам

Сегодня вывел для себя правило, которое можно сформулировать так:

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


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

Таким образом достигаю следующих целей:
1) Буду знать где читается\сохраняется настройка из реестра;
2) Аналогично для командной строки;
3) Аналогично для конфигурационных файлов;
4) Буду знать как прочитать\сохранить выбор сделанный пользователем через GUI-интерфейс;

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

ЗЫ:
Меня опять-таки выручает мой любимый вопрос "Чего ты Дима хочешь достигнуть используя это приложение?"

четверг, 17 июня 2010 г.

Куда приспособить, как опцию командной строки или все же в ini-файл?

Перед теми кто разрабатывает довольно серьезный проект приложения консольного типа, рано или поздно встает вопросы "А куда эту настройку приспобить? Может как аргумент командной строки? А может как параметр конфигурационного файла?"

Для того чтобы пояснить правило получения ответов на подобные вопросы, поясню вам, что все-таки является консольным приложением на практике?

Существует две категории пользователей:
1) Одни пользуются графическим интерфейсом и им удобней пользоваться мышью. Перемещать указатель, выбирать пункт меню на самом верху графического окна в приложении.
2) А есть другая категория людей, которые понимают, что они могут повысить скорость своей работы, если будут набирать команды, а не "возить" туда-сюда мышь по коврику и им куда-быстрее набрать команду плюс пару опций, чем задействовать GUI.

Именно в п.2. и следует искать ответ на вопрос: "а куда мне это?".

Есть множество настроечных параметров для работы приложения и делятся они на две категории:
1) Которые быстро и часто меняются
2) И такие которые наверное один раз задал и можно больше не касаться, по крайней мере до следующего билда.

К первым можно отнести "введите число для перевода его в двоичную", вот число как раз попадает под первую категорию, потому что уже через секунду может понадобиться новый результат. Ко втором можно отнести указание файлового пути к драйверу, с которым работает приложение. Думаю в случае, если разработчики и поменяют чтото в драйвере, то довольно часто оставляют тоже самое место в структуре папок своего продукта и вы можете положить туда же последний билд драйвера.

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

Пример из жизни, системная утиллита по исследованию внутренних объектов режима ядра у операционной системы. Для нее нужно написать драйвер, т.к. работая в пользовательском режиме вы врядли чего продуктивного получите, так вот драйвер редко меняет свое место расположение и поэтому его можно задать в ini-файле. Зато запрос на показание объекта, а какого, вот это уже быстро и часто меняющийся параметр к программе! Следовательно это лучше задать как опцию командной строки!

Правило:
Быстро и часто меняется ? "Да", значит в это кандидат в аргументы командной строки, если нет,то занести в качестве параметра конфигурационного файла.

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

четверг, 10 июня 2010 г.

Windows 7 UAC whitelist

Вчера столкнулся с трудностью установки драйвера под эту систему, выполнив строчку:

hSCMngr = ::OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);

получил "Access is denied". Хотя ранее этот код под XP работал на УРА, оно и не удивительно, там ведь не было UAC. Ввиду того, что пишу драйвер для утиллиты своих собственных нужд, которая будет работать исключительно на моем компе, то мне очень хочется чтобы все работало без спрашивания паролей или UAC-диалога. Начав изучать эту тему столкнулся с интересной информацией. Оказывается есть белый список ;) Насколько сейчас обстоят дела, но это весьма весьма занятная тема для размышления.

Интерисующимся читать белый лист .

Также рекомендовал поглядеть и High elevation can be bad for your application: How to start a non-elevated process at the end of the installation


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

понедельник, 7 июня 2010 г.

Полиморфные объекты от Microsoft

Решил сегодня поглядеть внутрь Win32k.sys через Hiew. Этот файл у меня располагается по пути:
c:\Windows\winsxs\amd64_microsoft-windows-win32k_31bf3856ad364e35_6.1.7600.16385_none_14e86b61b437d067\win32k.sys

Система win7 x64 и увидел:

.FF0C3761: 666666666666660F1F840000000000 nop [rax][rax][0]
.FF0C3770: 66666690 nop
.FF0C3774: 666690 nop

Удивлению нет предела )))

Причем здесь "полиморфизм"? А при том, что если вы детектили полиморфные объекты, то вы должны знать о способе детекта по мусору. Напомню, что суть детекта заключается в подсчете подозрительных(уникальных) инструкций и выдаче статуса "обнаружен", если их количество превысило допустимое значени. Думаю, теперь на лицо "подозрительная" инструкция nop :)

пятница, 4 июня 2010 г.

Lazy IRQL

У меня есть эл.версия книги:
М. Руссиновича, Д. Соломона, "Внутреннее устройство Microsoft Windows: Windows Server 2003, Windows XP и Windows 2000", 4 изд.

Читаю сейчас про очень интересный механизм оптимизации называемый "Lazy IRQL" и описываемый на стр. 100 в самом последнем абзаце.

Приведу абзац здесь:
"Поскольку доступ к PIC - операция довольно медленная, в HAL, использующих PIC, реализован механизм оптимизации "Отложоенный IRQL"(LazyIRQL), который избегает обращений к PIC. Когда IRQL повышается, HAL - вместо того чтобы изменять маску прерывания - просто отмечает новый IRQL. Если вслед за этим возникает прерываание с более низким приоритетом, HAL устанавливает маску прерывания в соответствии с первым и откладывает обработку прерывания с более низким приоритетом до понижения IRQL. Таким образом, если при повышенном IRQL не повзникает прерываний с более низким проритетом, HAL не потребуется обращаться к PIC."

Мне даже с n-ой итерации вдумчивого чтения не совсем стало понятны слова авторов. Уж больно туманно как-то все написано. Поэтому обратившись к Four-F получил более понятное пояснение:

"Если только в общих чертах. Т.к. запись в PIC относительно медленная операция, то ядро пытается избежать её таким образом. Когда IRQL повышается, то все все прерывания с этим и более низким уровнем д.б. замаскированы и обработка их должна быть отложена до понижения IRQL. Для этого раньше тупо прописывали маску в PIC. Но если во время обработки первого прерывания больше не произойдет прерываний того же или более низкого уровня, получается что мы зря писали в PIC. Поэтому современное ядро поступает так. Оно запоминают на IRQL первого прерывания, но в PIC не пишут. Если во время обработки этого прерывания действительно происходит прерывание того же или более низкого уровня, то тогда уже ядро записывает в PIC маску, соответствующую текущему обрабатываемому прерыванию. Т.е. в этом случае работает старая схема. Ну а если другого прерывания не случается, то и вообще в PIC ничего писать не нужно. Примерно так эта хрень работает. Более детально я не знаю, ибо нафиг не нужно :)"

Казалось бы вроде, слово в слово, но мне почему-то со слов Four-F более понятно стало, что же происходит?! ;)

четверг, 3 июня 2010 г.

Использование макросов при разработке на С\С++

Наверное каждый программист разрабатыващий ПО на С\С++ писал макросы сталкивался с некоторой хитростью, которая приводит к интересному и малопонятному багу, при попытке использовать их как функции. Приведу пример, допустим есть макрос возврата минимального числа из двух:

#define M_MIN(A,B) ( ((A) < (B)) ? (A) : (B) )

При попытке исползования в следующем коде:

int a = 2, b = 4;
int c = M_MIN(a++, b);

мы почему-то получаем не то что ожидаем! Это связано с тем что подставится в проверку (2++) < 4 , и потом еще раз при подстановке наименьшего ? (3++) , то есть 4 !

Из этого вытекает только одно правило: не использовать макросы, а если без них никак, то не использовать их как функции!!!!

четверг, 27 мая 2010 г.

Дружба VirtualKD и WinXP SP3 внутри VMware

Сегодня удалось подружить VirtualKD и WinXP SP3 поставленную в качестве гостевой системы внутри VMware.

Сначала коротко о том, что же такое VirtualKD ?
Если вы перейдете по следующей ссылке, то вы можете прочесть все сами, но приведу слова тут:

In English:
Welcome to the VirtualKD homepage. This project allows speeding up (up to 45x) Windows kernel module debugging using VMWare and VirtualBox virtual machines. If you have ever noticed that the standard debugging over virtual COM port is irritatingly slow, this software is for you!

In Russian(от меня)
Добро пожаловать на домашнюю страничку VirtualKD. Это проект позволяет провысить скорость(до 45x) отладки модулей ядра Windows используя виртуальные машины VMware и VirtualBox . Если Вы когда-либо замечали что стандартная отладка через виртуальный COM порт раздражающе медленная, то это программное обеспечение для Вас!

Думаю теперь вам цель этого проекта понятно и можно приступить к описанию установки, настройки.

1) Установить собственно Windows внутрь VMware
2) Каким-либо способом передать архив дистрибутива внутрь гостевой системы
3) Запустить "target\vminstall.exe" внутри этой гостевой системы
4) Запустить на хостовой, т.е. там где стоит VMware файл "virtualkd\vmmon.exe"
5) Через кнопку "Debugger path" указать путь к отладчику в проге vmmon.exe
6) Перезагрузить гостевую с выбором варианта отладочной загрузки системы
7) После выбора варианта загрузки, система остановится и не будет грузиться. Это нормально!!!
Для этого в загруженном отладчике нужно сказать "ГОУ", для WinDBG это команда "g" в его командной строке и возможно придется два раза, пока не появится "debugging running"
8) Система загрузилась

Теперь, предпочитаю "сохраниться" ;))) Для этого надо перейти в WinDBG и выбрать в верхнем меню Debug->break. После этого гостевая "замрет" и можно нажать кнопку "save snapshot". В комантариях к снэпшоту укажите что хотите не забыть в будущем, чтобы потом не тупить )

среда, 26 мая 2010 г.

Выгрузка драйвера, условия работы DriverUnload

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

Инициализация драйвера подобна процессу создания объекта класса в С++. Когда вы создаете объект класса, то в случае, если тело конструктора корректно не отработало и некорректно завершен, тогда не следует ждать работы деструктора объекта. Он отработает только, когда корректно создан объект, читай корректно отработал конструктор. Другими словами, если вам, к примеру, нужно сделать 5 действий, а из них корректно выполнены только 4, то вы должны внутри конструктора "откатить" изменения сделанные этими 4 действиями и только тогда вы можете завершать работу конструктора бросанием исключения. Не стоит надеяться на то что в деструкторе все почистится и завершится!

В модели драйверов WDM точно также, есле не отработана функция DriverEntry, т.е. не завершена кодом возврата STATUS_SUCCESS, то зарегистрированная функция DriverUnload не отработает!

Еще раз подчеркну важность освобождения ресурсов на случай, если что-то пошло не так в конструкторе объекта, если это С++ или в функции инициализации драйвера!

Кстати вот слова взятые тут:
"Note that a driver's Unload routine is not called if a driver's DriverEntry routine returns a failure status."

воскресенье, 16 мая 2010 г.

Развивая Hiew

Сбылась, мечта идиота! :))) Это я о том, что и у меня есть проект, в который можно вкладывать душу! ;) Ну а теперь все по порядку.

Давным-давно, у меня была мечта учавствовать в проекте развития программного средства или системы, которое используют очень множество людей. Очень долго зрела идея помогать множеству людей, быть действительно полезным и нужным, чтобы мой труд приносил пользу как можно большему количеству народу. Шло время, а возможности реализации этой идеи все не представлялось. Буквально недавно до меня дошло как же осуществить мою затею :)

До устройства на постоянную работу в ЗАО "Лабораторию Касперского"(далее ЛК) вирусным аналитиком, мне приходилось сталкиваться с анализом исполнимых файлов формата PE исключительно в личных целях, мне было интересно как устроены защиты ПО, как работают вирусы. В то время анализировал файлы только в основном с помощью небольшого множества инструментов, туда входили Hiew, OllyDebugger, PE-Tools, WinHex. Думаю, вы заметили что я не упомянул IDA Pro, потому что в то время ее не использовал, в силу сложности ее освоения, также не использовал и WinDbg. С течением времени, будучу сотрудником ЛК освоил множество других инструментов, поменялось почти полностью точка зрения на техники исследования. Страшно представить, какое количество файлов пересмотрел, проанализировал, сколько всего узнал работая вирусным аналитиком. Среди большого количества нового, интересного и полезного выделяется одна маленькая утиллита, весом не больше 200 КБ и называется она "Hiew". Именно о ней говорит множество системных программистов и реверсеров, потому что она имеет довольно простой интерфейс и множество весьма полезных возможностей.

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

Приведу, пиар-инфу ;)

Ссылка на домашнюю страницу на русском
Ссылка на интернет-магазин

На данный, момент разработал плагин "mbytes2csrc", цель которого выделенные байты в режимах Hex, Code скопировать в буфер обмена оформленых в виде исходников на Си.

суббота, 8 мая 2010 г.

Выдираем из Hiew-листинга байты инструкций

Получил тут листинг, который ребята получили в результате копирования в режиме Code из Hiew. Чтобы удобней было анализить, т.е. юзать IDA pro и ставить коменты в ходе анализа, то написал небольшой скрипт на Perl:

extract_code.pl:


#!/usr/bin/perl
use strict;
use warnings;

sub ParseFile
{
open (SRCFILE, $_[0]) or die "Can't open source file";
open (DESTFILE, ">$_[1]") or die "Can't create destination file";

while()
{
chomp;
if(/(\.[A-F0-9]{8}: )([A-F0-9]+)(.*)/)
{
my $bin = pack('H*', $2);
syswrite DESTFILE, $bin;
}
}

close(DESTFILE);
close(SRCFILE);
}

ParseFile($ARGV[0],$ARGV[1]);


extract_code.pl usage:
extract_code.pl

Хавает листинг вида:
.0043F3A5: 74F4 jz 00043F39B -- 1
.0043F3A7: 8D441812 lea eax,[eax][ebx][012]
.0043F3AB: EB12 jmps 00043F3BF -- 2
.0043F3AD: 8D742600 lea esi,[esi][0]

вторник, 4 мая 2010 г.

Проверочный ли выпуск у вашей системы ?

В виду того нет тулзы, которая бы ответила бы вам на вопрос в сабже, то предлагаю применить vbs-скрипт для этой цели:

1) сохраните следующее в osversion.vbs:
<начало вырезания>
strComputer = "."

' WMI Connection to the object in the CIM namespace
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

' WMI Query to the Win32_OperatingSystem
Set colItems = objWMIService.ExecQuery("Select * from Win32_OperatingSystem")

' For Each... In Loop (Next at the very end)
For Each objItem in colItems
Wscript.Echo "Caption: " & objItem.Caption
Wscript.Echo "Debug: " & objItem.Debug
Wscript.Echo "Version: " & objItem.Version
Next
WSCript.Quit
<конец вырезания>

2) выполните в командной строке:
cscript osversion.vbs

3) Результат будет примерено таким:
Caption: Microsoft Windows 7 Ultimate
Debug: False
Version: 6.1.7600

4) Где "False" говорит о том, что выпуск не проверочный.

Изначально о таком способе прочитал в книге Марка Руссиновича, но почему-то его скрипт не сработал на моей системе. ;( Пришлось немного видоизменить ;)

воскресенье, 2 мая 2010 г.

WDK(7600.16385.1) в одной упряжке с MS Visual Studio 2008 Team Suite

Ринг нуль!

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

Какой же вопрос встал передо мной в первую очередь? Правильно: "Как разрабатывать и  в чем?". Почитав в этой области и увидел множество разнообразных слов в виде "ddkbuild.cmd" или более старый "ddkbuild.bat" , позже натолкнулся на "ddkwizard", но только "VisualDDK" преподнесло мне те возможности какие я искал:

  1. Создание проекта на основе шаблонов;
  2. В проекте уже вставлены и добавлены нужные инклуды и либы;
  3. При создании проекта создаются привычные debug , release папки;

Поэтому я рекомендую всем начинающим посетить VisualDDK . Думаю, после установки этого продукта вам не захочется ставить что-либо другое! ;)

При установке меня всего-лишь спросили папку, где установлен WDK("c:\WinDDK\7600.16385.1\") и ВСЕ! Ну да и во время создания проекта указал, что нужен драйвер под Win XP ;)

среда, 28 апреля 2010 г.

Надежность текстового сообщения, где каждой букве соответствует свой уникальный символ

I. Введение.

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

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

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

Мы тогда думали, что верх надежности... Но так ли это ? ;)

Эта запись, покажет насколько это надежно и где это можно применять.

П. Анализ.

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

  1. Слова применяемые в языке имеют избыточность и особенность.
  2. Каждая буква может встречаться больше\меньше чем какая-либо другая
  3. Как правило при написании предложения используются пробелы.

Поясню п.1. возьмем слова "масса", "касса", как видим есть особеность "сс". Так что видя шифровки вида 1112131312 мы можем предполагать о том что "13" это возможно "с" или "н", а ведь есть слова где встречаются и "нн" ;) Замечу, что это не одна особенность русского языка, есть и другие.

Поясню п.2 можно взять самую большую книгу на русском языке, к примеру "Война и Мир" и подсчитать частоты встречаемости каждой буквы, в век ЭВМ и Интернет эту задачу не очень долго осуществить. Далее взяв шифро-текст, подсчитать частоты встречаемости каждого символа и можно строить предположения о каких-либо сопоставлениях символов с буквами, а учитывая при этом п.1 это еще и помогает ;)

Поясню п.3 при проделаных п.2 и п.1 моно выявить предлоги, можно также выделить, где начинаются слова и где они заканчиваются.

Дальше дело техники.

III. Че ваще никогда не юзать что-ли ?

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

суббота, 17 апреля 2010 г.

Получение адреса загрузки Kernel32 через PEB

Всем до боли знакомый способ получения адреса загрузки динамической kernel32.dll посредством доступа к PEB:

.code:0040100A 64 A1 30 00 00+ mov eax, large fs:30h
.code:00401010 8B 40 0C mov eax, [eax+0Ch]
.code:00401013 8B 40 1C mov eax, [eax+1Ch]
.code:00401016 8B 00 mov eax, [eax]
.code:00401018 8B 40 08 mov eax, [eax+8]

После свой работы на Windows 7 x64, поверг меня немного в изумление ;) по найденому адресу распологается совсем другая динамическая библеотека, это kernelbase।dll. Нет, я конечно слышал об отличиях, но столкнулся на практике только сегодня )))

Об этом можно почитать тут и здесь . Весьма ясно и не противоречиво написанно чего и где находится и как искать нужное ! ;)