如何在 C++ 中利用 C 风格的可变参数函数?

问题描述

我看到一个结论,即当攻击者将某种输入设计到函数中以运行任意代码时,使用 C 样式省略号的 C++ 可变参数函数可能容易受到攻击。但是怎么做呢?我的意思是,如何设计攻击向量来利用该漏洞?

解决方法

如果您的意思是使用格式字符串漏洞来运行任意代码,那么它的工作原理如下:

printf 允许您提供与参数计数不匹配的格式字符串。在这种情况下,变量会从堆栈中拉出。函数调用(如 printf)是通过将函数的所有参数放入堆栈来完成的,大致如下:

(low addresses)
^^^^^^ stack growth direction ^^^^^^

---------printf-stack------------
printf function arguments
stack base pointer of caller
return address for when printf() ends
---------printf-stack------------ <-- stack base pointer register (cpu)

---------caller-stack------------ 
stack variables (int a = 5,char cstr[500] = "hello world!",etc)
caller function arguments
stack base pointer of caller-caller
return address for when caller() ends
---------caller-stack------------

(high addresses)

读取比给定更多的参数将打印调用函数的堆栈基指针,然后是调用函数的返回地址和最终变量。

要允许任意代码执行,您需要覆盖任何函数的返回地址。不幸的是 printf 允许你用 %n 写一个变量(这真的是一个坏主意。)。这会将到目前为止打印的字符数写入参数位置提供的 int 指针。
起初这似乎没有用,但用户可以更改一些堆栈变量以指向堆栈上的返回地址。然后他可以打印任意数量的字符并使用 &n 将该数量的字符写入该堆栈位置(包含函数的返回指针)。用户可以将他的 shellcode 放在任何地方,然后通过返回执行。

可以在 here 找到 LiveOverflow 提供的详细视频来解释所有这些。

我认为可以在其他可变参数函数中利用类似的行为(写入作为参数给出的指针)。