Post

(메모리 보호 기법) PIE

symbol 없을 때나 PIE가 걸려있을 때 디버깅

Entry point + offset으로 bp 걸면 되는데, offset은 IDA로 알아내고, Entry point는 0x00에 bp걸고 실행한 다음

  • 첫 번째 call에서 리턴되는 값( $rax )이 Enrty point
  • 또는 그냥 info file

Entry point == start 함수의 시작 지점 start는 첫 번째 argmain의 func ptr을 넘기면서 \_\_libc\_start\_main을 호출하므로, call 직전에 넘어가는 argmain이다.

Position-Independent Executables

바이너리에 PIE를 설정하려면 컴파일 시 다음 옵션을 준다.

1
2
gcc -fPIE -pie pie\_test.c -o pie -lpictest -L.

1
2
3
$ file pie
pie: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=70990b73da080686c4d70b5183dfda697f6b8cbd, not stripped

1
2
3
$ file no\_pie
no\_pie: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=e9a5d685c5a869428e583975e9bf9de035b3c7fe, not stripped

file 명령어로 확인해보면, PIE가 걸려있는 경우 실행 파일이어도 shared object로 출력된다.

실행하기 전 main disas

no_pie’s main

1
2
3
4
5
6
7
8
9
10
0x00000000004006dd <+0>:     push   rbp
0x00000000004006de <+1>:     mov    rbp,rsp
0x00000000004006e1 <+4>:     mov    eax,0x0
0x00000000004006e6 <+9>:     call   0x4005e0 <picTest@plt>
0x00000000004006eb <+14>:    mov    edi,0x400784
0x00000000004006f0 <+19>:    call   0x4005b0 <puts@plt>
0x00000000004006f5 <+24>:    mov    eax,0x0
0x00000000004006fa <+29>:    pop    rbp
0x00000000004006fb <+30>:    ret

pie’s main

1
2
3
4
5
6
7
8
9
10
0x0000000000000815 <+0>:     push   rbp
0x0000000000000816 <+1>:     mov    rbp,rsp
0x0000000000000819 <+4>:     mov    eax,0x0
0x000000000000081e <+9>:     call   0x6e0 <picTest@plt>
0x0000000000000823 <+14>:    lea    rdi,[rip+0x9a]        # 0x8c4
0x000000000000082a <+21>:    call   0x6b0 <puts@plt>
0x000000000000082f <+26>:    mov    eax,0x0
0x0000000000000834 <+31>:    pop    rbp
0x0000000000000835 <+32>:    ret

PIE가 걸려있는 경우 이렇게 모든 주소를 상대 주소, offset으로 접근한다. 뿐만 아니라 0x400000에 mapping되는 일반적인 바이너리와 달리 Image Base가 고정되어있지 않다. mapping 위치를 정해놓지 않는게 PIE니까. no\_pie의 경우 실행하면 저 주소 그대로 적재되지만, pie는 실행하면 그 때 Image Base가 결정되어 그 위치에 적재된다.

실행 후 main disas

no_pie’s main

1
2
3
4
5
0x4006dd <main>:     push   rbp
0x4006de <main+1>:   mov    rbp,rsp
=> 0x4006e1 <main+4>:   mov    eax,0x0
0x4006e6 <main+9>:   call   0x4005e0 <picTest@plt>

pie’s main

1
2
3
4
5
6
7
8
0x555555554815 <main>:       push   rbp
0x555555554816 <main+1>:     mov    rbp,rsp
=> 0x555555554819 <main+4>:     mov    eax,0x0
0x55555555481e <main+9>:     call   0x5555555546e0 <picTest@plt>
0x555555554823 <main+14>:    lea    rdi,[rip+0x9a]        # 0x5555555548c4
0x55555555482a <main+21>:    call   0x5555555546b0 <puts@plt>
0x55555555482f <main+26>:    mov    eax,0x0

This post is licensed under CC BY 4.0 by the author.