我听说过这个理论.地址空间位置随机化需要库并将它们加载到虚拟地址空间中的随机位置,以便在黑客在程序中找到漏洞的情况下,他没有预先知道的地址来执行返回到libc的攻击例如,反对.但在考虑了几秒之后,它作为一种防御措施没有任何意义.
假设我们假设的TargetLib(libc或黑客正在寻找的任何其他东西)被加载到一个随机地址而不是一个确定性的地址.现在,黑客提前并不知道TargetLib及其中的例程,但是应用程序代码也没有.它需要在二进制文件中的某处具有某种查找表,以便找到TargetLib内部的例程,并且必须位于确定性位置.(或者在随机位置,由其他东西指向.您可以根据需要添加任意数量的间接,但最终您必须从已知位置开始.)
这意味着,不是将攻击代码指向TargetLib的已知位置,而是黑客需要做的就是将攻击代码指向应用程序的查找表的TargetLib条目,并取消引用指向目标例程的指针,并且攻击无阻碍地进行.
有什么关于ASLR的工作方式,我不明白吗?因为如上所述,我不知道它是什么,只不过是一个减速带,提供安全的图像,但没有实际的实质.我错过了什么吗?
如果我没有弄错的话,ASLR会在每次运行程序时使C编译器中的局部变量具有不同的地址.但是当我在Turbo C++和Dev-CPP IDE中尝试它时,它只返回一个类似的局部变量地址.我试过的代码:
#include <stdio.h>
#include <conio.h>
int main()
{
int x = 10;
int *ptr = &x;
printf("%d", ptr);
getch();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在此之前,我认为局部变量的地址是相同的,因为它分配在相同的堆栈区域中,因此分配了相同的内存地址.但是当我在stackoverflow中找到一个关于ASLR的线程时,它让我做了这些.我想这是因为编译器.任何人都可以对此有所了解吗?
编辑:
我正在使用Windows 7.
XCode Build Settings中有一个名为"Do not Create Position Independent Executables"的选项.这是直截了当的.
但是,我正在使用MonoDevelop和MonoTouch开发我的应用程序,我找不到相应的设置.我已经尝试将-fpie标志传递给编译器,但似乎不起作用.当我使用otool检查编译的二进制文件时,它没有设置PIE标志.
请帮忙.
我目前正在阅读计算机系统简介:程序员的视角(http://www.amazon.com/Computer-Systems-Programmers-Perspective-2nd/dp/0136108040/ref=sr_1_2?s=books&ie=UTF8&qid=1421029641&sr=1 -2&keywords=introduction+to+computer+systems)并尝试了解阻止缓冲区溢出的方法。
我理解为什么在使用地址随机化时我们需要 NOP 雪橇以及如何编写漏洞利用程序,但我很难理解书中给出的与 NOP 雪橇相关的地址计算。我在这里引用它:-
(假设程序在堆栈上的起始地址范围在32位系统上为2^23,在64位系统上为2^32)
“如果我们设置一个 256 字节的 NOP sled,那么可以通过枚举 2^15 个起始地址来破解 n=2^23 上的随机化,这对于坚定的攻击者来说是完全可行的。对于 64 位情况,尝试枚举 2^ 24个地址更令人畏惧。”
作者是如何分别为 32 位和 64 位情况得出数字 2^15 和 2^24 的?一个解释真的很有帮助。
我对ASLR非常熟悉,但今天我听到了一个关于在Windows中实现ASLR的新的有趣事实.
为了优化性能,如果进程A和B加载相同的dll,Windows只会将其加载一次到物理内存,并且两个进程将通过共享页面共享同一个实例.
这是旧闻.但有趣的是,进程A和B都将在同一个虚拟地址中加载共享库(为什么??).
在我看来,任何本地攻击(例如权限提升)都可以通过以下方式轻松绕过ASLR:
1. Create a new dummy process
2. Check the address of dlls of interest (kernel32, user32 ..)
3. Attack the privileged process and bypass ASLR with the information from step 2.
Run Code Online (Sandbox Code Playgroud)
我使用Olly做了一些简单的测试,发现共享库确实加载在同一个虚拟地址中.
如果确实如此,那么ASLR对于本地开发是否无用?
已解决: 解决方案是调用personality(0x40000)。请参阅下面评论中的详细信息。
ASLR 标志位于 ELF 文件中的什么位置?我需要禁用特定库 (.so) 的 ASLR。我尝试过使用 objdump 但不知道如何操作。
我无法使用 /proc,因为它似乎不适用于我的 Android 4.4.4,因此我尝试修改二进制文件。
编辑: 我已经编译了以下内容:
#include <stdio.h>
void* getEIP()
{
return __builtin_return_address(0) - 0x5;
}
int main(int argc, char** argv)
{
printf("EIP located at: %p\n", getEIP());
return 0;
}
Run Code Online (Sandbox Code Playgroud)
没有 ASLR (PIE):
arm-linux-androideabi-gcc.exe code.c -o noPIE --sysroot=%NDK%\platforms\android-3\arch-arm
Run Code Online (Sandbox Code Playgroud)
与ASLR(PIE):
arm-linux-androideabi-gcc.exe -fPIE -pie code.c -o withPIE --sysroot=%NDK%\platforms\android-3\arch-arm
Run Code Online (Sandbox Code Playgroud)
noPIE 二进制文件确实没有被随机化,尽管:
# cat /proc/sys/kernel/randomize_va_space
2
Run Code Online (Sandbox Code Playgroud) 有一个选项可以启用或禁用堆栈随机化,但有没有办法为ASLR算法提供种子以使其具有确定性?
编辑:上下文如下:一个内存错误我在ASLR下的十次执行中弹出一次,并且在禁用ASLR时无法复制.为ASLR算法提供随机种子将大大有助于调试过程.
我正在调试共享库。我发现在Linux主机上启用ASLR时可以触发该错误,而禁用ASLR时该错误消失。
我想用gdb进一步调试共享库。但是我发现它总是在固定地址加载共享库,这使得bug消失了。
有什么办法可以禁用这个 gdb 的功能吗?
这样做的不同部分libc(如.text,.plt,.got,.bss,.rodata,和其他人)在获得相同的偏移相对于装载libc基址每次?
我知道libc每次运行程序时加载器都会在随机位置加载。
先感谢您。
据我了解:
CPU 上有一个内存管理单元,用于控制对实际内存的访问。任何内存调用都流经这个单元,它将虚拟地址转换为实际内存地址。这允许计算机在 64 位机器上拥有 2^64 字节的虚拟内存空间。当没有足够的 RAM 时,CPU 或 MMU 会在需要时从磁盘交换页面进出。
Linux 上的 ELF 二进制文件包含一个标头,其中列出了二进制文件中二进制文件部分的地址(以及其他信息),其中包括代码部分和数据部分等。
ELF 标头还指定需要哪些共享库。它们由内核存储在内存中,当执行二进制文件时,它们的地址由内核提供给进程。
所以我更具体的问题是,作为 ASLR 的一部分,二进制文件和堆和堆栈的所有部分是否都从基位置随机偏移?
(对不起,如果其中任何一个是非常错误的,我在汇编/C/C++ 编程方面不是很有经验,并试图弄清楚二进制可执行文件如何工作的较小细节。)