Linux 실행 파일에서 사용되는 코드 변환 유형


13

리눅스 실행 파일을 만드는 데 사용되는 인코딩 유형 (예 : 16 진, 이진 또는 기타)을 묻고 싶습니다. 어떻게 변환됩니까? 이 실행 파일에서 원본 코드를 다시 가져올 수있는 방법이 있습니까?

내가 가진 약간의 코드는 다음과 같습니다.

ELF���������>�����%|�����@�������������������@�8��@���������������������@�������@�����7<�����7<������� ������������������f�����f���������������������� ������[�UPX!L
h�h�8����������?�E�h=��ڊ̓�N�    4���9ISloB�q�w�]ȉ.��,ς��Q䝦����#e��-�N����/�b,���d<��'��-E��6E�s�/�U���ly�V�Y2]"a��S�.�hU�|�S�J�I�2���X}
�G0�;���5d�$���.)

무슨 뜻입니까?


많은 것을 되 찾는 데 도움이되지는 않지만 strings필터 프로그램은 특정 이진 프로그램이 무엇인지 또는 무엇인지 식별하는 데 매우 유용 할 수 있다는 점에 주목할 가치가 있습니다. 이진 파일과 프로그램의 메시지를 보면 파일의 내용과 기능에 대해 많은 정보를 얻을 수 있습니다.
Joe

답변:


29

이진입니다. 소스 코드가 컴파일되었습니다. 편집기에서 볼 수 bless있지만 (보다 세밀한 변경을 수행 할 수 있는 16 진 편집기 ) 실제로 수행중인 작업을 알아야합니다. 문자열 변경에만 유용합니다.

더 많은 하드 코어를 위해 바이너리를 어셈블리 코드 로 리버스 엔지니어링하기 시작할 수 있습니다 . 이것은 종종 인간이 해석 할 수있는 가장 낮은 수준의 컴퓨터 언어로 간주됩니다.

objdump -d helloworld | less

그러나 많은 컴파일러 넌센스도 포함합니다. 예를 들어, G ++로 가장 단순하게helloworld.cpp 컴파일 한 다음에 objdump는 226 줄 (208 개)의 yuck로 끝납니다. 당신은 할 수 어셈블리의 15 라인에 "안녕 세계"를 작성 , 컴파일하고 objdump그것을하지만 166 선에 그 여전히 벚꽃 (제거).

만약 당신이 조립에 충분하다면, 이것은 당신에게 무슨 일이 일어나고 있는지 이해하고 심지어 그것을 바꾸게 할 수있는 충분한 접근권을 줄 것입니다 ... 그러나 원래의 질문에 대답하기 위해서 :

컴파일 된 코드를 원래 소스 코드 로 되돌릴 수 없습니다 .

죄송합니다. 정보 (설명, 형식, 판독 가능한 알고리즘 개념 등)를 잃어 버리고 다른 것들과 정적으로 연결되어 있으며 일반적으로 가장 노련한 프로그래머 외에는 이해할 수없는 방식으로 최적화되는 단방향 변환입니다.

문제의 규모에 대한 아이디어를 제공하기 위해 리버스 엔지니어링 소프트웨어의 전체 아이디어에는 자체 스택 교환 사이트가 있습니다 .


나는 소스를 잃은 사촌 내가 역을 엔지니어링 및 코드의 다시 최대 금액을 얻을 어떻게 말해 줄 수
redchief

7
최근 편집 내용을 참조하십시오. 원래 소스로 돌아 가지 않습니다. 많은 학습과 시간이 소요되면 디스 어셈블 된 어셈블리 코드를 기반으로 소스를 다시 작성할 수 있지만 대부분의 경우 비용이 저렴하고 처음부터 다시 작성하기가 더 쉽습니다.
Oli

1
최대량의 코드를 다시 얻는 방법은 가장 최근 백업을 복원하는 것입니다. 또한 우연히도 원본 소스 코드와 유사한 것을 안정적으로 되돌릴 수 있는 유일한 방법입니다.
CVn

1
마지막 단락에 전혀 동의하지 않고 부수적 인 참고 사항 : 일부 디 컴파일러 IME는 정확한 코드 구조를 복원하는 데 큰 역할을합니다 (물론 주석, 형식, 기호 이름 등은 말하지 않습니다). 처음에 프로그램을 작성하지 않은 경우 복구 된 소스 코드를 여전히 이해할 수 없지만 손실 된 소스 코드 / 알 수없는 소스 코드 (적어도 부분적으로)를 복구하는 것이 좋습니다 (적어도 부분적으로) 특정 코드와 운이 좋은지 여부에 따라 실제로 이해하기
쉽습니다

1
이것이 독점 소프트웨어 세계의 모든 EULA가 리버스 엔지니어링 / 분해를 허용하지 않는다고 말한 것입니다. 그들은 가능하기 때문에 이와 같은 절을 포함하지만 확실히 쉽지는 않습니다! 그러나 @ MichaelKjörling이 말했듯이, 물건을 되 찾는 유일한 좋은 방법은 관심있는 모든 것을 위해 여러 수준의 백업에서 얻는 것입니다.
Joe

7

의견에 대한 평판이 충분하지 않으므로 답변입니다.

아니요, "뒤로"변환 할 수 없습니다. upx packer에 대해 언급했는데 upx의 매뉴얼을 읽은 적이 있습니까?

