DongDD's IT

[2018 IceCTF] Write-up 본문

CTF/Write-up

[2018 IceCTF] Write-up

DongDD 2018. 9. 14. 13:30

[2018 IceCTF] Write-up




Lights out!


Point : 75

Category : Web


Problem :

Help! We're scared of the dark!


Challenge Link https://static.icec.tf/lights_out/index.html



주어진 주소에 접속하니 다음과 같은 페이지가 나왔다.

"Who turned out the lights?!?!" 라는 메시지가 있었고 다른 화면은 모두 검정색으로 출력되어있었다.

소스 코드를 확인해보았다.


body 부분을 확인해보니 다음과 같이 되어있었다.

html을 조금 공부해보긴 했지만 summary는 처음 보았다.

firefox로 해당 소스 코드를 보았을 때, 위처럼 회색으로 표시되어있었기 때문에 summary를 한번 지워보았다.



summary를 지웠더니 페이지에 Flag와 같이 보이는 문자 몇개가 출력되었다.

일정 부분은 보이지 않게 되어있었고 소스 코드를 다시 한번 확인해보았다.



소스 코드를 확인해보니 summary를 지우기 전에는 없었던 before와 after가 생겼다.

이 부분을 각각 클릭해보니 각 부분에 content가 담겨있는 것을 볼 수 있었다.


각 content에는 보이지 않던 부분이 나타나있었고 표시된 부분과 이 부분을 조합해 flag를 얻을 수 있었다.


Answer & Flag


FLAG : IceCTF{styles_turned_the_lights}



Modern Picasso


Point : 150

Category : Forensics


Problem :

Here's a rendition of some modern digital abstract art. Is it more than art though?


Challenge Link https://static.icec.tf/picasso/picasso.gif


문제에 들어가보니 gif 파일을 다운로드 받을 수 있게 되어있다.

다운로드를 받고 gif를 켜보니 위와 같이 바뀌는 것을 볼 수 있었다.

위와 같이 gif가 동작하는 것을 보고 왠지 이 그림들을 겹쳐서 보면 flag가 나올 것 같다는 생각이 들었다.



convert를 사용하여 gif를 png파일로 분리해보았다.

총 60개의 png 파일로 분리되었다.

png를 합치는 방법을 몰랐기 때문에 수동으로 투명도를 조절해가며 합쳐보았다.


첫 5개의 이미를 합쳤더니 다음과 같은 이미지가 나왔다.

뭔가 글씨가 써있는 것 같이 보였고 모두 합치면 flag가 나올 것 같아 수동으로 모두 합쳤더니 flag가 적혀있었다.


Answer & Flag


FLAG : IceCTF{wow_fast}



Simple Overflow


Point : 250

Category : Binary


Problem :

In programming, a buffer overflow is a case where a program, while it is writing data somewhere, overruns the boundary and begins overwriting adjacent memory. This is one of the first vulnerabilities used to exploit software. Modern programming languages tend to provide protection against this type of vulnerability, but it is still observed commonly in low-level software.

Buffer overflows can be a complex vulnerability to understand and exploit due to their low-level nature. To assist you in your training, we have provided a memory simulation in the middle to help you understand what happens when your input in the textbox is passed to the program on the left. The simulation shows you the memory layout of the underlying process, where your buffer is red, and the secret value is green. Try entering values into the box and observe how the values that the program sees change on the left.

In this case, the buffer sits on top of the stack memory, with the variable secret sitting just below it. As you will observe, the size limitation placed on buffer is not enforced, allowing you to write more than 16 characters. Get a feel for buffer overflows by exploring the above code.

Once you are comfortable with buffer overflows, exploit the program to grant you the flag.


Challenge Link https://eyrtut6ho8r9nyb-simple-overflow.labs.icec.tf/


문제에 들어가면 위와 같은 페이지가 나온다. 왼쪽에는 프로그램 실행 시 입력할 argument를 적을 수 있게 되어있었고 오른쪽에는 source code가 있었고 입력 값에 따라 변수에 저장되는 값이 달라지는 것을 표현해주고 있었다.

일반적인 buffer overflow 문제였지만 좀 더 쉽게 풀 수 있게 변수 값과 메모리를 보여주고 있었다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
 
const char* FLAG = "<REDACTED>"
 
