0
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>

#define MAX 3
#define ARG "cat .passwd"
integer main( integer argc, char ** argv )
{
char * names[] = {"strlen", "atoi", "printf", "puts"};
void (*reachable_functions[])( char * ) = {strlen, atoi, printf, puts};
void (*unreachable_functions[])( char * ) = {system};
integer i, index = 0;

for( i=1; i<argc; i++ )
{
    index += strlen(argv[i]);
}

if( index <= MAX )
{
    (reachable_functions[MAX-1])( "Calling ");
    (reachable_functions[MAX-1])( names[index] );
    (reachable_functions[MAX-1])( ".\n" );
    (reachable_functions[index])( ARG );
}
else
{
    (reachable_functions[MAX])( "Out of bounds !\n" );
}

return 0;
}

我可以得到分段错误,但无法调用无法访问的函数!?!我知道 Integer 有问题,但我无法利用它.... :( 有没有办法调用它?谢谢

4

1 回答 1

3

如果您传递足够长度的足够参数,则长度之和可能会溢出(如果整数类型为 32 位,则不确定 shell 实际上是否可以处理此类参数,但应该适用于 16 位整数)。

有符号整数的溢出(我想integer应该是int)是未定义的行为,因此在这种情况下会发生什么取决于编译器和平台(可能还有月相),但总和可能会环绕为负数。在这种情况下,根据编译器排列数组的方式,调用

(reachable_functions[index])( ARG );

实际上可以调用“无法访问”的功能。这是更多未定义的行为,用负索引索引数组,但它是一个可能的漏洞。

为了防止这种利用(只要未定义的行为允许),可以index在比较中强制转换为无符号类型,

if( (unsigned int)index <= MAX )

在所有合理的实现中,其中 的宽度unsigned int等于 的int,这保证了index确实是非负的(再次警告,在发生未定义的行为之后,标准不再保证程序的行为),因为那时负数被转换为大于 的数字INT_MAX

如果一个人是偏执狂,也可以在索引操作中进行强制转换。

于 2012-09-20T07:04:25.007 回答