[소고] 게임 보안: 커플링에 관한 오해들…

@codemaru · April 24, 2012 · 18 min read

게임사 미팅을 해보면 흔하게 겪는 일 중에 하나가 커플링에 관한 오해들입니다.

반지는 아니구요. ㅋㅋ 게임과의 결합도가 높은 보안 코드에 대한 이야깁니다.

소프트웨어 공학에서는 모듈간의 의존도 내지는 결합도를 나타내는 척도로 커플링이란 단어를 쓰거든요. 결합도가 낮으면 느슨한 결합이라고 하고 결합도가 높으면 강한 결합이라고 한답니다. 어떤게 좋을까요? 당연히 소프트웨어 공학에서는 커플링이 낮은 수준이 닥치고 갑입니다. 결합도가 높다는 건 덜 모듈화 됐고, 고치기 쉽지 않으며, 수정할 때 오류가 발생하기 쉽고, 유지보수 하기가 까다롭다는 그 모든 것을 의미합니다. 그래서 커플링을 피해야 할 그것으로 간주하죠.

하지만 요사이 많은 부분에서 게임보안 제품과 게임은 커플링이 높아지는 것이 필연적일 수 밖에 없다는 주장이 제기되는 것 같아서 몇 가지 사례별로 생각을 정리해 보았습니다. 자 그럼 과연 커플링이 높아야 해킹툴을 잘 잡는다는 말이 진실인지 아닌지 한 번 살펴볼까요? ㅎㅎ~

#0

언제부턴가 게임보안 업체들 사이에서 서버에 게임보안 코드를 탑재하는 것이 일반화 됐습니다. 저희가 XIGNCODE라는 제품을 개발하던 초기만 해도 서버 쪽에 코드를 탑재하는 것을 두고 게임 서버 개발자들 사이에서 반감이 굉장히 많았습니다. 그랬던 것이 요즘은 대부분 다 기본적으로 코드를 탑재해야 된다고 생각하시니 감사할 따름입니다. 격세지감도 좀 느끼고 그래요. 여튼 이러한 서버 코드 탑재와 함께 따라온 잘못된 관습(?!) 중에 하나가 클라이언트가 빌드될 때마다 서버에 클라이언트 해시 데이터를 업로드하는 것입니다. 보안 코드에서는 서버 쪽과 클라이언트를 비교해서 다른 경우에 끊겠다는 것을 목표로 개발된 기능인 것 같습니다. 매우 강한 결합 중에 하나죠.

이 경우에 실수가 발생할 소지는 굉장히 다분합니다. 관리자가 서버 쪽에 해시 데이터를 업로드 하는 것을 빼먹거나, 서버에 올린 해시 데이터와 다른 클라이언트가 패치 된다거나 하는 등의 실수 개입 요지가 많습니다. 근데 뭐 실수는 안한다고 차치하더라도 이 방법이 그다지 좋지 않은 이유는 대부분의 게임에서는 이런 조치가 전혀 필요하지 않기 때문입니다. 도둑이 모두 창문으로 넘나드는데 창문은 지키지 않고 정문을 유지보수 한다는 느낌일까요? 이런 이야기를 하면 꼭 그럼 정문은 안지켜도 되는거냐? 라고 물으시는 분들이 계신데 현실 세계에서 리소스는 항상 제한적입니다. 따라서 그 정문 지키는 리소스로 도둑이 드나드는 다른 곳을 지키는 것이 백배 더 현명하다는 이야기입니다.

그렇다면 게임 서버에 탑재되는 코드에서 해야 하는 일은 무엇일까요? 바로 실행 보장입니다. 게임보안 제품은 외부 라이브러리 형태로 제공되기 때문에 인터페이스가 노출되면 손쉽게 바이패스될 수 있습니다. 이런 경우를 검증하기 위함입니다. 즉, 모든 것들이 다 제거되고 우회되고 변경되더라도 단 하나 이거는 그래도 실행된다고 보장할 것이 필요하다는 것이죠. 그게 바로 서버에 적용된 코드가 해야 하는 일입니다. 실행 보장만 되면 변경된 지점을 찾아내는 것은 언제든지 할 수 있거든요. 하지만 실행 보장이 되지 않으면 백날 변경 지점을 찾는 코드를 넣어봐야 효과도 없습니다. 변경 지점을 찾는 그 코드가 변경될꺼거든요.

그리고 뭔가를 변경한다는 자체가 굉장히 오래된 발상입니다. 요즘 트렌드는 노모디피케이션입니다. 즉 아무것도 바꾸지 않고 바꾼 것과 동일한 효과를 내는 방법들이라는 것이죠. 왜냐면 해커들도 이제는 다들 알거든요. 뭔가를 바꿔서는 너무 쉽게 탐지된다는 사실을요.

