3CX CAMPAIGN: MALWARE ANALYSIS

Konoha
10 min readApr 5, 2023

--

1. Giới thiệu:

3CX là một nhà cung cấp phần mềm Voice over IP (VoIP) nổi tiếng, cung cấp giải pháp trung tâm cuộc gọi IP để kết nối các điện thoại IP và các thiết bị khác như máy tính để bàn, điện thoại di động và trình duyệt web.

Trong khoảng cuối tháng 3 vừa qua, một vụ tấn công chuỗi cung ứng (supply chain attack) đã xảy ra đối với nhà cung cấp phần mềm VoIP nổi tiếng 3CX. Đây là một trong những mối đe dọa đang trở thành nỗi lo ngại của nhiều doanh nghiệp và tổ chức. Vụ tấn công này đã phát tán mã độc vào hệ thống của các khách hàng của 3CX, đe dọa đến an toàn thông tin của hàng ngàn người dùng. Việc phân tích mã độc này trở thành cực kỳ quan trọng để tìm ra giải pháp phòng ngừa và đảm bảo an toàn cho các khách hàng của 3CX. Bài viết này sẽ phân tích chi tiết về vụ tấn công này và những hậu quả của nó đối với cộng đồng người dùng.

2. Phân tích

a. Overview

Theo như một bài viết đăng cùng ngày khi có dấu hiệu của campaign, cuộc tấn công chuỗi cung ứng (supply chain attack) này được bắt đầu khi bộ cài đặt MSI được download từ 3CX hay bắt đầu cập nhật 3CX. Sau khi được cài đặt hoặc cập nhật, 2 DLL bị compromise đã xuất hiện ffmpeg.dlld3dcompiler_47.dll. Ngoài ra, theo thông tin của bài viết CROWDSTRIKE, thì có thể hình dung được nơi bắt đầu phân tích sẽ là file ffmpeg.dll

Bên cạnh đó, nhà cung cấp ffmpeg.dll đã từ chối chịu trách nhiệm cho campaign này.

Về phần d3dcompiler_47.dll thì dll này đã được compile và có digital signature hợp lệ. Nhưng khi xem trên virustotal thì lại có báo cáo rằng file này không được sign.

valid signature của d3dcompiler_47.dll
Báo cáo trên virustotal

b. Phân tích

ffmpeg.dl

Tiếp cận ffmpeg.dl bắt đầu từ entrypoint của DLL. Entrypoint của DLL là điểm đầu vào của DLL, bất cứ khi một sự kiện load DLL thì entrypoint của dll đó sẽ được gọi đến. Có thể tìm hiểu thêm tại đây.

Từ Entrypoint sẽ đi đến DllMain. Đây là function chịu trách nhiệm chính của việc gọi entrypoint của DLL. Và như thấy trong hình thì sẽ thấy có 1 function, đặt tên cho function này là mainFunction.

Trong mainFunction, nó sẽ tạo một event duy nhất có tên là “AVMonitorRefreshEvent” nếu event đã tồn tài thì sẽ kết thúc. Bên trong event sau khi được tạo và tiến hành tạo và đọc file d3dcompiler_47.dll.

Sau khi đọc file dll, bắt đầu kiểm tra tính hợp lệ của file bằng cách so sánh 2 byte đầu tiên với 0x5A4D (Đây là signature của PE file) và bắt đầu tìm kiếm vị trí có signature bắt đầu 4 byte 0xFE 0xED 0xFA 0xCE ( Lưu ý rằng d3dcompiler_47.dll này đã bị compromise, vì ngoài kiểm tra tính hợp lệ còn tìm kiếm signature của file này bằng cách sử dụng các byte trong dll này để di chuyển đến và tìm kiếm, nếu như một file DLL khác rename cùng tên và đưa signature này vào có thể sẽ không hoạt động như mong muốn).

