이미 실행된 실행파일을 수정할 수 있나요?

이미 실행된 실행파일을 수정할 수 있나요?

임베디드 시스템에서 실행되는 Linux 시스템이 있습니다. 여러 가지 이유로 로그인할 수 없으며(그렇지 않으면 해고될 수 있음) 키보드나 SSH와 같은 일반적인 수단을 통해 시스템에 직접 액세스할 수도 없습니다. 실행 중인 파일을 변경하는 것은 악한 일이라는 것을 알고 있습니다. 하지만 저를 믿으십시오. 대안이 있다면 이를 받아들일 것입니다.

ARM CPU를 기반으로 구축된 이 시스템에는 순수 ARM 기계어 코드(C++에서 컴파일된)인 실행 파일이 있습니다. 이 코드에서 버그가 발견되었습니다. UXTB 명령어를 UXTH 명령어로 바꾸면 이 오류를 해결할 수 있다는 것을 알았습니다. 운 좋게도 이를 위해서는 opcode 바이트를 0xEF에서 0xFF로 변경해야 했습니다. 이 패치를 수행하려면 다음 명령을 실행하십시오.

printf '\xff' | dd of=path/to/executable bs=1 seek=$((0x01ce22)) conv=notrunc

수정된 바이트는 임베디드 시스템이 특정 명령을 수신할 때만 호출되는 함수의 일부입니다. 이 패치를 실행할 때 이 명령이 전송되지 않을 것임을 절대적으로 보장할 수 있습니다. 따라서 RAM과 스토리지에 서로 다른 버전의 코드가 발생할 위험이 없습니다.

불행하게도 변경해야 하는 프로그램(역시 시스템 시작 시 시작)은 시스템에 대한 액세스를 거의 허용하지 않는 제가 의존하는 프로그램이기도 합니다. 따라서 액세스 권한을 잃지 않도록 프로세스를 종료할 수 없습니다.

실행 파일의 이 바이트, 직접 사용되지 않는 이 작은 바이트를 수정하는 것이 가능합니까?

아마도 가장 좋은 해결책은 쉘 스크립트를 사용하여 기본 프로세스를 종료하고 바이트를 변경한 다음 다시 시작을 활성화하는 것입니까? 이상적으로는 변경 사항이 성공하는지 확인할 수 있도록 시스템이 활성 상태를 유지하고 싶습니다.

SSH를 통해 직접 액세스할 수 있는 동일한 시스템에서 실행되는 테스트 케이스 스크립트가 있습니다. 테스트 스크립트는 단순히 0.1초 단위로 1000번 파일에 값을 출력하는 C++ 스크립트입니다. 나는 그것을 분해하여 위의 printf |와 유사한 상수 값을 보유하는 바이트를 찾았습니다. dd 명령을 사용하여 상수를 수정할 수 있지만 프로그램이 실행되지 않을 때만 가능합니다. 나에게 이상적인 솔루션은 출력 파일이 500 정도의 C++ 원시 값과 올바른 바이트에 입력한 500 정도의 값을 유지하도록 상수를 동적으로 수정할 수 있다는 것입니다.

제공할 수 있는 도움이나 조언에 감사드립니다.

답변1

Linux 및 대부분의 기타 Unix 운영 체제에서는 실행 바이너리를 실제로 수정할 수 없습니다. 쓰기 위해 이러한 파일을 열려고 하면 ETXTBSY오류(텍스트 파일 사용 중)가 발생합니다. 이는 바이너리가 메모리 매핑될 수 있고 파일을 수정하면 거의 확실하게 의도하지 않은 방식으로 바이너리가 수정되기 때문입니다. 커널이 이 상황을 적절하게 처리하지 못할 수도 있습니다.

그러나 파일을 한쪽으로 복사하고 거기에서 수정한 다음 호출 rename(2)(또는 이와 함께 다른 것을 사용 mv(1))하여 새 바이너리의 이름을 이전 바이너리로 바꿀 수 있습니다. 이는 이전 바이너리가 여전히 디스크에 있지만 어떤 이름으로도 파일 시스템을 통해 액세스할 수 없고 마지막 사용자가 이를 닫을 때까지 그대로 유지되기 때문에 작동합니다. 바이너리를 다시 실행하면 새 버전이 다운로드됩니다.

관련 정보