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
문제와 같이 null byte 삽입이 불가능한 문제가 있으며,
본 문제에서는 특정 위치에 한번만 복사할 수 있는 특징 때문에 64 bit 환경에서는 푸는 것이 불가능할 것으로 예상한다.
32 bit 환경으로 코드를 수정해서 풀어볼까도 생각했지만, 결국은 heap three 문제와 동일할 것이기 때문에 패쓰!
4. exploit
없음! 끗!
'Wargame > Exploit Education' 카테고리의 다른 글
[Phoenix] Final zero (0) | 2022.10.18 |
---|---|
[Phoenix] Net two (0) | 2022.10.13 |
[Phoenix] Net one (0) | 2022.10.13 |
[Phoenix] Net zero (0) | 2022.10.13 |
[Phoenix] Heap three (0) | 2022.10.06 |