DongDD's IT

[2018 Angstrom CTF] Write-up(Web, Reversing, Binary) 본문

CTF/Write-up

[2018 Angstrom CTF] Write-up(Web, Reversing, Binary)

DongDD 2018. 3. 19. 16:25

[2018 Angstrom CTF] Write-up(Web, Reversing, Binary)



Source Me 1


Point : 20 point

Category : Web


Problem : 

There is only one goal: Log in.



admin으로 로그인하라고 되어있었다. 먼저 페이지 소스를 확인해보았다.


페이지 소스에 주석으로 admin 패스워드가 적혀있었다.

admin password : f7s0jkl

이 비밀번호와 admin으로 로그인을 했더니 flag가 보여지는 페이지가 나왔고 flag를 입력해 문제를 통과할 수 있었다.


Answer & Flag




FLAG : actf{source_aint_secure}




get me!


Point : 30 point

Category : Web


Problem : 

Get me! Over here.


Challenge Link : http://web.angstromctf.com:6999


위와 같은 페이지가 주어져있었다. submit을 클릭해보니 다른 페이지로 넘어가는 것을 볼 수 있었고 "Hey,you're not authorized!"라는 메시지를 볼 수 있었다.

그리고 GET방식으로 url에 auth=false라고 표시된 것을 볼 수 있었다.


source code를 확인해보니 hidden으로 auth가 false로 되어있었고 이 값을 true로 바꿔서 submit을 누르니 flag가 보이는 페이지로 넘어갈 수 있었다.

url에서 false로 되어있는 값을 true로 바꿔서도 flag를 획득할 수 있다.




Answer & Flag




FLAG : actf{why_did_you_get_me}




Source Me 2


Point : 50 point

Category : Web


Problem : 

Your goal hasn't changed. Log in.


Challenge Link : http://web.angstromctf.com:7000


Source Me 1과 똑같은 형태로 되어있었다. admin으로 로그인하면 문제를 통과할 것 같았다.
일단 소스 코드를 먼저 확인해보았다.



소스 코드에 script로 선언되어있는 함수가 있었고 이 함수에서 password가 md5로 해쉬되어 이 값이 특정 값과 일치하는지 확인해 admin으로 로그인할 수 있게 되어있었다.


md5(password) = bdc87b9c894da5168059e00ebffb9077

md5로 복호화해보니 이 값이 "password1234"로 복호화되었고 admin 계정으로 로그인해 flag를 얻을 수 있었다.




Answer & Flag




FLAG : actf{md5_hash_browns_and_pasta_sauce}




run me


Point : 20 point

Category : Reversing


Problem : 

For several challenges, being able to run executables on the shell server will be very important. For this challenge, you will need to connect via ssh to the shell server and navigate to /problems/run_me/. Once there, you will need to run the executable file using the command ./run_me.


이번 ctf에서는 서버를 주어지고 안에 flag파일과 실행 파일로 flag를 실행시켜 획득하는 문제로 되어있었는데, 이번 문제는 그냥 파일을 실행하니 flag가 나왔다. 아마 shell 접속을 해보라는 의미에 문제였던 것 같다.



Answer & Flag




FLAG : actf{why_did_you_run_me}




Rev 1


Point : 60 point

Category : Reversing


Problem : 

One of the commmon categories in CTFs is Reverse Engineering, which involves using a dissassembler and other tools to figure out how an executable file works. For your first real reversing challenge, here is an ELF file. Head over to /problems/rev1/ on the shell server to try it out, and once you have the input right, get the flag!


파일을 다운받을 수 있게 되어있었고 서버에서도 문제 폴더가 따로 존재했다. 일단 다운 받은 file을 IDA를 통해 열어보았다.


IDA를 통해 확인해보니 stdin으로 입력받는 값을 if문의 strcmp를 통과하기 위해 "s3cret_pa55word"를 입력하면 setesgid를 통해 권한 상승을 하고 flag파일을 출력해주는 형태로 되어있었다.

서버에서 파일을 실행하고 위 값을 입력하니 flag를 얻을 수 있었다.



