Wargame/Exploit Education

[Phoenix] Final two

wyv3rn 2022. 10. 19. 16:50
728x90
반응형

1. intro

2. code 및 분석

2.1.  C code

/*
 * phoenix/final-two, by https://exploit.education
 *
 * This level is linked against ftp://gee.cs.oswego.edu/pub/misc/malloc.c
 * version 2.7.2, with a SHA1 sum of 407329d164e4989b59b9a828760acb720dc5c7db
 *
 * Can you get a shell via heap corruption?
 *
 * A man drives train for a living in Bulgaria. He absolutely loved his job,
 * and it had been his dream job ever since he was a child. One day, he falls
 * asleep driving, and runs over someone walking on the tracks. Well, his case
 * goes to court, and the court finds him guilty of murder, as had he not been
 * asleep, he could have sounded the horn, or stopped for the person.  The
 * punishment for such recklessness is the death penalty. So, he's on death row
 * and the executioner approaches him.
 *
 * "What would you like for your last meal?"
 *
 * "I would like a banana please."
 *
 * The executioner thinks it's weird, but shrugs and gives him a banana. The
 * guy eats his banana, waits awhile, and gets strapped into the electric
 * chair. When the flip the switch, nothing happens! In Bulgaria, an act of
 * divine intervention means you get released.
 *
 * A few months go by, and the train driver has been working for a new company.
 * Well, old habits die hard, and he falls asleep again. This time, he killed 2
 * people. Bulgarian courts have no patience for recklessness, so he ends up on
 * death row again. After awhile, the same executioner from last time
 * approaches him.
 *
 * "You again? Shit. What do you want this time?"
 *
 * "Two bananas please."
 *
 * The executioner shrugs and hands him two bananas. A bit weird, but whatever.
 * There's no way he can cheat death twice! But, when they flip the switch,
 * nothing happens again. The train driver walks a second time.
 *
 * Some time passes, and the executioner is very busy. After another few
 * months, the same dude shows up, apparently having run over 3 people with a
 * train. Exacerbated, the executioner approaches him for the third time.
 *
 * "Let me guess. Three bananas?"
 *
 * "Actually yes! How did you know?"
 *
 * "Too bad! This has gone on long enough. No more bananas! Today you fry."
 *
 * So, the train driver gets strapped into the chair with no last meal. But,
 * when they flip the switch, nothing happens again.
 *
 * "I dont get it," says the executioner. "I didnt let you eat any bananas!"
 *
 * "Its not the bananas. It's just that I'm a bad conductor."
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define REQSZ 128

#define BANNER \
  "Welcome to " LEVELNAME ", brought to you by https://exploit.education"

void check_path(char *buf) {
  char *start;
  char *p;
  int l;

  /*
   * Work out old software bug
   */

  p = rindex(buf, '/');
  l = strlen(p);
  if (p) {
    start = strstr(buf, "ROOT");
    if (start) {
      while (*start != '/') start--;
      memmove(start, p, l);
    }
  }
}

void get_requests(int in_fd, int out_fd) {
  char *buf;
  char *destroylist[256];
  int dll;
  int i;

  dll = 0;
  while (1) {
    if (dll >= 255) break;

    buf = calloc(REQSZ, 1);
    if (read(in_fd, buf, REQSZ) != REQSZ) break;

    if (strncmp(buf, "FSRD", 4) != 0) break;

    check_path(buf + 4);

    dll++;
  }

  for (i = 0; i < dll; i++) {
    write(out_fd, "Process OK\n", strlen("Process OK\n"));
    free(destroylist[i]);
  }
}

int main(int argc, char **argv, char **envp) {
  printf("%s\n", BANNER);
  fflush(stdout);

  get_requests(0, 1);
  return 0;
}

 

2.2. 분석

드디어 마지막 문제다. 이걸로 올해 목표는 달성이닷!

2.2.1. main

main 함수 내에서 get_request 함수를 call 한다.
인자로는 0과 1을 전달. (stdin / out을 위한 것으로 큰 의미는 없...)

2.2.2. get_request

get_request 함수 내에서는 buf, destroylist, dll, i 변수를 선언하고

dll이 255보다 작은 동안

128 bytes heap 영역을 할당하고 해당 위치에 128 bytes의 값을 받아들인 다음

그 값이 128 bytes인지 확인하고,

처음 4 글자가 FSRD인지 확인한 뒤 check_path 함수로 FSRD 문자열을 제외한 buf 값을 넘겨준다.

2.2.3. check_path

check_path 함수 내에서는

buf 함수 내에서 뒤에서부터 "/" 문자를 찾아 그 주소를 p에 저장하고

i 변수에는 그 길이를 저장한다.

이후 buf 변수 내에 "ROOT" 문자열이 있으면 그 주소를 start에 저장하고,

start 위치에서부터 앞쪽 방향으로 "/" 문자를 찾고 이를 뒤에서부터 찾은 "/" 위치에 i 만큼 복사한다.

상기 조건들을 만족하지 못할 시 free 함수를 실행하는데, 사실상 destroylist 변수가 사용되지 않기에 free되는 것은 없다.

 

3. 취약점 확인 및 공격 준비

3.1. 취약점

취약점이 없...다...

정상적인 문제였다면 memmove 시 다음 chunk의 위치에 값을 쓸 수 있으며 continuous(double) free bug를 통해 exploit 가능하다.

 

3.2. 공격 준비

아무래도 이 문제는 코딩 오류라고 생각된다.

get_request 함수의 말미에 free 함수를 통해 calloc으로 할당된 heap들이 free 되면서 continuous(double) free bug가 발생해야하는 것 같은데, 출제자의 오류로 heap address가 제대로 destroylist에 들어가지 않는다.

더불어 memmove 함수에 따라 값이 복사될때 앞선

2022.10.06 - [Wargame/Exploit Education] - [Phoenix] Heap three

 

[Phoenix] Heap three

1. intro 2. code 및 분석 2.1. C code /* * phoenix/heap-three, by https://exploit.education * * This level is linked against ftp://gee.cs.oswego.edu/pub/misc/malloc-2.7.2.c * version 2.7.2, with a S..

wyv3rn.tistory.com

문제와 같이 null byte 삽입이 불가능한 문제가 있으며,

본 문제에서는 특정 위치에 한번만 복사할 수 있는 특징 때문에 64 bit 환경에서는 푸는 것이 불가능할 것으로 예상한다.

32 bit 환경으로 코드를 수정해서 풀어볼까도 생각했지만, 결국은 heap three 문제와 동일할 것이기 때문에 패쓰!

 

4. exploit

없음! 끗!

 

 

 

 

 

728x90
반응형