장님과 앉은뱅이
내 컴퓨터 메모장에는 그때 그때 생각나는 연구 주제를 적어놓은 문서가 하나 있다. 대학원생 때부터 적기 시작했으니 대략 한 10년정도 묵은 파일이다. 대단한 것을 적어 놓은 것은 아니다. 이런게 되면 좋겠다 싶은데 당장 어떻게 해야할지 생각이 떠오르지 않는 것들, 잠깐 시도해봤는데 잘 안되어서 아쉬운 것들이 주로 적혀 있다. 그러니 찬란한 보물이 담긴 상자는 아니고, 조금 지저분한 재활용품 수거함 정도 되겠다.
한 가지 재미난 점은, 이 수거함에 들어가는 내용물은 간혹 있는데, 명시적으로 여기서 꺼내어 재활용을 한 적은 한 번도 없다는 것이다. 명시적이라고 강조한 이유는 이러하다. 새로운 연구를 시작할 때 이 문서에 적힌 목록을 쭉 훑어보고, 그 중 하나를 선정해서 다시 시작해본 적은 한 번도 없다. 간혹 이 문서를 열어서 쭉 훑어보긴 하지만, 그 때마다 매번 드는 생각은 “아, 역시 잘 안될만 하니까 여기 아직 적혀 있구나”. 과거의 나에게 설득당하는 순간이다.
반면, 성공적으로 마친 연구가 나중에 알고 봤더니 그 수거함에 오래전에 적힌 것임을 발견하는 경우는 종종 있다. 이 측면도 상당히 놀랍고 재미있다. 그 간 세상이 바뀌어서 안되던게 된건가? 수거함에 있는 줄도 몰랐는데 언제 어떻게 이 일을 왜 시작하게 된 것인가? 어떤 귀인이 찾아와 영감을 준 것인가? 곱씹어보면 재미있을 것 같았다. 오늘 이야기는 그 문서에 나란히 적힌 (문서에 적힌 순서상 아마도 2016년 근처일 것으로 추정되는) 아래 두 줄에 관한 이야기이다:
- “특정 버퍼 접근 하나만 목표로 하는 정적 분석”
- “정적 분석 알람으로 향하는 테스팅”
프로그램에 있는 오류를 찾는 기술은 크게 정적 분석과 동적 분석 두 가지로 나뉜다. 두 기술은 뚜렷이 대비되는 장단점이 있다. 정적 분석은 원시안으로 프로그램을 본다. 전체를 잘 파악하지만 한 곳을 집중해서 자세히 보는 능력은 떨어진다. 그리하여 큰 프로그램에서도 오류를 놓치지 않고 잘 잡아 내지만, 오류가 아닌 것도 오류라며 흐릿한 판단을 하는 경우가 종종 있다. 반면 동적 분석은 근시안으로 프로그램을 보는 것이다. 하나하나 집중해서 세밀히 관찰할 수 있지만 큰 그림 보는 능력은 떨어진다. 눈 앞에 있는 오류는 잘 잡아내지만, 여기저기 퍼져있는 오류를 놓치는 경우가 종종 있다.
메모에 적힌 위 두 줄이 의미하는 바는, 이렇게 상반된 성질을 갖는 두 기술의 장점을 결합하는 것이 가능할까라는 의문이다. 프로그램의 전체가 아니고 특정 지점에 있는 오류만 대상으로 하는 분석 기술로 실현될 수 있지 않을까? 비록 목표지점은 한 군데이지만, 그 한 군데의 의미를 파악하기 위해서는 결국 관련 문맥을 파악해야한다. 그리고 그렇게 파악된 문맥을 따라서만 집중해서 세밀히 관찰하면 그 지점의 오류를 쉽게 찾아낼 수 있을 것 같다. 그런데 어떻게 해야할지 모르겠다. 여기까지가 그 시절 생각의 끝이었을 것이다.
카이스트에 온 이후에 저 두 줄의 존재는 까맣게 잊고 있었지만, 비슷한 필요성은 관련 연구를 하는 우리 연구실 학생들과 종종 논의를 했었다. 예를 들어, 오류를 수정하고 수정본이 맞다는 것을 검사할 때에도 위와 같은 특정 지점의 오류를 찾아내는 기술은 필요할 수 있다.
그러던 중 이 문제를 풀 기회가 찾아왔다. 기록을 보니 2021년 8월 26일인 것 같다. 우리 학부의 차상길 교수님을 통해서 지향성 퍼징 (directed fuzzing)이라는 기술을 알게 되었다. 프로그램 내의 한 지점만을 목표로 해서 자동으로 테스트 케이스를 생성하는 기술이었다. 그런데 기존 기술들이 아직 초보적이라고 한다. 그래서, 우리 연구실의 소스코드 정적 분석 연구 경험과 차 교수님 연구실의 퍼징 연구 경험을 합쳐 제대로 된 지향성 퍼징 기술을 만들어 보자고 제안을 하셨다. 분명 정적 분석을 이용하면 오류로 가는 길을 제대로 밝힐 수 있을 것이고, 길이 아닌 곳을 계속 탐색하느라 에너지를 소모하는 기존 기술들을 이길 수 있을 것이라는 차 교수님의 착안이었다. 그 이야기를 듣는 순간 번쩍 떠오른 기억이 있었다. 펜실베니아 대학에서 연구원으로 일하던 시절, 오류의 패턴에 관해 탐구하던 중이었다. 전체 오류 실행 경로 중 오류의 핵심 원인과 관련이 있는 지점의 비율은 얼마나 되는지 측정해본 적이 있었다. 수 만에서 수 백만 단계로 이어지는 실제 실행 경로 중 대략 열 지점 정도만이 오류의 핵심과 연관이 있었다. 비록 몇개 안되는 프로그램에서 단순한 오류를 갖고 한 실험이었지만, 성공을 가늠하기엔 충분했다. 컴퓨터를 뒤져서 그 때 작성한 자료를 차 교수님과 공유하고 의기투합을 하였다.
당시 우리 연구실에 막 들어와서 관련 논의를 하던 태은이와, 차 교수님 연구실에서 박사 학위를 받고 지금은 서강대의 교수가 된 최재승 박사가 고된 일을 도맡아서 했다. 우리가 하는 일이 대부분 그렇지만, 핵심 아이디어는 간단한데 실현하는 데 까지 매우 오래 걸린다. 실제 프로그램을 가져와서 하나하나 정적 분석하고, 컴파일하고, 실행하는 고생이 여간 어려운 것이 아니다.
하지만, 한 개인 혹은 연구팀의 실력과 노하우는 역설적으로 지적능력보다 그러한 노가다 능력에 있다. 다양한 아이디어를 많이 내는 것도 당연히 중요하다. 하지만, 우리가 내는 아이디어가 한 방에 성공할리가 만무하지 않은가. 따라서 그것을 빨리 현실에 적용해보고, 빨리 실패해 보는 것이 중요하다. 그래야 안되는 이유 하나를 더 빨리 배울 수 있고, 결과적으로 빨리 성공에 이른다. 여러 위대한 학자들이나 책에서 빨리 실패하는 것을 강조하는 이유이다.
다행히도 이런 쪽에 경험이 풍부한 최재승 박사가 있어서 일이 순조로웠다. 우리가 사용할 정적 분석기도 최 박사가 석사과정 때 질리도록 두들겼던 도구라서 식은죽 먹기였다. 차 교수님도 늘 날카로운 통찰과 직관으로 추진력을 불어넣어 주었다. 대학원에 처음 들어온 태은이는 처음에 약간 당황한 듯 했다. 아마 대학원이란 곳이 고상하게 앉아서 머리를 굴리는 데인 줄 알았는데, 허구헌날 실험 세팅으로 날밤을 샐 줄은 몰랐을 것이다. 누구나 처음에 그러한 충격을 받는다. 몇 달 쯤 지나서는 걱정스런 낯빛으로 조심스레 물었던것 같다. 핵심 연구 문제를 푸는 것보다 세팅에 시간이 더 오래 걸리는데, 실력은 언제 느는 것인가요? 걱정할 것 없다. 소림사에 가도 처음 3년은 청소만 한다카더라. 이 노가다는 이 연구 하나를 위해서가 아니라 앞으로 할 연구 다섯 개를 위해서 하는 것이다. 칼 하나 제대로 갈아놓으면 앞으로 눈에 보이는 대로 썰고 다닐 수 있다. 견뎌라. 버텨라. 참아라.
그렇게 시작된 연구는 약 2년이 흐른 후, 지난 주 USENIX Security 학회에서 태은이가 발표하는 것으로 세상에 첫 발을 내딛었다. 석사 입학과 동시에 시작하여 졸업과 함께 끝이 났으니 제법 멋진 궤적이다. 결과는 DAFL 이라는 논문과 도구로 공개했다. 발표도 매우 잘했다고 현장에서 많은 사람들이 나에게 축하인사를 건네왔다. 혹자는 발표를 잘 하도록 가르치는 방법이 있는지 물었다. 글쎄. 똑같은 내용으로 발표를 한 스무번 정도 하면 되지 않을까? 우리 연구실에서는 번갈아가며 대략 두 달에 한 번 정도 발표를 한다. 따라서 2년이면 12번 정도 연구실 구성원들 앞에서 발표를 하는 셈이다. 추가로 방학마다 두 번씩 국내 관련 연구자들 앞에서 발표를 하니 2년이면 8번 정도. 도합 스무번을 발표하고 하고 또하고 또하고. 슬라이드가 뼈에 새겨질 정도로 했으니 충분히 길이 들었을 것이다.
이것이 운 좋게도 재활용품 수거함을 열지 않고 재활용을 한 이야기이다. 정적 분석으로 길을 밝히고 동적 분석으로 재빨리 오류를 포착하는 방법. 각기 단점이 있지만 장점을 결합하여 더 나은 기술을 만드는 것. 장님과 앉은뱅이가 강을 건너는 것과 같은 이치이다. 나로서는 오래 묵은 숙제를 해결한 느낌이다. 2016년의 나에게 부끄럽지 않게 되었다.
이 글을 쓰기 위해 다시 수거함을 열었는데, 역시 재활용 가능성이 전혀 없어 보이는 쓰레기로 가득하다. 지난 학기에 버린 쓰레기도 몇개 보인다. 이 중에 어떤 것이 언제 나도 모르는 새에 또 재활용이 될 지? 그 때는 또 누구와 어떤 칼을 갈고 있을지? 아, 참고로 그 때 갈아놓은 칼은 지금은 날이 제대로 서서 태은이와 그 동료들이 여기 저기를 썰고 있다.