본문 바로가기
Programming

소프트웨어 크랙을 막기 위한 방법

by BITINITIALIZE 2008. 2. 26.
728x90

사용자 삽입 이미지
















<그래텍의 곰인코더 FAQ중 안습적인 일부>

이게 소프트웨어 업계의 현실이다.
상당히 괜찮은 소프트웨어를 개발하더라도 당장 크랙과 복제부터 걱정해야 하는 것.
이에 난 초보 개발자들에게 몇가지 조언을 하려 한다.




1. 소프트웨어의 크랙을 막기 위한 방법



소프트웨어의 크랙을 막기 위한 방법이라....고 제목은 쓰여 있지만 사실 그 딴건 없다.

소프트웨어를 공개하고 엔드유저의 PC에 설치된다면 이미 그건 크랙에 노출되어 있는 것이다.

수 많은 시간과 노력을 들여서 제작한 원천 기술이 포함된 제품을 등록한(구입한) 소수의 사용자에게만
실행되기를 바란다고 가정하자.

아마도 당신은 셰어웨어(Shareware)의 형태로서 공개를 고려하고 있는지도 모른다.
그렇다면 추가적으로 해야 할 일이 즉시 머리속에 그려질 것이다.

아마도 대부분의 개발자는 등록키를 생성해야 하는 코드를 만들고와 입력된 등록키를 검증하는 코드를
소프트웨어에 추가함으로서 정상적으로 구입한 사용자에게 등록키를 발급해서 등록을 유도할 것이며,
등록 절차가 끝나면 해당 기능의 잠금을 해제하여 소프트웨어에 포함된 모든 기능을
정상적으로 사용할 수 있도록 만들 것이다.

이부분만 놓고 보자면 여기서 크게 3가지의 취약점이 존재한다.
공격자(크래커, Cracker)의 입장에서 생각해보자.

등록키를 생성하는 것...즉 시리얼 넘버 생성기는 개발자만 보유하고 있을 것이므로
등록키 생성하는 부분에서의 취약점은 존재하지 않는다.

두번째를 보자.
바로 사용자가 발급받은 등록키(시리얼넘버)를 입력하고 등록 혹은 확인 따위를 누르는 순간
공격자는 등록키가 올바른지 틀린지 검증하는 부분 따위를(JE, JNE) 찾으려고 할 것이다.
이부분에서 취약점이 존재하게 되며

해당 루틴이 정말 잘 숨겨져 있어서 크래커가 쉽게 찾지 못할 경우라 할지라도 안심할 수 없다.
공격자가 상당히 하드코어적이라면 많은 고생하더라도 등록키 검증 루틴을 역으로 추적해서 분석하고
등록키 생성 루틴을 완전히 이해해서 키젠을 만들어 버릴지도 모른다.
바로 여기서 취약점이 존재한다.

세번째, 현존하는 대부분의 셰어웨어의 경우 모든 기능이 포함되어 있고 시리얼넘버를 입력함으로서,
평소에는 사용하지 못하는 잠겨있는(LOCKED) 기능이 해제되게 된다.
모든 기능을 가지고 있다는 것 이 자체만으로도 취약점이 존재한다.



이걸 대체 어떻게 하면 막을 수 있을까.....

결론부터 말하자면 불가능하다.

미션 임파서블 4가 제작된다는 가정하에 탐 크루즈가 프로그래머로서 크랙을 완전히 막기 위한 소프트웨어
개발자의 역할이라면 아마도 제작진은 영화 제작을 포기해야 할 것이다. 말그대로 불가능하기 때문이다.

그렇다면 난 왜 이런 뻘글을 쓰는 것인가...

불가능하지만 공격자에게 최대한의 어려움을 줄 수 있다는 것..그게 우리 개발자가 가진 유일한 힘이다.


소프트웨어를 공개한다면 또한 그것이 셰어웨어라면 어차피 크랙당하는 건 기정사실이니까
이 부분은 담담하게 받아들이자.

그러나!!!! 크랙하는데 최대한의 어려움을 주고 크래커를 골치아프게 해서 크랙을 포기하게 만들거나,
레벨 90 고수 이상의 크래커 외에는 '크랙실패'라는 뼈아픈 패배의 맛을 보여주자는 것이다.



2. 알고리즘은 최대한 어렵게 어렵게

당신이 대학교를 갓 졸업하거나 이제 막 취업하여 한창 열정적으로 일하고 있다면
복잡한 코드보다는 깔끔하고 직관적인 코드를 작성하기를 선호할 것이다.