void flag() {
    printf("FLAG: %s\n", FLAG);
}
 
void message(char *input) {
 
    char buf[16= "";
 
    int secret = 0// 0x0
 
    strcpy(buf, input);
 
    printf("You said: %s\n", buf);
 
    if (secret == 0xcafebabe) {
        flag();
    } else {
        printf("The secret is 0x%x\n", secret);
    }
}
 
int main(int argc, char **argv) {
    if (argc > 1){
        message(argv[1]);
    } else {
        printf("Usage: ./overflow <message>\n");
    }
    return 0;
}
cs


소스 코드를 분석해보았다.

main() 함수에서는 argument를 입력받았는지 확인하고 입력 받았다면 message() 함수를 호출한다.

message() 함수에서는 16bytes의 buf를 선언하고 이후에 int형 secret을 선언한다.

strcpy를 통해 입력받은 argv를 buf에 복사하고 이 후에 if 문을 통해 secret == 0xcafebabe 라면 flag()함수를 호출하여 flag를 출력해주는 방식으로 구현되어있었다.


buf를 overflow시키면 secret의 메모리를 침범할 수 있기 때문에 buf를 overflow시켜 secret을 조작할 수 있었다.

일반적인 CLI 환경이었다면 python이나 perl을 이용하여 0xcafebabe를 넣어주면 되지만 단순히 문자열로 넣어야 하기 때문에 hex값을 string으로 바꿔주는 사이트를 이용했다.


Ref) hex to string : https://codebeautify.org/hex-string-converter



0xcafebabe를 string으로 바꿔주니 위와 같은 문자가 나온 것을 볼 수 있었고 16 bytes의 null값을 채워주고 little endian으로 위 문자열을 넣어주니 점수를 획득할 수 있었다.


Answer & Flag




Cave


Point : 50

Category : Binary


Problem :

You stumbled upon a cave! I've heard some caves hold secrets.. can you find the secrets hidden within its depths?


Challenge Link https://shell.icec.tf/ssh/eyrtut6ho8r9nyb-cave

ssh -p 2222 ssh.icec.tf -l eyrtut6ho8r9nyb-cave



이번 문제는 들어가보니 왼쪽에는 webshell 창을 볼 수 있었고 오른쪽에는 소스 코드가 있었다.

shell에는 flag.txt 파일과 shout 실행 파일, shout 소스 코드 파일과 Makefile이 있었다.

먼저 소스 코드를 분석해보았다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
 
void shell() {
    gid_t gid = getegid();
    setresgid(gid, gid, gid);
    system("/bin/sh -i");
}
 
void message(char *input) {
    char buf[16];
    strcpy(buf, input);
 
    printf("The cave echoes.. %s\n", buf);
}
 
int main(int argc, char **argv) {
    if (argc > 1){
        message(argv[1]);
    } else {
        printf("Usage: ./shout <message>\n");
    }
    return 0;
}
 
cs





























main() 함수에서는 argument를 입력했는지 확인하고 입력했다면 message() 함수의 인자로 넘겨주며 호출한다.

message() 함수에서는 16 bytes의 buf를 선언하고 argument를 strcpy() 함수를 통해 복사한다.

그리고 사용하지 않는 shell() 함수에서는 setguid를 이용하여 system() 함수를 실행한다.


이 문제도 마찬가지로 buffer overflow 문제였다. buf를 overflow 시켜 return address를 조작하여 shell() 함수로 return되게 하면 flag를 획득할 수 있다.



gdb를 통해 shell() 함수의 주소를 확인했다.


shell 함수의 주소 : 0x0804850b



그 이후에 "A"를 16개 넣고 stack dummy가 있는지 확인해보았다.

16개를 넣었을 때, return address라고 판단되는 값이 buf+12 위치에 존재하는 것을 확인할 수 있었다.

즉, buf 16 bytes + dummy 12 bytes + return address와 같은 형태로 되어있는 것이다.

이 점을 이용하여 Payload를 작성하였고 Payload를 인자로 넣어 shell을 획득했고 flag를 얻을 수 있었다.


Answer & Flag


Payload : buf(16 bytes) + dummy(12 bytes) + return address(shell() 함수, 0x0804850b)

"A"*28 + "\x0b\x85\x04\x08"



FLAG IceCTF{i_dont_think_cavemen_overflowed_buffers}



Comments