问题实际上是关于C中的堆栈溢出。 我有一个不能为我的生活做的事情,我已经看了gdb中的所有内容而我无法想象它。
问题如下:
int i,n;
void confused()
{
printf("who called me");
exit(0);
}
void shell_call(char *c)
{
printf(" ***Now calling \"%s\" shell command *** \n",c);
system(c);
exit(0);
}
void victim_func()
{
int a[4];
printf("[8]:%x\n", &a[8]);
printf("Enter n: "); scanf("%d",&n);
printf("Enter %d HEX Values \n",n);
for(i=0;i<n;i++) scanf("%x",&a[i]);
printf("Done reading junk numbers\n");
}
int main()
{
printf("ls=736c --- ps = 7370 --- cal = 6c6163\n");
printf("location of confused %x \n", confused);
printf("location of shell_call %x \n", shell_call);
victim_func();
printf("Done, thank you\n");
}
好的,所以我设法正确地得到了第一个问题,即任意调用主路径中未明确调用的两个函数之一。顺便说一下,这必须在运行程序时完成而不做任何修改。
我是通过运行程序,将N
设置为7
来实现此目的的,这使我进入victim_func
帧的功能指针,我写了a[7]
,内存地址混乱或shell_call
,它有效。 (我有一台64位机器,这就是为什么我必须把它变为7,因为EBI指针是2英寸宽,而不是1)
我的问题如下,如何控制将哪个参数传递给shell_code
函数?即。如何将string
写入char* c
。
重点是执行unix命令,如 ps 等,只运行程序。
我想用EBLD指针编写 ps 的十六进制表示,并将shell_call
的arg列表设置为,但这不起作用。我还尝试输入argsv
个参数并将shell_call
的arg列表设置为main的arg_list
,但也没有用。
我认为第二个版本应该有效,但我相信我没有正确设置新堆栈帧的arg列表(我是通过将a[8]
写入0
来实现的,因为它是第一个函数指针的一部分,写a[9]=736c
和a[10]=0000
,但它可能不正确,因为它们是victim_func
的参数。所以如何访问shell_call
的参数?
答案 0 :(得分:8)
我可能不应该为你做功课。但基本上是:
你需要在内存中的某个地方获取一个字符缓冲区来存储你想要执行的字符串。显然,您可以像调用其他函数一样执行此操作(即您也将文本放在堆栈中)。编写完成后,需要在shell_code函数期望找到其参数的位置写入指向堆栈的指针。
在没有我为你做所有工作的情况下解决这个问题的最佳方法是在一张纸/白板上写下你的堆栈/内存内容。如果从程序内部正常调用shell_code,请记下它的外观。然后在victum_func中写下堆栈的样子,找出要改变的东西,让它看起来像“自然”一样(当然要记住一些东西“不关心”,如返回地址)。
这就是你今天要从我这里得到的所有慈善事业! :-P
答案 1 :(得分:2)
SoapBox已经做了很好的工作,引导你朝着正确的方向前进。
了解更多信息; http://www.skullsecurity.org/wiki/index.php/Example_4
答案 2 :(得分:1)
你需要操纵调用者的堆栈框架(main()
),并以这样的方式安排它从后面溢出的shell_call()
的epilog返回victim_func()
可以找到一个固定的堆栈,因为它已被主要调用。
这样做你可能不得不破坏受害者堆栈帧中的帧指针,它将通过leave
在%ebp中恢复。