을
x86은 명령어 길이가 다양하기 때문에 분해가 매우 어렵습니다. 처음 디스어셈블러 인 경우에는 권장하지 않습니다.
말하기 ... 내가 취하는 접근법은 opcode의 첫 번째 바이트 인 바이트를 식별하고 opcode 또는 데이터의 두 번째 바이트 또는 다른 바이트와 구분해야한다는 것입니다. 바이너리의 시작 부분에서 시작하여 opcode를 디스 어셈블 할 수 있다는 것을 알게되면.
어떻게하면 다른 바이트의 opcode를 찾아 낼 수 있습니까? 가능한 모든 실행 경로를 따라 가야하고, 재귀 문제와 같은 소리가 들릴 수도 있지만 그렇지 않아도됩니다. 인터럽트 벡터 테이블 및/또는 코드의 모든 하드웨어 진입 점을 살펴보십시오. 그러면 opcode 바이트의 짧은 목록을 얻을 수 있습니다. 비 재귀 방식은 opcode로 표시된 각 바이트를보고 바이너리를 여러 번 통과 시키며 소비하는 바이트 수를 알 수있을 정도로만 디코딩합니다. 또한 조건부 분기, 조건부 분기, 복귀, 호출 등이 있는지 여부를 알아야합니다. 조건부 분기 또는 반환이 아닌 경우이 명령어가 다음 명령어의 첫 번째 바이트 인 것으로 가정 할 수 있습니다. 분기 나 호출이있을 때마다 목적지 주소를 계산하고 그 바이트를리스트에 추가하십시오. 목록에 새 바이트를 추가하지 않는 패스를 만들 때까지 계속 패스를 만듭니다. 또한 3 바이트 명령어 인 바이트가 명령어로 표시되었지만 바이트가 발견되면 문제가 있음을 확인해야합니다. 조건부 분기점과 같은 것들은 결코 분기하지 않도록 보장합니다. 바이너리로 컴파일 된 높은 수준의 코드를 사용하는 경우에는이 정도를 보지 못한다.하지만 손으로 작성한 어셈블러 또는 코드 보호를 원하는 사람들이 옛날처럼 이런 일을 할 것이다.
불행히도 당신이 갖고있는 것이 모두 가변 길이의 악기 세트 인 경우에는 완벽하게 분해되지 않습니다. 일부 분기 대상은 런타임에 계산됩니다. 때로는 직접 코딩 된 어셈블리가 반환 할 코드를 변경하기 전에 스택을 수정합니다. 그 코드에 대한 유일한 경로라면 프로그래밍 방식으로 계산하지 않을 것입니다. 코드를 시뮬레이트합니다. 그리고 시뮬레이션으로도 모든 실행 경로를 다루지 않을 것입니다.
예를 들어 ARM과 같이 고정 길이 명령어 세트로 설정하면 (팔과 엄지가 섞여 있지 않은 한) 바이너리의 시작 부분에서 간단히 시작하여 단어가 부족할 때까지 분해 할 수 있습니다. 데이터 단어를 유효하거나 유효하지 않거나 사용하기 쉬운 지시로 분해 할 수는 있지만 괜찮습니다.
엘프 어딘가에 바이너리의 어떤 부분이 실행 가능하고 어떤 부분이 데이터인지 나타내는 것이 있으면 놀랄 것입니다. 어쩌면 그렇게 많은 데이터 경로를 걸어야 할 필요가 없다. objdump가 아마도 elf 파일에서 뭔가를 사용하는 것과 같은 작업을 수행하는지 의심 스럽다.
elf 파일 형식은 여러 곳에서 설명되어 있습니다. 기본 구조가 있고 공급 업체는 공급 업체가 문서화하는 특정 블록 유형을 추가 할 수 있습니다.
대단한 답변입니다! 기여할 시간을 내 주셔서 대단히 감사합니다. –