Recently, many software products have been developed as open source projects. Adopting an open source has the advantage of saving time and cost for developing software. For this reason, not only many programmers but also many software companies actively utilize open sources. However, illegal use of open sources may violate the license because open sources are released under the corresponding license. We need to be more cautious when developing software using open source because the licenses are strictly protected by copyright law. Generally, it is hard to recover original source codes from distributed commercial software because software is distributed in a binary format. However, Java applications are easy to analyze because Java applications are usually distributed as Java bytecodes that include much information to achieve high portability. Moreover, various decompilers were developed owing to the strict specification of the Java virtual machine. Thus, in most cases we can recover source codes from Java class files through decompilers even though the original source code is not available. As a result, Java applications are one of the most frequent targets of software theft. Hence, it is essential to devise techniques to detect code theft, especially for Java.
Research on code theft has been conducted mostly on source code plagiarism detection techniques. If we can get the source code of a suspicious program, plagiarism detection may be the most effective technique. However, we cannot always get the source code because an application program is generally distributed in compiled binary format. There is another research, code clone detection, for software theft detection. Code clones are duplicated code lines of programs. If two different programs have code clones, we can suspect those programs as copied programs. However, such code clone techniques need source codes of two compared programs like code plagiarism detection. To identify copied software, software watermarking is one of the most credible methods that prove copyright. However, it is not applicable to software that has already been distributed without embedded watermarks. When a program has already been distributed without a watermark, a birthmark can be considered as an alternative method. The software birthmark is an inherent characteristic that can be used to recognize or identify a program. If the same or similar birthmarks are extracted from two programs, we consider that the two programs may be in copy relation. In this thesis, we propose three static trace birthmarks to detect software theft.
First, an instruction trace birthmark for Java methods is presented. Because the static instruction traces can reflect the algorithmic structure of a program, they can be used to detect algorithm theft that existing static birthmarks cannot handle. Moreover, because the static instruction traces are extracted by static analyses, they can be applied to library programs with which previous dynamic birthmarks cannot deal. We evaluate the proposed birthmark with respect to two criteria: credibility and resilience. Experimental result shows that our birthmark is more resilient than and at least as credible as the existing Java birthmarks.
Second, an API trace birthmark for Java programs is suggested. The static API trace birthmark is the set of all possible run-time API traces of each Java method. Unlike existing birthmarks, the static API trace birthmark does not simply extract adjacent API sequences but analyzes the control flow of methods and generates the possible run-time API traces. Because the API traces can reflect the behavior of a program, our birthmark is more resilient than other static birthmarks. We evaluate the API trace birthmark in terms of credibility and resilience. Experimental results show that our birthmark can detect common library modules of two packages while other birthmarks fail to detect.
Third, an object trace birthmark for Java packages is presented. Because Java is an object-oriented programming language that provides various predefined class libraries, it helps programmers to produce software easily. In order to utilize Java class libraries, we have to use Java object instructions. The Java object instructions are hard to be replaced or removed, so a set of sequences of object instructions is a proper candidate of inherent characteristics of a program. We evaluate the static object trace birthmark with open source programs and compare it with previous static birthmarks. Experiments show that the detection capability of our birthmark is much higher than that of other static birthmarks despite obfuscations by Smokescreen and ZKM.
오늘날 세계적으로 수많은 소프트웨어들이 시시각각 작성되어 배포되고 있다. 소프트웨어는 각 기업들이 기울인 노력의 산물이기 때문에 소프트웨어 개발에 대한 노하우와 프로그램의 원본 소스 코드(Original Source Code)는 철저하게 비밀로 유지되어 왔다. 그러나 최근에는 오픈 소스 커뮤니티(Open Source Community)가 성장하면서 많은 소프트웨어들이 오픈 소스 프로젝트(Open Source Project)로 개발되고 있다. 오픈 소스 프로젝트는 소프트웨어 개발에 대한 정보를 서로 공유하는 개념에서 시작되었고, 많은 개발자들이 참가하여 지속적으로 성장해오고 있다. 소프트웨어를 개발할 때 오픈 소스를 활용하는 것은 개발 기간 및 비용을 단축할 수 있는 장점이 있기 때문에 많은 기업이나 개인들이 오픈 소스를 적극적으로 활용하고 있다. 그러나 오픈 소스도 정해진 라이선스(License)에 의거하여 공개되기 때문에 섣불리 오픈 소스를 사용하여 소프트웨어를 개발할 경우에는 의도하지 않은 라이선스를 위반을 야기할 수 있다.
소프트웨어 업체는 자신이 개발 중인 소프트웨어의 라이선스 위반 여부를 자체적으로 판단하여 저작권 관련 소송을 사전에 예방하는 것도 중요하지만, 업체의 집적된 노하우를 바탕으로 개발된 소프트웨어가 타 업체에 의해서 도용 당하지 않도록 보호하는 것도 매우 중요하다. 만일 다른 업체가 자사의 소프트웨어를 도용한 사실을 발견했다면 정당한 법적 소송을 통해서 해당 소프트웨어의 권리를 주장해야 한다. 일반적으로 소프트웨어는 이진 파일(Binary File) 상태로 배포되기 때문에 역공학(Reverse Engineering)이 쉽지 않다. 따라서 출시된 소프트웨어의 바이너리로부터 핵심 알고리즘(Algorithm)을 추출하거나 원본 소스를 얻어내는 것은 불가능에 가깝다. 그러나 자바 프로그래밍 언어(Java Programming Language)로 작성된 프로그램의 경우는 상황이 다르다. 자바 프로그램은 대부분 자바 바이트코드(Java Bytecode) 형태로 배포되는데 이 바이트코드는 이식성(Portability)이 높아서 운영체제(Operating System)에 상관없이 광범위하게 사용 가능하기 때문에 소프트웨어 도용의 주된 표적이 될 수 있을 뿐만 아니라, 엄격한 자바 가상 머신(Java Virtual Machine)의 명세(Specification) 때문에 다양한 역컴파일러(Decompiler)까지 개발된 상태이다. 따라서 소스가 공개되지 않은 자바 프로그램의 경우에도 대부분 역컴파일러를 이용해서 소스를 얻어낸 후 그 소스를 도용하는 것이 가능하다. 이와 같이 역공학 도구(Reverse Engineering Tool)만 사용한다면 누구나 쉽게 자바 프로그램을 도용할 수 있는 상황임에도 불구하고 그것을 탐지하는 것은 쉽지 않다.
프로그램 도용 탐지에 대한 연구는 소스 표절 검사 기법(Source Code Plagiarism Detection Technique)에서 많이 다루어지고 있다. 만일 도용이 의심되는 프로그램의 소스 코드를 얻을 수 있는 상황이라면 이 방법이 가장 효과적으로 사용될 수 있다. 그러나 일반적으로 프로그램은 컴파일(Compile) 되어 배포되기 때문에 항상 소스 코드를 얻을 수 있는 것은 아니다. 물론 이전에 언급한 역컴파일러를 사용할 수도 있다. 하지만 소스 코드를 도용한 사람이라면 도용 사실을 최대한 감추기 위해서 난독화 도구(Obfuscator)로 자바 클래스 파일(Java Class file)을 변환하여 배포하는 시나리오를 쉽게 예상할 수 있다. 이 경우에는 역컴파일이 불가능한 경우가 많다. 결국 소스 코드를 얻을 수 없는 상황에서도 자바 클래스 파일에 직접 적용할 수 있는 도용 탐지 기법이 필요하다.
이런 상황에서 소프트웨어 워터마크(Software Watermark)는 프로그램의 저작권을 증명하는 가장 신뢰도가 높은 방법이다. 소프트웨어 워터마크는 멀티미디어 워터마크(Multimedia Watermark)와 유사한 개념으로 소프트웨어 저작권 정보를 지문(Fingerprint) 형태로 소프트웨어 속에 삽입하는 방법이다. 그러나 개발자가 소프트웨어를 배포하기 전에 워터마크를 삽입하는 절차가 필요하기 때문에 워터마크가 없이 이미 배포된 소프트웨어에 대해서는 도용 탐지가 불가능하다. 그리고 워터마크를 삽입하기 위해서 부가적인 코드를 추가해야 하기 때문에 프로그램의 성능을 저하시키거나 프로그램의 크기가 커지는 문제가 발생할 수도 있다. 그리고 프로그램 전체의 도용이 아닌 클래스 단위나 메소드(Method) 단위로 도용한 경우에는 삽입된 워터마크가 검출되지 않을 수도 있다.
소프트웨어 워터마크가 사용될 수 없는 상황에서 대안으로 제시된 개념이 소프트웨어 버스마크(Software Birthmark)이다. 소프트웨어 버스마크는 프로그램의 소스 코드가 아니라 이진 파일로부터 직접 추출할 수 있으며 프로그램에 내재된 고유한 속성(Inherent Characteristics)으로 프로그램을 인식하는데 사용될 수 있는 특성을 의미한다. 만일 두 프로그램으로부터 동일하거나 유사한 버스마크가 추출되었다면 두 프로그램은 서로 도용 관계가 있다고 의심할 수 있다. 이런 목적으로 사용되기 위해서 소프트웨어 버스마크는 신뢰성(Credibility)과 강인성(Resilience)으로 표현되는 두 가지 속성을 만족해야 한다. 신뢰성이란 잘못된 탐지(False Positive)가 없어야 한다는 속성이다. 즉, 프로그램이 비록 유사한 기능을 수행하더라도 두 프로그램이 서로 소스 코드를 공유하지 않고 다른 개발자에 의해서 독립적으로 개발되었을 경우에는 도용 관계가 있다고 판단해서는 안 된다. 강인성은 난독화(Obfuscation)나 최적화(Optimization)와 같이 프로그램의 의미를 그대로 유지한 변환 기법(Semantics Preserving Transformation)을 적용하더라도 버스마크가 유지되어야 한다는 속성이다. 강인성이 필요한 이유는 프로그램을 도용하는 사람이 버스마크를 없애기 위해서 다양한 프로그램 변환 기법을 적용할 수 있기 때문이다.
본 논문에서는 소프트웨어 도용을 탐지하기 위한 세 가지 정적 트레이스 버스마크를 제안하였다.
첫째, 자바 메소드(Java Method)에 대한 정적 명령어 트레이스 버스마크(Static Instruction Trace Birthmark)를 제안하였다. 정적 명령어 트레이스는 프로그램의 알고리즘 구조(Algorithm Structure)를 반영할 수 있기 때문에 기존의 정적 버스마크가 해결하지 못했던 알고리즘 도용을 탐지하는데 사용될 수 있다. 그리고 명령어 트레이스가 정적 분석(Static Analysis)에 의해서 추출되기 때문에 기존의 동적 버스마크로(Dynamic Birthmark)는 불가능했던 라이브러리(Library)나 모듈(Module)의 도용 탐지에도 활용될 수 있다. 본 논문에서 제안한 정적 명령어 트레이스 버스마크를 신뢰도와 강인도로 평가하였다. 실험 결과로부터 정적 명령어 트레이스 버스마크는 기존의 정적 버스마크에 버금가는 신뢰도를 가지고 더 강인한 버스마크임을 보여주었다.
둘째, 자바 클래스(Java Class)에 대한 정적 API 트레이스 버스마크(Static API Trace Birthmark)를 제안하였다. 정적 API 트레이스 버스마크는 자바 메소드에서 실행될 수 있는 API(Application Programming Interface) 함수 호출의 시퀀스(Sequence)를 버스마크로 사용한다. 정적 API 트레이스는 단순히 프로그램 코드에서 물리적으로 인접한(Adjacent) API 시퀀스를 추출하는 것이 아니라 자바 메소드의 제어 흐름(Control Flow)을 분석하여 연속적으로 호출될 수 있는 API 시퀀스를 추출하는 방법을 사용한다. 따라서 정적 API 트레이스 버스마크는 프로그램의 동적인 특성을 반영하기 때문에 기존의 정적 버스마크보다 더 강인하다. 정적 API 트레이스 버스마크를 신뢰도와 강인도로 평가하였고, 실험 결과 기존의 정적 버스마크가 탐지하지 못한 공통 클래스 파일(Common Class File)의 도용을 탐지할 수 있음을 확인하였다.
셋째, 자바 패키지(Java Package)에 대한 정적 객체 트레이스 버스마크(Static Object Trace Birthmark)를 제안하였다. 자바는 객체 지향 프로그래밍 언어(Object Oriented Programming Language)이기 때문에 소프트웨어 개발을 용이하게 하기 위해서 다양한 클래스 라이브러리(Class Library)를 제공한다. 자바 클래스 라이브러리를 사용하기 위해서는 자바 객체 명령어(Object Instruction)를 사용해야만 한다. 따라서 자바 객체 명령어는 쉽게 교체하거나 삭제할 수 없고 객체 명령어의 시퀀스는 프로그램의 고유한 특성으로서 사용될 수 있다. 정적 객체 트레이스 버스마크를 오픈 소스 프로그램에 적용하여 공통 모듈(Common Module)을 탐지하는 실험을 수행하였고, 그 결과 다양한 난독화에 대해서 기존의 정적 버스마크보다 공통 모듈 탐지 능력이 우수하다는 것을 보여주었다.