passcode : new attacker
(NO DRAG, NO PASSCODE)
이 문제도 역시 RTL을 사용하는 문제인 것 같다. darkknight 문제와는 다르게 execve 함수를 이용해야 하는 것 같다. 코드에서 ret != execve_addr 이므로 RET을, 즉 argv[1][44]를 execve 함수로 덮어주어야 한다.
여기서 execve 함수는 다음과 같이 사용한다.
- execve(const char *filename, char *const argv[], char *const envp[])
payload를 어떻게 구성할지 생각해보자.
- 우선 main의 RET은 execve의 주소로 덮는다.
- execve의 RET은 system의 주소로 덮는다.
- system 함수는 ebp + 8, 즉 ret + 4 영역에 있는 문자열을 명령어로 판단하여 실행하게 되므로 system 함수의 ebp + 8은 "/bin/sh" 문자열의 주소로 덮는다.
- 이렇게 되면 system 함수의 ebp + 4는 비어 있으므로 그냥 dummy 값으로 채워주자.
이렇게 구성하게 되면 execve 함수가 실행되고, system 함수가 "/bin/sh" 문자열을 인자로 쉘을 실행시킬 것이다. main 함수 종료 직후에는 다음과 같은 메모리 구조를 갖는다.
먼저 exevce 함수의 주소를 구하자. 여기서 문제의 의도는 offset을 이용하여 execve 의 주소를 구하도록 유도하는 것 같다.
이렇게 소스코드에 나와 있는대로 입력하면 execve_offset과 lib_addr의 값을 구할 수 있다. 이 둘을 더한 값인 0x40018000 + 0x91d48 = 0x400a9d48 이 execve의 주소가 된다. 하지만 gdb에서 더욱 쉽게 구할 수 있다. 다른 함수들과 문자열의 주소도 다 구해보자.
execve → 0x400a9d48 (offset으로 구한 값과 일치)
system → 0x40058ae0
/bin/sh → 0x400fbff9
이제 이를 이용하여 payload를 구성하여 exploit 하자. 이때 "\x0a"를 "\x00"으로 인식하기 때문에 문자열이라는 것을 알려주는 double quotes("")로 묶어주어야 한다.
[giant] : one step closer
'Pwnable > LOB' 카테고리의 다른 글
[LOB] 15. ASSASSIN (0) | 2020.08.28 |
---|---|
[LOB] 14. GIANT (0) | 2020.08.28 |
[LOB] 12. DARKKNIGHT (0) | 2020.08.28 |
[LOB] 11. GOLEM (0) | 2020.08.28 |
[LOB] 10. SKELETON (0) | 2020.08.28 |