1. Petya?
2016년 3월 발견된 랜섬웨어로 디스크의 MBR 영역을 변조하여 PC의 부팅이 불가능하도록 하고 부팅 시 Ascii 코드로 작성된 해골 화면을 띄우며 결제를 유도하는 랜섬웨어다. MBR의 0번 섹터부터 56번 섹터 사이만 접근하여 조작하기 때문에 다른 부팅 디스크를 통해 부팅하여 MBR 영역만 복원해주면 정상적으로 사용이 가능하다.
2. Analysis
2-1. File information
윈도우 운영체제에서 실행되는 PE 형식의 파일이며 해당 파일에 대한 해시 정보는 위의 표와 같다.
분석에 앞서 Virustotal 사이트에서 제공하는 기본적인 정보에 대해서 파악하면 다음과 같다.
해당 PE 파일은 5개의 섹션으로 이루어졌으며 각 섹션의 엔트로피 값을 통해 섹션의 암호화 여부를 확인할 수 있다.
엔트로피를 통한 패킹 및 암호화 여부는 다음 논문에서 확인할 수 있었다.
Using Entropy Analysis to Find Encrypted and Packed Malware / J. Hamrock and R. Lyda / IBM in IEEE Security & Privacy / 2007.
발췌한 엔트로피를 통한 패킹 및 암호화 여부에 대해 파악할 수 있는 자료이다.
해당 자료를 참고하면 엔트로피 값이 7 이상일 경우 암호화된 데이터로 분류하며 따라서 엔트로피 값이 7.19로 나타난 text 섹션은 암호화된 코드가 삽입되었다고 판단할 수 있다.
백신 제품들이 API 호출 탐지 기반 등 고도화된 탐지 기법을 도입함에 따라 해당 기법들에 대해 우회하기 위한 방안으로 프로그램이 실행될 때 암호화된 코드 데이터를 복호화 하여 실행하는 백신 우회 기법을 사용한 것으로 의심해볼 수 있으며 좀 더 자세히 알아보기 위해 동적 분석을 진행해본다.
2-2. Dynamic Analysis
Petya를 동적 분석하기 위한 환경으로 VMware 가상화 도구를 사용했으며, 프로그램 역분석 도구로는 IDA Pro 6.6 도구를 사용했다. 먼저 Petya를 실행시킨 다음 컴퓨터가 강제종료 된 상황에서 볼 수 있는 화면이다.
Petya 실행 후 OS가 재부팅 되면 위와 같이 디스크를 확인하는 과정이 진행된다.
위 과정이 끝나면 다음과 같은 랜섬노트가 화면에 출력된다.
해골 문양이 출력된 이후에 이어서 위와 같은 랜섬노트가 화면에 출력된다.
사용자의 디스크가 암호화 됐으며 이를 복구하기 위해선 Tor Browser를 이용하여 가상화폐로 결제를 유도하는 화면이며 부팅을 할 수 없는 상황이다.
다음은 Petya 실행 전후의 MBR 영역이다.
Petya 실행 전 정상적인 MBR(좌)과 실행 후의 MBR(우)
위 사진과 같이 Petya를 실행 전후로 MBR이 변경된 것을 확인할 수 있다.
다음으로 동적 분석을 수행하기 전에 MBR이 무엇인지, PC의 부팅과 어떤 관련이 있는지 간략하게 정리한다.
파티션이 여러 개인 다중 파티션의 경우 각 파티션의 첫 번째 섹터에 존재하는 BR(Boot Record)만으로는 부팅 파티션을 결정할 수 없다.
MBR은 파티션 테이블을 참조하여 부팅이 가능한 파티션을 찾고 코드를 실행하여 해당 파티션으로 부팅이 되도록 하는 코드가 있는 메모리 영역이다.
저장매체의 첫 번째 섹터에 위치하는 512 bytes의 영역으로 구조는 다음과 같다
PC가 부팅되면 디스크의 첫 번째 섹터를 호출하며 부트 코드가 실행된다.
부트 코드는 파티션 테이블에서 부팅이 가능한 파티션을 찾아 해당 파티션의 부트 섹터를 호출해주는 역할을 하며, 파티션 테이블에는 각 파티션들에 대한 정보가 있으며 Signatrue는 MBR 디스크 영역이 가지는 고유의 바이트(0x55AA)이다.
각 파티션 테이블은 위와 같은 구조를 가지며 각 바이트들이 뜻하는 의미는 다음과 같다.
- Boot flag(1byte) : 해당 파티션이 부팅이 가능한 파티션인지 여부를 나타냄
(0x80 : 부팅 가능, 0x00 : 부팅 불가능)
- CHS Start(3bytes) : 해당 파티션의 시작 주소를 의미함
- Part Type(1byte) : 해당 파티션의 종류를 의미함
(0x0B : CHS 모드 FAT32, 0x0C : LBA 모드의 FAT32, 0x07 : NTFS 등)
- CHS End(3bytes) : CHS 방식의 종료 주소
- LBA Start(4bytes) : LBA 시작 주소, 파티션 시작 섹터 번호
- Size in Sector(4bytes) : 파티션의 섹터 수
MBR 방식을 사용하는 시스템에서는 MBR의 부트 코드는 부팅에 필수적인 코드이며 따라서 Petya와 같이 MBR의 영역의 데이터의 무결성을 해치는 공격이 발생할 경우 사용자의 PC가 부팅이 가능한 파티션을 찾지 못해 부팅을 할 수 없는 상황이 발생할 수 있다.
다음으로는 Petya가 어떤 과정으로 MBR을 암호화 하는지 파악하기 위해 IDA Pro disassembly 도구를 이용하여 정적 분석을 시행한다.
2-4. Static Analysis?
Petya를 정적분석하기 위한 환경으로 IDA Pro 6.6 + Hex-ray Decompiler plugin을 이용하여 역분석을 진행한다.
먼저 Petya는 실행 과정에서 특정 데이터 영역을 복호화 하여 코드 영역에 쓰며 해당 코드 영역을 실행시키는 형태로 실행된다.
복호화 하여 실행시키는 코드는 MZ 헤더 형식의 실행 파일이었으며 다음 사진은 프로그램 실행 도중에 MZ 헤더로 시작하는 코드를 복호화 하여 코드 영역에 올리는 사진이다.
왼쪽 사진은 프로그램을 실행하기 전의 코드이며 해당 프로그램을 실행할 경우 0041AE72 ~ 0041B358 까지의 코드를 반복하며 0041B35E에 MZ 헤더로 시작하는 코드를 삽입한다.
Petya가 수행하는 암호화 루틴은 해당 코드에서 수행되며 실행 도중에 메모리 덤프를 통해 해당 MZ 헤더의 실행 파일을 얻을 수 있다.
Petya가 수행하는 암호화 루틴을 분석하기 위해 해당 DLL을 확보하여 IDA에 올려서 이후 분석을 진행한다
분석 대상 MZ 실행 파일을 IDA로 올리고 DllEntryPoint에서 호출하는 몇 가지의 함수들을 타고 들어가보면 위와 같은 코드를 확인할 수 있다.
CreateFileA 함수를 통해 운영체제가 설치된 물리 디스크의 핸들을 받아오며 만약 핸들을 얻지 못하면 프로그램은 종료된다.
(line32) 핸들을 얻은 후 프로그램은 MBR이 있는 디스크의 0번지부터 0x7200번지까지 암호화 루틴에 들어간다.
다음은 첫 번째로 실행되는 암호화 과정이다.
위 코드는 0x200번지부터 512byte씩 블록 단위로 읽고 0x37과 xor 연산을 수행한 뒤에 같은 영역에 다시 쓰는 과정이다.
이 과정을 0x22번 수행하므로 0x200부터 0x4400 까지는 원본의 데이터와 0x37을 xor 연산을 한 결과가 저장된다.
위 사진에서 보이는 ReadFromFile 함수와 WriteToFile 함수는 함수들의 실행 코드를 분석하여 분석의 편의를 위해 임의로 붙인 이름이다.
다음은 각 함수들의 모습이다.
임의로 이름을 붙인 ReadFromFile 함수는 첫 번째 인자로 파일의 이름을 받고, 두 번째 인자로는 파일로부터 읽은 데이터를 저장할 버퍼를 전달받는다.
세 번째 인자와 네 번째 인자는 파일 포인터를 계산하는데 사용되며 결과적으로 해당 함수가 호출되면 첫 번째 인자로 전달받은 파일이름에 해당하는 파일을 열고 3번 째 인자로 전달받은 a3에 512를 곱한 지점부터 512바이트를 읽어서 두 번째 인자로 전달받은 버퍼에 저장한다.
위 함수에서 세 번째 인자로 전달받은 값을 ecx 레지스터에 저장한 후에 shift left를 9차례 수행하여 setFilePointerEx 함수의 인자로 전달한다. 결과적으로 파일 포인터는 세 번째 인자의 512배에 해당하는 지점을 가리키게 된다.
위 WriteToFile 함수는 첫 번째 인자로 전달받은 파일의 이름에 해당하는 파일을 열어서 세 번째 인자로 파일 포인터를 계산, 두 번째 인자로 전달받은 버퍼에 있는 데이터를 512바이트 쓰는 함수이다.
파일의 포인터 계산하는 방법은 위의 ReadFromFile 함수와 같다. Petya가 디스크로부터 데이터를 읽고 암호화 한 데이터를 쓰는 일련의 과정들은 모두 위의 두 함수를 통해서 진행된다.
디스크의 0x200 ~ 0x4400 영역을 암호화 한 이후에 오는 코드는 0x00번지부터 0x200번지까지 MBR 영역을 읽은 후에 암호화 하는 과정이다.
v47 변수에 해당 암호화 코드는 저장되며 이 v47 변수는 프로그램이 종료하기 다른 디스크 영역에 쓰이게 된다.
이후에 호출되는 함수에서는 두 변수에 악성 데이터를 쓰는 루틴이다.
v51 변수에 문자 ‘7’을 512 bytes를 쓰며, v50에는 함수로 이루어진 암호화 루틴을 수행하며 랜섬노트에 출력되는 URL 텍스트 중 일부를 저장한다.
해당 함수는 의미 있는 암호화 루틴이 아니므로 설명 및 분석을 생략한다.
앞에서 설명한 랜섬노트 일부 텍스트가 담긴 v50 변수를 0x6C00에 쓰고 ‘7’문자로 이루어진 512 bytes의 변수 v51은 0x6E00에 쓰여진다.
그 다음에 쓰여지는 데이터가 중요한데, v47 변수는 앞에서 0x00~0x200 MBR 영역을 암호화 한 데이터가 저장된 변수이다.
여기까지 Petya가 수행하는 암호화 루틴이며 이를 정리하면 다음과 같다.
실제로 Petya로 암호화된 가상머신의 디스크를 분석 프로그램을 이용하여 열어본 화면이다.
랜섬노트로 암호화된 0x4400~0x6E00 까지의 영역 중 일부이며 해골 문양의 일부와 랜섬노트에 출력되는 텍스트들을 확인할 수 있었다.
암호화 루틴이 끝난 후에 호출되는 함수이다.
해당 함수 내에서 GetCurrentProcess 함수를 통해 현재 프로세스의 핸들을 얻고 OpenProcessToken, LookupPrivilegeValueA, AdjustTokenPrivileges 함수들을 호출하여 시스템 종료 권한을 얻으며 권한을 상승한다.
그 이후에 “NTDLL.DLL”을 로드하고 NtRaiseHardError를 통해 PC를 강제 종료한다.
2-5. Decryption
분석한 Petya 랜섬웨어가 사용한 암호화 루틴은 블록암호 또는 비대칭키 암호와 같이 복잡한 암호화 알고리즘을 사용하지도 않았으며 키가 1 바이트인 스트림 암호라고 볼 수 있다.
해당 키는 역분석을 통해 간단히 찾을 수 있었고 암호화 한 MBR 데이터를 숨겨둔 위치 또한 분석을 통해 얻을 수 있었다.
따라서 암호화 된 MBR 영역의 hex 값을 복호화 하는 코드를 작성하여 암호화 전의 데이터와 비교해봤다.
MBR 영역의 데이터는 0x37과 XOR 연산을 통해 암호화 됐으며 해당 데이터를 0x37과 다시 XOR 연산을 해주면 원본의 데이터를 확보할 수 있다.
위와 같은 코드를 작성하여 암호화 된 데이터만 추출하여 해당 코드를 실행시키고 나온 복호화 데이터를 비교하면 다음과 같았다.
위 사진에서 왼쪽은 원본의 MBR 데이터이고 오른쪽의 사진은 암호화 된 MBR 데이터를 복호화 한 결과이다. 암호화 과정이 간단했던 만큼 쉽게 복호화 한 데이터를 얻을 수 있었다.
'Study > Reversing' 카테고리의 다른 글
우회 기법 (0) | 2019.03.20 |
---|---|
FSC_Level1 풀이 (0) | 2019.03.20 |
PE 헤더 (0) | 2019.02.18 |
2. C 문법과 디스어셈블리 (0) | 2019.02.14 |
1. IA-32 assembly (0) | 2019.02.14 |