728x90
이번 포스트에서는 Pwnable의 collision 문제에 대해 다루겠다.
문제 코드는 다음과 같다.
#include <stdio.h>
#include <string.h>
unsigned long hashcode = 0x21DD09EC;
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;
}
int main(int argc, char* argv[]){
if(argc<2){
printf("usage : %s [passcode]\n", argv[0]);
return 0;
}
if(strlen(argv[1]) != 20){
printf("passcode length should be 20 bytes\n");
return 0;
}
if(hashcode == check_password( argv[1] )){
system("/bin/cat flag");
return 0;
}
else
printf("wrong passcode.\n");
return 0;
}
## 문제 해석 :
문제 코드를 살펴 보니, 우리가 기입한 첫 번째 argv가 check_password() 함수의 인자가 되어 hashcode와 비교한다.
만약 hashcode와 같다면 Flag를 획득할 수 있는 것으로 보인다.
## 문제 풀이 :
그럼 hashcode와 같은 argument를 전송해야 하는데 여기서 argument의 길이 제한이 20으로 되어있다.
또한 check_password() 함수는 우리가 입력한 값을 4바이트씩 잘라서 더한 값을 반환한다.
먼저 파이썬을 통해 제시된 hashcode가 5로 나눴을 때의 값과 그 값들의 합이 hashcode와 같은지를 확인해보겠다.
Python 2.7.12 (default, Mar 1 2021, 11:38:31)
[GCC 5.4.0 20160609] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> hashcode = 0x21DD09EC
>>> hex(hashcode/5) # 5로 나누었을 때의 값
'0x6c5cec8'
>>> hex(hashcode%5) # 5로 나누었을 때의 나머지
'0x4'
>>> hex(hashcode/5+hashcode%5) # 5로 나누어 떨어졌을 때의 마지막 값(나머지 포함)
'0x6c5cecc'
>>> hex(hashcode/5*4+hashcode/5+hashcode%5) # 모든 값의 합 (초기 hashcode와 같다)
'0x21dd09ec'
값이 정확히 똑같다는 것을 알 수 있다.
## 최종 결과 :
Flag = daddy! I just managed to create a hash collision :)
'Wargame > Pwnable' 카테고리의 다른 글
Pwnable (6. random) (0) | 2022.07.04 |
---|---|
Pwnable (5. passcode) (0) | 2022.07.03 |
Pwnable (4. flag) (0) | 2022.07.02 |
Pwnable (3. bof) (0) | 2022.06.22 |
Pwnable (1. fd) (0) | 2022.06.18 |