gpt4 book ai didi

使用 IDA 创建一个基本的堆栈溢出

转载 作者:行者123 更新时间:2023-12-04 05:03:17 25 4
gpt4 key购买 nike

该程序在我的机器上以 root 权限运行,我需要对以下代码执行堆栈溢出攻击并获得 root 权限:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/sha.h>

void sha256(char *string, char outputBuffer[65])
{
unsigned char hash[SHA256_DIGEST_LENGTH];
int i = 0;
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, string, strlen(string));
SHA256_Final(hash, &sha256);

for(i = 0; i < SHA256_DIGEST_LENGTH; i++)
{
sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
}
outputBuffer[64] = 0;
}

int password_check(char *userpass)
{
char text[20] = "thisisasalt";
unsigned int password_match = 0;
char output[65] = { 0, };
// >>> hashlib.sha256("Hello, world!").hexdigest()
char pass[] = "315f5bdb76d078c43b8ac0064e4a0164612b1fce77c869345bfc94c75894edd3";

text[0] = 'a';
text[1] = 't';
text[2] = 'j';
text[3] = '5';
text[4] = '3';
text[5] = 'k';
text[6] = '$';
text[7] = 'g';
text[8] = 'f';
text[9] = '[';
text[10] = ']';
text[11] = '\0';
strcat(text, userpass);
sha256(text, output);

if (strcmp(output, pass) == 0)
{
password_match = 1;
}

return (password_match == 1);
}

int main(int argc, char **argv)
{
if (argc < 3)
{
printf("Usage: %s <pass> <command>\n", argv[0]);
exit(1);
}
if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}

if (password_check(argv[1]))
{
printf("Running command as root: %s\n", argv[2]);
setuid(0);
setgid(0);
system(argv[2]);
}
else
{
printf("Authentication failed! This activity will be logged!\n");
}

return 0;
}

所以我尝试用 IDA 分析程序,我看到文本段从较低的地址到较高的地址,高于我看到的数据,然后是 bss,最后是外部命令。

现在据我所知堆栈应该就在上面,但我不确定如何查看它,我应该如何查看堆栈才能知道我在写什么? (我什至需要它还是我完全一无所知?)

第二个问题是考虑输入的长度,我如何在代码中绕过这个检查:
if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}

我可以以某种方式通过引用将字符串提供给程序吗?如果是这样,我该怎么做? (再次,希望我不是完全无能为力)

最佳答案

Now as far as I know the stack should be just above that, but I'm not certain how to view it, how exactly am I supposed to view the stack in order to know what I'm writing on? (Do I even need it or am I completely clueless?)



堆栈位置一直在变化——你需要查看 ESP/ RSP 寄存器的值,它的值是栈顶的当前地址。通常,变量寻址将基于 EBP 而不是 ESP ,但它们都将指向相同的通用内存区域。

在分析过程中,IDA 为每个函数设置一个堆栈框架,它的作用很像 struct - 您可以在其中定义具有类型和名称的变量。这个框架总结在函数的顶部: stack summary view
双击它或函数体中的任何局部变量将打开一个更详细的窗口。这与您无需在调试器中实际运行程序一样好。

您可以看到 text 就在 password_match 旁边,从地址来看,正如人们所期望的那样,有 0x14 字节分配给 text 。但是,这并不能保证,编译器可以自由地将变量打乱、填充或优化到寄存器中。

Second question is considering the length of the input, how do i get around this check in the code:

if (strlen((const char *) argv[1]) > 10)
{
printf("Error: pasword too long\n");
exit(1);
}


你不需要绕过这个检查,它已经足够坏了。有一个逐一错误。

如果您想自己找出溢出,请停止阅读。


text 的有效索引范围从 text[0]text[19] 。在代码中,用户输入被写入从 text[11] 开始的内存区域。 strlen 检查允许的最大输入长度为 10 个符号 + NULL 终止符。不幸的是,这意味着 text[19] 包含第 9 个用户输入的符号,第 10 个符号 + 终止符溢出到相邻的内存空间。在某些情况下,这允许您用任意值覆盖 password_match 的最低有效字节,并用 0 覆盖第二个最低有效字节。如果 password_match 等于 1 ,则您的函数接受密码,这意味着密码中的第 10 个字符必须是 '\x01' (请注意,这与 '1' 不同)。

以下是 IDA 作为调试器运行的两个屏幕截图。 text 以黄色突出显示, password_match 以绿色突出显示。

我输入的密码是 123456789\x01
  • 用户输入密码之前的堆栈是 strcattext
    stack variables before overflow
  • strcat 之后的堆栈。请注意 password_match 已更改。
    stack variables after overflow
  • 关于使用 IDA 创建一个基本的堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15856085/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com