Với việc phát hành Windows 10 Fall Creators Update (Build 1709), công cụ Enhanced Mitigation Experience Toolkit (EMET) tuyệt vời và thanh lịch nhất không còn có sẵn hoặc có thể cài đặt trên hệ điều hành này. Thay vào đó, các mitigations này giờ là một phần tích hợp của Windows 10.
Vì tôi là fan hâm mộ lớn của EMET, và đang dùng nó trên tất cả máy Windows của mình, tôi quyết định viết hướng dẫn chi tiết, thực tế và sử dụng thực tế về cách triển khai và tinh chỉnh các mitigations mới trong Windows 10. Hãy theo dõi tôi.
Mục Lục
- Giới thiệu & đọc trước
- Windows 10 exploit protection
- System settings
- Program settings
- Export và import cấu hình
- Định dạng file cấu hình
- Dùng cấu hình EMET cũ
- Application template
- Sử dụng thực tế và ví dụ
- Import cấu hình mới
- Nội dung file cấu hình
- Chạy và sử dụng exploit protection
- Chỉnh sửa và tinh chỉnh cấu hình
- Bảo vệ quá đà
- Đọc thêm
- Kết luận
Giới thiệu & đọc trước
Nếu bạn tình cờ rơi vào bài viết này, điều không chắc chắn בהתחשב vào bản chất niche và nerdy của chủ đề này, thì hãy cho tôi giới thiệu ngắn gọn EMET. Tiện ích này là một tập hợp các cơ chế hệ thống và chương trình ngăn chặn bad code chạy. Cách này nó có thể tiềm năng ngăn chặn và chặn exploit trong các chương trình đang chạy.
Microsoft phát hành EMET như một công cụ độc lập nhiều năm trước, và bạn có thể thủ công triển khai nó trên bất kỳ hệ thống nào. Nó vẫn có sẵn trong hai phiên bản Windows trước đó cũng như Windows 10 cho đến Build 1709.
EMET hoạt động bằng cách hạn chế loại lệnh và truy cập bộ nhớ mà các chương trình đang chạy có thể thực thi. Vẻ đẹp của ý tưởng này là nó KHÔNG phân biệt giữa những gì chúng ta gọi là good programs và malware. Nó chỉ phân biệt giữa code tuân thủ, gọi là legal code và code không tuân thủ, gọi là illegal code. Vì vậy, ngay cả khi bạn có một chương trình hoàn toàn hợp pháp như Chrome hay Powerpoint, và chúng được bao bọc và bảo vệ bởi thư viện EMET, nếu chúng hành xử sai do một số lệnh bất hợp pháp - nhiều khả năng do lỗi lập trình lơ là hoặc ràng buộc legacy - thì EMET sẽ chặn thực thi và kết thúc chương trình.
Điều này làm cho ý tưởng EMET như một công cụ bảo mật - một khi được cấu hình đúng, nó là giải pháp fire-and-forget. Nó nhẹ, không xâm nhập, cực kỳ hiệu quả, và thông minh. Khái niệm nhìn phần mềm từ góc độ chất lượng thực thi khôn ngoan hơn việc cố gắng blacklist chương trình xấu.
EMET cũng hoạt động kết hợp với các cơ chế bảo mật cấp hệ thống có sẵn trong Windows, bao gồm DEP, SEHOP, ASLR, và những cái khác. Rất gọn gàng, rất tiện lợi, và cực kỳ hữu ích.
Tôi đã viết hướng dẫn chi tiết về cách dùng EMET. Nó được làm với phiên bản 4 của chương trình, nhưng hướng dẫn là 100% đúng và chính xác cho các phiên bản sau, với review cuối cùng của tôi về mitigation toolkit là phiên bản 5.5. Hãy đọc những cái đó để bạn làm quen với các khái niệm và bảo vệ khác nhau.

