#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;
}
我可以获得分段错误但无法调用无法访问的功能!?! 我知道整数有问题,但我无法利用它...... :( 有办法打电话吗? THX
答案 0 :(得分:3)
如果你传递了足够长度的足够的参数,长度的总和可能会溢出(如果整数类型是32位,不确定shell是否实际上可以处理这样的参数,但是应该适用于16位整数)。 / p>
有符号整数的溢出(我认为integer
应该是int
)是未定义的行为,所以在这种情况下会发生什么取决于编译器和平台(可能还有月亮的相位),但是总和可能会换成负数。在这种情况下,根据编译器如何排列数组,调用
(reachable_functions[index])( ARG );
实际上可以调用“无法访问”功能。这是更加未定义的行为,索引具有负索引的数组,但这可能是一种利用。
为了防止这种攻击(就未定义的行为而言),可以在比较中将index
转换为无符号类型,
if( (unsigned int)index <= MAX )
在所有合理的实现中,unsigned int
的宽度等于int
的宽度,这可以保证index
确实是非负的(同样,在发生未定义的行为之后需要注意,标准不再保证程序的行为,因为那时负数转换为大于INT_MAX
的数字。
如果一个是偏执狂,也可以在索引操作中进行投射。