Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #94, ОКТЯБРЬ 2006 г.

Трюки от Крыса

Крис Касперски

Хакер, номер #094, стр. 094-134-1

Строки в hex-числах

Допустим, нам потребовалось прочитать значение ячейки памяти некоторого процесса и вывести ее на экран. Или распечатать дескриптор заданного окна. Да все что угодно! Суть в том, что в программах, написанных «под себя» это обычно делается так:

printf("hWnd: %Xhn", FindWindow(0, "Калькулятор"));

Если же искомое окно отсутствует, то функция FindWindows() возвратит ошибку, и на экране появится «hWnd: 0h». Нормальные хакеры знают, что такого дескриптора в природе не существует, и это символ ошибки, но все равно получается как-то неаккуратно и «некультурно». Лучше, чтобы программа сообщала об этом явно. Проще всего использовать условный переход типа:

HWND hwnd;

hwnd = FindWindow(0, "Калькулятор");

printf("hWnd: "); if (hwnd) printf("%Xhn"); else printf("error!n");

Однако, все это слишком по-медвежьи как-то. Слишком прямолинейно, а прямолинейность для хакеров непростительна! К тому же нам потребовалось целых три вызова функции printf() вместо одного. Ты думаешь, если на тачке установлен целый гектар, то отдельные байты можно уже и не считать?! Некоторые, попытавшись неумело схитрить, преобразовывают hWnd в строку посредством нестандартной функцией _itoa(), поддерживаемой Microsoft Visual C++, но отсутствующей во многих других компиляторах. В этом случае для вывода значения дескриптора требуется всего лишь один вызов printf(), да и сама программа становится прозрачнее:

char buf[12]; // 12 байт хватит для любого числа, хватило бы и 9 (8 символов + x0)

HWND hwnd; // но компилятор все равно выровняет размер buf до кратной 4x

hwnd = FindWindow(0,"Калькулятор");

printf("hWnd: %sn", (hwnd)?_itoa((int)hwnd, buf, 0x10):"error!");

Программа стала более наглядной, но все равно это не по-хакерски и слишком прямолинейно. А что если подобрать такую шестнадцатеричную константу, которая бы читалась как осмысленное текстовое слово? Например, BADh?

HWND hwnd;

hwnd = FindWindow(0, "Калькулятор");

printf("hWnd: %Xhn", (hwnd)?(int)hwnd:0xBAD);

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

Разумеется, данную методику можно применять не только с дескрипторами окон, но и вообще с любыми возвращаемыми значениями, как с API-функциями, так и со своими собственными. Причем своя собственная функция запросто может сделать return 0xBAD в случае ошибки. И тогда вместо проверки в стиле if (foo()!=ERROR) мы будем писать if (foo()!=0xBAD). Заметь, это намного «элегантнее», и не потому, что 0xBAD короче ERROR (оба они одинаковы по длине), а потому, что при записи результата в лог (ты ведешь отладочные логи, верно?) отпадает необходимость преобразования численного кода ошибки в его строковое представление.

Кроме 0xBAD, существуют и другие комбинации — например, 0xDEADBEEF, 0xDEADA11, 0xFA11ED, да много всего можно придумать! Главное — фантазию иметь. Кстати, составление осмысленных слов из hex-символов само по себе является нехилой головоломкой и отличной гимнастикой для мозгов! Так что дерзай!

Содержание  Вперед на стр. 094-134-2
ttfb: 3.338098526001 ms