2016-06-16 2 views
1

uprobe tracer에 대한 설명서를 읽고 있으며 메모리에서 함수의 오프셋을 계산하는 방법에 대한 지침이 있습니다. 나는 그것을 여기서 인용하고있다.메모리에서 함수의 오프셋 계산

다음 예제는 프로빙 된 텍스트 주소에 % 레지스터를 덤프하는 방법을 보여줍니다./빈/zsh을 프로브에 zfree 기능 :

# cd /sys/kernel/debug/tracing/ 
# cat /proc/`pgrep zsh`/maps | grep /bin/zsh | grep r-xp 
00400000-0048a000 r-xp 00000000 08:03 130904 /bin/zsh 
# objdump -T /bin/zsh | grep -w zfree 
0000000000446420 g DF .text 0000000000000012 Base  zfree 

0x46420는 0x00400000에로드 객체/빈/zsh을 zfree에서 오프셋된다.

왜 그런지는 모르겠지만 출력은 0x446420이고 0x46420은 0x464000을 뺍니다. 그것은 나에게 오류로 이어졌다. 왜 0x400000입니까?

4.5.6-200 커널을 사용하여 Fedora 23에서도 동일한 작업을 수행하려고했습니다.

먼저 나는 바이너리가 메모리에 어디

$ cat /proc/`pgrep zsh`/maps | grep /bin/zsh | grep r-xp 
555555554000-55555560f000 r-xp 00000000 fd:00 2387155     /usr/bin/zsh 

오프셋

[email protected]:~ $ objdump -T /bin/zsh | grep -w zfree 
000000000005dc90 g DF .text 0000000000000012 Base  zfree 

툭 알아 낸 다음

echo 0 > /proc/sys/kernel/randomize_va_space 

메모리 주소 랜덤를 끄고 zfree가 어디 있는지 알아 냈어 gdb를 통해

$ gdb -p 21067 --batch -ex 'p zfree' 
$1 = {<text variable, no debug info>} 0x5555555b1c90 <zfree> 

[email protected]:~ $ python 
Python 2.7.11 (default, Mar 31 2016, 20:46:51) 
[GCC 5.3.1 20151207 (Red Hat 5.3.1-2)] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> hex(0x5555555b1c90-0x555555554000) 
'0x5dc90' 

당신은 아무 것도 빼지 않고 objdump와 같은 결과를 얻었습니다.

그런데 SLES를 사용하는 다른 컴퓨터에서 동일한 시도를했는데 거기에는 상향식 설명서와 동일합니다.

왜 이러한 차이가 있습니까? 올바른 오프셋을 어떻게 계산합니까?

+0

doc은 0x00400000에로드 된 object/bin/zsh에 있습니다. 오프셋은 아마도 프로그램로드 주소와 관련이 있기 때문에 함수의 절대 주소에서 프로그램로드 주소를 빼야합니다. – dbrank0

+1

많은 시스템의 기본 주소가 0x400000 인 이유는 - [리눅스 바이너리의 가상 메모리 주소가 0x8048000에서 시작하는 이유] (http://stackoverflow.com/questions/2966426)를 참조하십시오. Fedora 23은'-fPIC -shared'를 사용하여 패키지를 빌드하므로로드 오프셋은 0이고 기본 주소는 무작위 (ASLR 포함) 또는 0x555555554000입니다. –

답변

1

필자는 차이점은 바이너리 검사 방법에 의해서만 발생한다는 것을 알 수 있습니다. ELF에로드 주소가 고정되어 있는지 여부가보다 정확하게 말합니다. 간단한 실험을 할 수 있습니다. 우리는 간단한 테스트 코드가 있습니다 그리고

int main(void) { return 0; } 

을 두 가지 방법으로 그것을 만들기 : 이제

$ gcc -o t1 t.c  # create image with fixed load address 
$ gcc -o t2 t.c -pie # create load-base independent image 

을,이 두 가지 이미지를 확인 부하 기본 주소를 할 수 있습니다 :

$ readelf -l --wide t1 | grep LOAD 
    LOAD   0x000000 0x0000000000400000 0x0000000000400000 0x00067c 0x00067c R E 0x200000 
    LOAD   0x000680 0x0000000000600680 0x0000000000600680 0x000228 0x000230 RW 0x200000 
$ readelf -l --wide t2 | grep LOAD 
    LOAD   0x000000 0x0000000000000000 0x0000000000000000 0x0008cc 0x0008cc R E 0x200000 
    LOAD   0x0008d0 0x00000000002008d0 0x00000000002008d0 0x000250 0x000258 RW 0x2000 

여기 있습니다 첫 번째 이미지에는 고정로드 주소 -이 필요하고 두 번째 이미지에는 주소 요구 사항이 전혀 없음을 참조하십시오.

그리고 지금 우리가 objdump가 알 수 있다는 주소를 비교할 수는 약 main :

우리가 보듯이
$ objdump -t t1 | grep ' main' 
00000000004004b6 g  F .text 000000000000000b    main 
$ objdump -t t2 | grep ' main' 
0000000000000710 g  F .text 000000000000000b    main 

이 주소는 이미지가 주소에로드되는 경우 main의 첫 번째 바이트에 저장 차지할 완전한 가상 주소입니다 프로그램 헤더.물론 두 번째 이미지는 0x0에로드되지 않고 임의의 위치에서 다른 위치에로드되므로 실제 위치가 오프셋됩니다.

+0

감사합니다! 파이를 실행 파일로 사용하는 것은 무엇입니까? –

+0

@MarkoKevac 보안상의 이유로 유용합니다. 임의의로드 주소를 사용하면 여러 가지 취약점을 악용하기가 더 어려워집니다. 전역 개체와 코드의 위치가 때때로 변경되기 때문에 공격자는 상수 주소에서 더 이상 릴레이 할 수 없습니다. 예 : 이 이유 때문에 Android는 버전 5.0 (Lollipop) 이후 파이가 아닌 실행 파일 사용을 금지합니다. – Sergio

+0

무엇을 좋아합니까? AFAIK는 실행중인 프로세스에서 .text에 쓸 수 없기 때문에 함수의 고정 주소가 도움이되지는 않습니다. 아니? –

관련 문제