strcpy를 통해 argv[1]를 buffer에 복사합니다.
strcpy의 함수 원형을 찾아보면 다음과 같습니다.
Overflow를 막기 위해서는 destination의 크기를 충분히 크게 만들어야 한다고 적혀있습니다.
strcpy는 destination과 source의 크기를 측정하지 않으므로 사용자가 악의적으로 Overflow를 유발할 수 있습니다.
Stack 구조
Low addr
buffer (256-byte) |
sfp (4-byte)
|
ret (4-byte)
|
High addr
stack에 변수가 저장되는 방식을 모르시면 다음 글을 읽고 오세요.
-> http://slimv.tistory.com/entry/Var-on-stack
Process가 종료될 때 ret에 저장되어있는 주소를 통해 return하게 됩니다.
그러므로 ret를 사용자가 원하는 주소로 덮어쓰게 되면 덮어써진 새 주소로 이동하게 됩니다.
Idea가 나왔습니다.
buffer보다 큰 값을 입력해 Buffer Overflow를 일으키면 됩니다.
현재 문제에서는 364-byte를 입력하게 되면 ret를 덮어쓰게 됩니다.
gdb를 통해 ret가 덮어써지는지 확인해보겠습니다.
gdb로 gremlin을 열어 실행하면 permission error가 출력됩니다.
소스코드가 있으니 임시로 새로운 파일을 컴파일하고 gdb로 실행 해봅니다.
ret가 0x42424242로 덮어써졌습니다. ('B'의 ASCII 코드 값 = 0x42)
이젠 shell code가 올라가는 주소를 찾아야 합니다.
argv[1]이 사용되는 strcpy 함수 주변을 찾아보겠습니다.
Parameter로 edx와 eax가 넘어가는 것을 확인할 수 있습니다.
main+46에 Break point를 걸고 edx를 확인해 보겠습니다.
우리가 입력한 'A' 260개와 "BBBB"가 보입니다. ('A'의 ASCII 코드 값 = 0x41, 'B'의 ASCII 코드 값 = 0x42)
입력값의 시작주소는 0xbffffb7f 입니다.
이제 buffer에 shell code를 넣고 해당 위치로 return하도록 주소값을 설정해주면 됩니다.
공격에 성공했습니다.