접근
- 동일한 방식으로 ssh로 접근 후 문제 풀이가 시작된다.
- flag를 실행시켜 flag 실행파일이 출력하는 값을 문제의 답으로 입력한다.
- 그 과정에서 col.c를 통해 flag 실행파일을 시작시킬 수 있음을 확인하였다.
코드 분석 (col.c)
- 핵심은 세번째 if 문이라 생각한다.
- hashcode와 check_password 함수가 반환한 값이 같을 경우 flag 실행파일을 실행시킬 수 있다.
core function 분석 (func: check_password)
- input으로 main의 실행 파일 첫번째 인자를 받아 실행시킨다.
- 그 후 char * 의 주소값이 (int * )으로 캐스팅 되고, 그 주소값이 ip 포인터 변수로 할당된다.
- 이후 int 형 변수인 res에 ip배열로 접근할 수 있는 값을 for문을 통해서 누적시키고 누적된 값을 반환시킨다.
- 반환된 값이 hashcode와 같으면 문제가 해결된다.
for문을 반복시키면서 ip의 값들을 누적시키는 과정이 핵심이다.
- 5번을 반복시켜서 res 변수에 누적된 값이 0x21DD09EC와 같아야한다.
type casting
이 되는 과정에서 계속 혼동하고 있던 개념이 있었다.- char(1byte)를 int(4byte)로 접근하게 되면 메모리구조로써 해당되는 저장된 값이 순차적으로 4byte씩 분해되어 메모리에 저장되는 것이 아니다.
- 또한 메모리에 저장된다고해도, 해당 문제를 푸는 서버만의 특별 조취가 필요하다.
- 그냥 단순하게 char형 사이즈를 4byte로 5번씩 나누어 res 변수에 저장된다.
- 계속 인덱싱으로 접근을 통해, char 형으로 저장되어있는 메모리 구조에서, int형으로 포인터 변수로 인덱싱이 바뀐다면 int형 포인터로 접근하게되는 값들이, 메모리로 접근할 수 있는 값으로 어떻게 할당이 되어야하는가.. 이 부분에 대한 이해가 부족하였다.
해결
- 단순히 5번이 나눠진 것이라 생각하면 해결과정의 아이디어는 어렵지 않다.
- 5번 누적시키니, 해당값으로 만들기위한 실행파일의 인자값을 적절히 설정해주면 된다.
- target value가 char형인 0x21DD09EC이다.
- 나머지가 있을 것이라 확신한다. (물론 다시풀면서 미리 알았지만) C로 끝나는 16진수의 값이 5로 나눠떨어지지 않는다고 생각한다.
- 나머지 4가 남는다는 것을 확인하였고, 인자로 넘겨줘야할 값은 0x6c5cec8 * 4 + 0x6c5cecc 인것을 알 수 있다.
- 그럼 이 값을 어떻게 col 실행파일의 인자로 넘겨줄 수 있을지가 관건이다.
python -c 의 활용
- 나는 개인적으로 $( ) 명령어를 선호하기에 해당 쉘 안에 python -c 로 코드를 집어넣는 방식으로 문제 해결을 구성하였다. (직관적인걸 선호한다)
- python의 print문을 통하여 원하는 연산이 수행된 값을 실행파일의 인자로 넘겨줄 수 있을 것이라 생각한다.
- 또한 해당 테크닉은 이해보단 외우는 방향으로 가이드를 받았기에 시스템 해킹을 하는 과정에서 계산된 값을 주기위해서는 쉘 안에, 쓰고자 하는 명령어를 쓰기위해서는 큰따옴표(“) 안에 명령어를 써야하고, 해당 명령어의 인자를 설정하기 위해서는 작은따옴표(‘)를 실행해야 한다.
- 이때 궁금한게 너무 많았다. “(큰따옴표)안에 파이썬 문법이 들어갈텐데, 그 문법이 python2 대에서 쓰는 문법이었기 때문이다. 검색결과, python의 c flag의 특성이다
First Try:
./col $(python -c "print 'hex(0x6c5cec8*4)+hex(0x6c5cecc)'")
- 20byte가 안된다는 피드백을 받을 수 있었다.
- 파이썬 코드를 실행시켜보니,잘못된 방향으로 또 진행하고 있음을 알고 있었다. 과연 hex라는 python api의 역할을 알고 쓴게 맞는지 다시 고찰해보았고, hex api는 해당 인자값을 16진수로 바꿔주는 도구이다.(즉 당연히 오류가 나는 것이다.)
- 다음 방향으론 일단 python shell에서 hash_code를 만들고 실행파일의 인자로 주자는 생각을 하였다.
Second Try:
- 인자 값이 0x6c5cec8 을 잘 활용해서 hashcode와 같은 값이 되어야한다., 즉 python shell을 통해서 hashcode를 만들어야만 한다.
- 잘못썻던 hex api를 지우고 진행하였지만, python 자체의 출력이 될때 str으로 출력이 될텐데 그 과정에서 16진수가 10진수로 자동 변환이 되는 것으로 보였댜.
- int api는 python에서 10진수로 변환해주는 도구이다.), 두 값이 같은 것을 확인하고 print되는 과정중에 python 문법에서는 10진수로 자동 변환되는 것을 알 수 있었다.
- 그렇다면 정말 어떻게 16진수를 그대로 줘야할까?
Third Try:
- 이때 공부한 것이 메모리의 Little Endian과 python의 print에 대한 명령어이다.
- 인자로 쉘에서 출력되는 값을 줄것이기에 $()안에 내가 원하는 print 명령어에대한 값을 작성시켜준다.
- 그 이후 내부에 인자로 주고자 하는 값을 little-endian으로 설정하여 값을 전달시킨다.
고찰
- 1번을 쉽게 풀었다고 너무 만만하게 2번을 본 것 같다.
- 메모리 구조에 대한 이해, 및 각 변수형에 맞는 할당크기등 기초에 대한 추가적인 학습을 진행해야 한다.\
- mac의 zsh에서 붙으니까 똑같은 명령어일지라도 실행이 안되었다. 웬만하면 window에서 문제를 풀어야겠다.
- 문제를 해결해보니, $()내부의 작은따옴표랑 큰따옴표의 순서에대한 이용은 상관없는 것같다. 대신 os가 알 수 있도록 해당 인자들에 대한 구분은 확실하게 해줘야한다고 생각한다.