Process Ghosting
ในกระบวนการเพื่อระบุหาการมีอยู่ของมัลแวร์สภาพแวดล้อมที่เป็น Windows โปรแกรมในกลุ่ม anti malware มีการใช้เทคนิคหลายอย่างร่วมกันเพื่อให้แน่ใจว่าหากมีการ bypass เทคนิคใดเทคนิคหนึ่งแล้ว เทคนิคอื่นจะยังคงอยู่เพื่อทำให้การตรวจจับยังมีประสิทธิภาพ เราอาจรู้จักวิธีการที่ถูกใช้เหล่านี้ในชื่อต่าง ๆ อาทิ การทำ API hooking เพื่อตรวจหาการเรียกใช้ฟังก์ชันของระบบที่ผิดปกติ, การใช้ Event tracing for Windows (ETW) เพื่อรับข้อมูลการทำงานของระบบปฏิบัติการแล้วนำมาประมวลผล, การติดตั้งไดร์เวอร์เพื่อคอยดักจับเหตุการณ์ในระดับเคอร์เนลล์ รวมไปถึงการผสานเข้ากับฟีเจอร์บางอย่างที่ระบบปฏิบัติการมีให้เพื่อให้ได้มุมมองที่กว้างและลึกขึ้นอย่าง Antimalware Scan Interface (AMSI)
เมื่อมองกลับมาในมุมของการ bypass แล้ว การ bypass ก็มักจะเกิดขึ้นเพื่อตอบสนองต่อแนวทางการตรวจจับที่เฉพาะ ตัวอย่างเช่นการโจมตีในกลุ่ม Tampering attack ที่พุ่งเป้าไปที่กระบวนการซึ่งเกิดขึ้นเมื่อโปรเซสกำลังจะถูกสร้างมาจากไฟล์ เพื่อให้การเกิดขึ้นของโปรเซสนั้นไม่ถูกระบุโดยโปรแกรม Anti malware ว่าเป็นอันตราย เทคนิค Process Ghosting ซึ่งเราจะมาพูดถึงกันในวันนี้ก็คือหนึ่งเทคนิคในกลุ่มนี้
Tampering Attacks
ก่อนจะไปพูดถึงเมนูหลักของเราคือ Process Ghosting การแนะนำการโจมตีในกลุ่ม Tampering attack ให้ได้รู้จักกันโดยคร่าวก่อนอาจเป็นจุดเริ่มต้นที่ทำให้เราเข้าใจเทคนิคการโจมตีในลักษณะนี้ได้ดีมากยิ่งขึ้น
เทคนิคการโจมตีในกลุ่ม Tampering ซึ่งถูกค้นพบมาก่อนและมีอิทธิพลต่อการค้นพบ Process Ghosting มีอยู่ทั้งหมด 3 เทคนิค ได้แก่ Process Doppelgänging, Process Herpaderping และ Process reimaging
Process Doppelgänging
Process Doppelgänging เป็นเทคนิคการโจมตีที่อาศัยฟีเจอร์ของ Windows ในการทำไฟล์ซึ่งควรจะถูกนำมาสร้างเป็นโปรเซสนั้นไม่ปรากฎเมื่อถูกค้นหา
Process Doppelgänging อาศัยกลไกที่มีชื่อว่า Windows Transactional NTFS (TxF) ซึ่งทำให้ผู้ใช้งานสามารถสร้างสิ่งที่เรียกว่า atomic transaction บนระบบ NTFS ได้เช่นเดียวกับคอนเซ็ปต์ของ transaction ที่มีในฐานข้อมูล
ในการใช้เพื่อโจมตี ผู้โจมตีจะสร้างส่วนของไฟล์ที่เรียกว่าอิมเมจซึ่งจะถูกนำไปใช้ในการสร้างเป็นโปรเซสต่อ โดยอิมเมจทที่ถูกสร้างนั้นจะถูกสร้างจากไฟล์ที่อยู่ใน transaction ซึ่งจะถูก roll back (หนึ่งในคุณสมบัติของ transaction) หลังจากที่มีการสร้างอิมเมจเสร็จสิ้น ซึ่งจะทำให้ไฟล์ไม่ปรากฎในระบบไฟล์ และส่งผลให้เมื่อมีการนำอิมเมจไปสร้างเป็นโปรเซส ความพยายามในการระบุหาไฟล์ที่เชื่อมโยงกับโปรเซสจะไม่สามารถทำได้
Process Herpaderping
Process Herpaderping เป็นเทคนิคการโจมตีที่จะทำให้ความพยายามในการระบุหาไฟล์ที่เชื่อมโยงกับโปรเซสนั้นปรากฎผลลัพธ์เป็นไฟล์อื่น
อ้างอิงจากกระบวนการโดยทั่วไปของการเกิดขึ้นของโปรเซส ไฟล์ executable จะถูกเรียก/เปิด หลังจากนั้น handle ที่เกิดจากการเรียกไฟล์จะถูกระบุกับฟังก์ชันของระบบเพื่อสร้างเป็นอิมเมจที่จะถูกเอาไปสร้างเป็นโปรเซสต่อ Process Herpaderping จะอาศัย handle ที่ยังค้างอยู่ในหลังจากที่มีการสร้างอิมเมจแล้วในการเขียนทับไฟล์ executable ด้วยไฟล์ที่ไม่เป็นอันตราย ซึ่งส่งผลให้ไฟล์ที่ถูกเขียนใหม่และปรากฎบนดิสก์นั้นเป็นคนละไฟล์กับที่ถูกโหลดเข้าสู่หน่วยความจำ และทำให้การเชื่อมโยงไฟล์กับโปรเซสได้ผลลัพธ์ที่ไม่ถูกต้อง
Process Reimaging
Process Reimaging เป็นเทคนิคการโจมตีที่อาศัยการโจมตีปัญหาของการ synchronize cache ที่เกิดขึ้นในเคอร์เนล ผลลัพธ์ของ Process Reimaging จะทำให้พาธของไฟล์ executable ในระบบไฟล์กับพาธของไฟล์ executable ที่อิมเมจมีการอ้างถึงนั้นไม่ตรงกัน การใช้เทคนิค Process Reimaging สามารถทำได้ง่าย ๆ ด้วยการโหลดไฟล์ DLL ในพาธที่เป็นเหยื่อล่อ, ถอนการโหลดไฟล์ DLL ออก และทำการโหลดไฟล์ DLL ที่พาธใหม่ การดำเนินการในลักษณะนี้เมื่อถูกตรวจสอบโดยฟังก์ชันของระบบบางฟังก์ชันจะได้ผลลัพธ์เป็นพาธเหยื่อล่อ
Process Ghosting
แนวคิดหลักของเทคนิค Process Ghosting คือการเรียก executable ที่ถูกลบไปแล้วซึ่งจะทำให้การเชื่อมโยงเพื่อตรวจสอบไฟล์และโปรเซสนั้นไม่สามารถทำได้
อ้างอิงจากต้นฉบับของงานวิจัย เทคนิค Process Ghosting สามารถทำได้ตามขั้นตอนดังนี้
- ผ่านฟังก์ชัน
NtCreateFile
(อาจใช้เป็นฟังก์ชันที่เกี่ยวข้องกับการเปิดไฟล์แทนได้ เช่นNtOpenFile
)- กำหนด flag
FILE_SUPERSEDED
ในIoStatusBlock
ความหมายของการกำหนด flag นี้กับไฟล์ที่มีอยู่แล้วจะหมายถึงการลบไฟล์ปัจจุบันและทำการสร้างไฟล์ใหม่ - กำหนด flag
FILE_DELETE_ON_CLOSE
ในCreateOptions
ความหมายของการกำหนด flag นี้จะหมายถึงให้การลบไฟล์ทันทีหาก handle สุดท้ายที่เกี่ยวข้องกับไฟล์ทุกปิด (มีการเรียกใช้ฟังก์ชันNtClose
กับ handle ของไฟล์
- กำหนด flag
NTSTATUS stat = NtOpenFile(&file,
DELETE | SYNCHRONIZE | GENERIC_READ | GENERIC_WRITE,
&attr,
&status_block,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SUPERSEDE | FILE_SYNCHRONOUS_IO_NONALERT
);
- ผ่านฟังก์ชัน
CreateFileW
(อาจใช้เป็นฟังก์ชันที่เกี่ยวข้องกับการเปิดไฟล์แทนได้ เช่นOpenFile
)- กำหนด flag
CREATE_ALWAYS
ในdwCreationDisposition
เพื่อให้มีการสร้างไฟล์ใหม่เสมอแม้จะมีไฟล์เดิมอยู่ ซึ่งหากมีไฟล์เดิม การกำหนด flag จะเท่ากับการสร้างไฟล์ใหม่ทับไฟล์เดิม - กำหนด flag
FILE_FLAG_DELETE_ON_CLOSE
ในdwFlagAndAttributes
เช่นเดียวกับFILE_DELETE_ON_CLOSE
ในกรณีของNtCreateFile
การกำหนด flag นี้จะหมายถึงกำหนดให้ไฟล์ถูกลบทันทีหาก handle ที่เกี่ยวข้องกับไฟล์ดังกล่าวถูกปิด
- กำหนด flag
- หลังจากมีการกำหนด flag ทั้งในกรณีที่มีการเรียกใช้
NtCreateFile
หรือในกรณีที่มีการเรียกใช้CreateFileW
เสร็จแล้ว ให้ทำการเรียกใช้ฟังก์ชันNtSetInformationFile
ที่มีการระบุคลาสFileDispositionInformation
เอาไว้ คลาสFileDispositionInformation
ที่อ้างอิงมาจากสตรัคเจอร์FILE_DISPOSITION_INFORMATION
จะต้องมีการกำหนดค่าในฟิลด์DeleteFile
ให้เป็นTRUE
ด้วย
FILE_DISPOSITION_INFORMATION info = { 0 };
info.DeleteFile = TRUE;
NtSetInformationFile(
hDelFile,
&status_block,
&info,
sizeof(info),
FileDispositionInformation
);
- ทำการเขียนไฟล์จาก handle ของไฟล์ที่เราได้มาจาก
NtCreateFile
หรือCreateFileW
ด้วยโค้ด(ของมัลแวร์)ที่เราต้องการ
status = NtWriteFile(
hDelFile,
NULL,
NULL,
NULL,
&status_block,
payladBuf,
payloadSize,
&ByteOffset,
NULL
);
- เตรียมการสร้างโปรเซสด้วยการสร้างอิมเมจจากไฟล์ที่จะเป็นวัตถุดิบในการสร้างโปรเซสก่อนด้วยฟังก์ชัน
NtCreateSection
ในขั้นตอนนี้หากการสร้างอิมเมจสมบูรณ์ เราจะได้ handle ของอิมเมจมาเพื่อใช้สร้างโปรเซสต่อ
HANDLE hSection = nullptr;
status = NtCreateSection(&hSection,
SECTION_ALL_ACCESS,
NULL,
0,
PAGE_READONLY,
SEC_IMAGE,
hDelFile
);
- ก่อนจะทำการสร้างโปรเซส เรียกใช้ฟังก์ชัน
NtClose
เพื่อปิด handle ที่เกิดจากNtCreateFile
หรือCreateFileW
อ้างอิงจาก flag ที่เรากำหนดไว้ในขั้นตอนก่อนหน้า เมื่อมีการปิด handle ที่เกี่ยวข้องกับไฟล์แล้ว ไฟล์ที่ handle นี้เชื่อมโยงจะถูกลบ - นำ handle ของอิมเมจที่ได้จากการเรียกใช้ฟังก์ชัน
NtCreateSection
ไปสร้างเป็นโปรเซสต่อ โดยอาจใช้ฟังก์ชันอย่างNtCreateProcessEx
แล้วทำการระบุพารามิเตอร์ในส่วนsectionHandle
เป็น handle ของอิมเมจที่เรามีอยู่
NTSTATUS status = NtCreateProcessEx(
&hProcess,
PROCESS_ALL_ACCESS,
NULL,
NtCurrentProcess(),
PS_INHERIT_HANDLES,
hSection,
NULL,
NULL,
FALSE
);
สิ่งที่เราทำในขั้นตอนที่ผ่านมาทั้งหมดนั้นมีใจความสำคัญคือการสร้างไฟล์ที่มีสถานะ “กำลังจะถูกลบ” ติดอยู่ และทำการลบทันที “เมื่อมีการสร้าง section ที่เป็นอิมเมจ ก่อนที่จะนำอิมเมจไปสร้างเป็นโปรเซส”
หากอ้างคำพูดในรีเสิร์ชต้นฉบับ โปรเซสซึ่งเหมือนกับวิญญาณนั้นถูกสร้างจากไฟล์ซึ่งเหมือนกับร่างที่กำลังจะตาย (ถูกลบ) เทคนิคนี้จึงถูกเรียกว่า Process Ghosting
ในมุมของการพยายามตรวจสอบและเชื่อมโยงโปรเซสที่เกิดขึ้นใหม่กลับไปยังไฟล์โดยโปรแกรม Anti malware หากความพยายามในการตรวจสอบเกิดขึ้นหลังจากไฟล์ถูกลบออกไปแล้ว นั่นหมายถึงโปรแกรม Anti malware จะไม่เจอไฟล์ที่เชื่อมโยงกับโปรเซส และทำให้โปรแกรม Anti malware ไม่สามารถตรวจสอบได้
Proof of Concept
เทคนิค Process Ghosting มีการถูกอิมพลีเมนต์ให้พร้อมใช้งานจริงแล้วโดย hasherezade สามารถดูเพิ่มเติมได้ที่ hasherezade/proess_ghosting