Sau khi tìm đến vị trí của signature đó, dll này sẽ lấy data từ đó (nằm trong pointer bufferData) và tiến hành decrypt RC4 bufferData đó có key là “3jB(2bsG#@c7”.

Sau khi decrypt xong, dll sẽ thực hiện VirtualProtect với quyền PAGE_EXECUTE_READWRITE cho pointer bufferData đó (VirtualProtect là function sẽ thay đổi quyền truy cập đến vùng data với dữ kiện là pointer truyền vào và size của nó, xem thêm tại đây) sau đó sẽ execute tại pointer này. Điều này chứng tỏ một điều đây là shellcode, và shellcode này đã được encrypt và giấu trong file dll d3dcompiler_47.dll có signature là 0xFE 0xED 0xFA 0xCE.

Để lấy được đoạn shellcode này có thể dùng 2 cách: static hoặc dynamic. Static là lấy đoạn data từ vị trí có signature đó và decrypt RC4, dynamic là debug đến đoạn sau khi đã decrypt trong dll thì dump ra. Để thực hiện theo cách dynamic thì cần chuẩn bị một chương trình (có thể sử dụng 3CXDesktopApp.exe để debug) để trigger entrypoint của dll, đoạn code của chương trình:

Khi debug đã dừng tại điểm breakpoint thì dump data từ pointer bufferData với size là 0x43B08 ra thì thu được một đoạn shellcode đã decrypt.

Debug sâu hơn vào shellcode này thì thấy rằng nó sẽ truyền vào địa chỉ của một file PE khác.

Đi sâu vào function thì thấy được function đầu tiên ( đặt tên là get_function_from_number) bên trong function được truyền địa chỉ sẽ sử dụng “NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;” để đi qua một thuật toán và trả về địa chỉ đến một function khác trong lib được load trong process của dll này.

Ví dụ sau khi đi qua hàm get_function_from_number thì v9 sẽ là pointer đến LoadLibraryA

Sau khi debug và rename qua các hàm get function thì có được:

Dựa trên thông tin có một file PE khác trong shellcode này và có các function như VirtualAlloc và LoadLibrary thì có thể đoán được bước tiếp theo cần phải phân tích file PE đứa chèn trong file DLL này.

Dll inside shellcode

Trong file dll của shellcode đó có export ra 2 function: DllGetClassObjectentrypoint của DLL

Trong shellcode có một chỗ gọi đến DllGetClassObject nên đó sẽ là function DllGetClassObject sẽ là nơi cần phân tích

Quay về với hàm DllGetClassObject có thể thấy function CreateThread sẽ tạo thread mới để execute pointer StartAddress.

Trong thread mới, dll này sẽ tạo một file manifest dùng để lưu thời điểm kết thúc sleep nếu như file đó chưa tồn tại và sẽ đọc thời điểm kết thúc đó nếu file manifest tồn tại, điều này có nghĩa là activity malicious này sẽ sleep liên tục (mỗi một giây) một thời gian kể từ khi 3cx đã được cài đặt hoặc update và file manifest sẽ là nơi lưu trữ thời điểm kết thúc sleep. Lưu ý rằng 3CX là chương trình sẽ tự hoạt động lên mỗi khi khởi động nên activity malicious này sẽ luôn luôn available.

Sample manifest:

Thời điểm kết thúc sleep sẽ được tính bằng cách: “timeSleep = rand() % 1800000 + current_time + 604800;”; và 604800 sẽ là 7 ngày, 1800000 là ~ 21 ngày. Thời gian sleep của activity malicious sẽ là từ 7 ngày ~ 21 ngày.

Thời gian sleep này là thời gian để tránh bị phát hiện sớm ra điểm bất thường, và sau một thời gian sleep thì khi có một hành động bất thường thì sẽ ít khả năng bị nghi ngờ hơn. Ví dụ trong thời gian sleep của malware, khi user không làm những hành động gì có thể nghi ngờ đến việc có malware trong máy thì các hoạt động của malware sau thời gian sleep sẽ thường bị phớt lờ đi và cho rằng đó là hoạt động legit; hoặc cho dù biết đã có hành động khiến cho malware có trong máy trong thời gian sleep thì cũng ít có khả năng nghi ngờ đến là do 3CX.

Malicious activity:

Sau khi sleep thì dll trong shellcode này bắt đầu thực hiện hành vi phạm tội, tiếp tục phân tích từ function dosomething0.

Trong function này, nó sẽ chạy vòng lặp để lấy data từ file icon.ico theo format <https://raw.githubusercontent.com/IconStorages/images/main/icon%d.ico> với %d là nơi để thay số vào từ 0 → 15. Sau khi đã lấy data từ các file .ico từ github, hành động tiếp theo là đi ngược từ cuối đến đầu data để tìm vị trí của kí tự “$” và decode base64 + decrypt AES data từ vị trí tại hàm decrypt_something.

Vì repo đã bị xoá nên tham khảo từ bài viết của huntress để lấy manh mối về repo github đó. Repo github đó lưu trữ 16 file .ICO tương ứng với 16 vòng lặp như hình trên.

Source: huntress

Và trong mỗi file .ICO đều có một chuỗi base64 ở cuối file.

Source: huntress

Sau khi decode + decrypt thì có được các url của C2 server sau:

Source: huntress

Sau khi có được các url của C2 server, tiếp tục gửi request đến từng url và nhận data về nhưng không có dấu hiệu làm gì, nhưng hay để ý nó sẽ return về urlDecrypted. Có thể kết luận được rằng function này chủ yếu là kết nối đến github để lấy data được nhét vào cuối mỗi file .ICO và decrypt chúng để nhận được những url của C2 server sau đó kết nối để kiểm tra chúng, cuối cùng là return về url C2 cuối cùng.

Sau khi phân tích xong function dosomething0 thì có được giá trị trả về là url đến C2 server và giá trị đó sẽ được truyền vào hàm dosomething1

Tại hàm dosomething1 , dll này sẽ tiếp tục connect đến url của C2 server để nhận data và decrypt chúng. Sau đó sẽ execute đoạn data đã decrypt đó sau khi đã cho quyền XWR (excute + write + read) và đoạn data execute đó có thể chính là một con malware chính hiệu dùng để điều khiển máy của nạn nhân.

Vì repo của kẻ chủ mưu này đã bị remove khỏi github nên cuộc phân tích chỉ có thể kết thúc tại đây.

3. Kết luận

  • Sau cuộc phân tích malware được gắn trong 3cx này, thì ta có thể thu được các IOC như là url của các C2 server nhưng không thể đi sâu vào bên trong được vì con đường phân tích chỉ có hạn. Có thể hình dung rằng con malware được gắn trong các DLL này thực ra chỉ là một vỏ bọc dùng để tạo kết nối đến và pull cái core thực sự (có đầy đủ chức năng malware cần) mà C2 server sẽ gửi xuống và thực thi chúng tại máy nạn nhân. Vì không thể thu được core thực sự nên khó phòng tránh kẻ chủ mưu đằng sau hơn, ví dụ kẻ chủ mưu có thể sẽ sử dụng một vỏ bọc khác cho core của chiến dịch lần này chẳng hạn.
  • Ngoài ra kẻ chủ mưu đằng sau đã rất thông minh khi cho thời gian pending (sleep) của malware này khoảng 7~21 ngày và chọn github là nơi vận chuyển url của các C2 server, vì sau khoảng thời gian 7 ngày cũng xem là tương đối dài và một user bình thường khi thấy có kết nối bất thường đến repo github có tên là IconStorages cũng ít có khả năng nghi ngờ vì nghĩ đó chỉ là một hành động update icon gì đó. Không chỉ thế github lại có thể cập nhật một cách dễ dàng rất thuận lợi cho việc custom cho kẻ chủ mưu. Không chỉ thời gian pending và các repo github mà còn có các url C2 nhìn có vẻ khá là legit nên cũng sẽ khó nghi ngờ đến. Tệp manifest dùng để lưu trữ thời gian kết thúc pending được sinh ra cũng không được chú ý đến nhiều bởi vì cái tên tệp khá legit.
  • Trong quá trình phân tích, có một điều tôithắc mắc là file dll compromised d3dcompiler_47.dll có digital signature một cách hợp lệ nhưng khi đưa lên virustotal thì báo rằng không được sign.

4. Các link tham khảo về 3cx campaign:

https://www.bleepingcomputer.com/news/security/hackers-compromise-3cx-desktop-app-in-a-supply-chain-attack/

https://www.crowdstrike.com/blog/crowdstrike-detects-and-prevents-active-intrusion-campaign-targeting-3cxdesktopapp-customers/

https://www.huntress.com/blog/3cx-voip-software-compromise-supply-chain-threats

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

No responses yet

Write a response