'PyCL'에 해당되는 글 2건


 해당 프로그램은 악성코드 분석 연구 도중 흥미 위주로 만들어본 프로그램이며, 꼭 사용 전 파일을 백업해주세요. 필자는 이 프로그램을 사용함에 있어 생긴 피해에 대해 어떠한 책임도 지지 않습니다.


PyCLDecryptor.exe


 


 테스트를 위해 실제로 가상머신 내에서 PyCL 랜섬웨어를 돌려 일부러 감염시킨 테스트 파일들입니다.


 

 프로그램 실행 후 복호화 할 파일/폴더의 경로와 키 값을 입력하면 자동으로 해당 경로 하위를 전부 돌면서 감염된 확장자를 확인하고 입력받은 키로 복호화를 시도합니다. 복호화에 실패하더라도 원본 파일을 수정하거나 지우지는 않지만 혹시 모르니 항상 백업은 하고 사용해주시기 바랍니다. 랜섬웨어의 키를 찾는 방법은 이전 포스트의 마지막에 작성해두었습니다.


 소스코드는 gist로 첨부하겠습니다.

PyCLDecryptor.cpp 

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

댓글을 달아 주세요

 



 

1. 개요

[그림 1. 분석 대상 샘플]

 PyCL이라는 특이한 이름의 랜섬웨어가 등장했길래 재밌어보여서 분석해봤습니다.

 

 

[그림 2. 흐름도]

 

 

2. 샘플 정보

파일명

sample1

파일 크기

10,192,467 Bytes (9.71MB)

파일 타입

PE32+ executable for MS Windows (GUI) Mono/.Net assembly

MD5

0d9e127186433171791aaf2820be9575

SHA1

cb1f60268ff2146f3970d2afa40f8f07e5481e81

SHA256

115c02efdacb18478be9a92b81f2d9eba622189aa9f60ecdbde522c4d3111d38

SSDeep

196608:KJMSrtRIcI2tVHhEVSL2v8hp1yjAOHR3f1gu8N150IrE7N3sO5JvVWsj4Pz:rj27aVSLo8p323f4750jIsU

 

파일명

sample2

파일 크기

10,192,572 Bytes (9.71MB)

파일 타입

PE32+ executable for MS Windows (GUI) Mono/.Net assembly

MD5

eab2c08156d5372c34f02b486d70c2f6

SHA1

69a1da7bea8c49fb10e15f57e76dffdce7a7b801

SHA256

5b9cd4e6fd0d309a8a7c6fa9181b372d1ce85532f4c5181ba1bb9e38495f2c5e

SSDeep

196608:KJMSrtR8cI2tVHhEVSL2v8hp1yjAOHR3f1gu8N150IrE7N3sO5JvVWsj4Pz:pj27aVSLo8p323f4750jIsU

 

 그림 1의 아이콘과 위의 메타데이터들을 보면 알 수 있듯, 파일 크기가 클 뿐만 아니라 두 샘플 모두 비슷한 크기의 같은 타입, 거의 동일한 SSDeep 해쉬값을 갖고 있습니다. 패커 혹은 래퍼로 감싸져서 그런 것이라고 의심이 가능합니다.


 

3. 분석

[그림 3. Tkinter 아이콘 확인]

 랜섬웨어가 실행되고 나면 위와 같은 창과 메시지박스가 등장하는데, 메시지박스의 아이콘은 파이썬 내장 GUI 라이브러리인 Tkinter의 기본 아이콘입니다. 이름에서 이미 예상했지만 파이썬으로 작성된 프로그램이라는 것을 알게 되었고, PE 파일로 래핑되어 있으므로 이를 해제하기 위해 무슨 툴을 사용했는지를 알 필요가 있었습니다.

 

[그림 4. PyInstaller 문자열 확인]

 파이썬을 EXE로 래핑하기 위해 가장 많이 사용하는 툴인 PyInstallerPy2Exe를 체크해볼 생각이었는데 찾아보니 바로 PyInstaller로 확인되었습니다.

 