Answer & Flag




FLAG : actf{r3v_is_just_gettin_started!}




Rev 2


Point : 80 point

Category : Reversing


Problem : 

It's time for Rev2! This one is pretty similar to the first: once you get the inputs right to the program, you will get the flag. You don't need the shell server for this one, but the binary can be found at /problems/rev2/ if you would like to run it there.


이번 문제도 파일을 다운받을 수 있게 되어있고 서버에서도 실행할 수 있게 되어있었다.

IDA를 통해 확인해보았다.



v5를 입력받고 이 것이 4567이어야 if문으로 들어갈 수 있었다. 그 후에 v6, v7을 입력받고 9 < v6 <= 99,

9 < v7 <= 99, v6 <= v7, v6*v7 == 3431을 만족하는 값을 찾으면 이 값들로 flag를 만들어 출력하게 되어있었다.

python의 z3를 이용해 이 값을 간단히 계산할 수 있었다.


1
2
3
4
5
6
7
8
9
10
11
12
13
from z3 import *
 
= Solver()
= Int('x')
= Int('y')
s.add(x > 9, x <= 99, y > 9, y <= 99, x <= y, x*== 3431)
 
print s.check()
= s.model()
 
print "x =",f[x]
print "y =",f[y]
 
cs


프로그램을 작성하고 돌려 v6이 47, v7이 73인 것을 알 수 있었고 이 값들을 입력으로 넣어주고 프로그램을 실행하니 flag를 얻을 수 있었다.


Answer & Flag


FLAG : actf{4567_47_73}




Rev 3


Point : 110 point

Category : MISC


Problem : 

Let's try Rev 3! For this executable, you will need to figure out what input makes the program return "Correct". You don't need the shell server for this one, but the binary can be found at /problems/rev3/ on the shell server.


이번 문제도 파일 하나가 주어져있었고 서버에서도 실행할 수 있게 되어있었다.

IDA를 통해 확인해보았다.



argv를 통해 입력 받은 string을 encode함수를 통해 변환시키고 이 값을 strcmp로 비교해 같다면 flag라는 message를 띄어준다. 변환되기 전 string을 찾으면 되는 것 같았다.



encode함수를 살펴보니 입력받은 string을 각각 9와 xor하고 -3을 해준 값이 변환된 string이라는 것을 알 수 있었다.

즉, 이것을 반대로 생각해 변환된 메시지를 각각 +3해준 후 xor 9를 해주면 원래의 값이 나올 것이라는 생각이 들었다. python으로 프로그램을 작성해 실행해보니 flag가 나오는 것을 볼 수 있었다.


1
2
3
4
5
6
7
8
import sys
 
ss = "egzloxi|ixw]dkSe]dzSzccShejSi^3q"
 
for i in range(len(ss)):
    a = ord(ss[i])+3
    sys.stdout.write(chr(a^9))
print "\n"

cs



Answer & Flag




FLAG : actf{reversing_aint_too_bad_eh?}




ACCUMULATOR


Point : 50 point

Category : Binary


Problem : 

I found this program (source) that lets me add positive numbers to a variable, but it won't give me a flag unless that variable is negative! Can you help me out? Navigate to /problems/accumulator/ on the shell server to try your exploit out!


이 문제에서는 source code 파일과 실행 파일이 주어져있었다. 따로 실행 파일을 디스어셈블할 필요 없이 소스 코드를 확인하면 될 것 같았다.


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
#include <stdlib.h>
#include <stdio.h>
 
int main(){
 
    int accumulator = 0;
    int n;
    while (accumulator >= 0){
        printf("The accumulator currently has a value of %d.\n",accumulator);
        printf("Please enter a positive integer to add: ");
 
        if (scanf("%d",&n) != 1){
            printf("Error reading integer.\n");
        } else {
            if (n < 0){
                printf("You can't enter negatives!\n");
            } else {
                accumulator += n;
            }
        }
    }
    gid_t gid = getegid();
    setresgid(gid,gid,gid);
    
    printf("The accumulator has a value of %d. You win!\n", accumulator);
    system("/bin/cat flag");
 
}
 
