넵
사실 ld.so의 주소를 leak하는거구요.
하지만 간격은 거의 같으니까요, 아니면 0x1000 단위로 브포해도 되구요.
ELF의 엔트리포인트의 스택을 보면 이렇습니다.
argc |
argv + envp 포인터들 |
auxv 키-값 배열 |
argv, envp 문자열 값 |
요렇습니다.
주목할 건 auxv입니다.
auxv는 Auxiliary Vectors의 줄임말이구요.
http://articles.manugarg.com/aboutelfauxiliaryvectors.html 보시면 됩니다.
나중에 보셔도 되여.
/proc/[PID]/auxv 파일을 xxd 파일로 보죠.
32비트 프로세스입니다.
bob_121@ubuntu:~$ xxd /proc/$$/auxv
0000000: 2000 0000 14d4 fdb7 2100 0000 00d0 fdb7 .......!.......
0000010: 1000 0000 fdfb 8b07 0600 0000 0010 0000 ................
0000020: 1100 0000 6400 0000 0300 0000 3480 0408 ....d.......4...
0000030: 0400 0000 2000 0000 0500 0000 0900 0000 .... ...........
0000040: 0700 0000 00e0 fdb7 0800 0000 0000 0000 ................
0000050: 0900 0000 9804 0608 0b00 0000 9a04 0000 ................
0000060: 0c00 0000 9a04 0000 0d00 0000 9a04 0000 ................
0000070: 0e00 0000 9a04 0000 1700 0000 0000 0000 ................
0000080: 1900 0000 5bfe ffbf 1f00 0000 f2ff ffbf ....[...........
0000090: 0f00 0000 6bfe ffbf 0000 0000 0000 0000 ....k...........
bob_121@ubuntu:~$
네. 형식은 이렇습니다.
[키 4바이트(32비트)] [값 4바이트(32비트)]
64비트는 키가 8바이트, 값이 8바이트입니다.
이걸 다시 정리해보도록 하죠.
bob_121@ubuntu:~$ LD_SHOW_AUXV=1 /proc/$$/exe
AT_SYSINFO: 0xb7fdd414
AT_SYSINFO_EHDR: 0xb7fdd000
AT_HWCAP: fpu de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2
AT_PAGESZ: 4096
AT_CLKTCK: 100
AT_PHDR: 0x8048034
AT_PHENT: 32
AT_PHNUM: 9
AT_BASE: 0xb7fde000
AT_FLAGS: 0x0
AT_ENTRY: 0x8060498
AT_UID: 1178
AT_EUID: 1178
AT_GID: 1178
AT_EGID: 1178
AT_SECURE: 0
AT_RANDOM: 0xbffff87b
AT_EXECFN: /proc/20318/exe
AT_PLATFORM: i686
건질게 많아보이죠? 저는 AT_BASE에 대해 포스팅을 할건데 사실 여기서 건질게 많아요.
일단 AT_RANDOM은 없는 환경도 있긴 한데 스택 카나리값이 있는 주소에요. 여기서 변형을 해서 첫바이트가 0이 된다던지 이런식으로 세팅을 많이 하죠. 이 값 자체가 아니라 이 값이 있는 주소에요.
AT_SYSINFO_EHDR은 vdso의 주소입니다. linux-gate.so.1 이라고 보통 부르죠.
여기 int 0x80 가젯들이 고정되어서 박혀있는 경우가 많아요.
그거 말고 PIE 환경에서 AT_PHDR과 AT_ENTRY값이 중요할 지 모르겠네요. 프로그램 정보가 담겨있으니까요.
네. LD_SHOW_AUXV 값이 1로 세팅되어있으면 이 값을 해석해서 보여줍니다. ld.so 기능이구요, 다른 유저의 suid, sgid 바이너리에서는 동작하지 않습니다.
이 부분을 보면 AT_BASE가 있습니다. 이건 ld.so의 베이스주소에요.
08048000-08125000 r-xp 00000000 fc:00 1572866 /bin/bash
...
b7fde000-b7ffe000 r-xp 00000000 fc:00 393219 /lib/i386-linux-gnu/ld-2.17.so
...
생략합니다.
ld.so랑 libc의 간격은 그렇게 많이 바뀌지 않고 (ld.so가 아주 크게 바뀌지 않으면 말이죠), 0x1000단위로 브포하면 되니 참 편합니다.
그래서 버전 상관없이 브포를 많이 안해도 되고, 간격이 많이 바뀌지도 않죠.
역시 exploit이죠.
한번 보겠습니다.
스택을 봅시다.
gdb를 켜고.
_start에 브포를 걸고(엔트리포인트) 실행합니다.
네, argc와 argv + envp 포인터들과 auxv 값들과 문자열값들이 보이는군요.
보시면 0xb7fde000이 있네요. ld.so 로딩된 주소가 어디였는지 보겠습니다.
ld.so의 로딩 주소는 0xb7fde000입니다. 같네요.
이상으로 마치겠습니다.
Thanks to 장석인님