Я читаю книгу «Взлом: Искусство эксплуатации, 2-е издание», и я нахожусь в главе уязвимости форматной строки. Я прочитал эту главу несколько раз, но я не могу ее четко понять, даже если немного погуглил.
Итак, в книге есть этот уязвимый код:
char text[1024];
...
strcpy(text, argv[1]);
printf("The right way to print user-controlled input:\n");
printf("%s", text);
printf("\nThe wrong way to print user-controlled input:\n");
printf(text);
Затем после компиляции ,
reader@hacking:~/booksrc $ ./fmt_vuln $(perl -e 'print "%08x."x40')
The right way to print user-controlled input:
%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
%08x.%08x.
The wrong way to print user-controlled input:
bffff320.b7fe75fc.00000000.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252
e78.252e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.2
52e7838.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.30252e78.252e78
38.2e783830.78383025.3830252e.30252e78.252e7838.2e783830.78383025.3830252e.
Кажется, что байты 0x25, 0x30, 0x38, 0x78 и 0x2e повторяются много.
reader@hacking:~/booksrc $ printf "\x25\x30\x38\x78\x2e\n"
%08x.
Во-первых, почему это значение повторяется?
Как видите, они являются памятью самой строки формата. Поскольку функция форматирования всегда будет в самом верхнем кадре стека, пока строка форматирования хранится где-либо в стеке, она будет расположена под указателем текущего кадра (по более высокому адресу памяти).
Но мне кажется, что это противоречит тому, что он ранее написал, и способу организации кадров стека
Когда вызывается эта функция printf () (как и для любой функции), аргументы передаются в стек в обратном порядке.
Итак, не должна ли строка форматирования иметь меньший адрес памяти, поскольку она является первым аргументом? И где хранится строка формата?
reader@hacking:~/booksrc $ ./fmt_vuln AAAA%08x.%08x.%08x.%08x
The right way to print user-controlled input:
AAAA%08x.%08x.%08x.%08x
The wrong way to print user-controlled input:
AAAAbffff3d0.b7fe75fc.00000000.41414141
Здесь снова, почему AAAA
повторяется в 41414141
. Из того, что я понимаю, функция printf
сначала печатает AAAA
, затем, когда она видит первый %08x
, она получает значение из адреса памяти в предыдущем кадре стека, затем делает то же самое со вторым %08x
таким образом, значение второго находится в адресе памяти выше, чем первый, и, наконец, возвращается к значению AAAA
, расположенному в нижнем адресе памяти, в кадре стека функции printf
.
Я отлаживал первый пример с $(perl -e 'print "%08x."x40')
в качестве аргумента. Я запускаю: Linux 5.3.0-40-generi c, 18.04.1-Ubuntu, x86_64
(gdb) run $(perl -e 'print "%08x." x 40')
Starting program: /home/kuro/fmt_vuln $(perl -e 'print "%08x." x 40')
The right way to print user-controlled input:
%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.
The wrong way to print user-controlled input:
07a51260.4b3eb8c0.4b10e154.00000000.4b16c3a0.9d357fc8.9d357b10.78383025.30252e78.2e783830.3830252e.252e7838.78383025.30252e78.2e783830.3830252e.252e7838.78383025.30252e78.2e783830.3830252e.252e7838.78383025.30252e78.2e783830.3830252e.252e7838.78383025.30252e78.2e783830.3830252e.252e7838.4b618d00.4b5fd000.00000000.9d357c80.00000000.00000000.00000000.4b3ef6f0.
Breakpoint 1, main (argc=2, argv=0x7ffd9d357fc8) at fmt_vuln.c:19
19 printf("[*] test_val @ 0x%08x = %d 0x%08x\n", &test_val, test_val, test_val);
(gdb) x/-100xw $rsp
0x7ffd9d357940: 0x00000400 0x00000000 0x4b07c1aa 0x00007fb8
0x7ffd9d357950: 0x00000016 0x00000000 0x00000003 0x00000000
0x7ffd9d357960: 0x00000001 0x00000000 0x00002190 0x000003e8
0x7ffd9d357970: 0x00000005 0x00000000 0x00008800 0x00000000
0x7ffd9d357980: 0x00000000 0x00000000 0x00000400 0x00000000
0x7ffd9d357990: 0x00000000 0x00000000 0x5e970730 0x00000000
0x7ffd9d3579a0: 0x65336234 0x30663666 0x90890300 0x79e57be9
0x7ffd9d3579b0: 0x1cd79dbf 0x00000000 0x00000000 0x00000000
0x7ffd9d3579c0: 0x05cec660 0x000055ef 0x9d357fc0 0x00007ffd
0x7ffd9d3579d0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffd9d3579e0: 0x9d357ee0 0x00007ffd 0x4b062f26 0x00007fb8
0x7ffd9d3579f0: 0x00000030 0x00000030 0x9d357be8 0x00007ffd
0x7ffd9d357a00: 0x9d357a10 0x00007ffd 0x90890300 0x79e57be9
0x7ffd9d357a10: 0x4b3ea760 0x00007fb8 0x07a51260 0x000055ef
0x7ffd9d357a20: 0x4b3eb8c0 0x00007fb8 0x4b0891bd 0x00007fb8
0x7ffd9d357a30: 0x00000000 0x00000000 0x4b3ea760 0x00007fb8
0x7ffd9d357a40: 0x00000d68 0x00000000 0x00000169 0x00000000
0x7ffd9d357a50: 0x07a51260 0x000055ef 0x4b08af51 0x00007fb8
0x7ffd9d357a60: 0x4b3e62a0 0x00007fb8 0x4b3ea760 0x00007fb8
0x7ffd9d357a70: 0x0000000a 0x00000000 0x05cec660 0x000055ef
0x7ffd9d357a80: 0x9d357fc0 0x00007ffd 0x00000000 0x00000000
0x7ffd9d357a90: 0x00000000 0x00000000 0x4b08b403 0x00007fb8
0x7ffd9d357aa0: 0x4b3ea760 0x00007fb8 0x9d357ee0 0x00007ffd
0x7ffd9d357ab0: 0x05cec660 0x000055ef 0x4b0808f5 0x00007fb8
0x7ffd9d357ac0: 0x00000000 0x00000000 0x05cec824 0x000055ef
(gdb) x/100xw $rsp
0x7ffd9d357ad0: 0x9d357fc8 0x00007ffd 0x9d357b10 0x00000002
0x7ffd9d357ae0: 0x78383025 0x3830252e 0x30252e78 0x252e7838
0x7ffd9d357af0: 0x2e783830 0x78383025 0x3830252e 0x30252e78
0x7ffd9d357b00: 0x252e7838 0x2e783830 0x78383025 0x3830252e
0x7ffd9d357b10: 0x30252e78 0x252e7838 0x2e783830 0x78383025
0x7ffd9d357b20: 0x3830252e 0x30252e78 0x252e7838 0x2e783830
0x7ffd9d357b30: 0x78383025 0x3830252e 0x30252e78 0x252e7838
0x7ffd9d357b40: 0x2e783830 0x78383025 0x3830252e 0x30252e78
0x7ffd9d357b50: 0x252e7838 0x2e783830 0x78383025 0x3830252e
0x7ffd9d357b60: 0x30252e78 0x252e7838 0x2e783830 0x78383025
0x7ffd9d357b70: 0x3830252e 0x30252e78 0x252e7838 0x2e783830
0x7ffd9d357b80: 0x78383025 0x3830252e 0x30252e78 0x252e7838
0x7ffd9d357b90: 0x2e783830 0x78383025 0x3830252e 0x30252e78
0x7ffd9d357ba0: 0x252e7838 0x2e783830 0x4b618d00 0x00007fb8
0x7ffd9d357bb0: 0x4b5fd000 0x00007fb8 0x00000000 0x00000000
0x7ffd9d357bc0: 0x9d357c80 0x00007ffd 0x00000000 0x00000000
0x7ffd9d357bd0: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffd9d357be0: 0x4b3ef6f0 0x00007fb8 0x4b6184c8 0x00007fb8
0x7ffd9d357bf0: 0x9d357c80 0x00007ffd 0x4b3ef000 0x00007fb8
0x7ffd9d357c00: 0x4b3ef914 0x00007fb8 0x4b3ef3c0 0x00007fb8
0x7ffd9d357c10: 0x4b617048 0x00007fb8 0x00000000 0x00000000
0x7ffd9d357c20: 0x00000000 0x00000000 0x4b6179f0 0x00007fb8
0x7ffd9d357c30: 0x4b0030e8 0x00007fb8 0x00000000 0x00000000
0x7ffd9d357c40: 0x4b3efa00 0x00007fb8 0x00000480 0x00000000
0x7ffd9d357c50: 0x00000027 0x00000000 0x00000000 0x00000000
Значения, которые появляются перед "% 08x". в неправильном выводе отображаются в более низких адресах, чем «% 08x». ценности. Почему? Предполагается, что строка формата находится на вершине стека.
Значения, которые появляются после «% 08x». значения в выводе Неверный путь отображаются в более высоких адресах, чем «% 08x». ценности. Итак, в предыдущем стеке.
Почему это так? Разве вывод не должен начинаться со значения строки формата или после?
Кроме того, в книге он не печатает значения после «% 08x». ценности. Но некоторые напечатаны в моем случае. И некоторые значения в выводе даже не фигурируют в стеке, как 4b16c3a0 .