티스토리 뷰




[pwnable.kr] Toddler's Bottle - collision(3 pt) write-up



폰케알 collision 문제 입니다.


서버에 접속해보겠습니다.



ls명령으로 파일을 확인해보니,


실행파일 col, 코드 col.c, flag파일이 있네요.


코드를 확인해보겠습니다.


먼저, main함수부터 보겠습니다.


argc가 2아래 일 경우, 프로그램은 종료 됩니다.


또, argv[1]의 길이가 20바이트가 아닐 경우 종료됩니다.


따라서 입력은 argv[1] 의 문자열로 받겠군요.


그리고 해쉬코드인 0x21DD09EC와 check_password(argv[1])의 값을 비교해서 참일시 플래그가 출력됩니다.


그럼이제, check_password() 함수를 보겠습니다.


입력받은 argv[1]의 값을 가져오고 int*로 형변환을 해줍니다.


따라서, 포인터 배열이 됩니다.


왜냐하면 int* 는 4바이트이기 때문에 20바이트 크기인 문자열은 5등분 됩니다.


만약 A를 20개 입력했다면,


AAAA | AAAA | AAAA | AAAA | AAAA

ip[0]      ip[1]       ip[2]      ip[3]       ip[4]


이렇게 배열이 됩니다.


for문에서 이 5개의 값을 다 더해주고 res를 리턴해줍니다.


리턴해준 값이 hashcode와 같아야 하므로,


5개 다 더한 값이  0x21DD09EC 되야 합니다.



16진수는 계산하기 복잡하니, 10진수로 계산을 한 후 16진수로 바꾸겠습니다.


568134124를 5등분 하고 다 더해주면 됩니다.



그렇지만 소수점이 나옵니다.


정확히 5등분이 불가능하니,  A*4+B*1 로 해주면 되겠죠?


113626824 * 4 +  113626828 * 1 하면 되겠습니다.

113626824 | 113626824 | 113626824 | 113626824 | 113626828

    ip[0]              ip[1]               ip[2]            ip[3]             ip[4]

이 5개의 값들이 다 더해지면 hashcode와 일치할 것 같습니다.


지금은 10진수로 계산하였지만 payload를 짤 때에는 16진수로 계산해야 합니다.


먼저, 113626824는 0x06C5CEC8 이고, 113626828는 0x06C5CECC


리틀엔디안 형식으로 payload를 짜보겠습니다.


./col `python -c ‘print “\xc8\xce\xc5\x06”*4 + ”\xcc\xce\xc5\x06"'`


공격을 해보겠습니다.



플래그가 나옵니다.

Comments