당신이 좋은 프로그래머라는 사실은 알고 있다.
아마도 당신은 본인 스스로 또는 같이 작업하고 있는 동료 팀원을 위해서 깔끔하고
이해가 쉬운 코드를 작성하려고 할 것이다.
그러나 당신에게 내려진 미션이 시리얼넘버와 관련된 것이라면 직관적인 코드는 버려라.

시리얼 생성이나 비교 알고리즘이 들어가야 한다면 직관적이고 리딩이 쉬운 코드보다는
난해하고 어려운 코드를 짜도록 하라.
본인 스스로도 코드를 한참 동안 들여다 보고 트레이스 해야 이해할 정도로 어렵게 짜도록 하라.
만약 꽤 긴 시간이 흐른 후에 보았을 때 이해가 가지 않을 수도 있다.
다른 팀원을 위해서라도 주석을 세부적으로 달아놓도록 하되, 최대한 이해불가능한 코드를 작성해야 한다.

이 부분은 타협되어선 안된다.

이게 무슨 헛소리인가? 이해불가능한 코드를 짜라니?
우리가 그토록 읽어오고 공부해왔던 내용과는 전혀 상반된 이야기를 하고 있다니...
대체 내가 무슨 소리를 하는거지?

여기서 우리는 팀원을 위한 코드도 아니고 나를 위한 코드도 아니고 성능을 위한 코드를 작성하는 것도 아니다.
우리는 크래커가 디스어셈블 따위를 했을 때 크래커 본인이 들여다 보아야할 코드를 이야기 하는 것이다.
그 코드를 어렵게 짜도록 함으로서 크래커를 짜증나게 하자는 것이다.


3. 정크 코드의 대량 삽입

프로그래밍 세계에서의 정크 코드는 쓸데 없고...불필요한 코드를 말하는 것이다.
네이버 영어사전에는 '허섭쓰레기'라는 글귀도 보인다....-_-;

아무튼 보호장치가 되어 있는 루틴에 정크(Junk) 코드를 대량으로 삽입해서 크래커를 혼란스럽게 하자.

그러나 유의해야 할 점은 이 정크 코드도 정상적인 코드와 연계되어 반드시 무언가 액션을 취해야 한다는
것이다. 보호장치의 루틴과 관련된 변수를 공유해서 사용하며 정크 코드 자체만으로는 특별한 의미가
없도록 코딩한다.

정상적인 변수를 포함하여 수 많은 변수와 수 많은 연산을 사용하고 다른 함수(function)을 콜(call)하거나,
객체지향 프로그래밍에서의 금기사항으로 일컬어지는 goto 문도 적절히 사용해서
우리 불쌍한 초보 크래커에게 '여기서 왜 다른곳으로 분기되는지' 이해하는데 오랜 시간을 보내도록 작전을 짜자.


4. 인터넷과의 연동

과거에는 상상도 하지 못했던 일이지만 지금은 너무나 당연시 받아들여지고 있는 일이기도 하다.
프로그램의 제한사항으로 '인터넷 연결'을 필요로 한다고 제한사항을 붙이는 것이다.

그럼 무엇을 하려고 인터넷을 연동하라는 것인가?

사용자의 PC가 인터넷이 연결된 PC라고 가정하고 당신이 만든 프로그램을 설치하고 시리얼 넘버를
입력했을 때 서버로 전송하는 것이다.
물론 이 때 서버는 웹서버가 될 수도 있고 소켓 서비스를 하는 어플리케이션일 수도 있다.
취향에 맞게 구성하면 되는 것이다.

그렇게 되면 시리얼 넘버의 비교나 검증 루틴을 프로그램에서 빼버릴 수 있기 때문에 프로그램이 조금 더
가벼워지게 되며, 크래커의 분석이 용이하지 못하게 되며, 중앙(회사 또는 개발자PC)에서 보다 효율적인
관리를 할 수 있게 된다.

물론 이 경우에도 취약점도 존재한다.... 아 먹고 살기 힘드네... ㅜ_ㅜ

우리는 항상 크래커의 입장에서 생각해야 한다.
크래커는 소프트웨어의 등록이 인터넷의 연결을 필요로 한다면 반드시 패킷을 훔쳐보려고 할 것이다.
WinPCap를 사용하는 다양한 종류의 소프트웨어가 있는데 이것을 사용하면 게이트웨이에서
내 PC로 오고가는 모든 패킷을 볼 수 있다. 그러므로 등록절차를 할 때 서버와 오고가는 패킷을
분석해서 크랙에 도움을 줄 수도 있다.

반드시 모든 패킷은 암호화하자. 암호화가 풀릴 수도 있기 때문에 모든 암호화된 패킷을 검증할 수 있는
체크섬 루틴도 반드시 포함하자...
(초보들을 위한 주 : 패킷을 볼 수 있다는 것은 패킷을 조작할 수도 있다는 것을 의미한다)

