자신을 ELF 감지로 제한하려면 자신의 ELF 헤더 를 읽을 수 있습니다 /proc/$PID/exe
. 파일의 5 번째 바이트가 1이면 32 비트 이진입니다. 2이면 64 비트입니다. 위생 검사 추가 :
- 처음 5 바이트가
0x7f, "ELF", 1
: 32 비트 ELF 바이너리입니다.
- 처음 5 바이트 인 경우
0x7f, "ELF", 2
: 64 비트 ELF 이진입니다.
- 그렇지 않으면 : 결정적이지 않습니다.
당신은 또한 사용할 수 objdump
있지만 libmagic
의존성을 없애고 그것을 libelf
하나로 대체합니다 .
다른 방법 : /proc/$PID/auxv
파일을 파싱 할 수도 있습니다. 에 따르면 proc(5)
:
여기에는 실행 시간에 프로세스에 전달 된 ELF 인터프리터 정보의 내용이 포함됩니다. 형식은 하나의 부호없는 long ID와 각 항목에 대한 하나의 unsigned long 값입니다. 마지막 항목에는 두 개의 0이 있습니다.
unsigned long
키 의 의미 는에 /usr/include/linux/auxvec.h
있습니다. 당신은 원하는 AT_PLATFORM
인 0x00000f
. 저를 인용하지 마십시오, 그러나 char *
플랫폼의 문자열 설명을 얻기 위해 값을 해석해야합니다 .
이 StackOverflow 질문이 유용 할 수 있습니다 .
또 다른 방법 : 동적 링커 ( man ld
)에 실행 파일에 대한 정보를 덤프 하도록 지시 할 수 있습니다 . 디코딩 된 AUXV 구조를 표준 출력으로 인쇄합니다. 경고 : 이것은 해킹이지만 작동합니다.
LD_SHOW_AUXV=1 ldd /proc/$SOME_PID/exe | grep AT_PLATFORM | tail -1
이것은 다음과 같이 보일 것입니다 :
AT_PLATFORM: x86_64
32 비트 바이너리로 시도해 보았습니다 i686
.
작동 방식 : LD_SHOW_AUXV=1
동적 링커가 실행 파일을 실행하기 전에 디코딩 된 AUXV 구조를 덤프하도록 지시합니다. 당신이하지 않으면 정말 당신의 인생의 재미를 만들기 위해 좋아, 당신은 실제로 피하려고 실행 실행했다. 실제로 main()
함수를 호출하지 않고로드하고 동적으로 링크하는 한 가지 방법 은 해당 함수를 실행 ldd(1)
하는 것입니다. 단점 LD_SHOW_AUXV
은 셸에서 활성화되므로 하위 셸 ldd
및 대상 바이너리 에 대한 AUXV 구조 덤프가 표시 됩니다. 그래서 우리 grep
는 AT_PLATFORM 을 위해 마지막 줄만 유지합니다.
auxv 구문 분석 : auxv
구조를 직접 구문 분석하면 (동적 로더에 의존하지 않음) 약간의 수수께끼가 있습니다. auxv
구조는 설명하는 프로세스 규칙을 따르므로 sizeof(unsigned long)
32 비트 프로세스의 경우 4 , 64의 경우 8입니다 비트 프로세스. 우리는 우리를 위해이 일을 할 수 있습니다. 이것이 32 비트 시스템에서 작동하려면 모든 키 코드가 0xffffffff
이하 여야합니다 . 64 비트 시스템에서 가장 중요한 32 비트는 0입니다. 인텔 컴퓨터는 작은 엔디안이므로이 32 비트는 메모리에서 가장 중요하지 않은 컴퓨터를 따릅니다.
따라서 필요한 것은 다음과 같습니다.
1. Read 16 bytes from the `auxv` file.
2. Is this the end of the file?
3. Then it's a 64-bit process.
4. Done.
5. Is buf[4], buf[5], buf[6] or buf[7] non-zero?
6. Then it's a 32-bit process.
7. Done.
8. Go to 1.
지도 파일 파싱 : 이것은 Gilles가 제안했지만 제대로 작동하지 않았습니다. 수정 된 버전은 다음과 같습니다. /proc/$PID/maps
파일 읽기에 의존 합니다. 파일에 64 비트 주소가 나열되면 프로세스는 64 비트입니다. 그렇지 않으면 32 비트입니다. 문제는 커널이 4 그룹의 16 진 주소에서 선행 0을 제거하여 출력을 단순화하므로 길이 해킹이 제대로 작동하지 않는다는 것입니다. awk
구조에 :
if ! [ -e /proc/$pid/maps ]; then
echo "No such process"
else
case $(awk </proc/$pid/maps -- 'END { print substr($1, 0, 9); }') in
*-) echo "32 bit process";;
*[0-9A-Fa-f]) echo "64 bit process";;
*) echo "Insufficient permissions.";;
esac
fi
이것은 프로세스의 마지막 메모리 맵의 시작 주소를 확인하여 작동합니다. 그것들은 다음과 같습니다 12345678-deadbeef
. 따라서 프로세스가 32 비트 프로세스 인 경우 해당 주소의 길이는 8 개의 16 진수이며 9 번째는 하이픈이됩니다. 64 비트 주소 인 경우 가장 높은 주소가 그보다 깁니다. 아홉 번째 문자는 16 진수입니다.
주의 : auxv
파일이 이전에 없었기 때문에 첫 번째 방법과 마지막 방법을 제외한 모든 방법에는 Linux 커널 2.6.0 이상이 필요합니다 .
/proc/[pid]/auxv
. "ELF 인터프리터 정보가 실행 시간에 프로세스에 전달되었습니다. 형식은 하나의 부호없는 long ID와 각 항목에 대한 하나의 unsigned long 값" (man proc
)입니다.