A Hacker Next Door

[HSCTF 6 Write-up] Misc – Broken GPS

Category: Write-up
Tag: CTF
Broken GPS 333

Written by: Disha and Shray

Ella is following a broken GPS. The GPS tells her to move in the opposite direction than the one she should be travelling in to get to her destination, and she follows her GPS exactly. For instance, every time she is supposed to move west, the GPS tells her to move east and she does so. Eventually she ends up in a totally different place than her intended location. What is the shortest distance between these two points? Assume that she moves one unit every time a direction is specified. For instance, if the GPS tells her to move “north,” she moves one unit north. If the GPS tells her to move “northwest,” then she moves one unit north and one unit west.

Input Format:

You will receive a text file with N directions provided to her by the GPS (the ones that she will be following) (1<=N<=1000). The first line in the file will be N, and each consequent line will contain a single direction: “north,” “south,” “east,” “west,” “northwest,” “northeast,” “southwest,” or “southeast.”

Output Format:

Round your answer to the nearest whole number and then divide by 26. Discard the quotient (mod 26). Each possible remainder corresponds to a letter in the alphabet. (0=a, 1=b… 25=z).

Find the letter for each test case and string them together. The result is the flag. (For instance, a, b, c becomes “abc”). Remember to use the flag format and keep all letters lowercase!

Broken GPS 문제 다운로드


– index.html

index.html 페이지

Magic Number Generator 라는 제목으로 input 값을 입력받게 되어있는데요, 임의의 숫자를 입력해보면 “i like 0″라는 검색어로 구글링된 페이지로 리다이렉트 됩니다.

index.html 소스코드

index.html의 소스코드를 보시면 난독화되어 읽기가 힘듭니다.

firefox 브라우저의 요소검사 창.

이럴 때에는 브라우저의 요소검사 창을 보시는 것이 도움이 됩니다. F12키를 누르거나 마우스 우클릭을 한 후 요소검사를 클릭하면 됩니다. 요소검사에서는 브라우저가 해석한 코드를 볼 수 있습니다. html 코드에서 스크립트도 볼 수 있고 그 아래 리스트 박스의 데이터도 볼 수 있습니다.

list box 데이터

리스트 박스의 데이터를 보니 어떠한 패턴을 발견한 것 같습니다. 오른쪽 빨간박스의 1과 0의 데이터는 플래그의 2진수 데이터인 것 같고, 왼쪽 박스의 “aria-posinset”부분은 각각의 0이나 1이란 데이터의 위치를 나타내는 값 같아 보입니다.

이런 가정을 바탕으로 2진수 플래그 데이터를 추출해보는 작업을 해보겠습니다.


– 문제 설명

엘라는 망가진 GPS를 사용하고 있었는데, 이 GPS는 방향을 반대로 가르쳐준다고 합니다. 예를 들어, 동쪽으로 가야했다면 서쪽으로가고, 남쪽으로 가야했다면 북쪽으로 가는 식이죠. 엘라는 이 GPS를 전적으로 믿고있어서 GPS가 가르쳐주는대로 걸어갔다고 합니다.

제공되는 텍스트들 안에는 걸음 수가 정수로 적혀있고, 지나왔던 방향이 단어로 적혀있습니다.

플래그를 찾기 위해서는 엘라의 현재 위치와 원래 도착해야 했던 지점사이의 최단거리를 구해 정수형태로 반올림한 뒤, 알파벳의 길이인 26으로 나눠줘야 합니다. 그 나머지 값이 각각 알파벳 소문자와 대응됩니다. 이 때, 소문자 a는 0에 대응되고 z는 25에 대응됩니다. 제공되는 텍스트 파일은 총 12개 이므로, hsctf{} 플래그 형태 안에 삽입되어야 할 문자열의 길이는 12입니다.


– 문제 풀이 코드 설명

– 전체 코드

#include <stdio.h>
#include <string.h>
#include <math.h>

struct Pos {
	int x;
	int y;
};

struct Pos go(char *dir) {
	struct Pos cur = {0, 0};

	if(!strcmp(dir, "east")) {
		cur.x = -1;
	}
	else if(!strcmp(dir, "northeast")) {
		cur.x = -1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "north")) {
		cur.y = +1;
	}
	else if(!strcmp(dir, "northwest")) {
		cur.x = +1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "west")) {
		cur.x = +1;
	}
	else if(!strcmp(dir, "southwest")) {
		cur.x = +1;
		cur.y = -1;
	}
	else if(!strcmp(dir, "south")) {
		cur.y = -1;
	}
	else if(!strcmp(dir, "southeast")) {
		cur.x = -1;
		cur.y = -1;
	}

	return cur;
}