#1

오토, 매크로 프로그램과 특정 기술을 무한대로 사용하게 하는 핵들은 게임 내 특정 함수를 불법적으로 호출하는 기능을 통해서 많이 구현됩니다. 예를 들어서 레이싱 게임이라면 부스터 가속을 시키는 함수를 들 수 있습니다. 외부 해킹툴은 그런 함수를 불법적으로 계속 호출합니다. 이렇게 만들어진 것이 무한 부스터 핵입니다. 이런 기법이 게임 개발자들 사이에도 많이 퍼져서 요즘 흔하게 나오는 질문 중에 하나가 보안 프로그램이 특정 함수를 보호할 수 있는 기능을 제공하는가 물어보십니다. 이 기능이 제공되면 게임 개발자가 생각하기에 위험하다고 생각하는 함수 주소를 전달해서 불법 호출을 막겠다는 생각인거죠.

과연 효과적인 전략일까요? 솔직히 무용지물입니다. 게임 내 랙만 증가시킨다고 보시면 됩니다.

일단 기본적으로 반환 주소 체크 기법은 return address morphing이란 테크닉에 의해서 너무 쉽게 무력화됩니다. 그런 기법을 방어하기 위해서는 코드를 트레이싱해서 추적해야 하는데 해당 게임 함수 런타임에 이런 체크를 깊이 하게 되면 부하가 증가됩니다. 따라서 일정 범위 밖에 체크를 못하죠. 즉 우리가 N Depth를 추척하는데 상대가 N+1 Depth를 사용하면 그냥 우회된다는 겁니다. 참고로 이런 것들을 인식하고 N Depth를 검사하도록 넣은 보안제품도 잘 없답니다. 안타까운 현실이죠.

근데 더 안타까운 사실은 이러한 체크 기법이 후킹이란 방식에 의존하는데 제작자 입장에서는 해당 후킹 포인트를 지나서 함수를 호출하는 것 또한 너무 쉽다는 겁니다. 물론 이것도 방어하기 위해서 동적 코드 분석을 한 다음에 애매한 위치에 알박기를 할 수도 있지만 소프트웨어의 견고성만 떨어질 뿐 크게 효과적이진 못합니다.

진짜 최고로 안습한 사실은 해당 함수 주소를 차단하면 해커는 다른 함수를 찾아낸다는 겁니다. 100% 말이죠. 그래서 효과적이지 않습니다. 여러분이 해커와 같은 속도 내지는 해커보다 빠른 속도로 해커가 다시 찾아낸 그 함수를 찾아낸다 해도 효과는 없습니다. 그냥 하나의 경쟁 루프를 만들어낼 뿐이거든요. 상호 패치 공방 밖에는 벌어질 수 없는 방식이란 거죠.

저희도 중국 유료 해킹툴에 이 기법을 몇 차례 적용했었는데 별 재미를 못 봤습니다. 왜 재미를 못봤냐구요? 우리는 일주일이 걸려 겨우 그 함수를 찾았습니다. 그래서 이제 막으면 원천 차단이 되겠다 생각했죠. 근데 넣고 하루만에 다른 함수를 호출하더군요. 다시 일주일을 분석하느니 그냥 그런 방법은 개나 주는 편이 낫겠다고 생각했습니다. 저희는 다른 방법을 선택했고 그 해킹툴은 3월 2일부로 영원한 수면에 들어가셨습니다. ㅋㅋ~ 이 사례를 통해서 전 교과서에 나오는 방법들이 생각보다 훨씬 더 실전에서 쓸모가 없다는 저의 생각을 좀 더 굳히게 됐습니다.

XINGCODE로 인하여 3월 2일부로 영면하신 그 비운의 해킹툴…

XINGCODE로 인하여 3월 2일부로 영면하신 그 비운의 해킹툴…

저희가 커플링 높은 인터페이스를 게임 개발자들에게 권하지 않는 이유는 이런 겁니다. 첫째는 게임 개발자가 스터디를 해야하는 보안 제품을 만들어서는 안 된다고 생각하기 때문입니다. 여려분이 자동차를 사는데 그 엔진 구조를 모르고는 시동도 걸 수 없는 차라면 사시겠습니까? 저같으면 그런 건 개나 줄 것 같거든요. 다른 하나는 이러한 테크닉의 경우 자칫 남용되거나 내부 구현을 모르고 사용했다가는 게임 내 부하만 증대 시키고 해킹툴을 막는대는 하나도 보탬이 되지 않기 때문입니다. 결국 출혈을 감수해 가면서까지 가져간 높은 커플링으로 볼 수 있는 재미는 하나도 없다는 이야기입니다.

