通过堆栈更改变量的值

时间:2012-10-16 02:20:24

标签: c stack

好的,我们得到以下代码:

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "callstack.h"
#include "tweetIt.h"
#include "badguy2.c"

static char *correctPassword = "ceriaslyserious";
char *message = NULL;

int validateSanity(char *password) {
    for(int i=0;i<strlen(password);i++)
        if(!isalpha(password[i]))
            return 0;
    unsigned int magic = 0x12345678;
    return badguy(password);
}

int validate(char *password) {
    printf("--Validating something\n", password);
    if (strlen(password) > 128) return 0;

    char *passwordCopy = malloc(strlen(password) + 1);
    strcpy(passwordCopy, password);
    return validateSanity(passwordCopy);
}

int check(char *password, char *expectedPassword) {
    return (strcmp(password, expectedPassword) == 0);
}

int main() {
    char *password = "wrongpassword";
    unsigned int magic = 0xABCDE;
    char *expectedPassword = correctPassword;
    if (!validate(password)) {
        printf("--Invalid password!\n");
        return 1;
    }
    if (check(password, expectedPassword)) {
        if (message == NULL) {
            printf("--No message!\n");
            return 1;
        } else {
            tweetIt(message, strlen(message));
            printf("--Message sent.\n");
        }
    } else {
        printf("--Incorrect password!\n");
    }
    return 0;
}

我们应该使用函数main欺骗badguy发送推文。在badguy中,我们偏离了先前的问题,即passwordmain的声明与传递给badguy的参数之间的差异。我们已被指示使用此偏移量来查找main中correctPasswordpassword的地址,并将password中的值操作为correctPassword,因此在进行密码检查时,它被认为是合法的。我在查找如何使用此偏移量来查找地址并从那里继续时遇到了一些麻烦。

1 个答案:

答案 0 :(得分:2)

首先,确保您可以很好地控制编译器行为。那就是:确保你知道他们被尊重的调用约定(没有以任何方式优化或改变)。这通常归结为关闭优化设置,至少在更受控制的条件下进行测试,直到设计出稳健的方法。要特别注意expectedPassword之类的变量,因为它们极有可能被优化掉(expectedPassword可能永远不会在堆栈中创建,被等效的correctPassword替换,使用 no 堆栈引用正确的密码来呈现您。

其次,请注意"wrongpassword""ceriaslyserious"短;换句话说,如果我直截了当,试图破解passwordCopy指向的缓冲区(其大小为"wrongpassword"的长度加一),以便将"ceriaslyserious"复制到那里可能会导致分段违规。尽管如此,跟踪调用堆栈中expectedPassword的地址应该相对简单,如果存在(见上文),特别是如果你已经有{{1}的偏移量堆栈框架。

在受控环境下考虑x86 32位目标,main()将位于expectedPassword以下8个字节(password为4个,password为4个magic如果未优化远)。如上所述,从password到参数的偏移量,应该足以从该参数的地址中减去偏移量,然后加上8.结果指针应为expectedPassword,然后指向包含密码的静态区域。再次,仔细检查您的环境。检查this以获取有关x64中堆栈布局的说明(32位情况下的布局类似)。

最后,如果调用堆栈中不存在expectedPassword,那么,由于correctPassword是一个全局静态,它将驻留在数据段中,使该方法无用。要在这种情况下实现目标,您需要使用更智能的算法仔细扫描数据段。但是,简单地尝试在程序文本中找到check()的返回值的测试并替换为nop s(在正确操作页面权限以允许写入之后)可能会更容易。文本段)。

如果您遇到问题,请检查生成的汇编代码。如果您正在使用GCC,gcc -S将在汇编之前暂停编译(即,生成汇编源代码文件作为输出)。 objdump -d也可以提供帮助。 gdb可以在指令之间切换,显示框架的反汇编并显示寄存器内容;查看文档。

这些练习对于了解常见程序中安全漏洞的发生方式特别有用,并提供了一些关于防御性编程的基本概念。