加载库时需要随机化内存地址吗?

发布于 2024-09-28 12:14:55 字数 751 浏览 0 评论 0原文

ldd 显示共享库链接的内存地址在运行时

$ cat one.c 
#include<stdio.h>

int main() {
    printf ("%d", 45);
}
$ gcc one.c -o one -O3
$ ldd one
    linux-gate.so.1 =>  (0x00331000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00bc2000)
    /lib/ld-linux.so.2 (0x006dc000)
$

这个答案到另一个问题,

...地址基本上是随机数。在设计安全实现之前,ldd 将始终指示加载程序部分的内存地址。大约五年前以来,许多版本的 Linux 现在有意随机化加载地址,以挫败潜在的病毒编写者等。

我不完全理解如何使用这些内存地址进行漏洞利用。

问题是否类似于“如果地址是固定的,人们可以在该地址放置一些不需要的代码,这些代码将像库一样被链接”,还是比这更多?

ldd displays the memory addresses where the shared libraries are linked at runtime

$ cat one.c 
#include<stdio.h>

int main() {
    printf ("%d", 45);
}
$ gcc one.c -o one -O3
$ ldd one
    linux-gate.so.1 =>  (0x00331000)
    libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0x00bc2000)
    /lib/ld-linux.so.2 (0x006dc000)
$

From this answer to another question,

... The addresses are basically random numbers. Before secure implementations were devised, ldd would consistently indicate the memory addresses where the program sections were loaded. Since about five years ago, many flavors of Linux now intentionally randomize load addresses to frustrate would-be virus writers, etc.

I do not fully understand how these memory addresses can be used for exploitations.

Is the problem something like "If the addresses are fixed, one can put some undesirable code at that address which would be linked as if it was a library" or is it something more than this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

半边脸i 2024-10-05 12:14:55

“如果地址是固定的,人们可以在该地址放置一些不需要的代码,这些代码会像库一样被链接”

是的。

还。缓冲区溢出漏洞利用需要一致的内存模型,以便溢出缓冲区的字节对代码的已知部分执行已知的操作。

http://www.corewars.org/ 很好地说明了这一原则。

"If the addresses are fixed, one can put some undesirable code at that address which would be linked as if it was a library"

Yes.

Also. Buffer overflow exploits require a consistent memory model so that the bytes that overflow the buffer do known things to known parts of the code.

http://www.corewars.org/ A great illustration of the principle.

东京女 2024-10-05 12:14:55

某些漏洞允许覆盖某些地址(堆栈溢出允许覆盖返回地址,堆溢出漏洞通常会覆盖 Win32 上的 SEH 指针和 Linux 上动态调用函数的地址(GOT 条目),...)。所以攻击者需要让被覆盖的地址指向一些有趣的东西。为了使这一问题变得更加困难,采取了几种对策:

  • 不可执行的堆栈可防止漏洞利用跳转到攻击者放在堆栈上的某些代码。
  • W^X 段(永远不能同时写入和执行的段)会阻止其他内存区域发生同样的情况。
  • 库和位置无关的可执行文件的随机加载地址降低了通过返回到 libc 和面向返回的编程技术成功利用的可能性,...
  • 随机加载地址还可以防止攻击者提前知道在哪里可以找到一些有趣的函数(例如:想象一下攻击者可以覆盖 GOT 条目和下一次日志记录调用的部分消息,知道系统的地址将是“有趣的”)。

因此,您必须将加载地址随机化视为许多措施(多层防御等等)中的另一种对策。

另请注意,漏洞利用并不限于任意代码执行。让程序打印一些敏感信息而不是(或者除了字符串截断错误之外)一些非敏感信息也算作漏洞利用;编写一些具有此类漏洞的概念验证程序并不困难,其中知道绝对地址将使可靠的利用成为可能。

您绝对应该看看 return-into-libc 和 return-oriented-programming。这些技术大量使用可执行文件和库中的地址知识。

最后,我要指出的是,有两种方法可以随机化库加载地址:

  • 每次加载时都执行此操作:即使攻击者可以在一次运行中获取有关地址的信息并尝试在运行时使用该信息,这也会使(某些)漏洞利用变得不太可靠。又跑了一次。
  • 每个系统执行一次:这就是 prelink -R 的作用。它可以避免攻击者使用所有 Redhat 7.2 机器的通用信息。显然,它的优点是不会干扰预链接:)。

