2016-11-23 1 views
1

바이너리가 있습니다. mmap()을 사용하여 메모리에 씁니다. 그럼 내가 할당 된 메모리에서 바로 exec하려고하지만 지금은 아무런 결과가 없습니다. 누구든지 도와 줄 수 있습니까? 예를 들면 내가 우분투, 이진 (C 안녕하세요 세계)의 크기 FILE_SIZE, 다음의 기술자 fd와 오전 ) 감사합니다 :할당 된 메모리에서 mmaped 바이너리/코드를 바로 exec하는 방법

addr = mmap(NULL, file_size, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, pa_offset); 
      if (addr == MAP_FAILED) 
       handle_error("mmap"); 

그래서 내가 그것을

+2

예를 묻는 것뿐만 아니라 질문에 코드를 표시해야합니다. 실행 권한이있는 페이지가 있습니까? 실행할 "일부 바이너리"코드는 무엇입니까? 당신이 그것을 실행하려고하면 어떻게됩니까? 아무것도 아냐, 세그 폴트? 더 많은 세부 사항을 추가하십시오. – DUman

+0

이렇게해야 할 필요가 있습니까? 다른 프로세스에서 프로그램을 시작하는 일반적인 방법은 exec() 패밀리의 함수 중 하나를 사용하는 것입니다 ... – Rene

+0

"플러그인"을 사용하는 프로그램을 작성하려는 경우 C 라이브러리를 사용했습니다 : 플러그인을 실행 파일이 아닌 공유 객체로 빌드 한 다음 ['dlopen' 및'dlsym'] (https : //linux.die)을 사용하십시오.net/man/3/dlopen)를로드하여 호출하십시오. 즉석에서 기계 코드를 생성하여 실행하는 경우 ("적시"컴파일러 또는 유사), 아마도 [W^X 정책] (https : //en.wikipedia)을 파울 것입니다. .org/wiki/W % 5EX); 코드를 메모리에 쓴 다음 [mprotect'] (https://linux.die.net/man/2/mprotect)를 사용하여 실행 가능하게 만들어야합니다. C 라이브러리는 도움이되지 않습니다. – zwol

답변

3

동안 간부 인 방법을 잘 모릅니다 당신의 질문을 편집 한 후에도 여전히 혼란 스럽다. 나는 당신이 뭘 잘못하고 있는지 말하기에 충분하다고 말한 것 같다.

이진 (C 안녕하세요 세계)

당신은 mmap 실행할 수는 OS가 그것을 실행하는 것과 같은 방식으로 이진 파일을 에드. Linux에서 실행 중이므로 hello world는 ELF 형식의 이진 파일 일 가능성이 높습니다. Linux는 ELF 바이너리를 읽고 실행하는 방법을 알고 있지만 프로그램은 그렇지 않습니다. ELF starts with a header 그리고 메모리 매핑 된 데이터도 헤더로 시작합니다. 어떤 코드가 실행 가능하지 않습니다. 헤더는 0x7F으로 시작합니다.이 명령어는 x86의 jg 명령어에 해당하므로 ELF 헤더를 실행 코드로 '실행'하려고하면 플래그의 상태에 따라 다음 바이트로 구성된 가비지 주소로 즉시 이동합니다 헤더의.

이와 같은 코드를 실행하려면 ELF 파일을 구문 분석하고 해당 엔트리 포인트 (또는 아마도 .init 섹션을 찾으십시오)를 찾아서 거기에서 코드를 실행해야합니다. 당신은 분명히 학습 목적으로 이것을 운동으로 자유롭게해야하지만, 그것은 당신 자신의 다른 프로그램을 실행하는 정상적인 방법이 아닙니다. 일반적인 접근 방식은 대신 forkexec 호출을 사용하는 것입니다. 이를 통해 Linux는 프로그램을 시작하는 데 필요한 기술을 처리 할 수 ​​있습니다.

+0

실제로 작동합니까? 나는 한번도 시도한 적이 없지만 첫 번째 재배치에서 죽을 것이라고 추측합니다 ('main()'을 호출하기 전에 필요할 수도 있습니다). –

+0

@ TheVee 'ld.so'에 의해 정상적으로 수행되는 모든 작업을 수행해야합니다. – zwol

+0

@ TheVee 아마 정적으로 연결된 Hello World처럼 간단 할 것입니다. 일반적으로, 그것은 매우 빨리 segfault 할 것입니다. – DUman

1

다음으로는 임의의 메모리 이미지로 실행할 수 없습니다. ELF 파일은 프로세스 주소 공간에서 특정 방식으로 mmaped되어야하며 거의 절대 기본 파일의 연속 이미지로 mmaped되어서는 안됩니다.

제가 생각할 수있는 가장 가까운 실행 가능한 접근법은 이미지를 (아마도 이름이없는) 파일에 저장하고 execveat(fd, "", ...)을 통해 해당 파일을 저장하는 것입니다. execveat (2)에서 빈 경로 이름에 대해 말한 곳을 확인하고 O_TMPFILE에서 (2)를 엽니 다.

파일을 변경할 수있을 때 close/munmap과 execve 사이의 간격이 문제가되지 않는 한 명명 된 임시 파일과 일반 execve (2)도 작동합니다.

또 다른 아이디어는 사용자 공간에서 ELF 로딩을 완전히하고 새로운 프로세스를위한 적절한 주소 공간을 설정하고 LD 등을 호출하는 것입니다. 확실히 쉬운 일은 아닙니다. execve (2) 호출을 필요로하지 않고 그냥 fork하고 작업하십시오. execve (2)가 사용되지 않기 때문에, O_CLOEXEC 핸들링과 여분의 메모리의 un-mmap과 같은 것들은 간단한 해결 방법이 필요합니다.

관련 문제