Ret2win
기본 정보
Ret2win 도전 과제는 바이너리 공격을 포함하는 Capture The Flag (CTF) 대회에서 인기 있는 카테고리입니다. 목표는 주어진 바이너리의 취약점을 이용하여 바이너리 내의 특정하지 않은 함수를 실행하는 것입니다. 이 함수는 일반적으로 win
, flag
등으로 명명되며 실행되면 일반적으로 플래그나 성공 메시지를 출력합니다. 도전 과제는 주로 스택의 리턴 어드레스를 덮어쓰고 실행 흐름을 원하는 함수로 전환하는 것을 포함합니다. 예시를 통해 더 자세히 설명하겠습니다:
C 예시
취약점이 있는 간단한 C 프로그램과 호출할 win
함수가 있는 C 프로그램을 고려해보겠습니다:
이 프로그램을 스택 보호 기능 없이 컴파일하고 ASLR를 비활성화하려면 다음 명령을 사용할 수 있습니다:
-m32
: 프로그램을 32비트 바이너리로 컴파일합니다 (선택 사항이지만 CTF 도전 과제에서 일반적입니다).-fno-stack-protector
: 스택 오버플로우에 대한 보호 기능을 비활성화합니다.-z execstack
: 스택에서 코드 실행을 허용합니다.-no-pie
: 위치 독립 실행 파일을 비활성화하여win
함수의 주소가 변경되지 않도록 합니다.-o vulnerable
: 출력 파일의 이름을vulnerable
로 지정합니다.
Pwntools를 사용한 Python Exploit
해킹에는 pwntools를 사용할 것이며, 이는 해킹을 위한 강력한 CTF 프레임워크입니다. Exploit 스크립트는 버퍼 오버플로우를 유발하고 반환 주소를 win
함수의 주소로 덮어씁니다.
win
함수의 주소를 찾으려면 gdb, objdump, 또는 이진 파일을 검사할 수 있는 다른 도구를 사용할 수 있습니다. 예를 들어 objdump
를 사용하여 다음과 같이 할 수 있습니다:
이 명령은 win
함수의 어셈블리를 보여주며 시작 주소를 포함합니다.
Python 스크립트는 vulnerable_function
에서 처리될 때 정확히 조작된 메시지를 보내어 버퍼 오버플로우를 발생시키고 스택의 반환 주소를 win
의 주소로 덮어씁니다. vulnerable_function
이 반환될 때 main
으로 반환하거나 종료하는 대신 win
으로 이동하여 메시지가 출력됩니다.
보호 기능
PIE은 비활성화되어야 합니다. 그렇지 않으면 주소가 실행마다 신뢰할 수 없게 되어 함수가 저장될 주소가 항상 동일하지 않아서 win 함수가 로드된 위치를 파악하기 위해 일종의 leak이 필요합니다. 오버플로우를 일으키는 함수가
read
와 같은 경우, 반환 주소를 win 함수로 변경하기 위해 1 또는 2바이트의 부분 덮어쓰기를 수행할 수 있습니다. ASLR 작동 방식 때문에 마지막 세 개의 16진수는 무작위화되지 않으므로 올바른 반환 주소를 얻을 1/16 확률 (1개의 16진수)이 있습니다.Stack Canaries도 비활성화되어야 합니다. 그렇지 않으면 손상된 EIP 반환 주소가 결코 따라지지 않을 것입니다.
다른 예제 및 참고 자료
32비트, ASLR 없음
64비트, ASLR 있음, 바이너리 주소의 leak 포함
64비트, ASLR 없음
32비트, ASLR 없음, 더블 스몰 오버플로우, 스택 오버플로우 및 두 번째 오버플로우 크기 확장
32비트, relro, 캐너리 없음, nx, pie 없음, 주소
fflush
를 win 함수 (ret2win)으로 덮어쓰기 위한 형식 문자열32비트, nx, 그 외 아무것도 없음, EIP (1바이트)의 부분 덮어쓰기를 통해 win 함수를 호출
32비트, nx, 그 외 아무것도 없음, EIP (1바이트)의 부분 덮어쓰기를 통해 win 함수를 호출
프로그램은 입력의 크기를 확인하기 위해 숫자의 마지막 바이트만 유효성을 검사하므로 허용된 범위 내에서 마지막 바이트가 있는 한 어떤 크기도 추가할 수 있습니다. 그런 다음 입력은 ret2win으로 이용되는 버퍼 오버플로우를 생성합니다.
64비트, relro, 캐너리 없음, nx, pie. win 함수 (ret2win)를 호출하기 위한 부분 덮어쓰기
arm64, PIE, win 함수의 PIE leak은 실제로 2개의 함수이므로 2개의 함수를 호출하는 ROP 가젯
ARM64, off-by-one을 사용하여 win 함수를 호출합니다.
ARM64 예제
pageRet2win - arm64Last updated