加载库时需要随机化内存地址吗?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的。
还。缓冲区溢出漏洞利用需要一致的内存模型,以便溢出缓冲区的字节对代码的已知部分执行已知的操作。
http://www.corewars.org/ 很好地说明了这一原则。
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.
某些漏洞允许覆盖某些地址(堆栈溢出允许覆盖返回地址,堆溢出漏洞通常会覆盖 Win32 上的 SEH 指针和 Linux 上动态调用函数的地址(GOT 条目),...)。所以攻击者需要让被覆盖的地址指向一些有趣的东西。为了使这一问题变得更加困难,采取了几种对策:
系统
的地址将是“有趣的”)。因此,您必须将加载地址随机化视为许多措施(多层防御等等)中的另一种对策。
另请注意,漏洞利用并不限于任意代码执行。让程序打印一些敏感信息而不是(或者除了字符串截断错误之外)一些非敏感信息也算作漏洞利用;编写一些具有此类漏洞的概念验证程序并不困难,其中知道绝对地址将使可靠的利用成为可能。
您绝对应该看看 return-into-libc 和 return-oriented-programming。这些技术大量使用可执行文件和库中的地址知识。
最后,我要指出的是,有两种方法可以随机化库加载地址:
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:
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:
一个简单的例子:
如果在流行的操作系统上,标准 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 thesystem
function would be called. While they still haven't done everything needed to causesystem
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 tosystem
.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.
典型的方法是通过缓冲区溢出,将特定地址放入堆栈,然后返回到该地址。您通常会在内核中选择一个地址,它假定您在堆栈上传递给它的参数已经被检查过,因此它只是使用它们而不进行任何进一步的检查,从而允许您执行通常不允许的操作。
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.