Write-ups/pwnable.xyz

GrownUp - pwnable.xyz

dolphinlmg 2020. 2. 11. 23:13

Prob Info


Prob Info
Checksec

 

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char *src; // ST08_8
  __int64 buf; // [rsp+10h] [rbp-20h]
  __int64 v6; // [rsp+18h] [rbp-18h]
  unsigned __int64 v7; // [rsp+28h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  setup();
  buf = 0LL;
  v6 = 0LL;
  printf("Are you 18 years or older? [y/N]: ", argv);
  *((_BYTE *)&buf + (signed int)((unsigned __int64)read(0, &buf, 0x10uLL) - 1)) = 0;
  if ( (_BYTE)buf != 'y' && (_BYTE)buf != 'Y' )
    return 0;
  src = (char *)malloc(0x84uLL);
  printf("Name: ", &buf);
  read(0, src, 0x80uLL);
  strcpy(usr, src);
  printf("Welcome ", src);
  printf(qword_601160, usr);
  return 0;
}

맨 마지막 printf가 조금 이상한데 0x601160를 찾아 들어가보면 setup 함수에서 0x601168이란 값으로 초기화 해주고 0x601168에는 "%s\n"를 저장한다. 결국 printf("%s\n", usr) 와 같은 의미이다.

 

  src = (char *)malloc(0x84uLL);
  printf("Name: ", &buf);
  read(0, src, 0x80uLL);
  strcpy(usr, src);

이 부분을 잘 보면 힙 영역에 0x80 만큼 값을 입력받고 그 값을 다시 전역변수 usr에 strcpy를 통해 복사한다. 이 때 strcpy는 문자열을 다루는 함수이기 때문에 처리 후 맨 끝에 널바이트를 붙여준다. usr의 사이즈는 0x80이고 그 뒤에 qword_601160 변수가 존재하는데, strcpy 함수로 인해 최대 0x81 바이트를 복사할 수 있고 off-by-one이 발생한다. 이를 통해 qword_601160의 값이 0x601168에서 0x601100으로 바뀌게 되고 이는 usr의 중간부분이므로 fsb가 가능하다.

 

.data:0000000000601080                 public flag
.data:0000000000601080 flag            db 'FLAG{_the_real_flag_will_be_here_}',0
.data:0000000000601080 _data           ends

바이너리 내부에 플래그가 있으므로 fsb를 통해 이 문자열을 출력해주면 된다.