개요
Yara를 통해 특정 패턴을 기준으로 파일을 매칭 할 수가 있음을 저번 문서를 통해 알 수 있었다. 그렇다면 이러한 룰은 어떻게 생성되어야 할까? 우선 고려해야 할 사항으로 다른 정상적인 파일에 포함되어 있는 패턴은 배제시켜야 한다. 따라서 이번 문서는 다른 파일과 겹치지 않는 문자열을 걸러내도록 할 것이다. 

이를 위해 구상한 내용은 다음과 같다. 우선 정상적인 파일로부터 문자열을 추출한 다음, 이를 DB로 만들어 Yara 규칙을 제작해야 하는 대상 악성코드의 문자열을 DB와 비교한다. 만약 DB에 이미 해당 문자열이 존재할 경우, 해당 문자열은 정상적인 파일에 포함되어 있을 수 있으므로 제외한다. 이러한 작업을 반복하여 결국 DB에 포함되지 않은 악성코드 특유의 문자열만 남게 된다. 그리고 이러한 문자열을 통해 규칙을 생성할 것이다.
DB 생성

DB를 생성하기 위하여 두 가지 준비가 필요하다. 우선 Python을 통해 DB를 생성할 것이므로 Python을 설치해야 하며, 다른 준비물로는 Sysinternals의 Strgins가 필요하다. 아래의 링크를 통해 각 도구를 다운로드 하자.

[+] Python : https://www.python.org/downloads/

[+] Strigns : https://technet.microsoft.com/en-us/sysinternals/strings.aspx

프로그래밍을 해야 하지만, strings를 통해 어렵지 않을 것이다. 우선 여러 파일의 문자열을 넣어야 하므로 파일의 목록을 가지고 올 수 있는 부분을 먼저 제작해보자. 특정 폴더만을 지정할 경우 크게 두 가지 방법이 있는데, 하나는 os.listdir()을 통해 얻을 수가 있으며 다른 하나는 아래의 코드와 같이 지정된 디렉터리에 존재하는 하위 디렉터리까지 파일의 목록을 얻을 수가 있다.

위와 같이 파일의 목록을 얻은 다음 이를 아래의 Filelist 변수에 넣어주었다. 그리고 os.system 명령어를 통해 strings를 사용하여 하나의 파일씩 DB에 추가한다. 이렇게 지정된 모든 파일의 문자열이 DB에 존재하게 된다. 하지만 여기서 문제가 생긴다. 수많은 PE 파일들이 존재하기 때문에 공통적으로 포함되어 있는 문자열인 'MZ', 'PE', '. code', '. data' 등은 수 없이 중복되어 용량이 너무 커지게 된다. 따라서 모든 파일의 문자열을 추가한 다음, 이러한 중복 문자열을 제거하기 위한 코드를 제작하여야 한다. self.DB_Update()가 바로 그 내용으로 다음 그림에서 확인하자.

아래의 그림과 같이 'GenDB.tmp'라는 새로운 임시파일을 생성하여 기존의 'GenDB.db'의 내용을 0x2000000 씩 읽는다. 이렇게 읽은 문자열들을 배열로 놓기 위하여 split()를 사용하였으며, 이를 통해 arr이라는 배열(리스트)에 존재하게 된다. 파이썬에서 배열의 경우 자체적으로 아이템의 중복을 제거하기 위한 함수가 존재하는데 바로 set(arr)이다. 따라서 아래와 같이 arr=list(set(arr))을 통해 아이템의 중복을 제거한다. 중복이 제거된 문자열은 GenDB.tmp에 기록되고, 모든 바이트를 읽은 다음 GenDB.tmp를 GenDB.db로 이름을 변경한다.

위에서 0x2000000씩 읽는 이유는, buf = f.read()와 같이 DB의 내용을 한 번에 변수에 담으면 좋겠지만, DB는 말 그대로 데이터 베이스이기 때문에 수많은 파일의 문자열이 들어가게 될 경우 용량이 거대해진다. 따라서 이렇게 거대한 용량을 한 번에 읽으려 하면 파이썬은 "MemoryError"를 반환하게 되어 프로그램이 해당 데이터를 제대로 읽을 수 없게 된다. 그렇기에 이를 방지하기 위하여 지정된 바이트씩 읽는다. 

하지만 이 방법 또한 단점은 존재한다. 0x2000000씩 읽기 때문에, 0x2000000 만큼의 문자열에서만 중복되는 문자열이 제거된다. 즉, 0x000000에 'AAA"라는 문자열이 있고 0x2000010에도 'AAA'라는 문자열이 있을 경우 제거되지 않는다. 이러한 단점이 존재하지만 DB의 크기를 줄이는 것이 목적이기 때문에 몇 개는 남더라도 지우는 것이 훨씬 효과적이라 생각한다.

실습을 위하여 %SystemRoot%\System32\에 존재하는 3903개의 파일을 복사하였다. 이를 통해 DB를 생성하였으며, 최초 중복을 제거하기 전 파일의 크기는 약 400MB지만 중복을 제거한 뒤 DB의 크기는 약 135MB로 감소하였다. 이를 통해 중복제거가 완벽하지는 않지만 충분히 효과가 있다는 점을 알 수 있다.

DB 비교 & 패턴 생성

이제 약 3903개의 파일에 대하여 DB가 생성되었으니 한 번 성능을 테스트해보자. 대상으로 사용할 파일은 "Abex's Crackme01"을 UPX로 실행 압축한 파일이다. 따라서 DB에 존재하지 않다면 "UPX0", "UPX1"과 같은 내용들이 결과로 출력될 것이며 만약 DB에 UPX 관련 파일이 있을 경우 출력되지 않을 것이다. 우선 비교를 위한 코드는 다음과 같다.

이번에도 Strings.exe를 통해 문자열을 추출한 다음, 중복 문자열을 제거한다. 중복이 제거된 문자열을 배열의 형태를 통해 DB의 문자열 하나씩 비교한다. 이를 통해 DB에 일치하는 내용이 없는 문자열만 결과로 출력한다. 이제 이렇게 완성된 코드를 통해 파일을 비교해보자. 해당 결과는 다음과 같다.

abex's crackme01에서 볼 수 있는 몇 가지 문자열들이 결과로 출력되는 것을 확인할 수 있다. 대신 위에서 예상하였던 "UPX'와 관련된 문자열은 이미 DB에 존재하고 있기에 나타나지 않았다. 출력된 결과 중 몇 가지 문자열을 통해 Yara 규칙을 작성해보자.

아주 기초적으로 문자열 기반 규칙을 작성하였다. 그리고 해당 규칙을 적용하였을 때, 제대로 파일을 인식하는 것을 확인할 수 있었으며, 다른 3903개의 정상 파일에는 해당 시그니처가 부합되지 않다는 것 또한 확인할 수 있다.

직접 만들면서 부족한 프로그래밍임을 알 수 있었지만, 그래도 만들어보고 싶은 걸 초보적이 게나마 만들 수 있기에 공부하면서 재미있었다. 구글에 다른 훨씬 좋은 제너레이터가 존재하고 있으니, 그 코드들을 보며 다른 사람들은 어떻게 생각하면서 제작했는지 보는 것 또한 나쁘지 않을 것 같다. 아래는 부족하지만 내가 만든 위 프로그램의 코드이다.




'Reversing > Theory' 카테고리의 다른 글

Visual Studio 메인함수 찾기  (1) 2016.03.16
ClamAV & PEiD to Yara Rules  (1) 2016.03.11
Yara를 사용해보자  (0) 2016.03.06
악성코드 분류  (0) 2016.03.03
악성코드 분석 방법  (0) 2016.02.26