我目前正在阅读计算机系统简介:程序员的观点(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?解释会非常有用。
答案 0 :(得分:1)
他们只假设32位系统上的最大总共享内存(kbytes),8388608
就是2^23
,2^15
由以下公式计算:
(8388608 / 256) = 32768 == 2^15
换句话说:
total_memory_size / NOP_sled_length = total_iterations_to_find_NOP_sled_in_memory
他们根据我们的NOP雪橇可以在从0x0
一直到0x800000
(8388608
或2^23
的范围内的任何位置进行计算)。因为我们的NOP雪橇长度为256字节,所以我们不需要为每个猜测/迭代/蛮力增加1,而是我们计算每次增加256,从而给出我们上面等式0x800000 / 256 = 32768 == 2^15
的结果。所以我们只需要强制32768个可能的地址,因为其中一个地址将在我们的NOP雪橇开始处落地,并一直向下滑动到我们的有效载荷。
如果我们的NOP雪橇是500字节(假设我们的攻击允许我们适合那么大的NOP雪橇),那么等式将是:
0x8000000 / 500 = 268435
次迭代,找到我们的NOP雪橇的起始地址。
这种方法对于64位系统来说不是那么好的原因是因为以下等式:
2^32 / 256 = 16,777,216
(超过1600万个可能的地址,我们的NOP雪橇可以开始!即使你的NOP雪橇是500字节而你除以500,你仍然会有超过850万个地址你的NOP雪橇可以开始!)
0000
0000
NNNN
NNNN
NNNN
PPPP
PPPP
PPPP
0000
0000
如果您认为上面是我的堆栈,我的总内存大小为40.我有一个12字节的NOP底座(N' s)和12字节的有效负载(P' s) 。所以这个可利用场景的等式是:
40 / 12 = 3
给我3个可能的地址,我的NOP雪橇可以在尽可能少的尝试中找到(12,24,32或十六进制0x0c,0x18和0x20)。
因此,如果我的漏洞利用只是从堆栈的开头开始并以12为增量计数,那么它将在第一次尝试时找到我的NOP雪橇(将4个字节放入我的NOP底座)。
根据评论进行更新:
对于地址随机化的旁路技术,NOP雪橇背后的想法不是猜测NOP雪橇的 start - 它计算的最小量地址 ,可以保证你将降落在你的NOP雪橇内,尽可能少地解决猜测/暴力。当然,如果你想找到你的NOP雪橇的开头,你可以使用下面的等式:
total_mem_size / NOP_size = least_amount_of_guesses_to_land_inside_payload + 1
但请记住,通过添加额外的地址来尝试,在获得有效负载之前不再计算最少量的地址(这就是我和你正在读的书)正在计算,因为这是使用NOP雪橇背后的想法)。
如果我们再次访问我的小型堆栈"在上面确实可以有4个总地址,NOP雪橇可以在这个地址开始,但是这个等式计算了3个保证的地址来找到NOP雪橇(尽可能少的猜测是关键)。为了更清楚,你可以说漏洞开发者会试图通过增加NOP雪橇的尺寸(尽可能)来使这个数字尽可能小,这样他们就不用担心找到NOP的开头了。雪橇 - 他们只想降落在NOP雪橇内。
索引12
的猜测将使你的4个字节进入你的NOP雪橇,在你到达有效载荷之前只能执行8个NOP。索引24
的猜测将使您在有效负载中占据几个字节而导致崩溃,并且索引32
的猜测将使您越过有效负载也导致崩溃。
让我们使用您的方法(使用总共4个地址)来说明为什么额外地址没有在等式中考虑:
0000
0000
NNNN
NNNN
NNNN
PPPP
PPPP
PPPP
0000
0000
让我们的等式加1,给出4个可能的地址,堆栈布局与以前相同:
40 / 12 = 3 + 1 = 4
所以现在我们有4个地址蛮力登陆我们的NOP雪橇0, 12, 24, 32
。因为我们有一个12字节的NOP底座,所以仍然只有一个地址(索引12处的地址,原始等式所找到的地址)将落入我们的NOP底座,让我们在shellcode的开头执行shellcode。在我们的NOP雪橇之前,我们无法控制的数据将索引0放在堆栈上。因此,通过在混音中添加1个地址并不能帮助我们找到NOP雪橇 - 它只会增加尝试/暴力/猜测的地址数量。
是的,你是对的 - 我只是增加了更直观的地址,以便更有意义但是"计算"或者"递增"实际执行期间堆栈上的地址将从高地址开始。
答案 1 :(得分:0)
不确定这是否对您有所帮助:
对于32位系统,如果你的NOP雪橇是256字节(即2 ^ 8),如果你的堆栈的范围是2 ^ 23字节,你只需要2 ^ 15个实例(即2 ^ 23/2 ^ 8 = 2 ^ 15)(非重叠)雪橇。
64位系统也是如此