使程序崩溃只是验证漏洞的第一步,攻击者还可以利用格式化函数获得内存数据,为漏洞利用做准备。我们知道格式化函数会根据格式字符串从栈上取值,由于x86的栈由高地址向低地址增长,同时printf()函数的参数是以逆序被压入栈的,所以参数在内存中出现的顺序与在printf()调用时出现的顺序是一致的。接下来的演示我们都使用...
为了方便表述,约定:在printf("%d %d %d", a, b, c)中,a、b、c被称为格式化参数,其中a是第1个格式化参数,b是第2个格式化参数,c是第三个格式化参数;而字符串"%d %d %d"则是printf的第1个参数。 1.获取栈上的数据 获取栈上的数据是格式化字符串漏洞利用最简单的方式。 正如在讲解原理时介绍到的,依据C...
调试结果显示,字符数 0x18(十进制的 24,即 3 个%x 打印的字符数)已经被成功写入了地址0x407148。 4.3 执行任意代码 通过以上调试和测试可知,可以利用格式化字符串漏洞在任意地址写入任意数据。 要完成漏洞利用,执行任意代码,需要在程序执行0x0040187之前: ◆通过调整...
调试结果显示,字符数 0x18(十进制的 24,即 3 个%x 打印的字符数)已经被成功写入了地址0x407148。 4.3 执行任意代码 通过以上调试和测试可知,可以利用格式化字符串漏洞在任意地址写入任意数据。 要完成漏洞利用,执行任意代码,需要在程序执行0x0040187之前: ◆通过调整字符串的长度或者%x来调整打印的字符数,使其等于...
总结:即格式化漏洞的任意地址 读 其实仅需要 通过 “%偏移$格式输出” 便可以了,利用方式 很简单。这里主要 就是 要特别 注意一点,这里的偏移 是指的格式化 字符串的第几个参数,而不是说是printf 函数的第几个参数呐,因为 本来 格式化字符串 就是 printf 函数的第一个参数。两者 有 相差 1 的数学等式 关系...
一般来说,栈上的格式化字符串漏洞利用步骤是先泄露地址,包括ELF程序地址和libc地址;然后将需要改写的GOT表地址直接传到栈上,同时利用%c%n的方法改写入system或one_gadget地址,最后就是劫持流程。但是对于BSS段或是堆上格式化字符串,无法直接将想要改写的地址指针放置在栈上,也就没办法实现任意地址写。下面用3个例题...
综述 通过格式化字符串漏洞可以进行任意内存的读写。由于函数参数通过栈进行传递,因此使用%X$p(X为任意正整数)可以泄露栈上的数据。并且,在能对栈上数据进行控制的情况下,可以事先将想泄露的地址写在栈上,再使用%X$p,就可以以字符串格式输出想泄露的地址。 除此之外,
1.1 缓冲区溢出 vs 格式化字符串漏洞 由于过去几乎所有严重的漏洞都是某种缓冲区溢出,我们可以将这种严重并且低级的漏洞和这一新兴漏洞相比较。 1.2 统计:2000 年重要的格式化字符串漏洞 为了强调格式化字符串漏洞在 2000 年的危险影响,我们在这里例举了最为可利用的公开漏洞。
当利用这种漏洞,例如缓冲区溢出或者格式化字符串漏洞时,它通常会失败,因为没有当心最后的障碍:将所有偏移弄正确。基本上,寻找正确的偏移意味着“将什么写到哪里”。对于简单的漏洞,你可以可靠地猜测正确偏移,或者爆破它,通过一个一个尝试它们。但是一旦你需要多个偏移,这个问题就指数增长,它变得不可能爆破。
在格式化字符串中,"%s"、"%d" 等类型的符号叫符号说明,这些符号说明的基本格式为 %parameterfield width[length]type 。相信大家对于简单的符号说明并不陌生,但如果要利用格式化字符串漏洞,我们还需要用到几个比较冷门的符号说明,如: 调用约定 了解格式化字符串的解析方法后,我们还需要知道printf传参方式,以及格式化...