【问题标题】:How do I change EIP in a different process?如何在不同的进程中更改 EIP?
【发布时间】:2012-07-13 03:04:26
【问题描述】:

我正在尝试通过更改其 EIP 来破解另一个程序。有两个程序正在运行,一个是目标程序,它告诉作为“核心函数”的函数(例如,接收密码字符串作为参数并返回真或假的函数)在内存中的位置。 那么现在我知道核心功能在哪里,我想用其他程序修改 EIP,这样目标程序就可以调用我的函数并简单地从中获取一个真实的内容并打印出一个漂亮的“访问权限”。

我的代码现在是这样的:

目标计划:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


int checkPwd(char *pwd)
{
    printf("\nstill in the function\n");
    if(strcmp(pwd, "patrick") == 0) return true;
    else return false;
}


int main()
{
    char pwd[16];

    printf("%d", checkPwd);
    scanf("%s", &pwd);
    system("pause");
    if(checkPwd(pwd)) printf("Granted!\n");
    else printf("Not granted\n");
    system("pause");
}

攻击者程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>

int returnTrue()
{
    return true;
}
int main()
{
    int hex;
    scanf("%d", &hex);
    memcpy((void*)hex, (void*)returnTrue, sizeof(char)*8);
    system("pause");
}

我想补充一点,我试图将十六进制代码(没有 scanf 部分)直接放入攻击者程序中并且没有工作,它崩溃了。

所以我认为我在这里遗漏了一些理论。我很高兴知道它是什么。

提前致谢。

【问题讨论】:

  • 对于这样的事情,你可能应该包括目标程序的程序集转储。
  • 你通过弄乱堆栈上的返回地址来覆盖 EIP。
  • @sixlettervariables 你的意思是什么?
  • 我在 Windows 上,但我不想使用 WinAPI 并让我依赖它。仍然不明白你想告诉我关于弄乱堆栈的内容。你能说得清楚一点吗?

标签: c memory


【解决方案1】:

这不行——进程占用不同的内存空间!

现代操作系统旨在保护用户程序免受此类攻击。一个进程无法访问另一个进程的内存——事实上,数据地址仅在该进程内部有效。

当程序运行时,它有自己的内存视图,只能“看到”内核指示memory management unit (MMU)为其映射的内存。

一些参考资料:

【讨论】:

  • 那些在内存中搜索值并改变它的程序呢? SO 对此做了什么?因为它工作得很好。
  • @PatrickBassut:你想更清楚一点你的意思吗?您尝试做的事情对于普通用户程序来说是不可能的,但我确信涉及内核的黑客(因此通常是某种管理员权限)可以做到这一点,例如游戏教练。
  • 我是认真的。你要我说清楚哪一部分?但是好的,现在您提到“常规用户程序”不可能做到这一点。但仍然可以通过破解内核来实现。那么,我所说的程序会破解内核吗?好的。
  • ... 好吗?但是你试图做的事情显然没有做到这一点,因此它不会起作用。因此,与内核混淆的事情是特定于操作系统的,因此您不依赖 Windows API 的愿望将无法实现。
  • 难道我不可能对两个操作系统使用相同的代码吗?你说的是这个吗?
【解决方案2】:

可以将一个函数注入另一个进程,但它比您想象的要复杂一些。第一件事是你需要适当的函数长度,你可以通过创建两个函数来做到这一点。

static int realFunction() { ... }
static void realFunctionEnd() {}

现在,当您将函数复制到上面时,请执行以下操作:

realFunctionEnd - realFunction

这会给你尺寸。现在您不能只调用其他函数,因为如前所述,它们不能保证在其他进程中位于同一地址,但您可以假设,我将假设 windows,kernal32.dll 位于同一地址,因此您实际上可以在创建远程线程时将其传递给 realFunction。

现在,至于您的真正问题。您需要做的是注入一个 dll 或将一个函数复制到另一个进程中,然后挂钩您需要更改的函数。您可以通过复制另一个函数并使该代码可执行,然后通过跳转到注入的代码覆盖目标函数的前五个字节来做到这一点,或者您可以执行适当的 detour 类型挂钩。无论哪种情况,它都应该起作用。或者,您可以找到函数的偏移量并通过编写适当的操作码代替实际代码自行修补它,例如返回 true。

需要某种注入或修补程序才能完成此操作,您已经有了基本的想法,但目前的想法比您想象的要多。我有 Windows 的工作代码,可以将一个函数复制到另一个进程中,但我相信这是一次很好的学习体验。

【讨论】:

  • 函数必须是静态的吗?如果是,为什么?我如何将第二个功能用作“结束标志”?为什么我不能保证在其他进程中地址不会相同?是否有任何操作系统程序可以改变它?
  • 如果我没记错的话,静态函数会保持函数的顺序,但同样不能保证,因为它取决于编译器,但对于 VC++ 来说确实如此。这两个函数在内存中一个接一个地出现,所以它们的地址也是一个接一个。此属性以及函数名本质上是指向地址空间的指针这一事实,您可以将其视为常量 unsigned int。操作系统可能具有地址空间布局随机化,或者只是无法将 exe 映像设置为其首选基地址。您可以关闭 ASLR,以保持地址相似。
  • 知道了。关于测量函数的大小。这在任何情况下都适用吗?因为在声明第一个函数时,内存中的下一个空间可能会被其他东西填充。感谢您的帮助。
  • 不能保证它依赖于编译器,中间可能有额外的空间,但最终没关系,因为你在这个分配的内存的顶部调用。
猜你喜欢
  • 2011-04-19
  • 1970-01-01
  • 2017-05-01
  • 1970-01-01
  • 2012-04-26
  • 1970-01-01
  • 2023-02-06
  • 2011-04-27
  • 1970-01-01
相关资源
最近更新 更多