Взлом через покрытие

Как мы будем действовать


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

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

Ниже приведен листинг упрощенной версии анализатора логов, не использующей сортировку и выполняющий сравнение путем последовательного поиска, а потому объемные логи обрабатывающий довольно долго (впрочем, с учетом быстродействия современных процессоров времени потребуется не так уж и много):

#define XL    1024                 // максимальная длина одной строки лога

#define NX    (1024*1024)          // максимальное количество строк лога

// добавить новый адрес в массив,

// если он не встречался ранее

addnew(unsigned int *p, unsigned int x)

{

       int a;

      

       for (a = 1; a<*p; a++) if (p[a] == x) return 0; if (a == NX) return -1;

       p[0]++; p[a] = x; return 1;



}

// вывод результатов на экран

PRINT(unsigned int x, FILE *f)

{

       char *z; char buf[XL];

       while(fgets(buf,XL-1,f)) if((strtol(buf,&z,16)==x)&&(printf("%s",buf)|1))break;

}

// сравнение двух массивов адресов на предмет различий

diff(unsigned int *p1, unsigned int *p2, FILE *f)

{

       int a, b, flag;


       for (a = 1; a<*p1; a++)

       {

              for(b = 1, flag = 0;b<*p2; b++) if ((p1[a]==p2[b]) && ++flag) break;

              if (!flag) PRINT(p1[a],f);

       }

}

main(int c, char **v)

{

       int f=0; char buf[XL]; FILE *f1, *f2; unsigned int *p1, *p2; char *x;

      

       if (c < 3) return printf("USAGE: log-coverage-diff.exe file1 file2\n");

      

       p1 = (unsigned int*) malloc(NX*4); p2 = (unsigned int*) malloc(NX*4);

      

       f1 = fopen(v[1],"rb");if (!f1) return printf("-ERR: open %s\x7\n",v[1]);

       f2 = fopen(v[2],"rb");if (!f2) return printf("-ERR: open %s\x7\n",v[2]);

      

       fgets(buf, 1023, f1); fgets(buf, 1023, f2);

      

       while(f<2 && !(f=0))

       {

              if (fgets(buf, XL-1, f1)) addnew(p1,strtol(buf,&x,16)); else f++;

              if (fgets(buf, XL-1, f2)) addnew(p2,strtol(buf,&x,16)); else f++;

       }

      

       if (fseek(f1, 0, SEEK_SET)) return printf("-ERR: seek %s\x7\n",v[1]);

       if (fseek(f2, 0, SEEK_SET)) return printf("-ERR: seek %s\x7\n",v[2]);

      

       printf("\ndiff p1 -> p2\n");diff(p1,p2,f1);

       printf("\ndiff p2 -> p1\n");diff(p2,p1,f2);

      

       return 0;

}

Листинг 1 листинг программы log-coverage-diff.c, сравнивающий протоколы трассировки отладчика OllyDbg и определяющий разницу в покрытии

Компиляция осуществляется как обычно, то есть с ключами по умолчанию, в частности, при использовании Microsoft Visual C++ командная строка выглядит так: "cl.exe log-coverage-diff.c", а для создания оптимизированного варианта — "cl.exe /Ox log-coverage-diff.c" Только не надо выделять весь текст и копировать его в среду разработки, а потом нажимать F7 (Build) и удивляться почему это программа не компилируется! Она и не должна компилироваться, поскольку по умолчанию Microsoft Visual Studio создает проект на Си++, а это Си.Как говорится, почувствуйте разницу!



Рисунок 4 результат компиляции log-coverage-diff.c в Microsoft Visual Studio IDE – 3 ошибки, 6 предупреждений



Рисунок 5 а из командной строки компиляция проходит нормально!

На всякий случай (вдруг у кого под рукой не окажется компилятора) готовый исполняемый файл идет на прилагаемом диске.


Содержание раздела