Không còn cài được, tuy nhiên:
Windows 10 exploit protection
Chức năng của EMET giờ có sẵn trong Windows 10 Build 1709 như một khả năng built-in. Bạn có thể truy cập UI liên quan qua Windows Defender Security Center. Bên trái, trong sidebar, nhấp vào biểu tượng倒数第二个, cuộn xuống cuối danh sách, và nhấp Exploit protection settings.
UI mới được đơn giản hóa so với EMET - và cũng khó dùng hơn, vì bạn có ít khả năng nhìn thấy những gì bạn đang bật. Bạn cũng không có cái nhìn ma trận đầy đủ về app và mitigations đã bật của bạn. Nhưng hãy để các cân nhắc ergonomic qua một bên. Hãy chỉ tập trung vào chức năng thô. Chúng ta sẽ chạm đến việc giao diện thực tế có thể và nên được cải thiện như thế nào sau.
System settings
View mặc định liệt kê System settings. Giống như hệ điều hành cũ hơn, Windows 10 đi kèm với một vài cơ chế cấp thấp để ngăn chặn thực thi code độc hại (đọc: không chính xác/bất hợp pháp). Lại một lần, chúng ta không nói cụ thể malware, chúng ta nói bất kỳ code nào có thể tiềm năng gây crash hệ thống, sự không ổn định và những thứ giống nhau.
Sáu bảo vệ có sẵn đi kèm Windows 10 bao gồm: CFG, DEP, Mandatory ASLR, Bottom-up ASLR, SEHOP, và heap integrity. Chúng xấp xỉ tương đương với những gì Windows có trước đó, nhưng không có bản dịch 1:1 chính xác, vì đã có một vài thay đổi trong cấu trúc kernel bên dưới. Mặc định, tất cả các bảo vệ này đều ON.
Program settings
Nếu bạn nhấp vào danh mục thứ hai, điều này sẽ mở rộng danh sách các chương trình riêng lẻ hiện được che chở bởi cơ chế exploit protection. Chỉ chương trình có override mới được liệt kê. Nếu một chương trình có cấu hình khớp với system defaults, nó sẽ không được thêm.
Windows 10 đi kèm với một vài ứng dụng đã được liệt kê, bao gồm override cụ thể. Lúc này, chúng ta nên để những cái đó yên, vì chúng đã được Microsoft cấu hình cho bảo mật tối ưu so với tương thích.
Bạn có thể thêm chương trình mới, hoặc bằng đường dẫn hoặc bằng tên. Cái sau tốt hơn vì nó cho phép bạn bảo vệ bất kỳ phiên bản nào của ứng dụng cụ thể khớp với tên executable cụ thể, bất kể nó được cài ở đâu trên ổ đĩa của bạn.
Khi bạn thêm một chương trình, một cửa sổ mới sẽ bật lên, cho phép bạn tùy chỉnh cấu hình exploit protection của nó, với một danh sách dài và hơi gây nhầm lẫn các mitigations có sẵn. Bây giờ bạn có thể bật/tắt mitigations riêng lẻ. Bạn sẽ nhận thấy một số bảo vệ này Off mặc định - và những cái khác on, thường khớp với system configuration đề cập trước đó. Vì vậy bạn có thể override defaults.
Có 15 mitigations có sẵn - và nếu bạn bật chúng, chúng sẽ ưu tiên hơn system defaults. Bạn cũng có tùy chọn cho phép auditing - cơ bản là nếu gặp ngoại lệ, hệ thống sẽ thông báo bạn, và bạn sẽ cần thủ công đóng hoặc kết thúc chương trình. Nếu không, hệ thống sẽ kết thúc chương trình với lệnh bất hợp pháp khớp mitigations.
Export và import cấu hình
Bây giờ, phần thú vị và khó khăn. Vì cơ chế mới đi kèm với giao diện cồng kềnh hơn, cấu hình chương trình trở thành nỗi đau - chúng ta nói kiểu 20-30 chương trình với lên đến 15 mitigations mỗi cái, và này mất nhiều lần click chuột để sắp xếp.
May mắn thay, bạn có thể dùng file cấu hình XML để cập nhật bảo vệ nhanh hơn. Bạn thêm và xóa chương trình vào và từ danh sách, bạn có thể tinh chỉnh mitigations cụ thể, và thực hiện thiết lập cần thiết nhanh hơn và hiệu quả hơn. Để làm vậy, bạn cần hiểu định dạng cơ bản của file cấu hình.
Trong giao diện chính, nhấp Export settings và lưu file XML ở đâu đó trên ổ đĩa. Mở nó trong text editor, và hãy nhìn nhanh cấu hình, và ý nghĩa của các directive và giá trị khác nhau.
Định dạng file cấu hình
Hãy xem lại:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<SystemConfig>
<ASLR Enable="true" ForceRelocateImages="false"
OverrideForceRelocateImages="false"></ASLR>
</SystemConfig>
<AppConfig Executable="DevicesFlow.exe">
<ExtensionPoints DisableExtensionPoints="true"
OverrideExtensionPoint="false"></ExtensionPoints>
</AppConfig>
...
Đây là vài dòng đầu của một cấu hình thực tế; indentation ở đó để giúp phân biệt trực quan nơi mọi thứ bắt đầu và dừng, như hầu hết ngôn ngữ khác. Bạn có XML declaration ở trên. Sau đó, bạn có root section, cơ bản định nghĩa block bên trong đó bạn sẽ có system và application configurations.
System configurations được khai báo bởi SystemConfig. Applications được khai báo bởi AppConfig. Tên ứng dụng được khai báo bởi biến Executable. Sau đó chúng ta có các loại mitigations khác nhau, như ExtensionPoints, Fonts, Payloads, DynamicCode, và những cái khác. Ví dụ, danh sách gần như đầy đủ cho một ứng dụng thêm sẽ bao gồm thứ gì đó như:
<AppConfig Executable="chrome.exe">
<StrictHandle
Enable="true"
OverrideStrictHandle="false">
</StrictHandle>
<SystemCall
DisableWin32kSystemCalls="false"
OverrideSystemCall="false"
Audit="true">
</SystemCall>
<ExtensionPoints
DisableExtensionPoints="true"
OverrideExtensionPoint="false">
</ExtensionPoints>
<DynamicCode
BlockDynamicCode="false"
AllowThreadsToOptOut="false"
OverrideDynamicCode="false"
Audit="true">
</DynamicCode>
<Fonts
DisableNonSystemFonts="false"
AuditOnly="false"
OverrideFontDisable="false"
Audit="true">
</Fonts>
<ImageLoad
BlockRemoteImageLoads="false"
OverrideBlockRemoteImageLoads="false"
BlockLowLabelImageLoads="false"
OverrideBlockLowLabel="false"
AuditRemoteImageLoads="true"
AuditLowLabelImageLoads="true">
</ImageLoad>
<Payload
EnableExportAddressFilter="true"
OverrideExportAddressFilter="false"
AuditEnableExportAddressFilter="true"
EnableExportAddressFilterPlus="true"
OverrideExportAddressFilterPlus="false"
AuditEnableExportAddressFilterPlus="true"
EnableImportAddressFilter="true"
OverrideImportAddressFilter="false"
AuditEnableImportAddressFilter="true"
EnableRopStackPivot="true"
OverrideEnableRopStackPivot="false"
AuditEnableRopStackPivot="true"
EnableRopCallerCheck="true"
OverrideEnableRopCallerCheck="false"
AuditEnableRopCallerCheck="true"
EnableRopSimExec="true"
OverrideEnableRopSimExec="false"
AuditEnableRopSimExec="true">
</Payload>
</AppConfig>
Bỏ qua giá trị thực tế pro tempore. Hãy hiểu ba biến quan trọng:
Value - có thể true/false, định nghĩa mitigation có được bật hay không.
Override - trái ngược với những gì bạn nghĩ, điều này KHÔNG cho bạn biết nếu giá trị chỉ định override system defaults. Không. Đó đã là thiết kế. Nếu biến này được đặt thành true, nghĩa là bạn KHÔNG THỂ chỉnh sửa cài đặt qua UI. Điều này khá gây nhầm lẫn, đặc biệt vì false, nghĩa là bạn có kiểm soát qua Defender Security Center, và true nghĩa là bạn không. Tốt nhất bỏ qua biến này.
Audit - liệu chương trình chạy ở audit mode hay full enforced mode.
Vậy chúng ta có cơ bản sẵn sàng. Bây giờ, hãy thực sự tạo file cấu hình, và sau đó import nó vào exploits list. Và chúng ta sẽ làm điều đó bằng cách thực sự import một cấu hình EMET cũ, vì chúng ta không muốn mất tất cả công sức chúng ta đã làm.
Dùng cấu hình EMET cũ
Chúng ta sẽ thực sự dùng Powershell command line để làm một số nhiệm vụ. Cụ thể, chúng ta sẽ chuyển đổi file config EMET sang định dạng mới và sau đó import nó. Những lệnh này hiện không có GUI tương đương. Bạn cần Powershell và quyền administrator. Vì thế, file EMET sẽ trông giống như sau:
<EMET Version="5.1.5426.28431">
<Settings>
<ExploitAction Value="StopProgram" />
<AdvancedSettings DeepHooks="True" AntiDetours="True" BannedFunctions="True" />
<Reporting Telemetry="True" TrayIcon="True" EventLog="True" />
<SystemSettings DEP="Application Opt Out" SEHOP="Application Opt Out" ASLR="Application Opt In" Pinning="Enabled" />
</Settings>
<EMET_Apps>
<AppConfig Path="*" Executable="7z.exe">
<Mitigation Enabled="true" />
<Mitigation Enabled="true" />
<Mitigation Enabled="true" />
<Mitigation Enabled="true" />
Tôi nghĩ định dạng này sạch hơn và đẹp hơn. Nhưng không quan tâm. Hãy chuyển đổi file cấu hình này. Nếu chúng ta đọc tài liệu trực tuyến về cách làm, chúng ta cần lệnh sau:
ConvertTo-ProcessMitigationPolicy -EMETFilePath emetconfig.xml -OutputFilePath newconfig.xml
Tôi nhận được một đống lỗi:
Error: Should read Win10 setting for some reason?: PinRuleMember
Error: Should read Win10 setting for some reason?: Active
Error: Should read Win10 setting for some reason?: PinnedSite
Error: Should read Win10 setting for some reason?: Domain
Error: Should read Win10 setting for some reason?: PinRuleMember
Error: Should read Win10 setting for some reason?: Active
Rõ ràng, tất cả các quy tắc ghim cho chứng chỉ trong quy tắc pre-Windows 10 không tương thích với định dạng mới. Nếu bạn cố import cấu hình như vậy, nó sẽ fail. Bạn sẽ cần dọn dẹp XML trước khi chuyển đổi lại.
<Pinning>
<PinRules>
<PinRule>
<ID>{392c02ca-a7dd-49e3-888f-7fb505de9333}</ID>
<Name>FacebookCA</Name>
...
Lưu ý: Không có sự khớp 1:1 chính xác giữa EMET và cơ chế exploit protection mới, và đặc biệt nếu bạn di chuyển qua nhiều hệ điều hành. Khuyến nghị của tôi là dùng config cũ chỉ như một tham khảo.
Vì vậy, file chuyển đổi sẽ trông giống như sau - về mặt app mitigations:
<AppConfig
Executable="AcroRd32.exe">
<DEP
Enable="true"
EmulateAtlThunks="false"/>
<ASLR
ForceRelocateImages="false"
RequireInfo="false"
BottomUp="true"
HighEntropy="false"/>
<StrictHandle
Enable="false"/>
<SystemCalls
DisableWin32kSystemCalls="false"
Audit="false"/>
<ExtensionPoints
DisableExtensionPoints="false"/>
<DynamicCode
BlockDynamicCode="false"
AllowThreadsToOptOut="false"
Audit="false"/>
<ControlFlowGuard
Enable="false"
SuppressExports="false"
StrictControlFlowGuard="false"/>
<SignedBinaries
MicrosoftSignedOnly="false"
AllowStoreSignedBinaries="false"
EnforceModuleDependencySigning="false"
Audit="false"
AuditStoreSigned="false"
AuditEnforceModuleDependencySigning="false"/>
<Fonts
DisableNonSystemFonts="false"
Audit="false"/>
<ImageLoad
AuditPreferSystem32="false"
AuditLowLabelImageLoads="false"
AuditRemoteImageLoads="false"
PreferSystem32="false"
BlockLowLabelImageLoads="false"
BlockRemoteImageLoads="false"/>
<Payload
EAFModules=""
EnableExportAddressFilter="true"
AuditEnableExportAddressFilter="false"
EnableExportAddressFilterPlus="true"
AuditEnableExportAddressFilterPlus="false"
EnableImportAddressFilter="false"
AuditEnableImportAddressFilter="false"
EnableRopStackPivot="true"
AuditEnableRopStackPivot="false"
EnableRopCallerCheck="true"
AuditEnableRopCallerCheck="false"
EnableRopSimExec="true"
AuditEnableRopSimExec="false"/>
<SEHOP
Enable="true"
TelemetryOnly="false"
Audit="false"/>
<Heap
TerminateOnError="true"/>
<ChildProcess
DisallowChildProcessCreation="false"
Audit="false"/>
</AppConfig>
Application template
Hầu hết mitigations import từ EMET sẽ bị đặt thành false đáng tiếc - và system ones sẽ không còn khớp đầy đủ. Vì vậy khuyến nghị của tôi như sau: sáu system mitigations cover the basics. Bạn cũng có thể bật thêm sáu mitigations dường như khớp 1:1 giữa EMET và cơ chế bảo vệ mới, bao gồm: EAF, EAF+, IAF, StackPivot, CallerCheck, và SimExec. Do đó template cơ bản của chúng ta cho ứng dụng, dựa trên sử dụng trước đây trở thành:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<AppConfig Executable="executable.exe">
<Payload EnableExportAddressFilter="true"
EnableExportAddressFilterPlus="true"
EnableImportAddressFilter="true"
EnableRopStackPivot="true"
EnableRopCallerCheck="true"
EnableRopSimExec="true">
</Payload>
</AppConfig>
</root>
Chúng ta có thể mở rộng này với fonts protection (text được format cho sự rõ ràng trực quan):
<?xml version="1.0" encoding="UTF-8"?>
<root>
<AppConfig Executable="executable.exe">
<Fonts DisableNonSystemFonts="true"
AuditOnly="false"
OverrideFontDisable="false"
Audit="false">
</Fonts>
<Payload EnableExportAddressFilter="true"
EnableExportAddressFilterPlus="true"
EnableImportAddressFilter="true"
EnableRopStackPivot="true"
EnableRopCallerCheck="true"
EnableRopSimExec="true">
</Payload>
</AppConfig>
</root>
Và đây là template section bạn có thể dùng làm baseline:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<AppConfig Executable="executable.exe">
<Fonts DisableNonSystemFonts="true" AuditOnly="false" OverrideFontDisable="false" Audit="false"></Fonts>
<Payload EnableExportAddressFilter="true" EnableExportAddressFilterPlus="true" EnableImportAddressFilter="true" EnableRopStackPivot="true" EnableRopCallerCheck="true" EnableRopSimExec="true"></Payload>
</AppConfig>
</root>
Sử dụng thực tế và ví dụ
Được rồi, cho đến nay, chúng ta đã cover UI mới, system và program settings, tổng quan các exploit mitigations mới, cách export và import file cấu hình XML, cách chuyển đổi cài đặt EMET cũ, và bây giờ chúng ta sẽ import app template của chúng ta và sử dụng chúng.
Chúng ta sẽ dùng app template từ trên để nhanh chóng và thanh lịch thêm ứng dụng mới vào system list, nhớ rằng system settings tốt nhất để ở defaults, và chúng đã cover rất nhiều, cộng với sáu mitigations khác khớp gần với cấu hình quá khứ, và có khả năng hoạt động tốt. Đây là LÝ DO CHÍNH tại sao tôi chọn baseline này, cộng với fonts, điều này có ý nghĩa đơn giản, và cũng đi de pair với lỗ hổng quá khứ về vấn đề này.
Có mitigations khác chúng ta có thể bật tiềm năng, nhưng trừ khi bạn hiểu hoàn toàn bạn đang làm gì, bạn có thể tàn tật chương trình của mình. Trong một số trường hợp, ngay cả developer của phần mềm sẽ KHÔNG biết ứng dụng của họ đang làm sai gì, vì vậy rất có thể bạn không tìm thấy câu trả lời dễ dàng.
- ACG, low integrity và remote images - nên ổn.
- Code integrity guard - trừ khi ký bởi Microsoft, image sẽ không chạy - về cơ bản là Windows 10 S. Không khuyến khích.
- Extension points - rất có thể gây vấn đề trong cách phần mềm chạy.
- Disable system calls - rất có thể gây vấn đề.
- Child processes - chắc chắn sẽ tàn tật chương trình.
- Handle usage - có thể gây vấn đề với phần mềm thiết kế lơ là.
Phần còn lại chúng ta đã cover - sáu cơ bản, sáu mitigations cũ, fonts, và có thể ba cái viết trong bullet đầu tiên, phần còn lại tốt nhất để yên.
Import cấu hình mới
Điều này được làm như sau, lại từ Powershell, và với admin credentials:
Set-ProcessMitigation -PolicyFilePath .\config.xml
Nội dung file cấu hình
Dựa trên template của chúng ta, chúng ta có thể thêm ứng dụng bên trong file. Bạn có thể tạo một cấu hình đơn lẻ với vài chương trình liệt kê bên trong và import một lần, hoặc tạo template per-app và thực hiện nhiều lần import. Không có khác biệt.
Điều bạn cần tính đến là: 1) bạn có thể làm với Security Center chạy, nhưng nó SẼ KHÔNG hiển thị thay đổi on the fly; config được load một lần và/hoặc bất cứ khi nào bạn làm thay đổi qua UI 2) cài đặt app cũ sẽ bị xóa với cái mới.
Chạy và sử dụng exploit protection
Tôi test với các chương trình sau: Firefox, LibreOffice, VLC, IrfanView, Notepad++, và chúng chạy không có vấn đề gì, bao gồm cập nhật. Google Chrome sẽ không chạy với BẤT KỲ mitigation nào được bật trừ fonts - cả trang và extensions luôn crash. Điều này trái ngược với hành vi EMET. Như tôi nói, không có DANH SÁCH VÀNG nào về cái gì hoạt động và cái gì không, nhưng tôi tin bạn có thể có 7/15 và thậm chí 10/15 mitigations bật, với code signing, child processes và system calls disabling thực sự không cần thiết. Điều đó chỉ còn lại hai mitigations có thể cần nhìn gần hơn: extension points và handle usage. Khá tốt, tôi nói.
Chỉnh sửa và tinh chỉnh cấu hình
Bạn luôn có thể quay lại và làm thay đổi - cũng qua GUI sau khi bạn đã import phần lớn cấu hình, và bây giờ bạn chỉ cần fine tuning. Nếu mọi thứ không hoạt động, bạn luôn có thể xóa entry và bắt đầu mới.
Bảo vệ quá đà
Nếu bạn đi quá đà, và tôi đã thử, chỉ để xem cái gì xảy ra, bạn có thể hoàn toàn tàn tật chương trình của mình, và chúng sẽ không chạy. Việc này quá dễ làm, vì vậy hãy cực kỳ cẩn thận, và đảm bảo bạn hiểu bạn đang làm gì. Đây là đầu tư dài hạn. Làm tốt một lần và bạn sẽ không có vấn đề xuống đường.
Đọc thêm
Bạn cũng có thể muốn xem các bài viết chính thức của Microsoft:
Apply mitigations to help prevent attacks through vulnerabilities
Customize exploit protection
Kết luận
Đó là nó. Một hướng dẫn rất kỹ lưỡng, hands-on, thực tế về cách dùng cơ chế exploit protection mới trong Windows 10. Chúng ta không chỉ nhìn mù vào danh sách và ngạc nhiên phép màu xảy ra sau hậu trường, chúng ta đã đi sau hậu trường, và lấy chữ ký trên ngực chúng ta.
Về mặt kỹ thuật hơn, chúng ta đã học về exploit mechanism, UI mới, system và program settings, loại exploit và những gì chúng xấp xỉ làm, cách export và import file cấu hình XML, chúng ta tạo work template, chúng ta chuyển đổi và dùng cài đặt EMET cũ, chúng ta cố gắng khớp mức bảo vệ EMET cho chúng ta trong khi vẫn duy trì chức năng thực tế và hợp lý với hầu hết chương trình và hầu hết mitigations. Chúng ta có khoảng 80-90% coverage mà không làm hỏng thứ gì. Không có đảm bảo trong quy trình này, nhưng nó vượt xa bất kỳ phần mềm bảo mật truyền thống nào.
Bảo vệ mitigation vẫn là sản phẩm tốt nhất của Microsoft, và hy vọng, họ sẽ cải thiện workflow để nó dễ tiếp cận hơn cho advanced users. Cho thời điểm này, bạn có hướng dẫn này, và hy vọng nó sẽ làm cho hành trình của bạn vào thế giới post-EMET của mitigations đơn giản và nhanh hơn. Và app của bạn vẫn sẽ chạy! Hẹn gặp lại.
Nếu bạn thích hướng dẫn này, thì cho một chút tình yêu, support Dedoimedo. Đúng không?
Chúc vui.