[그림 5. pyinstxtractor]

 PyInstaller로 래핑된 파일을 래핑 해제하기 위해 pyintxtractor라고 하는 오픈소스 라이브러리(https://sourceforge.net/p/pyinstallerextractor/tickets/5/attachment/pyinstxtractor.py)를 사용하였습니다.

 

[그림 6. scriptedhind 파일]

 래핑 해제된 파일을 아무리 찾아도 메인 소스코드로 보이는 파일이 보이지 않아서 찾아보다 보니 scriptedhind라는 파일 내부에 랜섬웨어의 소스코드로 보이는 내용이 작성되어 있는 것을 볼 수 있었습니다. 파이썬 소스코드가 원형을 유지하고 있지는 않았지만 하드코딩된 문자열 등은 그대로 나타나 있었기 때문에 대충 어떤 랜섬웨어인지는 파악이 가능했고, 이것만으로는 정보가 불충분하다고 느껴서 파일명인 scriptedhind로 검색을 해봤습니다.

 

[그림 7. Ransomware Builder Github]

 검색 결과 scriptedhind라는 문자열을 포함하는 Github 주소가 등장했고, 접속해보니 자동으로 랜섬웨어를 만들어 주는 툴을 배포하고 있었습니다.

 

[그림 8. 책임 회피용 문구]

 작성자는 Github에 교육적인 목적으로만 제작된 것으로, 프로그램의 사용에 의한 책임을 지지 않겠다고 작성해놓았습니다. 하지만 이전에 오픈소스 원격관리도구라며 .Net기반 RATNanocore를 개발한 개발자가 유죄를 선고받은 사례도 있으므로 이게 합법이라고 판단하긴 힘들어 보입니다.



[그림 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파일은 맞는데 시그니쳐 부분만 날아갔던 것이었고, 그래서 시그니쳐를 복원하고 디컴파일을 돌려봤더니 정상적으로 디컴파일이 되었습니다.

 

[그림 23. 누락되었던 시그니쳐]

 

 이렇게 누락됐던 시그니쳐를 추가한 후 Easy Python Decompiler를 이용하여 pyc파일을 디컴파일했습니다.

 

[그림 24. 디컴파일된 소스코드]

 디컴파일로 추출한 소스코드 내에서 암호화 키를 확인 가능하고, 랜섬웨어가 띄운 창에 입력하면 정상적으로 복호화가 되지만 프로그램 자체가 무척 불안정해서 응답을 하지 않거나 복호화 하는 데에 시간이 상당히 소요됩니다. 복호화를 해주는 툴은 C++로 직접 짜볼 생각이며, 추후 포스팅하여 링크하겠습니다.


 복호화 키 얻는 방법 요약

1. python.org 에서 파이썬 설치. 2, 3 버전 관계 없음.

2. 랜섬웨어 파일을 pyinstxtractor를 이용하여 디컴파일하여 패킹된 파일들을 추출.

3. 내부에 scriptedhind 파일을 hxd등을 이용하여 맨 앞에 Hex값으로 '03 F3 0D 0A 00 00 00 00'을 추가 후 scriptedhind.pyc로 확장자 변경

4. Easy Python Decompiler를 이용하여 방금 만든 scriptedhind.pyc 파일을 디컴파일

5. 디컴파일되어 떨어진 scriptedhind.pyc_dis 파일을 열어서 strongkey 값 확인


 현재 가진 샘플 두 종류의 MD5 Hash와 키 값은 다음과 같습니다.

0d9e127186433171791aaf2820be9575 : !0oPQrSuUaOwc7upKgesZqrUOrwP7XCugYX3xHUKjZrc321308

eab2c08156d5372c34f02b486d70c2f6 : 1qazxsw21@@@

블로그 이미지

__미니__

E-mail : skyclad0x7b7@gmail.com 나와 계약해서 슈퍼 하-카가 되어 주지 않을래?

댓글을 달아 주세요

  • Whiteknight 2020.04.11 21:15 신고  댓글주소  수정/삭제  댓글쓰기

    파이썬 배경화면 설정법 검색하다 들어왔습니다. 파이썬같이 쉬운 도구가 없었다면 저 친구는 랜섬웨어 만들기 어렵지 않았을까 하면서도 파이썬의 능력에 또 한 번 감탄하게 됩니다. 글 잘 읽었습니다. 좋은 하루 보내세요!