테스트를 위해 실제로 가상머신 내에서 PyCL 랜섬웨어를 돌려 일부러 감염시킨 테스트 파일들입니다.
프로그램 실행 후 복호화 할 파일/폴더의 경로와 키 값을 입력하면 자동으로 해당 경로 하위를 전부 돌면서 감염된 확장자를 확인하고 입력받은 키로 복호화를 시도합니다. 복호화에 실패하더라도 원본 파일을 수정하거나 지우지는 않지만 혹시 모르니 항상 백업은 하고 사용해주시기 바랍니다. 랜섬웨어의 키를 찾는 방법은 이전 포스트의 마지막에 작성해두었습니다.
그림 1의
아이콘과 위의 메타데이터들을 보면 알 수 있듯, 파일 크기가 클 뿐만 아니라 두 샘플 모두 비슷한 크기의
같은 타입, 거의 동일한 SSDeep 해쉬값을 갖고 있습니다. 패커 혹은 래퍼로 감싸져서 그런 것이라고 의심이 가능합니다.
3. 분석
[그림 3. Tkinter 아이콘
확인]
랜섬웨어가
실행되고 나면 위와 같은 창과 메시지박스가 등장하는데, 메시지박스의 아이콘은 파이썬 내장 GUI 라이브러리인 Tkinter의 기본 아이콘입니다. 이름에서 이미 예상했지만 파이썬으로 작성된 프로그램이라는 것을 알게 되었고,
PE 파일로 래핑되어 있으므로 이를 해제하기 위해 무슨 툴을 사용했는지를 알 필요가 있었습니다.
[그림 4. PyInstaller
문자열 확인]
파이썬을
EXE로 래핑하기 위해 가장 많이 사용하는 툴인 PyInstaller와
Py2Exe를 체크해볼 생각이었는데 찾아보니 바로 PyInstaller로
확인되었습니다.
래핑 해제된 파일을 아무리 찾아도 메인 소스코드로
보이는 파일이 보이지 않아서 찾아보다 보니 scriptedhind라는 파일 내부에 랜섬웨어의 소스코드로
보이는 내용이 작성되어 있는 것을 볼 수 있었습니다. 파이썬 소스코드가 원형을 유지하고 있지는 않았지만
하드코딩된 문자열 등은 그대로 나타나 있었기 때문에 대충 어떤 랜섬웨어인지는 파악이 가능했고, 이것만으로는
정보가 불충분하다고 느껴서 파일명인 scriptedhind로 검색을 해봤습니다.
[그림 7. Ransomware
Builder Github]
검색 결과
scriptedhind라는 문자열을 포함하는 Github 주소가 등장했고,
접속해보니 자동으로 랜섬웨어를 만들어 주는 툴을 배포하고 있었습니다.
[그림 8. 책임 회피용
문구]
작성자는
Github에 교육적인 목적으로만 제작된 것으로, 프로그램의 사용에 의한 책임을 지지 않겠다고
작성해놓았습니다. 하지만 이전에 오픈소스 원격관리도구라며 .Net기반 RAT인 Nanocore를 개발한 개발자가 유죄를 선고받은 사례도 있으므로 이게 합법이라고 판단하긴 힘들어
보입니다.
[그림 9. 해당 Github 유저]
ScRipt1337이라는 닉네임을 사용하는
유저는 이외에도 직접 제작한 것처럼 보이는 여러 악성 프로그램을 ‘교육적인 목적’이라는 명목으로 공개해놓고 있습니다.
[그림 10.
Ransomware Builder]
아까 발견한 Ransomware Builder에 존재하는 두 개의 exe 파일은
둘 모두 랜섬웨어와 같이 PyInstaller로 래핑된 파이썬 기반 프로그램이었습니다. Builder.exe 파일을 실행하고 Github에 작성되어 있는
패스워드를 입력하면 위와 같은 창이 등장하고, 원하는 내용을 채워넣으면 이대로 랜섬웨어가 작성됩니다. 결과물은 Python 스크립트로,
단순히 위 항목들을 포맷팅하여 넣은 것에 지나지 않습니다. 드랍된 스크립트를 분석해보겠습니다.
[그림 11. 권한
체크]
생성된 파이썬 파일은 실행된 직후 Admin 권한을 가졌는지 체크하고, 아니라면 UAC 컨트롤로 관리자 권한 획득을 시도합니다.
[그림 12. AntiVM?]
이후 “WMIC
BIOS GET SERIALNUMBER” 명령을 이용해 하드웨어 정보를 가져옵니다. VMware 에서
생성한 VM 내부에서 사용할 경우 stdout으로 “VMware-56 4d 05 69 52 1c d8 fa-86 9e 1c 72 28 bd f5 46”라는 값이
출력되었는데, 저기에서 받는 result는 stdout을 받는 것이 아니라 프로그램의 종료 시 리턴 값을 받는 것이기 때문에 VM 여부에 관계없이 명령어가 성공한 이상 무조건 0이 반환되었습니다.
[그림 13. 작업
관리자 차단]
그림 12의 disabletask 함수 내부에서는 특정 레지스트리 값을 추가하는 것으로 작업 관리자의 사용을 차단합니다.
[그림 14. 실수?]
실수인지
고의인지는 모르겠지만, 이렇게 반환된 0을 int로 형변환한 후 문자열 “0”과 비교하는 어이없는 일을 수행합니다. 이미 타입 자체가 다르기 때문에 무조건 False가 될 수밖에 없고, main이 실행됩니다. 여기서 strongKey는
위의 Builder.exe에서 입력한 암호화 키 값입니다.
[그림 15. main]
main 함수 내에서는 “C:\” 하위의
파일들을 대상으로 총 145개의 확장자를 검색하여 일치하는 파일에 대해 암호화를 수행합니다. 여기서 문제는 파일이 존재할 때마다 바탕화면에 랜섬노트로 추정되는 파일을 계속해서 덮어쓴다는 것입니다. 이 랜섬웨어는 작동하는 속도가 비정상적으로 느려 전부 암호화가 될 때까지 10분
이상이 소요되는데, 이 작업이 거기에 한몫 하는 것으로 보입니다. (그러면서
자기가 작성한 랜섬노트마저 확장자가 .txt라는 이유로 암호화해버립니다;)
[그림 16. 암호화
루틴]
암호화에는 AES CBC를 사용하며, Initialization Vector는
그때그때 랜덤한 값을 뽑아서 사용합니다. 파일의 암호화 전에 파일의 크기와 IV를 총 32바이트 버퍼에 담아서 파일 앞부분에 저장하고, 이후 특정 크기씩 읽어와 블록 암호화를 진행합니다. 입력한 key는 키 그대로가 아니라 sha256으로 한번 해싱하여 AES의 키로 사용합니다. 암호화된 파일의 확장자는 .impect가 추가로 붙습니다.
[그림 17. 복호화
루틴]
바로 밑에 복호화 루틴도 있었는데, 복호화 완료된 파일명을 제대로 복원시켜주는게 아니고 뒤에서 offset -3까지만
가져오기 때문에 [원본파일명].imp 로 변환될 것으로 예상이
가능합니다.
[그림 18. 실수
2?]
이렇게 암호화가 전부 완료되고 나면 try~except 문으로 진입하는데, try문 내에서 특정 파일을
읽어와서 str형태로 변환한 다음 6을 더하는 행위를 하고
있습니다. Javascript도 아니고 str 타입 변수에
int형 상수를 더하는 것이 허용될 리 없으므로 무조건 except로
빠지게 되고, 결국 현재 시간을 작성하는 용도로밖에 쓰이지 않습니다.
except에서 현재 시간을 포맷팅한 후 offset -6까지를 저장하는 것으로 보아 현재의
‘시간’을 작성하는 것이고,
가져온 시간에 6을 더해서 일치할 경우(있을
수가 없는 일이지만) “C:\Users\유저네임” 이하의
모든 파일을 삭제합니다. 결코 발생할 수 없는 루틴이지만 일정 시간 내에 금전을 지불하지 않을 경우
해당 파일들을 전부 삭제하겠다는 류의 협박성 루틴인 것 같습니다.
[그림 19. 작업
표시줄 숨기기]
위 작업이 끝나고 나면 이유는 모르지만 작업
표시줄을 먼저 숨깁니다. 작업 표시줄과 함께 시작 버튼도 같이 숨기려고 하는 것 같은데, Windows 7에서 테스트 해본 결과 제대로 숨겨지지 않았습니다.
[그림 20. 바탕화면
변경 시도]
Builder.exe에서 입력했던 url을
이용하여 이미지 파일을 다운로드 받고, 그것을 이용하여 바탕화면을 변경하려고 시도합니다. 여기서는 64비트인지 체크하여 맞을 경우 SystemParametersInfoW를 사용하고 아닐 경우 SystemParametersInfoA를
사용하는데, 왜 굳이 저렇게 하는지는 잘 모르겠습니다. 윈도우
API에 익숙하지 않은 제작자라는 생각이 듭니다.
[그림 21. GUI 루틴]
위
작업까지 끝나고 나면 그림 3에서 볼 수 있듯이 Tkinter를
이용하여 GUI로 윈도우 하나를 띄우고, 랜섬웨어 감염 사실을 (욕설과 함께)알리고 키를 입력할 수 있는 Entry 칸을 하나 만들어둡니다. Decrypt 버튼을 누르면 runthefuckup 함수가 실행됩니다. 교육적인 목적으로 공개했다고
했는데 전혀 교육적이지 않아 보입니다.
[그림 22. runthefuckup
함수]
입력받은
키 값이 저장된 키 값과 일치할 경우 C:\ 하위를 돌면서 암호화된 파일에 대해 복호화를 수행하고, 다를 경우 욕설이 씌여 있는 메시지 박스를 띄웁니다.
4. 복호화 방법
pyinstxtractor를
이용하여 PyInstaller를 래핑 해제했을 때 메인 소스코드가 정상적으로 나오면 좋은데, 어째선지 제대로 메인 소스코드가 등장하지 않아서 키를 어떻게 찾아야 하는지 고민했었습니다. 단서는 랜섬웨어의 메인으로 보이는 scriptedhind 파일이었는데, pyc 디컴파일러를 돌려봐도 제대로 디컴파일이 되지 않았습니다. 하지만
알고 보니 pyc파일은 맞는데 시그니쳐 부분만 날아갔던 것이었고, 그래서
시그니쳐를 복원하고 디컴파일을 돌려봤더니 정상적으로 디컴파일이 되었습니다.
디컴파일로 추출한 소스코드 내에서 암호화 키를 확인 가능하고, 랜섬웨어가 띄운 창에 입력하면 정상적으로 복호화가 되지만 프로그램 자체가 무척 불안정해서 응답을 하지 않거나
복호화 하는 데에 시간이 상당히 소요됩니다. 복호화를 해주는 툴은 C++로 직접 짜볼 생각이며, 추후 포스팅하여 링크하겠습니다.
PUBG Ransomware는2018년 4월 10일쯤
발견된 랜섬웨어로, 기존에 장난삼아 제작되고 배포되어 이슈가 되었던 동방프로젝트 랜섬웨어(http://thegear.co.kr/14295)와
비슷한 느낌으로 제작된 랜섬웨어입니다. 장난삼아 만들었다고는 하지만 실제로 파일에 대한 암호화를 진행하기
때문에 자칫하면 실제 피해가 발생할 수 있어 주의가 필요합니다. 무척 간단히 분석이 가능할 거라고 예상이
가능했기 때문에 한번 분석해봤습니다.
이번에도 별다른 아이콘은 없고, 또 .NET 기반의 Win32
PE 파일입니다. 파일 크기는 40.5KB로
상당히 작습니다.
[그림 1. PUBG_Ransomware.exe
Exeinfo PE]
Exeinfo PE를 이용하여 분석해본 결과
패킹은 되어 있지 않은 것 같았습니다. 그럼 원본 바이너리 자체 크기가 40KB밖에 되지 않았다는 것인데 랜섬웨어 치고는 너무 작아서 꽤 놀랐습니다.
[그림 2. PUBG_Ransomware.exe
Bintext 분석]
패킹이 전혀 되어 있지 않기 때문에 내부
문자열을 찾아보면 재미있는 문자열이 무척 많이 보이지만, pdb 정보가 박혀 있길래 이를 가져왔습니다. 경로는 "C:\Users\ryank\source\repos\PUBG_Ransomware\PUBG_Ransomware\obj\Debug\PUBG_Ransomware.pdb”
로 지정되어 있으며 유저 이름이 ‘ryank’
인 것으로 보아 제작자는 ‘Ryan K’ 라는 닉네임을 사용하는 사람인 것으로 추정이 가능합니다.
[그림 3. PUBG_Ransomware.exe
dotpeek 디컴파일]
Jetbrain사의 Dotpeek을
이용하여 분석해본 결과 실행 직후 바탕 화면 아래의 특정 파일들을 암호화하도록 되어있는 것을 볼 수 있습니다. 여기서
함수명이 익숙하지 않아 확인해보니 스페인어인 것을 알 수 있었고, 이 랜섬웨어의 제작자는 스페인 국적의 인물인 것으로 추정해볼 수 있었습니다.
암호화를 진행하는 확장자들은 위와 같았습니다. 암호화가
완료된 파일은 뒤에 ‘.PUBG’ 확장자를 추가로 붙입니다.
[그림 4. 암호화
루틴]
AES 256 CBC 암호 방식을 사용하며 Zeros 방식의 패딩을 사용합니다. 이 패딩 방식은 모든 바이트를
0으로 채워 패딩하는 방식입니다. 인자로 넘어가는 문자열을
확인해 보니 항상 Key가 되는 문자열은 “GBUPRansomware”로
동일했습니다.
[그림 5. 프로세스
체크]
메인 Form이
로드됨과 동시에 시작된 루틴에서는 특정 이름을 가진 프로세스를 가져와서 존재할 경우 playtime을
늘리고, 이것이 3이 되는 순간 복호화 루틴으로 들어갑니다. 해당 프로세스 이름은 “TslGame”으로 게임 배틀그라운드의 프로세스
이름입니다. 타이머의 Interval을 1000으로 설정한 후 3번이므로 3초간만
저 프로세스를 켜두면 자동으로 복호화가 되는 로직입니다. 여기서 맹점이 하나 있는 것이, 프로세스 이름으로 체크하는 것이기 때문에 적당히 아무 프로그램이나 파일명을 TslGame.exe로
바꾼 후 실행시키면 알아서 복호화를 해줍니다.
[그림 6. 리소스
내부 그림]
리소스 내에는 Form의 배경에 지정할 이미지 파일 하나만 들어있었습니다. 이외에
딱히 레지스트리를 건드리는 부분도 없었고, 정적 분석이 더 필요한 부분도 없어서 바로 동적 분석으로
들어갔습니다.
바탕
화면 밑의 파일들만 암호화하기 때문에 바탕 화면에 실행 파일과 암호화될 파일들을 함께 둔 후 동적 분석을 시작했습니다.
[그림 8. 랜섬노트(?) 및
암호화된 파일들]
바탕 화면 아래의 파일들만 암호화하는 단순함
때문인지 실행 직후 바로 파일들이 암호화됩니다. Form에는 배틀그라운드 게임을 1시간동안 플레이하거나, ‘s2acxx56a2sae5fjh5k2gb5s2e’라는
키 값을 주면서 이것으로 복구하라고 씌여 있습니다. 하지만 Restore
Code를 입력하는 Input Box와 Restore 버튼은
Disabled 상태라 키 입력이 불가능합니다.
[그림 9. 복호화된 파일들]
정적
분석으로 알아낸 것처럼, 프로세스 이름을 기반으로 게임이 실행 중인지 여부를 판단하기 때문에 적당히
아무 프로그램이나 이름을 ‘TslGame.exe’로 변경 후 실행시키면 3초 뒤 자동으로 복호화를 완료해줍니다. Hex Editor로 열어
봤을 때 정상적으로 복호화된 것을 확인할 수 있었습니다. 이후 랜섬웨어는 자동으로 종료됩니다.
PUBG
Ransomware는 분류는 랜섬웨어가 되겠지만 금전적인 요구는 전혀 하지 않고 사실상 거의 대가 없이 모든 파일을 복호화 해 주는
등 악의가 느껴지지 않는 프로그램입니다. 이전에 장난삼아 개발되었던 다른 ‘게임 플레이 시간에 따라 복호화를 해 주는 랜섬웨어’들과 비슷한 느낌으로
개발된 것으로 보입니다. 악의가 느껴지지 않는다고는 하나 실제로 유저의 파일들을 암호화하여 피해를 줄
수 있는 것은 사실이기 때문에 수많은 안티바이러스 벤더사에서 악성으로 탐지하고 있습니다.
패킹도
프로텍팅도 전혀 되어 있지 않고 .NET 기반 프로그램인데다 난독화 처리도 되어 있지 않아서 그냥 정적
문자열 패턴 기반으로도 충분히 탐지가 가능하며, 바탕화면의 특정 파일들을 암호화하는 행위 자체도 무척
뚜렷합니다. 하지만 랜섬노트를 따로 드랍하거나 보여주는 행위가 없어 자동 분석은 약간 힘들 수도 있겠습니다. 네트워크 행위도 전혀 하지 않고, 단순히 암호화 및 복호화 행위만
수행합니다.
패킹
및 프로텍팅이 되어 있지 않다는 점을 보면 분석에 익숙하지 않은 분들이나 간단히 분석할 수 있는 .NET 기반
악성코드를 찾아보고 있는 사람들에게는 좋은 샘플일 것 같습니다.
그림 3을 확인해 보면 “mssecsvc2.0”이라는 서비스를 열어서 특정
함수의 인자로 넘기고, ServiceStartTable의 lpServiceProc에
다른 함수를 등록한 뒤 StartServiceCtrlDispatcherA함수를 호출하여 해당 함수를
실행시키는 것을 볼 수 있습니다.
[그림 4. SERVICE_CONFIG_FAILURE_ACTION
설정]
위에서
넘어간 특정 함수는 서비스가 특정 상황일 때 어떤 동작을 할 지를 설정하는 부분입니다. 여기에는 ChangeServiceConfig2라는 API가 사용되는데, 이 API의 세번째 인자는 두번째 인자에 따라 달라지며, 현재 그림 5에서 보이는 2는
서비스가 SERVICE_CONFIG_FAILURE_ACTIONS, 즉 서비스가 실행 도중 실패할 때를
나타냅니다.
[그림 5. SERVICE_FAILURE_ACTIONS
구조체]
세번째
인자인 SERVICE_FAILURE_ACTIONS 구조체의 lpsaActions
멤버를 보면 특정 상황일 때 어떤 Action을 취할 지 설정할 수 있습니다. 그림 4에서 scAction.Type에 1을 지정하는 것은 SC_ACTION_RESTART이므로 서비스를
재시작하는 것이라고 볼 수 있으며, 1000 * delaySec으로 실행 딜레이를 지정하는데 60이 인자로 넘어왔으므로 서비스가 실행 도중 실패할 경우 60초 후
서비스를 재시작하도록 설정하는 것이라고 볼 수 있습니다.
[그림 6. SMB
Exploit Thread]
그림
3에서 StartServiceCtrlDispatcher 함수에
넘기는 구조체에 설정된 disseminateServiceProc 함수 내부를 확인해 보면 위와 같은
부분이 있습니다. 내부에서 랜덤하게 IP Address를
생성하여 SMB Exploit을 시도하기 때문에 위와 같이 함수를 네이밍 해두었습니다.
[그림 7. SMB
Exploit Function]
내부에선 랜덤하게 IP Address를 생성하여 SMB 포트인 445포트로 접속을 시도한 후, 접속에 성공하면 해당 IP의 마지막 1바이트를 1~254까지
바꿔가며 접속 및 Exploit을 시도합니다. SMB 익스플로잇의
경우 EternalBlue 라고 명명된 CVE-2017-0144를
사용하는데 이는 따로 분석하지 않겠습니다. 이 방식으로 수많은 취약한 호스트를 자동으로 공격하고 전파되는
방식을 사용했기 때문에 첫 등장 이후 큰 이슈가 되었습니다.
인자가
존재하지 않을 경우 “mssecsvc2.0” 서비스를 생성하고 실행합니다. 어디서 많이 본 서비스인데요, 위에 인자가 존재할 경우에 실행된
루틴에서 핸들을 가져와 SERVICE_FAILURE_ACTIONS를 정의한 그 서비스입니다. CreateService 함수의 인자인 Binary Path에는
“argv[0] –m security” 형식이 되어 인자가 들어간 상태로 실행되도록 설정되어 있습니다. 이러면 자동으로 새로 생성된 서비스가 직접 스스로에게 SERVICE_FAILURE_ACTIONS를
정의하고 SMB Exploit을 하는 Thread를 만들어서
계속 실행될 것입니다.
[그림
9. 리소스 드랍 및 실행]
서비스
생성을 마친 후 “C:\Windows\tasksche.exe” 파일을 “C:\Windows\qeriuwjhrf” 파일로 옮긴 후, 리소스
영역에서 PE 파일을 가져와 “C:\Windows\tasksche.exe”에
드랍합니다. 이후 CreateProcess를 이용하여 실행합니다. 이 파일은 tasksche.exe 라고 부르겠습니다. 분석해본 결과 실제 파일을 암호화하고 랜섬노트를 드랍하는 랜섬웨어의 행위는 여기서 드랍된 tasksche.exe에서 실행되었습니다.
WannaCry.exe의
리소스 영역에서 그대로 드랍된 파일입니다. 파일 크기가 거의 변화가 없는 것으로 보아 WannaCry.exe의 거의 대부분은 이 파일이 차지하고 있었던 것으로 보입니다. 이 파일을 드랍한 후 WannaCry.exe의 나머지 부분은 서비스를
만들어서 특정 Host에 EternalBlue취약점을 이용하여
SMB Exploit으로 전파되는 행위를 수행했습니다. 이
파일에서는 실제로 랜섬웨어의 행위를 진행합니다.
[그림
10. 자가복제 작업]
tasksche.exe 파일은 실행되고 나면 argv[1]을 검사하여 “/i”와 일치하는지 확인합니다. Anti-Sandbox 기법인지는 모르겠으나 이 값이 없을 경우 아무것도 하지 않고 종료됩니다.
[그림
11. 랜덤 문자열 생성 루틴]
SetRandomString_by_PCName이라고
이름 붙인 함수 내부에서는 PC 이름에 따라 8~15글자의
소문자 알파벳 + 3글자의 대문자 알파벳으로 이루어진 문자열을 생성하여 파라미터로 전달받은 포인터에
저장합니다. 이 값은 특정 루틴 내에서 PC 이름을 이용해
seed를 생성하고, 이를 이용해 srand한 후 생성한 문자열이므로 PC 이름이 같을 경우 다른 환경에서도
똑 같은 값을 뽑아낼 것입니다. 이후 그림 10의 루틴을
계속 타면서 “C:\Windows\ProgramData\<RANDOM>”,
“C:\Windows\Intel\<RANDOM>”, “C:\Windows\<RANDOM>”,
“%TEMP%..\<RANDOM>” 경로에 순차적으로 시도해가면서 디렉토리를 생성하고 CurrentDirecotry를
설정합니다. 그 다음 CopyFile API를 이용해 자가복제하고
복제한 파일을 서비스 또는 프로세스를 이용하여 새 프로세스로 생성하고, 다시 원래 디렉토리로 돌아옵니다. 그리고 현재 실행되고 있는 디렉토리를 “HKEY_CURRENT_USER\Software\WannaCrypt0r”,
“HKEY_LOCAL_MACHINE\Software\WannaCrypt0r”에 등록합니다.
[그림
12. 리소스 unzip]
unzipResource라고 이름붙인 함수 내에서는 리소스 파일을 하나
가져와서 unzip을 수행합니다. 인자로 넘어간 s_WNcry_2o17의 값은 “WNcry@2ol7”로, 압축파일의 비밀번호에 해당했습니다. 해당 리소스를 덤프하여 확인해
보면 확실히 zip 압축 파일이었고, 압축을 해제하면 여러
파일들이 드랍됩니다.
[그림
13. 리소스 내부 파일들]
[그림
14. msg 내부]
msg 폴더 내부에는 PC 언어
환경에 따라 다른 메시지를 보여줄 수 있도록 다양한 언어로 랜섬노트가 작성되어 있습니다.
[그림
15. b.wnry]
b.wnry 파일은 BMP 포맷
이미지 파일로, 파일 암호화가 완료된 뒤 이것으로 바탕 화면을 변경할 것으로 보입니다.
[그림
16. c.wnry]
c.wnry 파일은 Tor브라우저
관련 설정이 들어 있는 파일로, 도메인과 토르 브라우저를 다운받을 수 있는 URL이 적혀 있었습니다.
[그림
17. r.wnry]
r.wnry 파일은 랜섬노트 텍스트 파일이었습니다.
[그림
18. s.wnry]
s.wnry 파일은 zip 포맷
압축 파일로, 내부에는 토르 브라우저 관련 파일들이 들어 있었습니다.
[그림 19. 랜섬 행위 시작]
현재 디렉토리를 숨김 설정하고 모든 사용자에게 폴더 접근 권한 준 후 t.wnry 파일을 읽고 랜섬 행위를 시작합니다. t.wnry 파일은
리소스에도 존재하지 않았고 어디서 드랍되는지 찾을 수가 없어 분석이 불가능했습니다. 핵심 부분은 그림
19의 p_CustomFuncPointer에 접근해야 알
수 있는데, 이는 t.wnry 파일에서 가져온 버퍼이기 때문에
내용을 알 수 없었으며 분석하는 도중 깨달은 것이지만 정상적으로 실행되지도 않기 때문에 동적으로 분석하는 것도 불가능했습니다. 마지막으로 문자열 내부를 확인하여 랜섬행위를 진행하는 확장자명을 뽑아 보았는데, 이는 다음과 같습니다.
API Monitor를 이용하여 동작을 확인해 보니 정적 분석에서 확인한
것처럼 “mssecsvc2.0”으로 서비스를 만들고,
“C:\Windows\tasksche.exe”에 리소스 드랍 후 CreateProcess로
실행시키지만 드랍한 파일이 정상이 아닌지 제대로 시작되지 않는 것을 볼 수 있습니다. 이 문제로 실제
암호화 행위를 진행하는 부분은 분석이 불가능한 상태에 있습니다.
[그림
21. WannaCry.exe 동적 분석 - 2]
서비스로 등록되어 실행된 루틴을 보니 수많은 쓰레드들이 계속해서 생성되면서
무언가 작업을 진행하고 있었습니다.
[그림
22. 등록된 mssecsvc2.0 서비스]
mssecsvc2.0 이름으로 등록하는 루틴이 존재했던 것과 같이 서비스가
등록되어 실행되고 있었습니다.
[그림
23. WannaCry.exe 네트워크 분석]
네트워크로는 수많은 호스트의 445포트로
연결을 시도하고, SMB 익스플로잇을 시도하는 내용이 보입니다. 드랍했던
파일인 tasksche.exe도 동적으로 분석하고 싶었지만 위에 언급한 대로 정상적인 실행이 되지 않았기
때문에 분석이 불가능했습니다.
WannaCry.exe는 2017년
5월경 등장하여 SMB 취약점을 이용한 강력한 자가 전파
능력으로 전 세계에 큰 충격을 안겨줬던 랜섬웨어입니다. 처음에 연결을 시도한 도메인은 킬
스위치였던 모양입니다. 어떤 방식으로 접속에 성공할 경우 전파되지 않는지는 잘 모르겠지만, 기사는 이렇게 나와 있습니다. ( http://www.itworld.co.kr/news/104756
)
분석을 시작하기 전까진 몰랐지만 패킹이나 프로텍팅이 전혀 되어 있지 않은
깔끔한 바이너리였고, 따라서 정적으로 분석하는 데에 큰 무리는 없었습니다. 그냥 문자열 패턴만으로도 내부에 “*.wnry”와 여러 확장자명들, 킬 스위치로 사용된 도메인 등이 들어 있기 때문에 정적으로도 무리 없이 탐지가 가능할 것으로 보입니다. tasksche.exe 내부 리소스로 zip파일에 암호를 걸어서
넣어둔 것은 데이터를 자동 분석으로 뽑아내기는 어렵게 만들었지만 zip 파일 구조 특성상 파일, 디렉토리명 등은 전혀 암호화가 되지 않기 때문에 정적으로 탐지하는 데에 전혀 지장을 주지 않았습니다. 또한 동적 분석으로도 특정 이름의 서비스를 등록하거나, 파일을 드랍하거나, 특정 포트로의 수많은 접근을 시도하는 등 뚜렷한 행위가 나타났기 때문에 탐지에 큰 어려움이 없을 것으로 보입니다. 탐지 가능한 지표에는 대표적으로 “C:\Windows\tasksche.exe” 파일을 생성하고, “mssecsvc2.0” 서비스를 등록하거나, “*.wnry” 확장자의 파일을
읽고 쓰는 행위 등이 있겠습니다.
요약하면, 이 샘플은 취약점을
Exploit하여 네트워크를 통해 자동으로 전파되는 기능을 가진 랜섬웨어입니다. 정상 파일로 위장하기 위해 “mssecsvc2.0”이라는 이름의 서비스를 생성하고 실패시 자동으로 다시 시작하는 루틴을 만들고, 여러 프로세스와 파일을 넘나들며 실행되는 것을 보면 상당히 정교하게 만들어져 있습니다. 하지만 그럼에도 패킹이나 프로텍팅이 전혀 되어있지 않아 정적 분석에 어려움이 별로 없었다는 점이 특징이며, 리소스에서 드랍된 tasksche.exe는 실제 VirusTotal등에서 수많은 벤더가 악성으로 진단하고 있는 상황임에도 정상 동작하지 않았습니다. 정적 시그니쳐는 물론이고 패턴, 문자열 등으로 충분히 악성 판단이
가능하고, 동적으로도 서비스 등록 및 네트워크를 통한 Exploit 등
특징이 두드러지기 때문에 쉽게 악성 판단이 가능한 샘플인 것으로 보입니다.
IDA를 이용하여 정적 분석을 하다 보면 악성코드가 직접 만든 custom struct들을 자주 만나게 됩니다. 특히 이번에 분석했던
WannaCry의 경우는 그게 더 심했는데요, 1000바이트가
넘어가는 크기의 struct를 선언하고 사용하는 경우가 있어 이를 직접 만들긴 힘들어 보여 idapython을 사용하였습니다. idapython은 IDA와 연동하여 사용할 수 있는 일종의 Python 라이브러리인데, IDA를 켰을 때 아래에 있는 커맨드라인 입력 창에서 인터프리트 형식으로 사용이 가능합니다. 예를 들어, 크기가 상당히 큰 Struct이고
멤버 변수를 모두 4바이트 DWORD로 선언하고 싶은 경우
다음과 같이 사용이 가능합니다.
[그림
24. idapython 사용]
IDA 에서 Python 스크립트를
이용하는 것은 2~3년쯤 전 BoB를 하면서 배웠었지만 지금까지
실감하지 못하고 있었는데 상당히 강력한 도구인 만큼 잘 활용하면 분석에 큰 도움이 될 것으로 보입니다.