CTF/리버싱

[DCTF] Seek - 리버싱 / C / fseek

SecurityMan 2022. 4. 19. 06:30

C언어 리버싱 문제이다.

 

문제 파일로 seek.c 과 flag.txt 파일 두개가 주어진다.

 

 

flag.txt 파일을 메모장으로 열어보면 아무것도 써있지 않다.

 

파일이 잘못됐나 싶어서 다시한번 봤더니

 

 

크기도 0바이트인게 진짜 아무것도 안써있는게 맞았다.

 

다음으로 seek.c 파일을 열어보았다.

 

 

열어보면 752줄로 파일이 꽤 길다.

 

내용을 살펴보면

 

flag.txt 파일을 읽어fp 변수에 우선 저장한다.

 

그다음부터 약 700줄 가량은 fseek 라는 함수가 실행되고 있다.

 

fseek 함수를 찾아봤더니 파일의 읽기/쓰기 위치 변경함수라고 한다.

 

int fseek(FILE *stream, long offset, int origin)

 

이게 기본 문법이다.  매개 변수를 세개를 받는데

 

첫번째는 파일을 지정해주고(FILE *stream), 두번째는 offset을 입력받는다.

 

offset는 origin으로부터 떨어진 바이트 수를 의미한다.

 

마지막 세번째는 origin을 입력받는데 세가지 종류가 있다.

 

SEEK_CUR : 파일 포인터의 현재 위치
SEEK_END : 파일 끝
SEEK_SET : 파일 시작

 

위 세가지 중 하나가 와야하며, 이번 문제같은 경우는 SEEK_SET 이라고 적혀있으니

 

파일 시작부터 offset를 계산하면 된다.

 

첫번째 줄만 먼저 보자.

 

fseek(fp,540,SEEK_SET);
c=fgetc(fp);
if(c != 32){
	oops();
}

 

한줄로 되어있는걸 가독성 있게 나눠봤다.

 

먼저 fseek 함수로 fp(flag.txt)의 시작부터 540번 글자를 가져온다.

 

만약 가져온 글자가 32와 같지 않으면 oops() 함수를 실행시킨다.

 

32는 ascii 코드인듯 하다.

 

int oops(){
   printf("oops this wasn't the char I was looking for\n");
   exit(1);
   return 0;
}

 

oops() 함수는 위에도 써있지만 이거다.

 

그냥 틀렸다고 알려주는 역할을 한다.

 

이제 어떤식으로 동작하는지 알았으니 코드를 짜주면 된다.

 

700줄이 넘기 때문에 코드를 짜는게 훨씬 편하다.

 

f = open('seek.c','r')

flag = [0 for i in range(730)]
index = ''
string1 = ''
string2 = ''

for i in range(747):
    line = f.readline()

    if 'fseek' in line:
        index = int(line.split(',')[1])
        string1 = line.split('!=')[1]
        string2 = chr(int(string1.split(')')[0]))

        flag[index] = string2

for i in range(len(flag)):
    print(flag[i], end='')

 

문제풀이 코드는 python으로 작성했다.

 

먼저 open으로 seek.c 파일을 열어준다.

 

크기가 730인 flag 배열을 하나 만들어주고 내용을 0으로 채운다.

 

그런다음 파일을 한줄씩 읽으면서 fseek 라는 내용이 나올때마다 

 

index와 string 변수에 각각 특정한 값들을 넣어주는데

 

index에 들어가는건 fseek(fp,540,SEEK_SET); 이렇게 540 위치에 있는 값이고

 

string에 들어가는건 if(c != 32){oops();} 이렇게 32 위치에 있는 값들이 들어가게 된다.

 

flag[index] = string 으로 flag 배열에 차곡차곡 값들을 저장해주고

 

마지막에 출력까지 해주는 코드이다.

 

 

코드를 실행시키면 이렇게 플래그가 그림으로 나온다.

반응형