Some vulnerabilities allow overwriting some address (stack overflows allow overwriting return addresses, exploit for heap overflows typically overwrite SEH pointers on Win32 and addresses (GOT entries) of dynamically called functions on Linux, ...). So the attacker needs to make the overwritten address point to something interesting. To make this more difficult, several counter-measures have been adopted:

  • Non-executable stacks prevents exploits from just jumping to some code the attacker has put on the stack.
  • W^X segments (segments which can never be writable and executable at the same time) prevents the same for other memory areas.
  • Randomized load addresses for libraries and position independent executables decrease the probabilities of succesful exploitation via return-into-libc and return-oriented-programming techniques, ...
  • Randomized load addresses also prevent attackers from knowing in advance where to find some interesting function (e.g: imagine an attacker that can overwrite the GOT entry and part of the message for the next logging call, knowing the address of system would be "interesting").

So, you have to view load address randomization as another counter-measure among many (several layers of defense and all that).

Also note that exploits aren't restricted to arbitrary code execution. Getting a program to print some sensitive information instead of (or in addition to, think of string truncation bugs) some non-sensitive information also counts as an exploit; it would not be difficult to write some proof-of-concept program with this kind of vulnerability where knowing absolute addresses would make reliable exploits possible.

You should definitely take a look at return-into-libc and return-oriented-programming. These techniques make heavy use of knowledge of addresses in the executable and libraries.

And finally, I'll note there are two ways to randomize library load addresses:

  • Do it on every load: this makes (some) exploits less reliable even if an attacker can obtain info about addresses on one run and try to use that info on another run.
  • Do it once per system: this is what prelink -R does. It avoids attackers using generic information for e.g: all Redhat 7.2 boxes. Obviously, its advantage is that it doesn't interfere with prelink :).
心碎的声音 2024-10-05 12:14:55

一个简单的例子:

如果在流行的操作系统上,标准 C 库总是加载在地址 0x00100000 处,并且标准 C 库的最新版本在偏移量 0x00000100 处具有 system 函数,那么如果有人能够利用在具有此操作系统的计算机(例如 Web 服务器)上运行的程序中存在缺陷,导致其向堆栈写入一些数据(通过缓冲区溢出),他们会知道,如果他们将 0x00100100 写入放置在当前函数期望其返回地址的堆栈上,然后他们可以将其放置在从当前函数返回时,将调用system函数。虽然他们还没有完成导致 system 执行他们想要的事情所需的一切,但他们已经很接近了,并且有一些技巧可以将更多内容写入堆栈,而不是上面提到的地址通过对 system 的强制调用,很可能会产生有效的字符串指针和命令(或一系列命令)。

通过随机化加载库的地址,攻击者更有可能导致 Web 服务器崩溃,而不是获得系统控制权。

A simple example:

If on a popular operating system the standard C library was always loaded at address 0x00100000 and a recent version of the standard C library had the system function at offset 0x00000100 then if someone were able to exploit a flaw in a program running on a computer with this operating system (such as a web server) causing it to write some data to the stack (via a buffer overrun) they would know that it was very likely that if they wrote 0x00100100 to the place on the stack where the current function expected its return address to be then they could make it so that upon returning from the current function the system function would be called. While they still haven't done everything needed to cause system to execute something that they want it to, they are close, and there are some tricks writing more stuff to the stack aver the address mentioned above that have a high likelihood of resulting in a valid string pointer and a command (or series of commands) being run by this forced call to system.

By randomizing the addresses at which libraries are loaded the attacker is more likely to just crash the web server than gain control of the system.

一袭水袖舞倾城 2024-10-05 12:14:55

典型的方法是通过缓冲区溢出,将特定地址放入堆栈,然后返回到该地址。您通常会在内核中选择一个地址,它假定您在堆栈上传递给它的参数已经被检查过,因此它只是使用它们而不进行任何进一步的检查,从而允许您执行通常不允许的操作。

The typical method is by a buffer overrun, where you put a particular address on the stack, and then return to it. You typically pick an address in the kernel where it assumes the parameters you've passed it on the stack have already been checked, so it just uses them without any further checking, allowing you to do things that normally wouldn't be allowed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文