물론 잘 아시겠지만 여러분이 모르는 그런 곳에 이 반환 주소 체크 기법을 사용해서 재미를 볼 수 있는 곳은 많이 있습니다. 당연히 그런 건 여기다 적진 않겠죠? 단물 좀 더 빼먹고 누구나 알게 될 즈음에 마치 제가 처음 발견한 마냥 교과서에다 공개하겠습니다. ㅋㅋ~

#2

끝으로 요즘 가장 핫한 데이터 중에 하나인 DirectX 인터페이스 주소를 좀 살펴보겠습니다. DirectX 가상 함수 변조를 체크하기 위해서 해당 인터페이스의 포인터를 전달 받는 것이 이 커플링 높은 방식의 골격같습니다. 하지만 이 또한 안타깝게도 큰 의미는 없습니다. 우선 전달받지 않고도 주소를 획득할 수 있고, 무조건 전달을 받아야만 막을 수 있는 방식이 한가지 있긴 한데 그 방식은 속도 상의 이유로 실전에서 거의 사용되지 않습니다. 또한 사용한다 하더라도 다른 루트를 통해서 검출할 수 있습니다.

전 이런 방식을 사용해 본 업체들에게 페르미의 역설처럼 한 번 여쭤보고 싶습니다. 달라고 하는 DirectX 인터페이스 주소를 가르쳐 주셔서 재미 좀 보셨습니까? 라구요. 아마 그닥 재미를 못 보셨을 겁니다. 인터페이스를 조작하는 해킹 방식은 제가 지난 번에 썼던 것처럼 Visual C++ 일주일 배우고 게임 커뮤니티에서 DirectX Hook Toolkit을 받아서 월핵 샘플따라 코딩하는 경우 외에는 잘 없거든요. 참 올드 패션드한 테크닉이란 이야기죠. 요즘은 저런 방식 자체가 전문 해커들에게는 거의 사용되지 않습니다. 물론 사용하는 해커가 있다면 그건 B급 해커겠죠. 그리고 그런 B급 해커가 조작하는 것들은 인터페이스를 받지 않아도 다 차단할 수 있답니다. 그러라고 비싼 돈주고 솔루션 사서 쓰는 것 아니겠습니까?

#3

게임보안 제품을 왜 사용하는 걸까요? 해킹툴을 막기 위함일겁니다. 그런데 요 근래에 몇몇 게임 업체와 미팅을 하면서 느낀 점은 보안 제품을 해킹툴을 막는 본연의 목적이 아니라 보안 제품한테서 컨설팅을 받고 계시더군요. 그것도 잘못된 보안 컨설팅을요. 그럴 때 마다 정말 안스러움을 느낀답니다.

해킹툴을 막는 데에는 여러 수천가지 방법이 있습니다. 제가 생각하는 가장 상책은 개발사나 운영사 모두가 전혀 신경 쓸 필요가 없는 방법입니다. 중책은 개발사에서 뭔가 정보를 알려줘야 하는 방법이고, 가장 하책은 게임 업데이트를 보안 업체에 신고해야 하는 방법입니다. 왠만하면 상책을 사용하는 업체와 일을 하세요. 그게 여러분에게도 보안 업체에게도 정신 건강에 이롭습니다. 물론 저희도 과거에 ‘나는 보안이다’라면서 하책을 남발했던 경험이 있습니다. 결과는요? 상호 멘붕상태가 오더군요. 그 때 깨달았습니다. ‘아 진짜 이거 없이는 답이 없겠다 하는 경우를 제외하고는 절대로 하책을 써서는 안되겠다’라고 말이죠.

다시 한 번 기억하세요. 여러분이 사용하는 솔루션은 해킹툴을 차단하기 위한 솔루션입니다. 게임의 보안 결함을 찾아서 나열해 주는 솔루션이 아니라는 이야기죠. 더 나아가서는 해킹툴 분석 보고서를 그럴듯하게 쓰는 솔루션도, 특허를 나열하는 솔루션도 아닙니다. 단지 여러분의 그 지긋지긋하게 골치아픈 해킹툴들을 알아서 잘 차단해 줄 솔루션을 선택하세요. 그럼 게임 내 보안 결함을 찾을 필요도, 해킹툴 분석 보고서를 쓸 필요도, 특허를 나열할 필요도 없거든요. 맞습니다. 카드를 쥐고 있는 한 여러분이 갑입니다. 이제는 갑의 권리를 다시 찾아 올 때 입니다. ㅋㅋ~

right now는 빼도 된다는 거 아시죵? ㅎㅎ~

right now는 빼도 된다는 거 아시죵? ㅎㅎ~

@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중