보통 리버스엔지니어링은 비교적 쉬운 네트워크나 Develope 등과 다르게 조금 더 어려운 분야라고 생각한다. 왜냐하면 어셈블리나 구조 이외에 개발 지식이 필요하기 떄문이다. 보통 알고리즘을 볼때에는 짜는 사람보다 보고 이해하려고 하는 사람이 더 많은 시간을 소비하고 어렵게 느껴지는 것과 같다. 일단 그의 기초인 어셈블리부터 공부해 보자.
1. 어셈 블리는?
보통의 프로그래밍이라면 어떠한 함수에(Function)에 다양한 행동들이 함축적으로 정의(Defined)되어 있다. 예를들어 "먹을 것을 먹는다()"라는 함수가 있다면 그 속에는 "방문을 열어 나간다. 몇 발자국 걸어갈지 계산한다. 그 계산한 값을 기준으로 내장고로 걸어간다.....등"의 기능들이 함축적으로 정의되어 있다.
하지만 어셈블리는 다르다. 어셈블리는 한가지 동작밖에 하지 못한다. 따라서 다른 High Level 프로그래밍 언어는 함수나 메서드 등을 사용하면 끝나는 동작으로 몇 줄이상의 코드를 커쳐서 실행해야한다는 것이다. 편리성에서는 위의 C/C++같은 언어들이 더 높지만, 단순함을 따지자면 어셈블리가 더욱 간단하다는 것이다.
2. 어셈블리의 명령 포맷
"명령어 + 인자"
이것이 어셈블리의 기본적 구조이다. 명령어를 옵코드(Opcode)라고 하며 인자를 오퍼랜드(Operand)라고 한다. 명령어는 하나밖에 오지 못하지만 오퍼랜드는 2개까지의 명령어가 올 수 있다.
"Push 1"
이 명령어는 인자가 한 개인 경우이며, Opcode가 Push가 되고, Operand가 1이된다. 해석을 하자면, '스택에 1이라는 인자를 집어 넣어라!' 정도가 될 수 있다.
"Mov eax, 23"
이 명령어는 인자가 2 개인 경우이며, Opcode가 Mov가 되고, Operand가 eax와 23이 된다. 보통 앞에 있는 인자가 목적지 오퍼랜드(Destination Operand)가 되고 뒤에 있는 것이 출발지 오퍼랜드 (Source Operand)가 된다. 명령어를 해석하자면 "Eax 레지스터에 23인 값을 이동(Mov)시켜라", 간단하게 "eax에 23을 저장하셈"이런 뜻이다.
어셈블리는 간단하다. 그러면서도 복잡하고 처음에는 이론적인 이야기가 대부분을 차지한다. 레지스터나 명령어들 그리고 기본적 PE구조를 이해할 때에는 필자도 많이 졸고 졸았다. "재미가 없기 때문이다."
하지만, 영어 ABCDE, 한글 가나다라마, 일본어 히라가나 가타카나를 배울 때에는 재미가 있었나? 물론 있을 수 있지만 일반적으로는 보통 재미있을 수가 없다. 하지만 문법을 배우고 라이팅과 리스닝을 할떄 조금의 재미를 느끼고 외국인이나 팝송의 가사를 이해할 때에 비로소 빛을 바라는 것 같다.