1. 코드의 내용으로 특징 추출하기
1.1. 코드 섹션을 찾는 법
pe_header.py 가 pe파일의 헤더만 보고 특징을 추출해 냈다면 이번엔 파일의 데이터 영역에 있는 실제 코드의 특징을 추출해 본다.
이를 위해서는 데이터 영역 안에 코드가 어디에 위치하는지부터 찾아야 한다.
책에서 소개하는 방법은 세 가지가 있다.
일반적으로 코드가 저장된 섹션인 .text 섹션을 찾기
Entrypoint 찾기
속성(Characteristics)에 CNT_CODE 와 MEM_EXECUTE 플래그가 활성화된 섹션
이 프로젝트에서는 두 번째, entrypoint를 사용하여 특징을 추출한다.
1.2. 바이트 코드를 어셈블리코드로 바꾸기
코드를 작성하여 컴파일을 하면 고급언어(c, java 등)에서 컴퓨터가 이해할 수 있는 0x66, 0x80, 0xOD, 0x00, 0x00 같은 바이트코드로 변환된다.
이를 다시 특징 추출을 할 수 있을 정도로 읽을 수 있게 어셈블리코드로 변환해주어야 한다.
이 과정을 디스어셈블이라고 한다.
1.3. ngram
이 어셈블리코드가 각각의 PE 파일을 구분하는 '다른 점'이 되려면 어떻게 무엇을 기준으로 삼아야 할까?
어떤 명령을 수행하는지, 어떤 명령을 몇 번 수행하는지는 모든 파일들이 서로 다를 것이다.
그리고 악성코드와 정상프로그램들 간 수행하는 명령의 차이도 있을 것이다.
이것을 특징으로 추출해야 한다.
그럼 추출은 어떻게 해야 할까? 모든 명령어를 전부 if 구문으로 분류하는 것은 불가능하다.
amd 아키텍처의 명령어 개수가 1000개 이상이다.
이 책에서는 ngram이란 방식으로 분류하고 있다.
n-gram이란 n개의 연속된 문자열의 패턴을 찾는 방식으로
예를 들어 "엄마가 좋아 아빠가 좋아 저는 엄마 아빠 다 좋아요"라는 문구가 있다면,
- 1-gram (단어 단위):
["엄마가"(1), "좋아"(2), "아빠가"(1), "저는"(1), "엄마"(1), "아빠"(1), "다"(1), "좋아요"(1)]
- 2-gram (단어 단위):
["엄마가 좋아"(1), "좋아 아빠"(1), "아빠가 좋아"(1), "좋아 저는"(1), "저는 엄마"(1), "엄마 아빠"(1), "아빠 다"(1), "다 좋아요"(1),]
- 3-gram (단어 단위):
["엄마가 좋아 아빠"(1), "좋아 아빠가 좋아", "아빠가 좋아 저는", "좋아 저는 엄마", "저는 엄마 아빠", "엄마 아빠 다", "아빠 다 좋아요"]
이렇게 어떤 단어가 한 문장 안에 몇 개나 들어있는지를 분석한다.
1.4. ngram.py 실행하기
코드를 우분투 가상환경에서 실행해 보자. 코드는 실습자료에 있다.
코드의 내용은 다음과 같다.
엔트리포인트를 사용하여 코드 시작위치를 파악한다.
바이트 코드에서 어셈블리코드로 변환한다.
4 - gram을 사용하여 해당하는 패턴을 개수가 많은 순서대로 100개를 선별하여 특징으로 추출한다.
추출한 특징을 csv파일로 저장한다.
파이썬 3을 사용 중이라면 3에 맞게 수정을 해준다.
폴더경로도 맞게 수정한다.
실행
conda activate mlsec_3811
python3 ngram.py
1.5. 오류
610번째 프로세스 중 MSDeployIcon.exe 파일을 검사하던 중 오류가 났다고 한다.
PEFormatError라고 하는데, dos 헤더가 발견되지 않았다는 의미로 해당파일이 PE파일이 아니라는 의미이다. 그러므로 제거해 준다,
ollydbg.ini 파일에도 같은 문제가 발생하였다. 제거해 주자.
이제 정상적으로 특징 추출이 완료되었다.