我正在研究 The Shellcoder's Handbook 的 Format String 部分。正如本书建议的那样,我使用这样的代码进行测试:
[格式字符串.c]
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc>1) {
if(argc>2) {
printf("Push a key to continue...\n");
getc(stdin);
}
printf("Sortie format string => ");
printf( argv[1] );
printf("\n");
}
printf("\n");
}
所以,我明白诀窍是在堆栈上找到你的参数(你传递给 formatstring 的链,稍后由 printf 使用)。
./formatstring "aaaa%$offset\$x"
(将 kernel.randomize_va_space 设置为 0,因此偏移量保持不变)。为了找到这个偏移量,他们使用了一个小批量脚本
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%$i\$x"; done | grep 4141
我得到了这个(这里偏移量= 137)
137 Sortie format string => AAAAAAAA41414141
138 Sortie format string => AAAAAAAA25414141
首先,我的“AAAAAAA”在堆栈上没有“对齐”(我在这里只能数 7 个 41,但我将 8 个“A”发送到格式字符串),并且它们在堆栈上的放置方式似乎会随着时间而改变 => 如果我在 2 小时后启动我的 bash 脚本(for)可能是“A”的“对齐”会改变。
更令人不安的是,当我向发送到 ./formatstring 的参数添加字节时,偏移量似乎发生了变化。如果我跑
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%32x%$i\$x"; done | grep 4141
我明白了
136 Sortie format string => AAAAAAAA b7ff103041414141
137 Sortie format string => AAAAAAAA b7ff103025414141
或运行
for((i=0; i<1000; i++)); do echo -n "$i " && ./formatstring "AAAAAAAA%320x%$i\$x"; done | grep 4141
我明白了
139 Sortie format string => AAAAAAAA b7ff103041410067
140 Sortie format string => AAAAAAAA b7ff103041414141
141 Sortie format string => AAAAAAAA b7ff103033254141
如您所见,偏移量发生变化并遵循我无法理解的逻辑。根据这本书,这一切都不应该发生。你知道它来自哪里吗?它是一种堆栈保护机制吗?当我 gcc formatstring.c 时我可以删除它吗?