단, 암호화된 패킷과 별도로 패킷을 분석하기 위해 들여다 보고 있을 크래커를 위해서
do not try crack this shit! fuck you! 와 같은 쉽게 식별가능한 Plain Text도 종종 넣어주자. ^.~


5. 암호화는 해야 한다 그래야 나도 먹고 살지 from Hacker


시리얼 넘버나 제품번호 기타 일반적으로 이야기하는 '등록(registration)'과 관련되는
모든 코드에서 사용되는 중요 알고리즘에 반드시 암호화를 포함하도록 하자.

2중 3중으로 암호화를 해도 모자를 판이다. 귀찮더라도 반드시 하자.
Win32에는 암호화를 쉽게 할 수 있도록 Crypt 라이브러리가 있으며 공개 라이브러리도 많다.

물론 이 경우에도 취약점은 존재한다...아 먹고 살기 힘드네... ㅜ_ㅜ

암호화를 사용한 흔적이 발견되면 아마도 크래커는 암호화와 관련된 부분은 Skip하고
적어도 키젠 생성 따위는 포기할 수 있을지는 몰라도 전체적인 흐름(Flow)만을 보고 등록 성공과
실패에 관련된 제어 부분을 공략하려 할 것이다.


6. 용병을 고용하자

여기까지만 보았을 때 우리는 개발자 스스로가 작성한 코드는 쉽게 노출이 된다는 것을 알 수 있다.
하지만 우리는 크래커와 달리 선택권이 많다. 즉, 많은 다양한 방패로 막을 수 있다는 것이다.


게임 디아블로2를 해본 적이 있는가? 마을에서 돈을 주고 나를 위해 싸워주는 용병을 구입할 수 있다.

개발자의 힘만으로는 한계가 있으므로 우리도 돈을 주고 용병을 고용하자.
코드를 난독(Fuscator) 처리해주는 도구가 있다. 어떤 툴은 최대 80%까지의 코드 난독 처리가
가능하다고 하니 이 정도면 중수 정도의 크래커라 할지라도 GG칠지 모른다.

난독처리와 함께 압축 기법을 사용하면 더 좋다.
실행 파일 자체를 압축하거나 암호화하고 난독 처리를 해서 하나의 강력한 완전체(?)를 만드는 것이다.

물론 이 경우에도 취약점은 존재한다...아놔 진짜 먹고 살기 힘드네... ㅜ_ㅜ 어쩌란 말이냐...

자 이제 2가지의 비밀무기를 공개하겠다.


/*
실행 파일 패킹과 관련된 이야기 하나할까요?

본인이 고등학교 1학년때 도스와 함께 윈도우 95를 함께 쓰던 시절이었는데 그 때까지만 해도
V3+ Neo를 쓰던 시절(임형택 님이었나? 터보백신과 함께 경쟁하던 시절)이었습니다.
그 정도로 V3가 잘나가는 시절이었습니다.
그러던 어느날 호기심에(진짜임..다른 이유는 없음) V3를 분석해보고 있는데 PK라이트로
패킹되어 있다는 걸 알았습니다. 그래서 PKUNLITE로 언팩을 시도해 보았으나 이게 웬일?
언팩할 수가 없다는 메시지가 뜨더군요.

정식으로 구입한 제품으로 패킹할 경우 언팩할 수 없도록 하는 옵션이 있어서 V3+ Neo는
언팩이 불가능한 것이었습니다.

당시 나는 TC++ 3.0으로 PC툴즈 비스무리한 유틸을 만들고 있었는데 저 역시 PK제품을 쓰고 있었습니다.
전 외국 제품이라 구입하는 절차도 잘 모르겠고 해서 비등록판을 쓰고 있었는데
어느 날 V3+ Neo를  다양한 버전을 구해서 Hex Editor로 분석해보다가
Pkware.... 문자열 바로 앞이 항상 01 값이라는 걸(아마도 맞을겁니다. 기억이 조금 가물가물한데...)
알게 되었습니다. 그래서 제가 만든 프로그램를 PKLITE로 패킹하고 00을 01로 바꾸고
언팩을 시도해보았는데...이게 웬일? 언팩할 수가 없다는 메시지가....ㅋㅋ
단 1바이트만을 바꾸었는데 정식 프로그램과 똑같은 기능을 사용할 수가 있다는 것이지요.
그래서 그 이후부터는 항상 PK라이트로 패킹한 다음에 00을 01로 바꾸곤 했습니다.
*/



7. Build with Description

크랙과 암호화는 창과 방패의 싸움으로 불리곤 한다.
무엇이든 막을 수 있는 방패와 무엇이든 막을 수 있는 창의 싸움이다. 과연 누가 이길까?

