컴파일 후 바이너리 파일의 내용을 이해할 수없는 이유는 무엇입니까? 사용되고 있음을 해석 할 수 있습니다. 불행히도

내가 아는 한, 모든 프로그램은 프로세서 레지스터 에서 작동하는 특정 데이터 변수 (float, int, char …)가있는 프로세서 명령어 팩으로 구성됩니다 .

그래서 (오래 전에) 내가 생각한 첫 번째 것은 %¨#$¨#(임의의 예) 의 ASCII 값이 x86 의 스택 포인터 레지스터 (예시)의 주소로 해석 될 수 있다는 것 입니다 프로세서. 이것이 사실이라면, 이진 파일의 내용을 읽을 때이 “읽을 수없는”값을 찾을 때마다 스택 포인터 레지스터가 일부 데이터 변수를 관리하는 데 사용되고 있음을 해석 할 수 있습니다.

불행히도 이것은 일어나지 않습니다. 아래에는 ping.exeWindows에서 시작한 프로그램 내용의 예가 있습니다 notepad.exe.

MS 메모장에서 본 Ping.exe

이진 파일이며 데이터는 인간에게는 이해할 수 없습니다 (기계에서는 이해할 수 있습니다). 어셈블리 코드 (가장 낮은 수준의 기계 언어) 를 알고 있더라도 누구에게도 의미가 없습니다 .

따라서 모든 것을 올바르게 이해했다면 누군가가 설명 할 수 있습니까?

  1. 바이너리 코드가 똑같은 깊이까지 어셈블리 코드로 돌아갈 수없는 이유는 무엇입니까?
  2. 어셈블리 코드를 이해할 수 있다면이 코드로 인해 컴파일 된 바이너리가 더 이상 “판독 가능하지 않은”이유는 무엇입니까?


답변

첫째, 레지스터에는 주소가 없습니다. 어셈블리 언어의 각 명령어는 opcode로 변환됩니다. x86의 opcode는 1, 2, 3 또는 그 이상의 바이트가 될 수 있습니다 (일부 프로세서에서는 “고정 너비”임). 일반적으로 opcode는 명령어, 주소 지정 모드 및 관련된 레지스터를 식별합니다. “주소 지정 모드”는 CPU에서 opcode보다 더 많은 것이 필요한지 여부를 결정합니다. 즉, “즉시”주소 지정 모드는 해당 명령어에 대한 명령어 바로 뒤에 (또는 “즉시”) 추가 데이터가 있음을 의미합니다. “절대”주소 지정 모드는 메모리 주소는 명령어를 따르며 해당 명령어에 사용됩니다.

MOV AL,SP유사하거나 유사한 opcode를 찾은 다음 검색 할 수 있습니다. x86에는 스택 포인터에서 작동하는 많은 명령이 있습니다.

그러나, 제발 제발 메모장을 사용하여 종료하고 대신 16 진수 편집기를 사용합니다. 다른 많은 것들이 있지만 HxD를 추천합니다.

그리고 @David Schwartz가 맞습니다. 디스어셈블러는 파일을 반복하고 opcode를 다시 읽을 수있는 텍스트로 변환합니다. 당신이하고 싶은 것은 완전히 가능합니다.

그러나 잘못된 주소에서 시작하면 opcode에 대한 “피연산자”여야하는 일부 데이터 (예 : 피연산자 또는 “인수”에 대한 주소를 사용하는 명령어)는 파일에서 명령어가 시작되는 위치를 알아야 합니다. opcode로 잘못 해석됩니다. 이를 알기 위해서는 실행 파일의 형식, 즉 Windows의 경우 “포터블 실행 파일”또는 PE 형식에 대한 지식이 필요하며 Linux 시스템의 경우 ELF입니다. PE 등을 이해하는 디스어셈블러가 있다고 확신하지만, 나는 아무 손도 모른다.


답변

모든 것을 올바르게 이해했다면

좀 빠지는.

이진 파일이며 그 데이터는 우리 인간에게는 이해할 수 없습니다

일반적으로 이진 파일은 특히 파일의 목적을 알 수없는 경우 사람과 컴퓨터에서 이해할 수 없습니다. 모든 이진 파일이 실행 파일 인 것은 아닙니다. 많은 이진 파일은 컴퓨터 명령어가 포함되지 않은 데이터 파일입니다. 그렇기 때문에 파일 이름을 지정할 때 파일 확장자가 사용됩니다 (일부 OS에서). . com 확장명은 CP / M에서 실행 파일을 나타 내기 위해 사용되었습니다. . exe 확장자는 다른 실행 파일 형식을 나타 내기 위해 MS-DOS에 의해 추가되었습니다. * nixes는 execute 속성을 사용하여 코드는 물론 스크립트 일 수도 있지만 실행할 수있는 파일을 나타냅니다.

