요즘 이상하리만큼 많은 사람들이 리버싱에 관심을 보인다. 리버싱이란 리버스 엔지니어링의 준말로 우리말로는 역공학 정도가 된다. 남이 만든 것을 역으로 분석하는 것이라고 생각하면 된다. 소스 코드를 컴파일하면 컴퓨터가 이해하는 바이너리 코드가 생성된다. 우리는 이러한 작업을 하는 사람들을 개발자라 부른다. 리버싱은 이렇게 생성된 바이너리 코드로부터 소스 코드를 유출해내는 기술을 말한다. 이런 작업을 하는 사람들을 우리는 리버서라 부른다.
이렇게 관심을 끌고 있는 기술인 만큼 주변에서 리버싱을 공부하는 사람을 찾는 것은 어렵지 않다. 하지만 공부를 하는 사람에 비해서 리버싱을 배웠다고 느끼는 사람은 적다. 그들이 실패하는 이유는 잘못된 학습 방식에 기인한 경우가 많다. 보통의 경우 리버싱 과정을 설명한 온라인 튜토리얼을 따라하면서 하나씩 배워 나간다. 하지만 이런 방식을 취할 경우 늘 새로운 실행 파일 앞에서는 속수 무책이 된다. 기본 원리를 모르기 때문이다.
패턴
리버싱을 잘 하려면 중학교 수학책에 나오는 인수분해를 잘해야 한다. 물론 사실 인수분해를 잘할 필요는 없다. 어떻게 하면 인수분해를 잘할 수 있는지를 아는 것이 중요하다. 같은 과정을 리버싱에 적용하면 득도의 경지에 도달할 수 있다고 감히 말할 수 있다.
인수 분해란 나열된 수식을 정리해서 간단한 인수의 곱으로 바꾸는 것을 말한다. x^2 + 2xy + y^2과 같은 수식을 (x+y)^2으로 나타내는 것을 말한다. 처음 인수 분해를 배우는 학생들은 당황한다. 늘 해왔던 것과는 반대로 진행되기 때문이다. 리버싱을 처음 배우는 개발자와 같은 심정인 것이다.
하지만 신기한 사실은 두, 세 시간의 수업 후에는 대부분의 학생들이 능숙하게 인수 분해를 해낸다는 점이다. 이는 리버싱과는 대조적인 차이라 할 수 있다. 어떻게 그렇게 됐을까? 답은 간단하다 10가지 안팎의 공식에 있다. 교과서에는 인수 분해에 대한 설명과 함께 암기 해야 할 필수 공식이 나온다. 이 공식들은 인수 분해에 자주 사용되는 것들로 이것들을 암기하고 나면 대부분의 역행 패턴을 쉽게 유추할 수 있는 것이다.
리버싱도 마찬가지다. 개발자들이 프로그램을 작성하면서 사용하는 코드는 한정적이고, 여기에는 일정한 패턴이 존재한다. 이렇게 자주 사용하는 코드들의 변환 결과와 패턴을 모두 암기하고 있다면 변환 결과로부터 원 소스를 유추해 내는 과정은 그리 어렵지 않다. 실제로 유능한 리버서들은 어셈블리 코드를 보면 바로 C 코드가 떠오를 정도로 기계적이라고 한다(보통 중국 애들). 개발자들이 많이 사용하는 코드도 그 결과를 어떻게 보는지도 모르겠다고 생각할 수도 있다. 하지만 걱정할 필요가 없다. 우리보다 먼저 그 길을 간 사람들이 우리를 위해서 잘 정리해 둔 결과물이 있기 때문이다. Hacker Disassembling Uncovered는 그러한 패턴을 설명하는 뛰어난 책이다.
상상력, 그리고 경험
세상은 언제나 한 가지로 끝나지 않는다. 인수 분해 또한 마찬가지다. 교과서에 나온 공식을 다 암기하고 나면 대부분의 것들을 인수 분해 해내는 수준이 된다. 하지만 아직도 어려운 문제를 인수 분해하기에는 모자란다. 어려운 인수 분해 문제의 특징은 수식에 뭔가를 추가 해야 한다는 점에 있다. 수식에 + 2y – 2y 등을 추가해야 인수 분해가 되는 것이다. 이런 작업을 해보기 전까지는 절대 인수 분해되지 않는다.
수식에 + 2y – 2y를 추가하는 것은 수학적 직관력과 매우 밀접한 관련이 있다. 직관력이 뛰어난 학생들은 답을 보지 않고도 이 미친 짓들을 수식에 종종 적용하고는 한다. 하지만 나머지 대부분의 학생들은 이런 과정을 상상도 하지 못한다. 안타깝게도 우리는 보통 나머지 대부분인 경우가 많다.
부족한 직관력과 상상력을 보충하는 방법은 부단한 연습을 통한 경험 축적 뿐이다. 실제로 수학적 직관력이 떨어지는 학생들도 + 2y - 2y를 추가하는 문제를 여러번 접하다 보면 나중에는 인수 분해가 잘 되지 않으면 각종 수식들을 첨가 삭제 요리하는 단계에 이른다. 경험에 의해서 방법을 알게되는 것이다. 리버싱도 마찬가지다. 동등한 실력을 가진 경우에 열 번 해본 사람이 한 번 해 본 사람보다 새로운 문제를 풀 확률이 높다. 열 번 중에 한 가지가 이번 문제의 패턴일 수 있기 때문이다.