문제의 c 소스 코드입니다.
ioManager라는 구조체가 생성됩니다.
문자형 배열 buf와
문자열 포인터를 인자로 가지는 함수 포인터 printer를 가지고 있습니다.
vuln() 함수에서 ioManager 구조체 변수 io를 선언합니다.
무한루프 안에는
메뉴를 보여주는 printMenu() 함수가 실행되고
변수 choice에 양의 정수를 입력 받아 각 번호에 맞는 기능을 수행합니다.
1번 기능은 io의 buf에 적힌 문자열을 출력해줍니다.
2번 기능은 io의 buf에 문자열을 적을 수 있습니다.
그 외 나머지 값이 입력되면 무한루프를 빠져나갑니다.
보호 기법을 확인해줍니다.
카나리가 설정되어 있는 것 외에 특별한 건 설정되어 있지 않습니다.
gdb로 vuln() 함수를 디스어셈블 해봅니다.
<vuln+160>을 보면 버퍼의 주소가 rbp-0x110임을 알 수 있습니다.
구조체 멤버들은 배열처럼 연결되어 있으므로
buf의 크기 0x100 이후 0x8에 printer가 저장이 될 겁니다.
<vlun+202>를 보면 rbp-0x8에 스택 카나리가 저장되어 있음을 알 수 있습니다.
위 정보를 토대로 스택 프레임 구조를 시각화해보면 아래와 같습니다.
_______________
buf(0x100)
_______________
printer(0x8)
_______________
canary(0x8)
_______________
rbp(0x8)
_______________
ret(0x8)
_______________
printer의 주소는 소스 코드에서 printer() 함수로 지정해주지만
2번 기능의 scanf() 함수에서 입력 값에 대한 길이 제한이 없어 printer의 주소를 변조할 수 있습니다.
셸을 획득하기 위해 win() 함수를 사용합니다.
win() 함수에 인자로 "/bin/sh"을 지정해줘야 합니다.
이 때, 1번 기능을 활용할 수 있습니다.
2번 기능으로 printer에 win() 함수 주소를 저장한 뒤
buf에 "/bin/sh" 문자열을 저장하고
1번 기능을 실행하면 win() 함수의 인자로 io의 buf가 인자로 지정되어서
system("/bin/sh")이 실행될 수 있습니다.
위 정보를 토대로 익스플로잇 코드를 작성합니다.
먼저 2번 기능으로 함수 포인터의 주소를 win() 함수로 바꿔준 뒤
다시 2번 기능을 사용해 버퍼에 "/bin/sh" 문자열을 넣어준 뒤
1번 기능을 실행시킵니다.
실행해주면 셸을 획득하고 플래그가 나왔습니다..!
'write-up(pwn) > G04T' 카테고리의 다른 글
[G04T] Simple FSB 3 (0) | 2022.09.08 |
---|---|
[G04T] Simple FSB 1 (0) | 2022.09.07 |
[G04T] Simple FSB 2 (0) | 2022.09.06 |
[G04T] Simple BOF 2 (0) | 2022.09.05 |
[G04T] Simple BOF 1 (0) | 2022.09.05 |