이 꽤 긴 글을 읽을 동안 아마도 당신은 방패가 이길 수 없다는 사실은 알고 있을 것이다.

그렇다면 생각을 달리하자.
방패가 이길 수는 없다...그렇다면 어차피 지는 게임이면 아예 하지 않는게 좋을지도 모른다.

뭐하러 어렵고 머리를 쥐어뜯고 돈까지 써가며 막으려고 하는가...어차피 깨질 코드인데.

그리하여 나온 것이 바로 BWD(Build with Description) 이다. 이건 내가 지어낸 이름이다.
바로 주석 빌드를 하는 것이다.

여러분이 작성한 원천 기술, 즉 핵심 코드를 포함하지 말고 주석처리한 후에 빌드하는 것이다.

즉 알맹이가 없는 껍데기와 같은 데모(Only Demonstration) 프로그램이다.
해당 기능이 없으니 크래커는 뚫으려고 노력하지도 않을 뿐더러 사실 여부를 모르는 크래커는
삽질이나 반복하다가 접을지 모른다.

아니 뭐 이딴 프로그램이 다 있어 할지 모르나 이미 꽤 많은 어플리케이션에도 적용된 방법이다.
해당 프로그램의 이름을 여기에 나열할 수는 없으니 이해하기 바란다.



8. NO PUBLIC + MONITORING

크랙을 막을 수 있는 가장 강력한 방법이다.

바로 공개하지 않는 것이다.

공개하지 않으면 크래커는 구할 수 조차 없으니 그림의 떡일 뿐이다.

오직 구입한 사용자에게만 프로그램을 보내주기만 하면 된다.
그렇게 되면 우리는 우리의 프로그램이 공개되는지 현존하는 거의 모든 웹폴더와
강력한 인터넷 검색 엔진을 사용해서 인터넷(카페, 블로그, 커뮤니티 사이트 등)을 모니터링만 하면 된다.

그럼 여러분은 아마도 구입한 사용자가 배포할 수도 있지 않느냐고 반문할지도 모르겠다.

당연하다.
물론 이 경우에도 당연히 프로그램내에 보호할 수 있는 기술적 조치가 취해져야 한다.
본인이 가장 최근에 개인적으로 개발한 메일 전송 프로그램 AnySend2008도 NO PUBLIC 정책을
유지하고 있으며 적절한 보호장치가 포함되어 있다.

단 이 경우에도 취약점은 있다.
구입한 사용자가 레벨 90 이상의 크래커라서 보호장치를 무장해제하고 배포하면 게임 오버이다.

아놔 먹고 살기 힘들다....ㅜ_ㅜ


9. 결론

어떠한 보호장치를 채택하던지 어떠한 암호화를 적용하든 완벽한 크랙 방지는 불가능하다.

크랙을 완벽하게 방어하기 위해서는 위에 열거한 모든 방법을 적용하고 지속적인 관심이 필요하다.
개발자들은 만드는 입장이기 때문에 크래커보다는 처음부터 많은 선택권이 주어지지만
방심은 금물이다.

암호화? 필요없어. 이건 꽤 난해하게 만든 코드니까 안전하겠지? 이 루틴이 하는 일은 절대 알아낸지 못할거야.

알아낸다. -_-;

본인 스스로가 완벽하게 안전하다고 생각하다면 꽤 많은 노력을 들였다고 생각되지만
공개되는 순간 이미 지는 게임이다.

당신의 코드가 안전하기를 바라기 보다는 이 글의 가장 위에 그래텍에서 만든 곰인코더의 FAQ에
나와있듯이 적당한 애교와 적절한 인정을 바탕으로 하는 호소를 하는 편이 효과적일지도 모른다.

그럼에도 크랙과 복제물이 돌아다닌다? 어쩔 수 없다.
법은 우리편이다. 프로그램을 공개하면 그에 맞는 법적인 조치를 취하도록 하자.


저는 이 글에서 초보 개발자들을 위해 몇 가지 대안을 제시합니다. 물론 완벽한 방법은 아닙니다.

그러나 인터넷상에서 크랙강좌 조금 읽어보고 크랙미 몇 개 풀어본 게 전부인 Newbie들에게는
충분한 대응를 하는데 도움이 될 것입니다....
저도 예전부터 크랙에 대한 공부는 계속 해왔습니다만, 파고 들면 파고 들수록 어렵습니다.

개발자들에게 가장 필요한 것은 지속적인 관심과 공부입니다.
마지막으로 하고 싶은 말.....


아놔 먹고 살기 진짜 힘드네...ㅜ_ㅜ
728x90

댓글