다른 사람들이 이미 언급했듯이 숫자를 포함하는 이진 파일은 텍스트 뷰어가 아닌 16 진 덤프 프로그램 또는 16 진 편집기로보아야합니다.

ping.exe 프로그램의 내용의 예가 있습니다

이 파일은 실제로 재배치 가능한 프로그램이며 해당 파일의 모든 데이터가 기계 코드를 나타내는 것은 아닙니다. 필요한 동적 라이브러리, 링크 할 루틴, 스택 및 프로그램 및 데이터 메모리 요구 사항, 프로그램 시작점 등 프로그램에 대한 정보가 있습니다. 파일의 주소 피연산자는 절대 값으로 계산해야하는 상대적인 값이거나 해결해야하는 참조 일 수 있습니다.

아마도 “프로그램 파일”을 바이너리 이미지 파일 또는 프로그램 메모리 덤프라고합니다. 이러한 파일에는 머신 주소와 데이터 만 포함되며 모든 주소 참조는 실행을 위해 올바르게 설정됩니다.

어셈블리 코드 (가장 낮은 수준의 기계어)를 알고 있더라도

어셈블리 언어는 기계 언어와 다릅니다 . 일반적인 (고급 언어 컴퓨터 제외) CPU는 한 번에 한 명령 씩 머신 코드를 입력으로 받아들입니다. 피연산자는 레지스터 또는 숫자 메모리 주소입니다. 어셈블리 언어는 명령 위치 및 변수에 기호 레이블을 사용하고 숫자 op 코드를 니모닉으로 대체 할 수있는 고급 언어입니다 . 어셈블리 언어 프로그램은 실제로 실행되기 전에 기계 언어 / 코드로 변환해야합니다 (일반적으로 어셈블러, 링커 및 로더라는 유틸리티에 의해).

심볼 파일의 일부 성공 및 손실로 프로그램 파일에서 역 조작, 디스 어셈블을 수행 할 수 있습니다. 코드 및 데이터 위치를 수동으로 식별해야하기 때문에 메모리 덤프 또는 프로그램 이미지 파일의 분해가 더 시행 착오입니다.

BTW (숫자) 기계 코드를 읽고 코딩 할 수있는 사람이 있습니다. 물론 이것은 12 개의 메모리 주소 모드를 가진 32 비트 CISC 프로세서보다 8 비트 CPU 또는 마이크로 컨트롤러에서 훨씬 더 쉽습니다.


답변

메모장을 통해 이진 파일의 올바른 의도 된 인코딩을 볼 수 없습니다. 나중에 참조 할 수 있도록 이것을 검토하십시오 . 대부분의 텍스트 편집 프로그램은 이진 인코딩 형식을 구문 분석하지 않으며 ASCII 문자 코드 형식을 구문 분석해야합니다.

따라서 텍스트 편집기에서 이진 파일을 열면 텍스트 편집기에서 파싱 된 이진 데이터의 원래 형식을 이해하지 못하는 동등한 ASCII 문자가 생성됩니다. 언급했듯이 16 진 편집기 및 일부는 바이너리 기능을 가지고있어 순수한 2 진 형식으로 컨텐츠를 볼 수 있습니다.

이진 파일의 내용을 이해할 수 없다는 것이 잘못되었습니다. 그것들은 어려울 것이고 현대 컴퓨터 아키텍처 에서는 바이너리 (binary)에서 실행 (또는 에뮬레이트 / 가상 CPU) 등을 위해 CPU에 의해 인식되는 적절한 명령으로 바이너리를 수동으로 분해하기가 매우 어렵 습니다.

에뮬레이터가 어떻게 프로그래밍되어 있다고 생각하십니까? 개발자는 가상 시스템이 어떤 방식 으로든 실제 하드웨어처럼 인식하고 작동하도록 가상 시스템을 프로그래밍 할 수 있도록 opcode를 알아야합니다. 문서에는 많은 CPU 아키텍처가 설명되어 있으며 GPU조차도 더 비밀이 있습니다.

주목해야 할 또 다른 사항은 가장 낮은 수준에서 상관 관계는 있지만 “이진 데이터”는 실제로는 0과 1이 아니라 전기 회로를 통해 전류로 증폭 및 스위칭되는 고전압과 저전압입니다.

이진수는 일반적으로 1 : 1이므로 숫자 시스템을 사용하는 것이 좋습니다.