쓰기 권한으로 파일 복사하기

원래 읽기 권한이 있어야 파일 복사가 가능하도록 되어있지만, 실행 권한이 있는 경우 읽기 권한이 없어도 ptrace를 이용해 파일을 복사하여 내 소유 파일로 얻어낼 수 있다.

파일을 실행하게 되면 해당 파일이 메모리에 적재된다는 점을 이용하여, ptrace로 프로세스의 가상메모리 공간 중 실행한 파일이 매핑된 공간에 접근해서 데이터를 추출해 파일에 쓴다.

이렇게 얻어낸 파일은 원본 파일과 동일하게 동작하며, 얻어낸 파일에 gdb, strings 등을 사용할 수 있기 때문에 유용하게 활용할 수 있다.

* 얻어낸 파일이 원본 파일과 완전히 동일하지는 않다.

file 명령어 등을 이용해 속성을 확인해보면 손상된 것으로(stripped) 나온다. 

readelf : 섹션 안나옴, objdump : 안됨, nm -D : 심볼 없는 것으로 나옴.

gdb도 마찬가지로 symbol을 찾을 수 없다고 나온다. 그러나 직접 메모리 주소에 접근해서 bp걸고 디버깅하는 것은 가능하다.


excp


실행 권한 파일 복사 프로그램. 다음과 같이 동작한다.

fork, exec를 이용해 복사하고 싶은 프로그램을 child로 실행한 다음, procfs로 프로세스에서 실행한 파일이 매핑된 주소를 구하고, ptrace를 이용해 이 주소의 데이터를 읽어 파일에 쓴다.

fork 후 child에서 ``c ptrace(PTRACE_TRACEME, ...)``를 호출해 주어야 kernel이 exec를 수행하다 child에게 SIGTRAP을 보내게 된다.

fork 후 parent에서 wait()를 호출하면 parent는 child의 종료 또는 상태변화를 기다리며 대기하게 된다.

child가 SIGTRAP을 받으면 wait하던 parent가 재개된다.

2016/12/27 - [Coding] - fork - exec / wait


usage

```bash

excp SRC DST [-o|-m]

```

`` -o`` 옵션을 주면 구식OS로 간주하고 `` addr2start``에 더했던 `` 0x1000``을 다시 뺀다.

`` -m`` 옵션을 주면 직접 복사할 주소를 입력할 수 있다.


-o option

구식 OS :

  • r--p section이 없다.

  • 타인이 실행한 프로세스의 proc maps에도 접근이 가능하다.

  • r 권한이 없어도 proc maps에 접근이 가능하다.


최근 OS :

  • r--p section이 존재한다.
  • 타인이 실행한 프로세스일 경우 proc maps에 접근할 수 없다.
  • 내가 실행한 프로세스여도 r 권한이 없으면 proc maps에 접근할 수 없다.


뭐가 문제인지는 정확히 모르겠으나 최근 OS의 경우 r--p section까지 복사하면 Segmentation fault가 난다.


fgets로 2번째 line을 읽고, r--p이면 line을 한번 더 가져와 rw-p line의 주소를 얻으려고 했으나 프로세스 실행 직후에는 최근 OS도 구식 OS처럼 r--p section이 따로 없고 rw-p section에 포함되어 있기 때문에 다음 line을 가져오는 것이 의미가 없다.


그래서 그냥 두번째 line에서 얻은 addr2start에 0x1000을 더한 곳을 rw-p section으로 간주했다.

r--p section 크기가 항상 0x1000라고 장담할 수는 없지만, 대체로 이 크기인 듯 싶다.


* 그리고 어차피 최근 OS는 r 권한 없으면 proc maps도 접근 불가하기 때문에 address를 유추해서 넣어줘야 한다.


-m option

Ubuntu 16.04에서는, 내가 실행한 파일이더라도 r 권한이 없으면 `` /proc/<pid>/maps`` 파일을 읽을 수 없다.

또는 타인의 권한으로 실행된 프로세스에 대해서도 읽을 수 없도록 되어있다. ( 그래서 setUID가 걸려있는 경우 읽을 수 없다. )


그러나 r-xp section의 시작지점이 대체로 0x08048000 이라는 점과

memory allocation은 page 단위로 이루어 진다는 점을 통해서 memory mapping address를 유추할 수 있다.


  1. 마지막 rw-p section이 끝나는 주소는 
    ``c 0x08048000 + ( filesize || filesize + 0x1000 || filesize + 0x2000 )``
    으로 추정할 수 있다. (file size는 page size 단위로 올림해야 한다.)
  2. r--p section의 크기는 0x1000이다.
즉, r-xp section이 어디서 끝나는지만 결정하면, rw-p section의 범위는 자동으로 결정된다.
r-xp section이 끝나는 주소를 정확히 알 수는 없지만, rw-p section의 크기도 0x1000인 경우가 대부분인 듯.
이게 안될경우, -m옵션을 주면 직접 복사할 주소를 입력할 수 있다.
* 왜 ``c 0x08048000 +filesize + 0x2000``이 최대 크기냐면, 각 section의 최소 크기가 `` 0x1000``이기 때문이다.
filesize가 0x1555이고 r-xp section에 0x1001, rw-p section에 0x0554 만큼이 할당되어야 한다고 하면
page 단위로 할당되므로 
r-xp section은 0x2000,
r--p section은 0x1000,
rw-p section은 0x1000 의 크기를 가지게 된다.

filesize를 page 단위로 반올림해도 0x2000이니까, 0x2000만큼을 더 더해줘야 rw-p section이 끝나는 주소가 된다.
그러나 filesize에 0x2000을 더해야 하는 경우는 아직 보지못했고, 대부분 filesize 또는 filesize + 0x1000 이다.

참고

박찬암님의 hktrace



'OS > LINUX & UNIX' 카테고리의 다른 글

[Ubuntu] 초기 설정 / 업데이트  (0) 2016.12.25
ptrace  (0) 2016.12.25
.s 파일 수정  (0) 2016.12.10
GOT( Global Offset Table ) Layout과 link_map structure  (0) 2016.12.09
[Linux] Memory Layout, Segment + Kernel  (0) 2016.11.21