سؤال

كنت أفكر في محاولة يدي في بعض جيت Compilataion (فقط من أجل التعلم)، وسوف يكون من الجيد أن تعمل منصة العمل الخاصة بها منذ أن قمت بتشغيل جميع الثلاثة الرئيسية في المنزل (Windows، OS X، Linux). مع وضع ذلك في الاعتبار، أريد أن أعرف ما إذا كان هناك أي طريقة للخروج من استخدام وظائف Windows Virtual الذاكرة لتخصيص الذاكرة بأذونات التنفيذ. سيكون من الجميل فقط استخدام Malloc أو جديد ونقيف المعالج في مثل هذه الكتلة.

أي نصائح؟

هل كانت مفيدة؟

المحلول

احتمال واحد هو جعله متطلبات أن تثبيتات Windows التي تعمل بتشغيل البرنامج قد تم تكوينها لأي فائضة DEP (فكرة سيئة) أو DEP Optout (فكرة أفضل).

يمكن تكوين هذا (ضمن WinXP SP2 + و WIN2K3 SP1 + على الأقل) عن طريق تغيير ملف Boot.ini للحصول على الإعداد:

/noexecute=OptOut

ثم تكوين برنامجك الفردي لإلغاء الاشتراك عن طريق اختيار (ضمن XP):

Start button
    Control Panel
        System
            Advanced tab
                Performance Settings button
                    Data Execution Prevention tab

يجب أن يسمح لك هذا بتنفيذ التعليمات البرمجية من داخل البرنامج الذي تم إنشاؤه أثناء الطيران malloc() كتل.

ضع في اعتبارك أن هذا يجعل برنامجك أكثر عرضة للهجمات التي كان من المفترض أن يمنع ذلك.

يبدو أن هذا ممكن أيضا في نظام التشغيل Windows 2008 مع الأمر:

bcdedit.exe /set {current} nx OptOut

ولكن، أن نكون صادقين، إذا كنت ترغب فقط في تقليل الرمز المعتمد من المنصة، فمن السهل القيام به فقط عن طريق عزل الشفرة في وظيفة واحدة، شيء مثل:

void *MallocWithoutDep(size_t sz) {
    #if defined _IS_WINDOWS
        return VirtualMalloc(sz, OPT_DEP_OFF); // or whatever
    #elif defined IS_LINUX
        // Do linuxy thing
    #elif defined IS_MACOS
        // Do something almost certainly inexplicable
    #endif
}

إذا قمت بوضع جميع وظائفك التابعة لمنظمة النظام الأساسي الخاصة بك في ملفاتها الخاصة، فإن بقية التعليمات البرمجية الخاصة بك هو النظام الأساسي تلقائيا.

نصائح أخرى

DEP هو مجرد إيقاف إذن التنفيذ من كل صفحة غير شفافية من الذاكرة. يتم تحميل رمز التطبيق على الذاكرة التي لديها إذن التنفيذ؛ وهناك الكثير من الطيور التي تعمل في ويندوز / لينكس / ماكوسكس، حتى عندما يكون DEP نشطا. هذا لأن هناك طريقة لتخصيص الذاكرة ديناميكيا مع مجموعة الأذونات اللازمة.

عادة، لا ينبغي استخدام malloc العادي، لأن الأذونات هي في كل صفحة. لا يزال محاذاة الذاكرة الملوكة إلى الصفحات ممكنة بسعر بعض النفقات العامة. إذا لم تستخدم Maloc، فقم ببعض إدارة الذاكرة المخصصة (فقط للحصول على التعليمات البرمجية القابلة للتنفيذ). الإدارة المخصصة هي وسيلة شائعة للقيام JIT.

هناك حل من مشروع Chromium، والذي يستخدم JIT for JavaScript V8 VM والذي هو منصة عرضية. أن تكون عبر منصة، يتم تنفيذ الوظيفة المطلوبة في العديد من الملفات ويتم تحديدها في وقت الترجمة.

Linux: (Chromium SRC / V8 / SRC / Platform-linux.cc) Flag Prot_Exec من MMAP ().

void* OS::Allocate(const size_t requested,
                   size_t* allocated,
                   bool is_executable) {
  const size_t msize = RoundUp(requested, AllocateAlignment());
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
  void* addr = OS::GetRandomMmapAddr();
  void* mbase = mmap(addr, msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if (mbase == MAP_FAILED) {
    /** handle error */
    return NULL;
  }
  *allocated = msize;
  UpdateAllocatedSpaceLimits(mbase, msize);
  return mbase;
}

Win32 (SRC / V8 / SRC / Platform-Win32.cc): Flag is page_execute_readwrite من Virtualalloc

void* OS::Allocate(const size_t requested,
                   size_t* allocated,
                   bool is_executable) {
  // The address range used to randomize RWX allocations in OS::Allocate
  // Try not to map pages into the default range that windows loads DLLs
  // Use a multiple of 64k to prevent committing unused memory.
  // Note: This does not guarantee RWX regions will be within the
  // range kAllocationRandomAddressMin to kAllocationRandomAddressMax
#ifdef V8_HOST_ARCH_64_BIT
  static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
  static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
#else
  static const intptr_t kAllocationRandomAddressMin = 0x04000000;
  static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
#endif

  // VirtualAlloc rounds allocated size to page size automatically.
  size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
  intptr_t address = 0;

  // Windows XP SP2 allows Data Excution Prevention (DEP).
  int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;

  // For exectutable pages try and randomize the allocation address
  if (prot == PAGE_EXECUTE_READWRITE &&
      msize >= static_cast<size_t>(Page::kPageSize)) {
    address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits)
      | kAllocationRandomAddressMin;
    address &= kAllocationRandomAddressMax;
  }

  LPVOID mbase = VirtualAlloc(reinterpret_cast<void *>(address),
                              msize,
                              MEM_COMMIT | MEM_RESERVE,
                              prot);
  if (mbase == NULL && address != 0)
    mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);

  if (mbase == NULL) {
    LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed"));
    return NULL;
  }

  ASSERT(IsAligned(reinterpret_cast<size_t>(mbase), OS::AllocateAlignment()));

  *allocated = msize;
  UpdateAllocatedSpaceLimits(mbase, static_cast<int>(msize));
  return mbase;
}

ماكوس (SRC / V8 / SRC / Platform-Macos.cc): العلم هو prot_exec من mmap، تماما مثل لينكس أو posix الأخرى.

void* OS::Allocate(const size_t requested,
                   size_t* allocated,
                   bool is_executable) {
  const size_t msize = RoundUp(requested, getpagesize());
  int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
  void* mbase = mmap(OS::GetRandomMmapAddr(),
                     msize,
                     prot,
                     MAP_PRIVATE | MAP_ANON,
                     kMmapFd,
                     kMmapFdOffset);
  if (mbase == MAP_FAILED) {
    LOG(Isolate::Current(), StringEvent("OS::Allocate", "mmap failed"));
    return NULL;
  }
  *allocated = msize;
  UpdateAllocatedSpaceLimits(mbase, msize);
  return mbase;
}

وأريد أيضا ملاحظة ذلك bcdedit.exe- يجب استخدام طريقة الاستخدام فقط للبرامج القديمة جدا، والتي تنشئ رمز قابل للتنفيذ جديد في الذاكرة، ولكن لا يحدد خاصية EXEC في هذه الصفحة. بالنسبة للبرامج الأحدث، مثل Firefox أو Chrome / Chromium، أو أي JIT الحديثة، يجب أن تكون DEP نشطة، وسوف تدير JIT أذونات الذاكرة بطريقة محترمة بشكل جيد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top