<Reversing> 1. Binary
해커 등 많은 분야의 엔지니어들이 프로그램을 바이너리(Binary)라고 부르곤 합니다. 이는 Stored-Program Computer에서 프로그램이 저장 장치에 이진(Binary)의 형태로 저장되기 때문입니다.
Compile Process
소스코드를 컴퓨터가 이해할 수 있는 기계어의 형식으로 번역하는 것을 compile이라고 합니다. 컴파일을 해주는 소프트웨어는 compiler라고 부르죠. 한번 컴파일 되면 결과물이 프로그램으로 남기 때문에 언제든지 이를 실행하여 같은 명령을 처리하게 할 수 있습니다.
그러나 모든 소스코드가 컴파일을 필요로 하지는 않습니다. Python, Javascript같은 언어는 사용자가 작성한 스크립트를 그때 그때 번역하여 컴퓨터에 전달합니다. 이 동작을 interpreting이라고 부르며, 이를 처리해주는 프로그램을 interpreter라고 합니다.
대표적인 컴파일이 필요로하는 C로 작성된 코드는 Preprocess, Compile, Assemble, Link의 과정을 거쳐 Binary로 번역됩니다.
Preprocess
Preprocessing은 Compile하기 전 필요한 형식으로 가공하는 과정입니다. 주로 주석을 제거하고 저의한 매크로를 값으로 치환하고 파일을 병합합니다. 여기서 파일을 병합한다는 말은 일반적인 프로그램은 여러 개의 소스와 헤더 파일로 이루어져 있는데 이를 합친다는 말입니다.
Compile
Compile은 작성된 소스 코드를 어셈블리어로 번역하는 과정입니다. 여기서 Compiler가 소스코드의 문법을 검사하고 문법적 오류가 있다면 Compile을 중지하고 에러를 출력합니다.
Assemble
Assemble은 Compile과정에서 만들어진 어셈블리어로 된 코드를 실행파일 형식의 Object file로 변환하는 과정입니다. 간단하게 Object file을 다시 말하자면 컴파일 혹은 어셈플러 프로그램을 통해 변환된 파일이라고 이해하시면 될 것 같습니다. Object file로 변환되고 나면 어셈블리로 된 코드가 기계어로 번역되기 때문에 사람이 해석하기 어려워집니다.
Link
Assemble과정에서 만들어진 Object file을 Excutable한 file로 만들어주는 과정을 Link라고 합니다.
Binary를 분석하려면 당연히 Binary를 읽을 줄 알아야 합니다. 허지만 Compile된 코드는 기계어로 되어있기 때문에 이를 이해하기란 불가능에 가깝습니다. 그래서 이를 다시 Assembly 언어로 재번역하여 분석을 진행합니다. 이 과정은 Assemble의 역과정이기 때문에 Disassemble이라고 부릅니다.
Disassembler의 등장으로 전보다 Binary의 분석이 쉬워졌습니다. 하지만 여전히 규모가 큰 바이너리의 동작은 Assembly로 이루어진 코드만으로 이해하기는 어려웠습니다. 그래서 리버서들은 더 이해하기 쉬운언어로 번역하는 Decompiler를 개발하였습니다.
하지만 Assembly와 기계어는 거의 일대일 대응이 되어 오차없는 Disassembler를 개발할 수 있었지만 이런 대응관계가 없는 고급 언어와 Assembly는 코드를 작성할 때 사용했던 변수, 함수의 이름등이 전부 사라지고 최적화로 인해 코드의 일부분이 컴파일러에 의해 완전히 변형되기도 합니다. 그래서 이런 이유로 Decompiler는 일반적으로 Binary의 소스 코드와 동일한 코드를 생성하지 못합니다. 하지만, 이 오차가 실행 과정을 변화시키지는 않고 Disassembler를 사용했을 때보다 압도적으로 분석 효율을 높혀줍니다.