cs

0으로 초기화된 accumulator값이 0보다 작아질 때까지 while문을 도는데, 입력한 값만큼 이 값에 더해준다. 하지만 음수를 입력할 수 없게 되어있었다. 즉, 더하는 것만 이용해 음수를 만들어야 이 while문을 끝내고 나와 flag를 출력해줄 수 있게 되어있었다.

int형 오버플로우를 이용해 문제를 해결할 수 있었다. int형으로 선언되어있는 값을 INT_MAX값보다 초과시켜주면 오버플로우로 인해 음수로 변하게 되어 문제를 통과할 수 있다.
대략 22억이면 INT형을 초과하기 때문에 21억을 더하고 모자란 부분을 더해주니 while문이 끝나고 flag가 출력되었다.



Answer & Flag



FLAG : actf{signed_ints_aint_safe}




Cookie Jar


Point : 60 point

Category : Binary


Problem : 

Note: Binary has been updated Try to break this Cookie Jar that was compiled from this source Once you've pwned the binary, test it out by connecting to nc shell.angstromctf.com 1234 to get the flag.


이번 문제도 source code 파일과 실행 파일이 주어져 있었고 flag를 얻기 위해서는 nc를 통해 프로그램을 실행시켜야 되게 되있었다.

먼저 주어진 소스 코드 파일을 확인해보았다.


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
 
 
#include <stdio.h>
#include <stdlib.h>
 
#define FLAG "----------REDACTED----------"
 
int main(int argc, char **argv){
  
    gid_t gid = getegid();
    setresgid(gid, gid, gid);
 
    int numCookies = 0;
 
    char buffer[64];
 
    puts("Welcome to the Cookie Jar program!\n");
    puts("In order to get the flag, you will need to have 100 cookies!\n");
    puts("So, how many cookies are there in the cookie jar: ");
    fflush(stdout);
    gets(buffer);
 
    if (numCookies >= 100){
        printf("Congrats, you have %d cookies!\n", numCookies);
        printf("Here's your flag: %s\n", FLAG);
    } else {
        printf("Sorry, you only had %d cookies, try again!\n",numCookies);
    }
        
    return 0;
}
 
cs

numCookies가 0으로 선언되어있었고 그 후에 buffer 64bytes가 선언되어있었다. 
numCookies가 100보다 크거나 같으면 flag가 출력되는 형태로 되어있었다.
buffer를 오버플로우시켜 numCookies의 영역을 100보다 크게 만들면 flag가 출력되게 할 수 있다.

원래는 stack을 분석해 정확한 위치를 찾아내야하지만 대략의 계산으로 overflow를 일으켜 100을 넘겨서 통과시켜 flag를 얻을 수 있었다.



Answer & Flag




FLAG : actf{eat_cookies_get_buffer}




Number Guess


Point : 70 point

Category : Binary


Problem : 

Ian loves playing number guessing games, so he went ahead and wrote one himself (source). I hope it doesn't have any vulns. The service is running at nc shell.angstromctf.com 1235.


이번 문제도 source code 파일과 실행 파일이 주어져있었다. nc를 통해 접속해 flag를 획득할 수 있게 되어있었다.

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


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
39
40
41
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
 
char *flag = "REDACTED";
char buf[50];
 
