我今天正在学习缓冲区溢出,我遇到了许多易受攻击的程序示例.令我好奇的是,如果有任何理由使用这样的程序参数:
int main(int argc, char *argv[])
{
char argument_buffer[100];
strcpy(argument_buffer, argv[1]);
if(strcmp(argument_buffer, "testArg") == 0)
{
printf("Hello!\n");
}
// ...
}
Run Code Online (Sandbox Code Playgroud)
而不是简单地:
int main(int argc, char *argv[])
{
if(strcmp(argv[1], "testArg") == 0)
{
printf("Hello!\n");
}
}
Run Code Online (Sandbox Code Playgroud)
请注意我知道strcpy等等的缺点- 这只是一个例子.我的问题是 - 是否有任何真正的理由使用临时缓冲区来存储来自argv的参数?我假设没有,但我很好奇,为什么它出现在溢出的例子中,而在现实中它从未被使用过?也许是因为纯理论.
我从一本书中读到,缓冲区溢出可能用作注入将攻击系统的漏洞利用代码的方式。和堆栈随机化是防范此类攻击的有效途径之一。
我不明白什么是堆栈随机化及其如何防止这些攻击?
我试图利用测试程序中的缓冲区溢出来执行任意代码。我在 NetBSD 6 i386 上。这是C代码:
int checkPassword(char *password)
{
char savePassword[64] = {0};
char *logMessage;
int isUser = 0;
int isAdmin = 0;
int i;
if (!strcmp(password, userPassword))
isUser = 1;
strcpy(savePassword, password);
for (i = 0; password[i]; ++i)
password[i] ^= xorKey;
if (!strcmp(password, adminPassword))
isAdmin = 1;
if (!(isAdmin | isUser)) {
/* ... */
}
return isAdmin ? ADMIN : isUser ? USER : NOBODY; /* main.c:79 */
}
Run Code Online (Sandbox Code Playgroud)
我将代码插入savePassword缓冲区 (at %ebp - 0x58)。下面是 GDB …
阅读缓冲区溢出,我遇到了下面给出的示例代码: -
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
}
void main() {
function(1,2,3);
}
Run Code Online (Sandbox Code Playgroud)
这是来自着名的粉碎堆栈的乐趣和利润文章我猜.(参考:http://insecure.org/stf/smashstack.html)
文章说,要为buffer1和buffer2分配空间,需要20个字节(缓冲区1为8个字节,缓冲区2为12个字节),因为只能以字大小的倍数访问存储器地址(在这种情况下,1个字= 4个字节).
但我记得内存是字节可寻址的,即我可以从内存中一次访问1个字节.我将此与处理器的位数相关联.例如,32位处理器可以访问2 ^ 32个存储器位置,并且由于1个存储器位置保持1个字节(8位),因此32位处理器的总可寻址存储器等于(2 ^ 32)/(1024*1024*1024)= 4096 MB = 4GB.
因为在上面的例子中,buffer1和buffer2都是char类型,假设需要1个字节,为什么我们不能分别为buffer1和buffer2分配5个字节和10个字节?
为什么内存访问限制为字大小的倍数?
我目前正在阅读计算机系统简介:程序员的视角(http://www.amazon.com/Computer-Systems-Programmers-Perspective-2nd/dp/0136108040/ref=sr_1_2?s=books&ie=UTF8&qid=1421029641&sr=1 -2&keywords=introduction+to+computer+systems)并尝试了解阻止缓冲区溢出的方法。
我理解为什么在使用地址随机化时我们需要 NOP 雪橇以及如何编写漏洞利用程序,但我很难理解书中给出的与 NOP 雪橇相关的地址计算。我在这里引用它:-
(假设程序在堆栈上的起始地址范围在32位系统上为2^23,在64位系统上为2^32)
“如果我们设置一个 256 字节的 NOP sled,那么可以通过枚举 2^15 个起始地址来破解 n=2^23 上的随机化,这对于坚定的攻击者来说是完全可行的。对于 64 位情况,尝试枚举 2^ 24个地址更令人畏惧。”
作者是如何分别为 32 位和 64 位情况得出数字 2^15 和 2^24 的?一个解释真的很有帮助。
我有以下代码,它可以从指定父窗口的所有子窗口加载文本。它工作正常,但有时,有一些父窗口(例如打开的带有很长 C++ 源文件的记事本)具有大量文本并导致缓冲区溢出。
BOOL CALLBACK EnumChildProc(__in HWND hWnd, __in LPARAM lParam) {
LRESULT TEXT_LENGTH = NULL;
WCHAR szText[32767];
LPWSTR szWindowText;
UINT nBuffer = NULL, nText = NULL;
szWindowText = reinterpret_cast<LPWSTR>(lParam); szText[0] = L'\0';
nBuffer = (UINT)wcslen(szWindowText);
TEXT_LENGTH = SendMessage(hWnd, WM_GETTEXTLENGTH, NULL, NULL);
if (TEXT_LENGTH > NULL)
{
SendMessage(hWnd, WM_GETTEXT, (WPARAM)32767, reinterpret_cast<LPARAM>(&szText));
szText[TEXT_LENGTH] = L'\n'; szText[TEXT_LENGTH + 1] = L'\0';
while ((nBuffer < 32766) && (szText[nText] != L'\0'))
{ szWindowText[nBuffer++] = szText[nText++]; }
szWindowText[nBuffer] = L'\0';
}
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
该行 …
我一直在关注一些有关缓冲区溢出利用的教程。但是我的问题是,我无法打开根外壳程序,而是总会得到一个普通的用户外壳程序。我检查了以下几点
我重新验证了以下各项,但仍然无法实现实际的root shell:
有人知道可能是什么问题吗?为什么我仍然无法获得root shell?
在此先感谢您的任何建议和提示。最好的Zaphoxx
易受攻击的C代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void shell(){
system("/bin/sh");
exit(0);
}
int vuln(){
char buf[4];
ssize_t l=0;
printf("[+] input: ");
l=read(0,buf,128);
printf("[+] recv: ");
write(1,buf,l);
return 0;
}
int main(){
//setbuf(stdout,0);
setuid(0);
seteuid(0);
vuln();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
python利用脚本创建有效负载: …
我正在尝试使用格式字符串攻击向量对以下代码实施返回到 libc 攻击。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char a[10];
scanf("%s",&a);
printf(a);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我想通了使用系统()的地址p system的命令gdb。通过使用 对堆栈帧的检查x/500s $esp,我计算出包含\bin\sh.
system: 0xf7e2cda0
exit: 0xf7e209d0
\bin\bash: 0xffffd207
Run Code Online (Sandbox Code Playgroud)
有了这些东西,我构造了以下格式字符串:
python -c 'print "A"*14 + "\xbc\xcd\xff\xff" + "\xa0\xcd\xe2\xf7" + "\xd0\x09\xe2\xf7" + "\x07\xd2\xff\xff"' > inp
Run Code Online (Sandbox Code Playgroud)
其中0xffffcdbc - 0x4是包含系统地址0xf7e2cda0值的本地地址。
我使用编译程序gcc -m32 -fno-stack-protector -o sh sh.c并使用gdb sh. 执行后,在输入时r<inp,我得到以下输出
如上所示,显示了一些错误命令,我只有在r再次运行命令后才能进入 shell …
我开始研究软件安全性,但我很难理解缓冲区溢出攻击和 ROP 攻击是什么。
据我了解,
缓冲区溢出攻击:
当缓冲区达到一定大小时,填充缓冲区并添加额外的代码,以便攻击者可以执行代码中的另一个函数或他/她自己的shellcode。
ROP攻击:
给出某个可以覆盖返回地址的输入,以便攻击者可以控制流量。
但两者之间的确切区别是什么?
我觉得两者都只是给出了过多的输入来覆盖不应该接近的区域。
例如,如果我有一个代码
1 #include <stdio.h>
2
3 void check(){
4 printf("overflow occurs!\n");
5 }
6
7 int main(int argc, char* argv[]){
8 char buffer[256];
9 gets(buffer);
10 printf("%s\n", buffer);
11 return 0;
12 }
Run Code Online (Sandbox Code Playgroud)
并尝试check()通过向函数提供特定输入来执行该函数gets()。
这是 ROP 攻击还是缓冲区溢出攻击?
我在编写需要该功能的程序时遇到了这个问题sprintf。
在某些情况下,使用该sprintf函数可能会导致内存溢出并带来安全风险。因此,您可以使用snprintf或sprintf_s函数来避免这些风险。
但这两个函数的定义是相同的。那么,为什么存在这两个函数而不是只有一个呢?
int sprintf_s(char *_DstBuf, size_t _DstSize, const char *_Format, ...);
int snprintf(char *__restrict__ __stream, size_t __n, const char *__restrict__ __format, ...);
Run Code Online (Sandbox Code Playgroud)
一开始,我认为该sprintf_s函数是Windows库特有的,我也认为该snprintf函数是POSIX特有的。但事实上,这两个函数都包含在<stdio.h>库中。