บทนำ
ในด้านการพัฒนาซอฟต์แวร์ โดยเฉพาะเมื่อจัดการข้อมูลที่สำคัญ ความปลอดภัยของหน่วยความจำเป็นสิ่งสำคัญมาก นักพัฒนามักพบสถานการณ์ที่พวกเขาจำเป็นต้องปกป้องข้อมูลสำคัญ เช่น รหัสการใช้งานหรือรหัสผ่านจากการมองเห็นที่ไม่ได้รับอนุญาต คำถามที่เกิดขึ้นในบริบทดังกล่าวคือ: เราจะสร้างตัวจัดสรรหน่วยความจำที่ปลอดภัยใน C++ ที่ป้องกันการเพจไปยังดิสก์และเข้าถึงได้ยากผ่านดีบักเกอร์ได้อย่างไร?
ในบล็อกโพสต์นี้ เราจะสำรวจปัญหาที่เกี่ยวข้องกับความปลอดภัยของหน่วยความจำและพิจารณาวิธีการนำไปใช้ในการสร้างตัวจัดสรรใน C++ ที่ตอบโจทย์เหล่านี้
การเข้าใจความท้าทาย
ก่อนที่เราจะดำดิ่งไปสู่การแก้ปัญหา สิ่งสำคัญคือต้องเข้าใจความท้าทายบางประการที่มาพร้อมกับการปกป้องหน่วยความจำ:
-
การป้องกันการเพจไปยังดิสก์: บนระบบที่ใช้หน่วยความจำเสมือน หน่วยความจำสามารถถูกเพจไปยังดิสก์ ทำให้เสี่ยงต่อการเข้าถึงที่ไม่ได้รับอนุญาต เมื่อหน่วยความจำถูกเพจออก จะถูกเก็บในพื้นที่สลับซึ่งอาจเข้าถึงได้โดยกระบวนการอื่นๆ
-
การเข้าถึงผ่านดีบักเกอร์: ดีบักเกอร์สามารถเข้าถึงและจัดการหน่วยความจำ ทำให้เป็นสิ่งสำคัญในการหาแนวทางเพื่อลดความเสี่ยงนี้ โดยเฉพาะสำหรับข้อมูลสำคัญ
-
ข้อจำกัดในระดับ OS: ไม่ว่าวัตถุประสงค์ของเราจะเป็นอย่างไร ระบบปฏิบัติการมีการควบคุมกระบวนการและอาจสามารถอ่านเนื้อหาของหน่วยความจำ
ตัวจัดสรรหน่วยความจำที่ปลอดภัยใน C++
แม้จะมีความท้าทายเหล่านี้ แต่เราสามารถ implement ตัวจัดสรรแบบกำหนดเองใน C++ โดยใช้ฟังก์ชัน API ของ Windows มาแบ่งการแก้ปัญหาเป็นขั้นตอนๆ ดังนี้:
1. การใช้ VirtualAlloc
เครื่องมือหลักสำหรับการจัดสรรหน่วยความจำอย่างปลอดภัยคือ VirtualAlloc
ฟังก์ชันนี้ช่วยให้เราจัดสรรหน่วยความจำในลักษณะที่กำหนด:
- เราสามารถตั้งระดับการป้องกันเพื่อควบคุมวิธีการเข้าถึงหน่วยความจำที่จัดสรร
LPVOID pMem = ::VirtualAlloc(NULL, allocLen, allocType, allocProtect);
ที่นี่ allocType
ถูกตั้งค่าเป็น MEM_COMMIT
และ allocProtect
ถูกตั้งค่าเป็น PAGE_READWRITE
ซึ่งเปิดใช้งานการเข้าถึงทั้งการอ่านและการเขียน
2. การล็อคหน่วยความจำ
เพื่อป้องกันไม่ให้ระบบปฏิบัติการเพจหน่วยความจำไปยังดิสก์ เราจะใช้ฟังก์ชัน VirtualLock
:
if (pMem != NULL) {
::VirtualLock(pMem, allocLen);
}
อย่างไรก็ตาม โปรดทราบว่า VirtualLock
มีข้อจำกัดในปริมาณของหน่วยความจำที่คุณสามารถจัดสรรได้ ซึ่งอาจเป็นที่จัดการได้ตามความต้องการของคุณ
3. การปล่อยหน่วยความจำอย่างปลอดภัย
เมื่อปล่อยหน่วยความจำ การทำให้เนื้อหาที่สำคัญเป็นศูนย์ก่อนที่จะปล่อยมันเป็นสิ่งสำคัญ ซึ่งสามารถทำได้โดยใช้ SecureZeroMemory
:
::SecureZeroMemory(_pPtr, allocLen);
::VirtualUnlock(_pPtr, allocLen);
::VirtualFree(_pPtr, 0, MEM_RELEASE);
ตัวอย่างที่สมบูรณ์
นี่คือตัวอย่างการ implement ตัวจัดสรรหน่วยความจำที่ปลอดภัยของเรา:
template<class _Ty>
class LockedVirtualMemAllocator : public std::allocator<_Ty> {
public:
template<class _Other>
LockedVirtualMemAllocator<_Ty>& operator=(const LockedVirtualMemAllocator<_Other>&) {
return (*this);
}
template<class Other>
struct rebind {
typedef LockedVirtualMemAllocator<Other> other;
};
pointer allocate(size_type _n) {
SIZE_T allocLen = (_n * sizeof(_Ty));
DWORD allocType = MEM_COMMIT;
DWORD allocProtect = PAGE_READWRITE;
LPVOID pMem = ::VirtualAlloc(NULL, allocLen, allocType, allocProtect);
if (pMem != NULL) {
::VirtualLock(pMem, allocLen);
}
return reinterpret_cast<pointer>(pMem);
}
void deallocate(void* _pPtr, size_type _n) {
if (_pPtr != NULL) {
SIZE_T allocLen = (_n * sizeof(_Ty));
::SecureZeroMemory(_pPtr, allocLen);
::VirtualUnlock(_pPtr, allocLen);
::VirtualFree(_pPtr, 0, MEM_RELEASE);
}
}
};
// ตัวอย่างการใช้งาน
typedef std::basic_string<char, std::char_traits<char>, LockedVirtualMemAllocator<char>> modulestring_t;
สรุป
การสร้างตัวจัดสรรหน่วยความจำที่ปลอดภัยใน C++ เป็นงานที่ซับซ้อนซึ่งเกี่ยวข้องกับการนำทางข้อจำกัดในระดับระบบและความท้าทายด้านความปลอดภัย แม้ว่าจะไม่สามารถบรรลุการปกป้องแบบสมบูรณ์จากการเข้าถึงหน่วยความจำได้ แต่การใช้ฟังก์ชันเช่น VirtualAlloc
, VirtualLock
และ SecureZeroMemory
สามารถเพิ่มความปลอดภัยของข้อมูลสำคัญได้อย่างมาก
สิ่งสำคัญคือการตระหนักว่าไม่มีระบบใดสามารถมั่นคงได้อย่างสมบูรณ์จากเจ้าของอุปกรณ์ ดังนั้น การเข้าใจข้อจำกัดเหล่านี้จะช่วยให้นักพัฒนาสามารถสร้างแอปพลิเคชันที่มีความทนทานและแข็งแกร่งมากขึ้น
สำหรับผู้ที่สนใจในการรับรู้ข้อมูลเชิงลึกเพิ่มเติม แหล่งข้อมูลเช่น Practical Cryptography โดย Neil Ferguson และ Bruce Schneier สามารถให้บริบทที่มีคุณค่าในแนวปฏิบัติทางเข้ารหัสและระเบียบวิธีการจัดการหน่วยความจำที่ปลอดภัย