2023. 9. 23. 20:17ㆍ포너블
오늘은 저번 시간에 했던 rop_x32에 이어서 rop_x64문제 풀이를 진행하고자 한다. rop_x64는 64비트로 컴파일된 바이너리 파일이다.
먼저 어떤 보호기법이 걸려져 있는 지 살펴보겠다. Partial RELO는 5섹션에 대해 쓰기가 불가능하지만 .got.plt, .bss, .data영역에 대한 got 덮어쓰기가 가능하다. NX비트가 활성화되어 스택에서 쉘코드가 실행이 안된다. pie는 안걸려져 있음으로 바이너리 주소가 랜덤화하게 바뀌진 않는다.
먼저 바이너리 파일을 실행시키기 전 소스코드를 살펴보겠다. 소스코드를 보면 buf값이 0x40으로 지정되어 있는데 read함수에서 0x400만큼 입력받음으로써 버퍼오버플로우 취약점이 발생한다. 따라서 이 버퍼오버플로우 취약점을 활용해서 rop로 연계할 수 있다.
먼저 필요한 가젯부터 구해보겠다. pop rdi, read_plt, read_got, puts_plt, write_got, main, ret가젯 주소를 구했다. 참고로 64비트는 함수에 인자 값을 넣어줄때 스택이 아닌 레지스터를 우선으로 활용하게 된다. rdi, rsi, rdx, rcx, r9, r8레지스터가 인자 값으로 전달된다.
pop rdi가젯은 위 사진과 같이 구할 수 있다.
buf부터 ret주소까지의 거리는 0x48이다.
payload를 구성해보면 다음 위 사진과 같다. '\x90'으로 48만큼 ret주소 전까지 채워주고 pop rdi가젯으로 read_got를 넣어주고 puts_plt로 read_got를 출력하게 된다. 이후 다시 메인 주소로 리턴해줘서 system의 실제 주소를 구해서 페이로드를 재구성할 수 있다.
p.recv(40)으로 write sizeof(buf)만큼 받은 다음 read@got주소를 구해주고 leak된 주소를 read offset을 빼준 뒤 나온 베이스 주소를 이용해서 system함수의 실제 주소를 구해준다. 이후 libc에서 /bin/sh를 찾고 base를 더해주면 실제 주소가 된다.
다시 리턴주소까지 0x48만큼의 크기를 채워주고 ret가젯을 이용해서 스택 정렬을 맞춰준 뒤 pop rdi 가젯으로 binsh를 넣어주고 system함수로 리턴해주면 쉘을 획득할 수 있다.
전체적인 코드는 아래와 같다.
'포너블' 카테고리의 다른 글
format string bug 32bit (0) | 2023.09.30 |
---|---|
Dreamhack - oneshot (0) | 2023.09.24 |
Dreamhack - basic_rop_x86 (0) | 2023.09.16 |
Plaid CTF ropasaurusrex (0) | 2023.09.16 |
[dreamhack] basic_exploitation_000 (0) | 2023.09.04 |