1 분 소요

1. 문제

ssh col@pwanble.kr -p2222 로 접속 후 디렉토리를 보자.
col.c, col, flag를 확인할 수 있다.

collision

이제 col.c의 소스 코드를 보도록 하자.

col.c

argc가 2 이상, 즉 프로그램이 입력받는 인자가 1개 이상이어야 한다는 것이 첫 번째 조건이다.
두 번째 조건은 프로그램의 첫 번째 인자의 길이가 20이어야 한다.
세 번째 조건은 hashcode 값과 check_password의 반환값이 같아야 한다.
세 번째 조건을 통과하면 플래그가 출력되도록 되어 있다.

2. check_password

우선 파라미터로 char 포인터를 받는다.
이후 이 포인터를 int 포인터로 형변환하고 해당 주소부터 총 5회동안 주소에 있는 값을 res에 더하고 res를 반환한다.
main 함수에서 사용되는 것을 보면 argv[1], 즉 프로그램의 첫 번째 인자가 이 함수의 파라미터로 들어온다.
그리고 argv[1]은 길이가 총 20인 문자열이다.
이제 이것이 무엇을 의미하는지 알아보자.

이 함수는 char 포인터를 int 포인터로 변환한다고 했다.
char 포인터는 1바이트의 크기를 가지며, int 포인터는 4바이트의 크기를 가진다.
따라서 int 포인터의 주소로부터 값을 읽어 더하며 이 것을 5번 반복한다는 것은
20바이트 크기의 문자열을 4바이트 씩 끊어 5번 동안 더한다는 의미가 된다.

3. hashcode

hashcode는 0x21DD09EC 라는 16진수 값을 가진다.
check_password 함수의 반환값이 이것과 같아지기 위해서는 어떻게 해야 할까?
위에서 설명한대로 입력한 20바이트 문자열을 int형으로 변환되어 4바이트씩 끊어 더해진다.
그렇다면 hashcode 값을 5로 나누어 보자.
몫은 0x6C5CEC8, 나머지는 4가 된다.
그럼 이제 풀이를 작성해 보자.

4. 풀이

0x6C5CEC8 4번, 0x6C5CEC8+4(0x6C5CECC) 1번을 더하면 hashcode 값과 같아진다. 그렇다면 우리는 프로그램의 첫 번째 인자로 이 값들을 넣어주면 된다.
하지만 그냥 무턱대고 넣으면 안된다. 리눅스의 경우 주소를 저장할 때 little endian 이라는 방식으로 저장하기 때문에 해당 방식을 이용해야 한다.
little endian은 뒤에서부터 두 자리씩 끊어 적으면 된다.

즉 넣어주어야 할 입력은 \xC8\xCE\xC5\x06 4번, \xCC\xCE\xC5\x06 1번이다.

파이썬을 이용해 입력을 넣어주면 아래와 같다.

flag

flag가 출력된 것을 확인할 수 있다.

카테고리:

업데이트: