Code Note 0x1: DeathRansom
Code Note คือชุดของบล็อกและโพสต์ซึ่งจะนำโค้ดจากโครงการโอเพนซอร์สมาทำการวิเคราะห์และทำความเข้าใจ ให้ความหมายและข้อเสนอตามจุดประสงค์ของแต่ละโครงการ
Code Note ฉบับแรกที่ 0x1 จะขอเริ่มต้นด้วยโค้ดจากโครงการ DeathRansom ซึ่งเป็นโครงการมัลแวร์เรียกค่าไถ่ที่ผู้พัฒนาชื่อ ReddyyZ มีการนำซอร์สโค้ดของโครงการมาเผยแพร่บน GitHub และไม่ได้มีระบุจุดประสงค์อย่างชัดเจนถึงการปล่อยซอร์สโค้ดในลักษณะนี้
เนื่องจากซอร์สโค้ดของโครงการนั้นชัดเจนว่าสามารถนำมาประกอบร่างให้กลายเป็นมัลแวร์เรียกค่าไถ่ที่สามารถใช้งานจริงได้ แนวทางในการทำ Code Note ของเราวันนี้จึงจะเป็นการทำในแนวทางของการวิเคราะห์ภัยคุกคามหรือโปรแกรมที่เป็นอันตราย โดยพุ่งเป้าไปที่การอธิบายฟังก์ชันการทำงานของมัลแวร์ วิธีการทำมัลแวร์ใช้ในสร้างเงื่อนไขเพื่อขู่กรรโชกและเรียกค่าไถ่ วิธีการที่มัลแวร์ใช้ในการหลบหลีกการตรวจจับ และปัญหาซึ่งอาจเกิดขึ้นในการทำงานของมัลแวร์และอาจนำไปสู่ผลการกระทบที่คาดไม่ถึงได้
รายละเอียดหัวข้อย่อยใน Code Note 0x1: DeathRansom มีตามรายการด้านล่างครับ
Project Overiew
ข้อมูลจาก GitHub แสดงให้เห็นว่าโครงการนี้ทั้งหมดถูกพัฒนาด้วยโค้ดในภาษา Python เวอร์ชัน 2 และ 3 โครงการนี้มีโครงสร้างของไฟล์และไดเรกทอรีตามแผนภาพด้านล่างครับ
.
├── LICENSE
├── README.md
├── Ransom Request
│ ├── main.py
│ ├── main.ui
│ ├── resources.qrc
│ └── resources_rc.py
├── deathransom.py
├── modules
│ ├── __init__.py
│ ├── bypass
│ │ ├── __init__.py
│ │ ├── anti_debugger.py
│ │ ├── anti_sandbox.py
│ │ └── anti_vm.py
│ ├── generate_key.py
│ ├── learn_key.py
│ └── rsa.py
├── requirements.txt
└── time_script.py
การตรวจสอบไฟล์แต่ละรายการที่ปรากฎในโครงสร้างของโครงการทำให้เรารู้หน้าที่และจุดประสงค์ของโค้ดที่อยู่ในไฟล์ ได้แก่
- ไฟล์ในไดเรกทอรี
Ransom Request
รับผิดชอบการแสดงหน้าต่าง ransom note หลังจากที่ DeathRansom ดำเนินการเสร็จ- ไฟล์
main.py
จัดเก็บโค้ดซึ่งควบคุมลักษณะของหน้าต่าง ransom note โดยการใช้ PyQt เป็นผลมาจากการนำไฟล์main.ui
มาทำการแปลง - ไฟล์
main.ui
โค้ดใน XML ซึ่งเป็นผลลัพธ์มาจากการใช้ Qt Designer - ไฟล์
resources.qrc
เก็บการอ้างอิงไปยัง resource อื่นๆ ที่ใช้ในโครงการ - ไฟล์
resources_rc.py
โค้ดซึ่งจัดเก็บข้อมูล resource จริงๆ ในลักษณะไบนารีของโครงการเอาไว้ เป็นผลมาจากการนำไฟล์resources.qrc
มาทำการแปลง
- ไฟล์
- ไฟล์
deathransom.py
จัดเก็บโค้ดการทำงานหลักของ DeathRansom โดยประกอบไปด้วยโค้ดซึ่งสั่งการให้ฟังก์ชัน Anti-analysis ทำงาน, โค้ดที่ทำให้มีการสร้างกุญแจสำหรับเข้ารหัสและทำการเข้ารหัสไฟล์ และโค้ดที่สั่งการฟังก์ชันซึ่งรับผิดชอบการสร้าง ransom note - ไฟล์ในไดเรกทอรี
modules
: จัดเก็บโค้ดซึ่งเป็นโมดูลอื่นๆ ของ DeathRansom- ไฟล์ในไดเรกทอรี
bypass
: จัดเก็บโค้ดที่เกี่ยวกับการ Anti-analysis- ไฟล์
anti_debugger.py
โค้ดสำหรับตรวจจับว่ามีการใช้งาน debugger อยู่หรือไม่ผ่านฟังก์ชันIsDebuggerPresent()
- ไฟล์
anti_sandbox.py
รวมฟังก์ชันการตรวจจับว่าโค้ดทำงานอยู่ใน sandbox หรือไม่ - ไฟล์
anti_vm.py
เก็บฟังก์ชันการตรวจจับว่าโค้ดทำงานอยู่ใน virtualized environment หรือไม่
- ไฟล์
- ไฟล์
generate_key.py
เป็นไฟล์ซึ่งเก็บชุดคำสั่งสำหรับสร้างคู่กุญแจด้วยอัลกอริธึม RSA แบบ 4096 บิต - ไฟล์
learn_key.py
เก็บฟังก์ชันซึ่งสร้าง HTTP GET request ไปยังพาธบนอินเตอร์เน็ตเพื่อเอาข้อมูลกุญแจสาธารณะของผู้พัฒนามัลแวร์ - ไฟล์
rsa.py
เก็บฟังก์ชันสำหรับกระบวนการเข้ารหัสไฟล์
- ไฟล์ในไดเรกทอรี
- ไฟล์
time_script.py
: เก็บโค้ดจับเวลาซึ่งจะทำการลบไฟล์ที่ถูกเข้ารหัสเมื่อถึงเวลาที่กำหนด
อ้างอิงจากไฟล์ README.md
กระบวนการ build โครงการนี้จะประกอบไปด้วยขั้นตอนดังต่อไปนี้
- ลง dependencies ตามที่ปรากฎในไฟล์
requirements.txt
และลงPyQt5
- ผู้ควบคุมมัลแวร์ทำการสร้างคู่กุญแจสาธารณะ และทำการอัปโหลดกุญแจสาธารณะไปยังบริการซึ่งมัลแวร์สามารถเข้าไปอ่านค่าของกุญแจสาธารณะได้ และให้เปลี่ยนตำแหน่งภายในสคริปต์ให้สอดคล้องกับตำแหน่งที่อัปโหลดไฟล์ไปไว้ด้วย
- ใช้โมดูล
pyinstaller
ในการเปลี่ยนโค้ดในภาษาไพธอนไปเป็นไฟล์ portable executable โดยต้องเปลี่ยนทั้งไฟล์time_script.py
และmain.py
ในพาธRansom Request
- อัปโหลดไฟล์ portable executable จากขั้นตอนที่ 3 ไปไว้ในบริการอัปโหลดไฟล์ที่มัลแวร์สามารถดาวโหลดมาแสดงได้ แก้ไขสคริปต์เพื่อระบุพาธที่จะให้มัลแวร์ทำการดาวโหลด
- ใช้โมดูล
pyinstaller
ในการเปลี่ยนโค้ดในภาษาไพธอนของไฟล์deathransom.py
ไปเป็นไฟล์ portable executable และนำผลลัพธ์ที่ได้ไปเอ็กซีคิวต์ในระบบเป้าหมาย
Functions
Anti-Analysis
ฟังก์ชัน anti_disassembly()
ยังไม่มีลักษณะของโค้ดที่ป้องกันการถูก disassembly ได้จริง
ฟังก์ชันในกลุ่มของการตรวจสอบว่าโปรแกรมถูกรันอยู่ใน sandbox หรือไม่ประกอบไปด้วยการตรวจสอบ 6 เงื่อนไข ซึ่งค่าเริ่มต้นในโค้ดของโครงการไม่ได้ตั้งค่าให้เช็คทุกเงื่อนไข โดย 6 เงื่อนไขที่จะมีการตรวจสอบได้แก่
- ใช้การตรวจสอบหาโปรเซสจากรายการของโปรเซสที่มักพบใน sandbox หรือที่เกี่ยวข้องกับการวิเคราะห์มัลแวร์ด้วยฟังก์ชัน
check_sandbox_in_process()
กระบวนการนี้ใช้การตรวจสอบจากผลของการใช้คำสั่งtasklist
ไม่ได้เป็นการตรวจสอบจากผลลัพธ์ของการใช้ WinAPI
def check_sandbox_in_process():
EvidenceOfSandbox = []
sandbox_processes = "vmsrvc", "tcpview", "wireshark", "visual basic", "fiddler", "vmware", "vbox", "process explorer", "autoit", "vboxtray", "vmtools", "vmrawdsk", "vmusbmouse", "vmvss", "vmscsi", "vmxnet", "vmx_svga", "vmmemctl", "df5serv", "vboxservice", "vmhgfs", "vmtoolsd"
runningProcess = []
for item in os.popen("tasklist").read().splitlines()[4:]:
runningProcess.append(item.split())
for process in runningProcess:
for sandbox_process in sandbox_processes:
if sandbox_process in process:
if process not in EvidenceOfSandbox:
EvidenceOfSandbox.append(process)
break
if not EvidenceOfSandbox:
return True
else:
return False
- ฟังก์ชัน
check_sleep_acceleration()
ทำงานและส่งผลให้มัลแวร์จะหยุดกระบวนการทำงานเป็นเวลา 60 วินาที หลังจากช่วงเวลาดังกล่าวแล้วมัลแวร์จะทำการตรวจสอบเวลาจากเซิร์ฟเวอร์ NTP เพื่อระบุหาการทำ sleep acceleration ของ sandbox
Sleep acceleration เป็นฟีเจอร์ของ sandbox บางประเภทซึ่งทำหน้าปลอมเวลาของระบบเพื่อเร่งให้มัลแวร์ซึ่งกำลังถูกวิเคราะห์อยู่และมีการหยุดการทำงานในช่วงเวลาหนึ่งเอาไว้นั้นเชื่อว่าเวลาได้ผ่านไปแล้ว การตรวจสอบการมีอยู่ของฟีเจอร์นี้จึงมักจะถูกดำเนินการโดยการเปรียบเทียบกับแหล่งที่มาของเวลาจากภายนอก แทนที่จะอ่านค่าจากของระบบซึ่งอาจถูกปลอมแปลงได้
- ฟังก์ชัน
display_prompt()
ทำงาน โดยฟังก์ชันนี้มีสมมติฐานว่าในสภาพแวดล้อมซึ่งเป็น sandbox นั้นจะไม่มีการควบคุมจากผู้ใช้งาน ฟังก์ชันนี้จึงรับหน้าที่ในการสร้างหน้าต่าง pop-up ขึ้นมาและตรวจสอบว่าเกิดการมีปฏิสัมพันธ์กับหน้าต่างนี้หรือไม่ - ฟังก์ชัน
check_idle_time()
ทำงาน ฟังก์ชันนี้ใช้สมมติฐานเดียวกับฟังก์ชันdisplay_prompt()
คือการตรวจสอบว่าภายในช่วงเวลาที่กำหนดนั้น ผู้ใช้งานมีปฏิสัมพันธ์กับระบบใดไม่ว่าจะเป็นลักษณะใดๆ หรือไม่ โดยมัลแวร์มีการกำหนดไว้ว่าผู้ใช้งานจะต้องมีปฏิสัมพันธ์ใดๆ กับระบบในช่วงระยะเวลาไม่เกิน 60 วินาที - ฟังก์ชัน
check_click()
ทำงาน ฟังก์ชันใช้วิธีการตรวจสอบจำนวนการคลิกเมาส์ที่เกิดขึ้นเพื่อยืนยันว่าผู้ใช้งานมีปฏิสัมพันธ์กับระบบ โดยมีเงื่อนไขว่าผู้ใช้งานจะต้องคลิกเป็นจำนวน 10 ครั้งมัลแวร์ถึงจะเริ่มทำงาน - ฟังก์ชัน
check_cursor_pos()
ทำงาน ฟังก์ชันนี้ตรวจสอบว่ามีการเลื่อนของเคอร์เซอร์หรือไม่เพื่อระบุการมีปฏิสัมพันธ์ของผู้ใช้กับระบบ
ในส่วนต่อมามัลแวร์จะเรียกใช้ฟังก์ชัน anti_debugger.check()
เพื่อตรวจสอบหาการมีอยู่ของ debugger ผ่านทางการเรียกใช้ฟังก์ชัน windll.kernel32.IsDebuggerPresent()
ฟังก์ชัน anti_vm.check()
ทำงานเป็นฟังก์ชันสุดท้าย โดยฟังก์ชันใช้วืธีการระบุว่าโปรแกรมมัลแวร์ทำงานอยู้ใน virtualized environment หรือไม่ด้วยการตรวจสอบ MAC address ของเน็ตเวิร์กอินเตอร์เฟสว่ามีค่าตรงกับรายการที่ฝังมากับมัลแวร์หรือไม่ ค่า MAC address เหล่านี้โดยส่วนใหญ่เป็นของ MAC address ของซอฟต์แวร์ virtualization ซึ่งค่อนข้างตายตัวทั้งหมด
Files Encryption
ส่วนของโค้ดซึ่งเกี่ยวข้องกับการเข้ารหัสไฟล์จะถูกดำเนินการถัดมาหลังจากที่มัลแวร์ผ่านการตรวจสอบระบบเรียบร้อยแล้วในขั้นตอนก่อนหน้า โดยมัลแวร์จะถูกระบุให้ดำเนินการค้นหาไฟล์และเข้ารหัสเฉพาะภายใต้พาธ %USERPROFILE%
รวมไปถึงมีการกำหนดนามสกุลของไฟล์ที่จะเข้ารหัสเอาไว้ด้วย
valid_extension = [".pl",".7z",".rar",".m4a",".wma",".avi",".wmv",".d3dbsp",".sc2save",".sie",".sum",".bkp",".flv",".js",".raw",".jpeg",".tar",".zip",".tar.gz",".cmd",".key",".DOT",".docm",".txt", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".odt", ".jpg", ".png", ".csv", ".sql", ".mdb", ".sln", ".php", ".asp", ".aspx", ".html", ".xml", ".psd", ".bmp"]
มัลแวร์จะไม่เข้ารหัสไฟล์ที่ปรากฎนามสกุลไฟล์เป็น .wannadie
ซึ่งหมายถึงไฟล์ที่ถูกเข้ารหัสโดย DeathRansom ไปแล้ว
กระบวนการเข้ารหัสไฟล์จะเริ่มต้นโดยการเรียกใช้ฟังก์ชัน rsa.encryptar()
ซึ่งมีการระบุพารามิเตอร์ 2 รายการ ได้แก่ พาธของไฟล์และค่ากุญแจสาธารณะของผู้โจมตีซึ่งถูกดาวโหลดมาจากอินเตอร์เน็ต
def encryptar(FileName,public_key):
try:
public_key = RSA.importKey(public_key)
encryptor = PKCS1_OAEP.new(public_key)
OutputFile = os.path.join(os.path.dirname(FileName), "(encrypted)" + os.path.basename(FileName) + '.wannadie')
with open(FileName,'rb') as initial_file:
text = initial_file.read()
initial_file.close()
encrypted = encryptor.encrypt(text)
with open(FileName,'wb') as output_file:
output_file.write(encrypted)
output_file.close()
os.rename(FileName,OutputFile)
return True
except:
return False
ภายใต้ฟังก์ชัน rsa.encryptar()
มัลแวร์เรียกค่าไถ่ DeathRansom จะดำเนินการเข้ารหัสไฟล์ตามขั้นตอนดังนี้
- มัลแวร์นำกุญแจสาธารณะของผู้โจมตีมาผ่านฟังก์ชันเพื่อสร้าง object สำหรับการเข้ารหัสข้อมูลด้วยอัลกอริธึม RSA แบบ PKCS#1 OAEP
- สร้างสตริงซึ่งเก็บชื่อไฟล์ใหม่หลังจากที่ถูกเข้ารหัสแล้ว
- เปิดไฟล์ตามพาธที่ถูกส่งเข้ามา อ่านเนื้อหาในไฟล์ หลังจากนั้นใช้ object ซึ่งเกิดขึ้นจากการนำเข้ากุญแจสาธารณะมาทำการเข้ารหัสเนื้อหาไฟล์
- เปิดไฟล์เดิมใหม่อีกครั้ง แล้วเขียนข้อมูลที่ถูกเข้ารหัสแล้วทับลงไป
- เปลี่ยนชื่อไฟล์เป็นชื่อใหม่ตามที่ได้สร้างไว้ในขั้นตอนที่ 2
ถ้าเกิดข้อผิดพลาดใดๆ ในขั้นตอนเหล่านี้ กระบวนการเข้ารหัสไฟล์ในพาธดังกล่าวนี้จะไม่เกิดขึ้นทันที
Post-Infection
หลังจากกระบวนเข้ารหัสไฟล์เสร็จสิ้น มัลแวร์จะมีการสร้างไฟล์สคริปต์ไว้ที่พาธ %USERPROFILE%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\delete_ransom.bat
ไฟล์ดังกล่าวจะมีจัดเก็บคำสั่งสำหรับการลบไฟล์โปรแกรมของมัลแวร์เอาไว้
หลังจากนั้นมัลแวร์จะทำการดาวโหลดโปรแกรมซึ่งจะทำการแสดง ransom note มาทำงานในระบบด้วยฟังก์ชัน download_ransomware_request
ท้ายที่สุดมัลแวร์จะทำการป้องกันไม่ให้ผู้ใช้สามารถเปิดใช้งานโปรแกรม Registry editor, Task manager และ Command prompt ได้ ก่อนจะบังคับให้ระบบทำรีสตาร์ทตัวเอง
Comments
- โครงการนี้ใช้ไลบรารีในการอิมพลีเมนต์อัลกอริธึมการเข้ารหัสและถอดรหัสซ้ำซ้อนกัน โดยมีการปรากฎของไลบรารีทั้ง
Crypto
และpycryptodome
ในไฟล์requirements.txt
ซึ่งสามารถเลือกใช้อย่างใดอย่างหนึ่งได้ อีกทั้งไม่มีการระบุโมดูลPyQt5
ในไฟล์requirements.txt
- กระบวนการเข้ารหัสไม่จำเป็นต้องที่จะต้องมีการดาวโหลดกุญแจสาธารณะของผู้ควบคุมัลแวร์ก่อน เนื่องจากหากกระบวนการดาวโหลดไม่สำเร็จหรือถูกตรวจจับได้ก่อน มัลแวร์จะไม่สามารถทำง่นได้ มัลแวร์เรียกค่าไถ่อย่าง WannaCry ใช้วิธีการฝังค่ากุญแจสาธารณะของผู้โจมตีเข้าไปไว้ในโค้ดของมัลแวร์เลย
- โครงการไม่ได้รวมหน้าต่าง Ransom note ไว้ในโค้ดของมัลแวร์ทำให้มีขั้นตอนเพิ่มในการเตรียมการที่ไม่จำเป็นและไม่สมเหตุสมผล
- การตรวจสอบว่าโปรแกรมทำงานอยู่ใน sandbox หรือไม่ด้วยการตรวจสอบจากรายการโปรเซสเป็นวิธีการตรวจสอบที่ไม่สมบูรณ์ malware analyst สามารถเปลี่ยนชื่อของโปรแกรมซึ่งจะส่งผลให้ชื่อโปรเซสเปลี่ยนไปได้
- มีพาธของโค้ดซึ่งจะไม่ทำงานเนื่องจากโค้ดถูกบังคับให้จบการทำงานก่อน โดยเฉพาะอย่างยิ่งในส่วนของกระบวนการตรวจสอบหาความพยายามวิเคราะห์โปรแกรม
- การเข้ารหัสข้อมูลในไฟล์เพื่อเรียกค่าไถ่โดยการใช้ค่ากุญแจสาธารณะนั้นจะทำให้มัลแวร์ทำงานได้ช้าลง และหากคู่ของกุญแจสาธารณะถูกส่งมาเหยื่อเพื่อถอดรหัสไฟล์ เหยื่อจะสามารถทำการคัดลอกค่าดังกล่าวและแจกจ่ายไปยังเหยื่อคนอื่นๆ เพื่อให้สามารถถอดรหัสไฟล์ได้โดยที่ไม่ต้องจ่ายทันที