int main(int argc, char **argv) {
 
    
    puts("Welcome to the number guessing game!");
    puts("Before we begin, please enter your name (40 chars max): ");
    fflush(stdout);
    fgets(buf, 40, stdin);
    buf[strlen(buf)-1= '\0';
        
    strcat(buf, "'s guess: ");    
    puts("I'm thinking of two random numbers (0 to 1000000), can you tell me their sum?");
    
    srand(time(NULL));
    int rand1 = rand() % 1000000;
    int rand2 = rand() % 1000000;
 
    printf(buf);
    fflush(stdout);
    int guess;
    char num[8];
    fgets(num,8,stdin);
    sscanf(num,"%d",&guess);
 
    if (guess == rand1+rand2){
        printf("Congrats, here's a flag: %s\n", flag);
    } else {
        printf("Sorry, the answer was %d. Try again :(\n", rand1+rand2); 
    }
    fflush(stdout);
    return 0;
}
 
 
cs


stdin을 통해 40 bytes를 입력받고 rand1과 rand2를 rand()함수를 이용해 랜덤한 값을 생성해준다.

그 후에 printf(buf)를 통해 입력한 값을 출력해주는데, Format String Bug를 이용해 메모리 영역을 확인해 rand1, rand2의 값을 확인할 수 있을 것 같았다.

이 문제에서는 추측한 값을 입력했을 때 틀리면 답이 뭔지 알려주기 때문에 정확한 메모리 분석없이 %d 서식문자를 이용해 추측을 통한 문제 해결을 할 수 있었다.



%d를 어느 정도 넣어주면 메모리에 들어있는 값들을 int형으로 볼 수 있다. 그 후에 아무 값을 입력하게 되면 틀렸다는 메시지와 함께 정답을 알려준다. 

이 정답과 메모리를 비교해보며 더해서 정답이 나오는 값을 찾아보니 3번째의 값과 9번째 값을 더하면 정답이라는 것을 알 수 있었다.

이 방법을 이용해 flag를 획득할 수 있었다.



Answer & Flag





FLAG : actf{format_stringz_are_pre77y_sc4ry}




Rop to the Top


Point : 130 point

Category : Binary


Problem : 

Rop, rop, rop

Rop to the top!

Slip and slide and ride that rhythm... 


Here's some binary and source. Navigate to /problems/roptothetop/ on the shell server to try your exploit out!


이번 문제에서도 source code파일과 실행 파일이 주어져있었다. 서버에 접속하면 실행 파일과 flag파일이 있었다.

문제만 보고 rop이겠거니 생각했었는데 소스 코드를 확인해보니 아니라는 것을 알 수 있었다.


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
 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
 
void the_top(){
 
    system("/bin/cat flag");
 
}
 
void fun_copy(char *input){
 
    char destination[32];
    strcpy(destination, input);
    puts("Done!");
}
 
int main (int argc, char **argv){
    gid_t gid = getegid();
    setresgid(gid,gid,gid);
 
    if (argc == 2){
        puts("Now copying input...");
        fun_copy(argv[1]);
    } else {
        puts("Usage: ./rop_to_the_top32 <inputString>");
    }
 
    return 0;
}
 
cs

argv[1]을 입력받고 이 값을 fun_copy의 인자로 넘겨주고 이 함수에서는 strcpy를 통해 32 bytes의 버퍼로 복사해준다. 즉, 여기서 argv[1]을 32 bytes 이상의 값을 넣어 오버플로우를 통해 system함수가 있는 the top()으로 return 할 수 있게 된다.


gdb를 통해 return해야 할 the_top()함수의 주소를 알 수 있었다.


the_top() 함수의 주소 : 0x80484db


이 주소와 buffer의 overflow를 strcpy를 통한 overflow를 계산해 payload를 작성했다.


Payload = dummy(40 bytes, buffer+ stack dummy) + sfp(4 bytes) + return address(the_top의 주소, 0x80484db)


위에서 작성한 payload를 argv에 넣어줘 실행하니 the_top()함수가 실행되어 flag를 얻을 수 있었다.




Answer & Flag




Payload = dummy(40 bytes, buffer+ stack dummy) + sfp(4 bytes) + return address(the_top의 주소, 0x80484db)

argv[1] = "A'*44 + "\xdb\x84\x04\x08"


FLAG : actf{strut_your_stuff}



'CTF > Write-up' 카테고리의 다른 글

[2018 TUCTF] Write-up  (0) 2018.11.26
[2018 IceCTF] Write-up  (0) 2018.09.14
[2018 Angstrom CTF] Write-up(MISC,Crypto)  (0) 2018.03.19
[2018 Pragyan CTF] Write-up & 후기  (0) 2018.03.05
[2017 SECCON CTF Quals] Write-up & 후기  (0) 2017.12.10
Comments