我在Linux x86_64上重现了Smashing the Stack for Fun and Profit的例子3 .但是,我无法理解应该递增到返回地址的正确字节数是多少,以便跳过指令:
0x0000000000400595 <+35>: movl $0x1,-0x4(%rbp)
Run Code Online (Sandbox Code Playgroud)
这是我认为x = 1指令的地方.我写了以下内容:
#include <stdio.h>
void fn(int a, int b, int c) {
char buf1[5];
char buf2[10];
int *ret;
ret = buf1 + 24;
(*ret) += 7;
}
int main() {
int x;
x = 0;
fn(1, 2, 3);
x = 1;
printf("%d\n", x);
}
Run Code Online (Sandbox Code Playgroud)
并在gdb中拆解它.我已禁用地址随机化并使用该-fno-stack-protector选项编译程序.
我可以从下面的反汇编输出中看到,我想跳过地址指令0x0000000000400595:返回地址callq <fn>和movl指令地址.因此,如果返回地址是0x0000000000400595,并且下一条指令是0x000000000040059c,我应该在返回地址中添加7个字节?
0x0000000000400572 <+0>: …Run Code Online (Sandbox Code Playgroud) 我有一个复杂的c ++代码.
这是一个使用http://althenia.net/fcgicc的FastCGI程序
当我问它一个looooong url时,我得到了
*** stack smashing detected ***: ./tileserve terminated
Erreur de segmentation
Run Code Online (Sandbox Code Playgroud)
对于现实生活,这不是问题,因为我从来没有使用这么长的网址,但这意味着任何人都可以终止我的服务器......我不喜欢这样.
是否有工具(以及如何使用它?)来找出问题出现在哪里?
好的解决了.
我在做
int len;
char uri[200];
len = strlen(request.params[std::string("REQUEST_URI")].c_str());
printf("%d\n", len);
if (len > 200) return 1;
strcpy(uri, request.params[std::string("REQUEST_URI")].c_str());
Run Code Online (Sandbox Code Playgroud)
对于len测试看起来200太高了.它实际上在194失败了.
所以我做了 :
if (len > 190) return 1;
Run Code Online (Sandbox Code Playgroud)
现在,没关系.
我希望能够检查在Xcode 9上构建的iOS应用程序中是否启用了堆栈粉碎保护(-fstack-protector-all),目标是iOS 11.
我在"其他C标志"中启用了-fstack-protector-all的应用程序,它确实构建并运行,但是如何验证是否启用了堆栈粉碎保护?
有很多较旧的(2013年及之前的)资源提到otool -Iv appName |grep stack_chk,但我在我的应用程序二进制文件上运行它,并且在输出中找不到stack_chk.
那个命令有现代的等价物吗?是-fstack-protector - 根据Xcode中当前的默认设置,所有甚至都是必需的?
我希望能够强制'双回',即有一个强制从其调用函数返回的函数(是的,我知道并不总是有一个真正的调用函数等).显然我希望是能够通过操纵堆栈来做到这一点,并且我认为至少在一些非便携式机器语言方式中它是可能的.问题是这是否可以相对干净和便携地完成.
为了填写一段具体的代码,我想写一下这个函数
void foo(int x) {
/* magic */
}
Run Code Online (Sandbox Code Playgroud)
这样以下功能
int bar(int x) {
foo(x);
/* long computation here */
return 0;
}
Run Code Online (Sandbox Code Playgroud)
回来,比方说1; 并且不执行长计算.假设它foo()可以假设它只被具有条形签名的函数调用,即int(int)(因此具体知道它的调用者返回类型是什么).
笔记:
bar()).它不会知道所调用的函数是什么.(再次在示例中,只能修改位)./* magic */我正在阅读Smashing the Stack for Fun and Profit(特别是,这篇文章指的是"Buffer Overflows"部分).这篇文章是为32位机器编写的,但我正在研究64位,我在我的例子中考虑了这一点.一个特殊的例子是导致一些我无法解释的问题.example3.c具有覆盖返回地址以跳过main函数中的指令的功能.这是我的代码:
#include <stdio.h>
void function(int a, int b, int c)
{
char buf1[5];
char buf2[10];
int *retptr;
retptr = (void*)(buf2 + 40);
(*retptr) += 8;
}
int main(void)
{
int x;
x = 0;
function(1,2,3);
x = 1;
printf("%d\n", x);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我使用gcc v4.8.2使用以下命令编译此程序:
gcc example3.c -o example3
Run Code Online (Sandbox Code Playgroud)
请注意,默认情况下,gcc编译器似乎实现了一些堆栈保护,例如地址空间布局随机化和堆栈金丝雀.我在计算ret指针值时考虑了这些安全措施.这是由gcc example3.c -S -fverbose-asm -o stack-protection.s以下产生的相应组件
:
.file "example3.c"
# GNU C (Ubuntu 4.8.2-19ubuntu1) version 4.8.2 (x86_64-linux-gnu)
# compiled by …Run Code Online (Sandbox Code Playgroud) 我一直试图通过堆栈粉碎更改返回地址来跳过指令.以下代码跳过main中的++并输出"1 3"的输出.我已经在32位英特尔机器上执行了这段代码.
#include<stdio.h>
void fun(int a,int b) {
// buffer
char buf[8];
char *p;
p = (char *)buf+24;
*p=*p+5;
return;
}
int main() {
int a=1,b=2;
fun(a,b);
a++;
b++;
printf("%d %d",a,b);
}
Run Code Online (Sandbox Code Playgroud)
我无法理解为什么返回地址存储在距buf起始地址24字节的位移处.我尝试在不同的32位英特尔机器上执行相同的代码,我不得不使用20字节而不是24字节的位移.我已将我的理解放在下图中.我不确定是什么填补了"?"所代表的差距.在图中.gcc是否存在任何金丝雀价值或者我错过了什么?
链接到图:http://www.cse.iitb.ac.in/~shashankr/stack.png
粉碎堆栈example3.c混乱问了同样的问题,但无法解释一般的置换原因.
下图给出了通过在函数中放置断点获得的堆栈的视图.
堆栈内容http://www.cse.iitb.ac.in/~shashankr/stack4.png
以下是main和fun的汇编代码:
Dump of assembler (fun):
0x08048434 <+0>: push %ebp
0x08048435 <+1>: mov %esp,%ebp
0x08048437 <+3>: sub $0x18,%esp
0x0804843a <+6>: mov %gs:0x14,%eax
0x08048440 <+12>: mov %eax,-0xc(%ebp)
0x08048443 <+15>: xor %eax,%eax
0x08048445 <+17>: lea -0x14(%ebp),%eax
0x08048448 <+20>: add $0x18,%eax
0x0804844b <+23>: …Run Code Online (Sandbox Code Playgroud) 仍在学习安全类的缓冲区溢出,我正在尝试利用此应用程序中的漏洞:
//vuln.c
#include <stdio.h>
int bof(char *str)
{
char buffer[12];
//BO Vulnerability
strcpy(buffer,str);
return 1;
}
int main(int argc, char* argv[])
{
char str[517];
FILE *badfile;
badfile = fopen("badfile","r");
fread(str, sizeof(char),517, badfile);
bof(str);
printf("Returned Properly\n");
return 1;
}
Run Code Online (Sandbox Code Playgroud)
使用此漏洞利用程序:
//exploit.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char code[] =
"\x31\xc0"
"\x50"
"\x68""//sh"
"\x68""/bin"
"\x89\xe3"
"\x50"
"\x53"
"\x89\xe1"
"\x99"
"\xb0\x0b"
"\xcd\x80"
;
int main(int argc, char* argv[])
{
char buffer[517];
char large_string[512];
FILE *badfile;
badfile = fopen("./badfile", "w");
//NOPslide
memset(&buffer,0x90,517); …Run Code Online (Sandbox Code Playgroud) 作为安全CS课程的一部分,我班的任务是利用漏洞利用堆栈/缓冲区溢出来击败密码检查。带有漏洞的代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/md5.h>
int main(int argc, char **argv) {
char correct_hash[16] = {
0xd0, 0xf9, 0x19, 0x94, 0x4a, 0xf3, 0x10, 0x92,
0x32, 0x98, 0x11, 0x8c, 0x33, 0x27, 0x91, 0xeb
};
char password[16];
printf("Insert your password: ");
scanf("%29s", password);
MD5(password, strlen(password), password);
if (memcmp(password, correct_hash, 16) == 0) {
printf("Correct Password!\n");
} else {
printf("Wrong Password, sorry!\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我了解经典的“堆栈粉碎”原理(我认为),并且这里存在一个明显的溢出漏洞,该漏洞correct_hash可以通过在提示时输入长度超过15个字符的密码来覆盖数组的前14个字节。但是,我不知道如何利用此功能使memcmp检查通过,从而完成挑战。我发现/尝试过的一些东西:
设置password为等价是correct_hash行不通的,因为password使用MD5()进行了哈希处理(无论如何都不可能将两者相等),因为 …
码:
int str_join(char *a, const char *b) {
int sz =0;
while(*a++) sz++;
char *st = a -1, c;
*st = (char) 32;
while((c = *b++)) *++st = c;
*++st = 0;
return sz;
}
....
char a[] = "StringA";
printf("string-1 length = %d, String a = %s\n", str_join(&a[0],"StringB"), a);
Run Code Online (Sandbox Code Playgroud)
输出:
string-1 length = 7,char*a = StringA StringB
***堆栈粉碎检测****:/ T02终止
中止(核心倾倒)
我不明白为什么它会显示堆栈粉碎?什么是*堆栈粉碎?或者是我编译器的错误?
我理解"堆栈粉碎检测"是什么意思.关于这一点,这里已经有很多问题了.但我没有找到以下问题的答案.拿C代码
int main(int argc, char **args) {
char puffer[5];
strcpy(puffer, *++args);
printf("%s\n",puffer);
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
当我在Ubuntu 13.10中使用gcc 4.8.1编译时./buffer 123456789会引发预期的错误stack smashing detected.但为什么不./buffer 12345678引起错误呢?我希望每个超过5个字符的字符串都会引发错误.