쉽고 깔끔하게
[pwnable.kr] Toddler's Bottle 2번 collision 문제풀이 본문
문제
아빠가 오늘 멋진 MD5 해시 충돌에 대해 말씀해주셨어요.
저도 그런 거 하고 싶어요!
문제를 해결하기에 앞서,
• 해시함수 (Hash Function)
: 임의의 길이를 갖는 메시지를 입력으로 하여 고정된 길이의 해시값 또는 해시 코드라 불리는 값을 출력하는 일방향 함수
→ 메시지가 다르면 해시값도 다르다는 특징을 가지고 있음
• 해시 충돌 (Hash Collision)
: 2개의 다른 메시지가 같은 해시값을 갖는 것
→ 해시함수가 유한한 가짓수의 출력값을 생성하는 경우 해시 충돌이 발생함
터미널을 이용하여 ssh col@pwnable.kr -p2222에 접속합니다. (password : guest)
ls -l 명령어를 통해 현재 디렉터리에 존재하는 파일들의 정보를 확인합니다.
[ col ] 파일의 속성은 -r-sr-x---로 SetUID가 설정되어 있으며 실행 시 파일 소유자(col_pwn)의 권한으로 실행됩니다.
[ col.c ] 파일은 유일하게 제 3자(other)가 파일을 읽을 수 있는 권한(-rw-r--r--)을 가지고 있습니다.
[ flag ] 파일은 파일 소유자인 col_pwn만이 해당 파일을 읽을 수 있습니다.
▶︎ 따라서 SetUID가 설정된 [ col ] 파일이 실행되는 동안에는 [ flag ] 파일을 읽을 수 있습니다.
cat 명령어를 통해 [ col.c ] 파일의 내용을 확인합니다.
해당 코드를 살펴보면,
- Code 1
unsigned long hashcode = 0x21DD09EC;
hashcode를 0x21DD09EC로 정의하고 있습니다.
- Code 2
unsigned long check_password(const char* p) {
int* ip = (int*)p;
int i;
int res = 0;
for(i=0; i<5; i++) {
res += ip[i];
}
return res;
}
check_password라는 이름을 가진 사용자 함수를 따로 정의해줬습니다.
이 함수는 char*형으로 정의된 p를 int*형으로 변환시킨 뒤, 이를 4byte(int의 크기)씩 나눠 res에 더해줍니다.
- Code 3
if(argc<2) {
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
인자의 갯수가 2보다 작으면(argc<2) 'usage : argv[0] [passcode]'를 출력하고 프로그램을 종료합니다.
▶︎ 따라서, [ col ] 파일 실행 시 ./col 인자값 과 같은 형태로 실행해야 합니다.
- Code 4
if(strlen(argv[1]) != 20) {
printf("passcode length should be 20 bytes\n");
return 0;
}
strlen() 함수를 이용하여 argv[1] 인자값의 길이를 구한 뒤 20byte가 아니라면(!= 20) 'passcode length should be 20 bytes'를 출력하고 프로그램을 종료합니다.
- Code 5
if(hashcode == check_password( argv[1] )) {
system("/bin/cat flag");
return 0;
}
사용자에게 입력받은 인자값 argv[1]을 check_password 함수에 넣어 반환된 res 값을 hashcode인 0x21DD09EC과 비교합니다.
▶︎ 따라서 check_password 함수의 p값이 for문을 5번 돌아 hashcode의 값인 0x21DD09EC가 된다면 flag를 얻을 수 있습니다.
결과적으로,
code 3) [ col ] 파일 실행 시, ./col 인자값 형태로 실행하기
code 1, 2, 5) 인자값과 hashcode의 값이 일치해야 하므로 0x21DD09EC를 5로 나눈 값을 인자값으로 넘겨주기
- 0x21DD09E / 5
이에 0x21DD09EC를 5로 나눠주게 되면 0x6C5CEC8이라는 값이 나오게 됩니다.
- 0x21DD09EC - 0x21DD09E8
그러나, 0x6C5CEC8에 5를 곱해주게 되면 0x21DD09E8이라는 값이 나오면서 hachcode와 다른 값이 나오게 됩니다.
→ hachcode 값인 0x21DD09EC에 0x21DD09E8을 빼주게 되면 (0x21DD09EC - 0x21DD09E8) 0x4 차이가 난다는 것을 알 수 있습니다.
▶︎ 따라서, hachcode 값과 일치하는 값을 만들어 주기 위해 ⭐️0x6C5CEC8 * 4 + 0x6C5CECC 을 인자로 전달해줍니다.
<정답>
'Pwnable > pwnable.kr' 카테고리의 다른 글
[pwnable.kr] Toddler's Bottle 1번 fd 문제풀이 (0) | 2021.06.09 |
---|