[collision
Twenty input bytes are read as five ints and summed; any five values adding to 0x21DD09EC pass the check.
col.c. C 언어 코드를 둘러보자. 밑에 코드를 보면 가장 중요한 4개를 알수있다.
- 입력 길이는 정확히 20 bytes
- 입력 문자열을 int*로 캐스팅
- 4바이트씩 5개로 나눠서 더함
- 합이 0x21DD09EC이면 성공
즉, 입력은 20바이트 → 4바이트 × 5개
ip[0] + ip[1] + ip[2] + ip[3] + ip[4] = 0x21DD09EC
그럼 목표값을 계산해보자. 일단 10진수로 16진수를 바꿔준다. 0x21DD09EC = 568134124 (decimal). 그리고 코드대 로 //5 해준다.
part = target // 5
568134124 // 5 = 113626824
113626824 × 4 = 454507296
남은 값 = 113626828
따라서 113626824 113626824 113626824 113626824 113626828

여기서 중요한 사실은 리눅스 우분투는 리틀 엔디안을 사용한다는것이다. 파일 안만들어져서, 걍 파일없이 한줄로 실행하기로 했다. 즉, 4바이트 정수는 거꾸로 저장된다. 그 사실을 기억하고 코드 를 짜자. 참고로 파이썬 코드 파일이 따로 안만들어져서, 한줄로 바로 실행 시킬수있도록 했다.
./col ”$(python3 - <<‘PY’ import struct target = 0x21DD09EC part = target // 5 # target 값을 5개 int로 나누기 위해 균등 분배 # 5개 중 4개는 동일한 값으로 설정 payload = struct.pack(“<I”, part)4 # part 값을 4바이트 Little Endian unsigned int로 변환 # 이를 4번 반복하여 총 16바이트 생성 payload += struct.pack(“<I”, target - part4) # 앞에서 만든 4개의 합을 제외한 나머지 값을 계산 # 마지막 4바이트로 추가하여 총 20바이트 완성 import sys sys.stdout.buffer.write(payload) PY )” 그리고 실행 시켜보면.