소스를 잃어 버렸거나 다른 사람의 코드에 액세스 할 수없는 경우 여기가 중요하지 않습니다.

바이너리 실행 파일은 컴파일러로 제작되었으며이 사이트에 언급 된 내용을 믿지 말고 정확히 해당 컴파일러의 설명서를 읽으십시오. 그런 다음 원래 코드가 작성된 언어, 어떤 컴파일러가 사용되었는지 여기에 추가 할 수 있으며이 단계 (전처리, 컴파일, 링크, 패킹)는 전체적으로 역전되지는 않지만 단지 원저자가 의도 한 내용과 글을 분석 할 수 있습니다.



3

Oli가 그의 답변에서 이미 지적했듯이 실행 파일의 원본 소스 코드는 얻을 수 없습니다.

소스 코드를 컴파일하는 동안 (일반적으로 광범위하게 받아 들여 지도록 컴파일되므로 소스 코드를 실행 파일로 "변환하는 전체 프로세스") 많은 정보가 손실됩니다.

C 프리 프로세서는 다음과 같은 작업을 수행합니다.

  • 전 처리기 지시문 ( #문) 해석, 실행 및 제거
  • 댓글 제거
  • 불필요한 공백 제거

반면에 소스 코드를 컴파일하는 동안 손실되지 않은 것은 기능적으로 동등한 소스 코드로 기술적으로 되돌릴 수 있습니다.

이 때문입니다:

  • 이진 명령어는 어셈블리 명령어와 1 : 1의 일치 성을 갖습니다. 어셈블리 소스 코드의 어셈블 링은 단지 대응 테이블에 기초한 어셈블리 명령어를 이진 명령어로 변환하는 것에 불과하다. 단일 이진 명령은 항상 식별 가능하고 단일 어셈블리 명령으로 되돌릴 수 있습니다 .
  • 조립 설명서 에는 C 명령어와 1 : 1의 일치 성이 없습니다 . C 소스 코드의 컴파일은 일반적으로 C 테이블을 해당 테이블을 기반으로하는 어셈블리 명령으로 변환하는 것만이 아니라 실제로는 반대입니다. 일반적으로 C 명령어는 여러 (종종 컴파일러에 따라 다름) 어셈블리 명령어로 변환됩니다. 그러나, 다수의 조립 명령의 패턴은 일반적으로 식별 가능하고 단일 C 명령으로 되돌릴 수있다 ;

실행 파일을 기능적으로 동등한 소스 코드로 되돌리려는 목적으로 디 컴파일러라는 도구가 있습니다. 그러나 결과는 일반적으로 원래 소스 코드와는 거리가 멀다 (그리고 보통 컴파일 할 수 없다).

이 프로그램을 고려하십시오 :

#include <stdio.h>

#define MESSAGE "Literal strings will be recovered" // This preprocessor directive won't be recovered

/*

This comment and the comment above won't be recovered

*/

int main(int argc, char* argv[]) {
    printf(MESSAGE);
    return 0;
}

실행 파일로 컴파일하고 소스 코드로 다시 컴파일하면 일반적으로 얻는 것입니다 (이 특정 경우 gcc/ Boomerang 사용 ).

// address: 0x80483fb
int main(int argc, char **argv, char **envp) {
    printf("Literal strings will be recovered");
    return 0;
}

예상대로 :

  • 전 처리기 지시문이 없습니다
  • 주석이 누락되었습니다 ( // address: 0x80483fb디 컴파일러가 추가 한 제외 ).
  • 불필요한 공백이 없습니다 (디 컴파일러가 추가 한 줄 바꿈 및 표 제외)

이것은 또한 꽤 좋은 결과입니다. 인라인 어셈블리 명령어를 코드에 넣는 것은 드문 일이 아닙니다.

asm("assembly_instruction");
__asm__("assembly_instruction");

결론은 (다른 답변에서 이미 지적했듯이) 실행 파일의 원본을 얻을 수는 없습니다 *.

그러나 실행 파일과 운에 따라 디 컴파일러를 사용하여 무언가를 얻을 있습니다.


2

실행 프로그램은 컴파일 된 프로그램에 대해 이야기하는 경우 일반적으로 이진입니다. 을 사용하여 자세한 정보를 찾을 수 있습니다 file path/to/executable. 예를 들어 hexdump -C path/to/executable | less(좋은 것이 무엇이든) 사용하여 이진 실행 파일을 16 진수로 표시 할 수 있습니다 . "원래 형식으로 다시 변환"하려면 적절한 디 컴파일러를 사용해야합니다 . 예를 들어 , 이 게시물을 참조하십시오 . 컴파일 된 바이너리가 아닌 경우 일종의 실행 가능한 스크립트가되며 텍스트 편집기에서 쉽게 읽을 수 있어야합니다. 여기서 우리에게 보여준 것은 아마도 컴파일 된 실행 파일 일 것입니다. ELF는 Linux / Unix 시스템에서 일반적인 이진 형식 인 "실행 가능 및 링크 형식"을 의미합니다. 그곳에'strings path/to/executable이것이 필요한 경우입니다.


나는 upx packer로 리버스 엔지니어링을 시도했지만 작동하지 않았으며 제안한 게시물로 작동하지 않았습니다. 다른 방법이 있는지 알려주세요.
redchief

매우 죄송하지만 @Oli의 우수한 게시물에 쓰여진 것 이상을 말할 수는 없습니다.
Hinz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.