int main(int argc, char *argv[])
{
	if(argc != 2) {
		printf("Error! : Input txt file isn't defined.\n");
		return 1;
	}

	FILE *fp;
	fp = fopen(argv[1], "r");

	if(fp == NULL) {
		printf("Error! : Can't open %s - exit.\n", argv[1]);
		return 1;
	}

	int N;
	char step[10] = {0};
	
	struct Pos her={0, 0};
	struct Pos tmp;

	double dist = 0.0;
	int rounded = 0;
	int divided = 0;
	
	fscanf(fp, "%d", &N); // number of footsteps
	for(int i=0; i<N; i++) {
		fscanf(fp, "%s", step);
		tmp = go(step);

		her.x += tmp.x;
		her.y += tmp.y;
	}

	printf("[Her position] \n");
	printf("X : %d\n", her.x);
	printf("Y : %d\n", her.y);
	printf("\n");
	printf("[Original position] \n");
	printf("X : %d\n", -(her.x));
	printf("Y : %d\n", -(her.y));
	printf("\n");
	printf("[Distance] \n");
	printf("dist : %lf\n", dist = sqrt(pow(double(her.x*2), 2.0) + pow(double(her.y*2), 2.0)));
	printf("\n");
	printf("[Round and divide by 26]\n");
	printf("Rounded : %d\n", rounded = int(round(dist)));
	printf("Divided by 26 : %d\n", divided = (rounded % 26));
	printf("\n");
	printf("[Converted to lower case]\n");
	printf("Alphabet : %c\n", char(divided + 97));
	printf("\n");

	fclose(fp);

	return 0;
}

– 현재 위치 좌표 값 구하기

struct Pos {
	int x;
	int y;
};

x, y 좌표 값을 저장하기 위해 구조체를 사용했습니다.

struct Pos go(char *dir) {
	struct Pos cur = {0, 0};

	if(!strcmp(dir, "east")) {
		cur.x = -1;
	}
	else if(!strcmp(dir, "northeast")) {
		cur.x = -1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "north")) {
		cur.y = +1;
	}
	else if(!strcmp(dir, "northwest")) {
		cur.x = +1;
		cur.y = +1;
	}
	else if(!strcmp(dir, "west")) {
		cur.x = +1;
	}
	else if(!strcmp(dir, "southwest")) {
		cur.x = +1;
		cur.y = -1;
	}
	else if(!strcmp(dir, "south")) {
		cur.y = -1;
	}
	else if(!strcmp(dir, "southeast")) {
		cur.x = -1;
		cur.y = -1;
	}

	return cur;
}

각각의 방향에 따른 x, y 좌표 값을 리턴해주는 함수 입니다. 구조체를 반환합니다.

	fscanf(fp, "%d", &N); // number of footsteps
	for(int i=0; i<N; i++) {
		fscanf(fp, "%s", step);
		tmp = go(step);

		her.x += tmp.x;
		her.y += tmp.y;
	}

파일 첫 줄에 적혀있는 발자국 수만큼 반복문을 돌립니다. 지나왔던 방향만큼 엘라의 좌표 값에 더해줍니다.

	printf("[Her position] \n");
	printf("X : %d\n", her.x);
	printf("Y : %d\n", her.y);
	printf("\n");
	printf("[Original position] \n");
	printf("X : %d\n", -(her.x));
	printf("Y : %d\n", -(her.y));
	printf("\n");

그녀의 위치를 찾았으면, 원래 도착했어야 할 위치는 찾기 쉽습니다. x, y 의 방향만 바꿔주면 됩니다.

	printf("[Distance] \n");
	printf("dist : %lf\n", dist = sqrt(pow(double(her.x*2), 2.0) + pow(double(her.y*2), 2.0)));
	printf("\n");

두 점 사이의 거리를 구하는 공식은 다음과 같습니다 :

두 점 사이의 거리 (사진 출처)
sqrt()는 제곱근 함수이고, pow()는 거듭제곱 함수 입니다.

    printf("[Round and divide by 26]\n");
	printf("Rounded : %d\n", rounded = int(round(dist)));
	printf("Divided by 26 : %d\n", divided = (rounded % 26));
	printf("\n");

round()함수는 반올림 함수이고, 나머지를 구하기 위한 모듈러 연산을 하려면 ‘%’ 기호를 쓰면 됩니다.

	printf("[Converted to lower case]\n");
	printf("Alphabet : %c\n", char(divided + 97));
	printf("\n");

알파벳으로 바꿔주기 위해 방금 구한 나머지 값에 소문자 ‘a’에 해당하는 ASCII 값 97을 더해줍니다.


– flag

프로그램을 텍스트 파일의 개수만큼 12번 돌려보면 플래그를 찾을 수 있습니다 :

hsctf{garminesuckz}

▲top