공부 초기에 offset을 찾는 방법이 너무 헷갈렸다.
왜 /bin/sh 문자열의 offset은
strings -tx filename | grep /bin/sh
로 찾아지고
system 함수는
strings -tx filename | grep system
으로 찾아지긴 하지만 실제 offset과 왜 다른가?
요약하자면 그 이유는 "함수명"은 함수 초기에 무조건 나오는 것이 아니기 때문이다.
strings 명령어는 말 그대로 파일 내에 string을 찾아 출력해준다.
그 말인 즉슨, 파일 내에는 hex 값으로된 수 많은 데이터들이 있다.
이 값들 중 string으로 저장된 값들만 출력해주는 역할을 한다.
예를 들어보자.
/bin/sh는 파일 내에 문자열로 들어있을 것 같지만 실제로는 ascii code에 따라 hex 값으로 저장되어 있다.
즉, 2f62696e2f7368 와 같이 저장되어있다는 말이다.
하지만 system 함수는 어떠한가?
system 함수의 시작점이 과연 73797374656d 로 저장되어있을까?
아니다.
함수의 시작점은 문자열이 아닌 어셈블러 코드로 작성되어있을 것이다.
다시 한번 예를 들어보자.
/bin/sh는 문자열로 libc 파일 내에 존재한다.
┌──(kali㉿kali)-[~/Downloads]
└─$ strings -tx ./libc-2.27.so | grep /bin/sh
1b3e9a /bin/sh
그럼 코드 상에는 어떻게 존재할까?
아래와 같다.
┌──(kali㉿kali)-[~/Downloads]
└─$ gdb -q libc-2.27.so
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 10.1.90.20210103-git in 4.42ms using Python engine 3.10
Reading symbols from libc-2.27.so...
(No debugging symbols found in libc-2.27.so)
gef➤ grep /bin/sh
[*] No debugging session active
gef➤ x/x 0x1b3e9a
0x1b3e9a: 0x6e69622f
gef➤ x/s 0x1b3e9a
0x1b3e9a: "/bin/sh"
이번에는 system 함수를 보자.
system 함수를 strings로 찾아보면 아래와 같다.
┌──(kali㉿kali)-[~/Downloads]
└─$ strings -tx ./libc-2.27.so | grep system
14857 svcerr_systemerr
14b30 __libc_system
1b364d RPC: Remote system error
1b411c Interrupted system call
1b4279 Too many open files in system
1b42ee Read-only file system
1b4b4f Bad system call
1b4f48 system bytes = %10u
1b5939 /sys/devices/system/cpu
1b80e0 Interrupted system call should be restarted
1b8539 <system type="current" size="%zu"/>
1b855d <system type="max" size="%zu"/>
1b86bb <system type="current" size="%zu"/>
1b86df <system type="max" size="%zu"/>
1b9e38 /sys/devices/system/cpu/online
1ba6b0 Fatal error: gettimeofday system call failed
해당 위치가 system 함수의 시작점일까?
그렇지 않다.
┌──(kali㉿kali)-[~/Downloads]
└─$ gdb -q libc-2.27.so
GEF for linux ready, type `gef' to start, `gef config' to configure
90 commands loaded and 5 functions added for GDB 10.1.90.20210103-git in 4.42ms using Python engine 3.10
Reading symbols from libc-2.27.so...
(No debugging symbols found in libc-2.27.so)
gef➤ p system
$1 = {<text variable, no debug info>} 0x4f440 <system>
gef➤ x/10gx 0x4f440
0x4f440 <system>: 0xfa66e90b74ff8548 0x0000441f0f66ffff
0x4f450 <system+16>: 0x4800164a4b3d8d48 0xfffffa50e808ec83
0x4f460 <system+32>: 0xc48348c0940fc085 0x001f0fc3c0b60f08
gef➤ x/i 0x4f440
0x4f440 <system>: test %rdi,%rdi
위에서 보듯 system 함수의 시작점은 문자열이 아닌 test %rdi,%rdi 의 어셈블러 코드임을 알 수 있다.
그럼 strings 명령어에서 나온 저 값들은 무엇일까.
gef➤ p system
$1 = {<text variable, no debug info>} 0x4f440 <system>
gef➤ grep system
[*] No debugging session active
gef➤ x/x 0x14857
0x14857: 0x73
gef➤ x/s 0x14857
0x14857: "svcerr_systemerr"
위에서 보듯 system이라는 문자열이 저장된 주소이다.
이에 문자열은 strings 명령어로, 함수의 주소는 gdb 또는 objdump로 찾아야 한다.
다만, gdb로 함수의 시작점이 나오지 않는 경우가 다소 있다.
이 경우 objdump로 찾으면 쉽게 찾을 수 있다.
유의해야하는 점은, objdump로 찾은 주소는 해당 함수의 직접적인 주소가 아닌 경우가 있다.
출력된 값을 보면 offset이 적혀있으니 이를 유의해서 계산해야한다.
예를 들면 free_hook의 주소는 0x3eaee8이 아닌 0x3eaee8 - 0x2a00이다.
┌──(kali㉿kali)-[~/Downloads]
└─$ objdump -d ./libc-2.27.so | grep free_hook
objdump: Warning: Separate debug info file libc-2.27.so found, but CRC does not match - ignoring
objdump: Warning: Separate debug info file /home/kali/Downloads/libc-2.27.so found, but CRC does not match - ignoring
90da9: 48 8b 05 38 a1 35 00 mov 0x35a138(%rip),%rax # 3eaee8 <__free_hook@@GLIBC_2.2.5-0x2a00>
'Tips & theory' 카테고리의 다른 글
유용한 사이트 (0) | 2022.08.03 |
---|---|
patchelf 사용법. (0) | 2022.08.03 |
pwntools - elf, symbol을 가져올때 (0) | 2022.08.03 |
heap tcache poisoning & double free (0) | 2022.08.02 |
보호 기법 및 공격 시나리오 요약 (0) | 2022.08.01 |