Frage

Ich dachte an meine Hand irgend jit compilataion versuchen (nur im Interesse des Lernens) und es wäre schön, es Cross-Plattform arbeiten zu lassen, da ich alle wichtigen drei zu Hause laufen (Windows, OS X, Linux) . Vor diesem Hintergrund möchte ich wissen, ob es einen Weg gibt, um aus den virtuellen Speicher Windows-Funktionen unter Verwendung des Speichers mit der Ausführung Berechtigungen zuzuweisen. Wäre schön, nur malloc oder neu zu verwenden und den Prozessor in einem solchen Block zeigen.

Irgendwelche Tipps?

War es hilfreich?

Lösung

Eine Möglichkeit ist es eine Voraussetzung, um die Windows-Installationen Ihr Programm läuft entweder für DEP AlwaysOff (schlechte Idee) oder DEP OptOut (bessere Idee) konfiguriert werden.

Dies kann (unter WinXp SP2 + und Win2k3 SP1 + mindestens) konfiguriert werden, indem die Datei boot.ini Ändern der Einstellung haben:

/noexecute=OptOut

und dann Ihr individuelles Programm zu konfigurieren, indem Sie Opt-out (unter XP):

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

Dies sollten Sie ermöglichen, Code auszuführen, aus Ihrem Programm, das im laufenden Betrieb in malloc() Blöcken erstellt wird.

Beachten Sie, dass diese Angriffe Ihr Programm anfälliger macht, dass DEP zu verhindern gemeint war.

Es sieht aus wie das in Windows 2008 mit dem Befehl auch möglich ist:

bcdedit.exe /set {current} nx OptOut

Aber, um ehrlich zu sein, wenn Sie nur plattformabhängige Code minimieren wollen, das ist einfach nur zu tun, indem Sie den Code in eine einzige Funktion zu isolieren, so etwas wie:

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
}

Wenn Sie alle setzen Sie Ihre plattformabhängige Funktionen in ihren eigenen Dateien, der Rest des Codes ist automatisch plattformunabhängig.

Andere Tipps

DEP dreht gerade Execution Erlaubnis von jeder Nicht-Code-Seite des Speichers ab. Der Code der Anwendung in den Speicher geladen, die Ausführungserlaubnis hat; und es gibt viele JIT, die in Windows / Linux / Mac OS X funktioniert, auch wenn DEP aktiviert ist. Dies liegt daran, es ist ein Weg, um dynamisch Speicher mit dem benötigten Berechtigungen Satz zuweisen.

Normalerweise sollte schlicht malloc nicht verwendet werden, da Berechtigungen pro-Seite sind. Aligning von malloced Speichern auf Seiten ist immer noch möglich, zum Preis von einem gewissen Aufwand. Wenn Sie nicht malloc verwenden, einige benutzerdefinierte Speicherverwaltung (nur für ausführbaren Code). Benutzerdefinierte Management ist ein gemeinsamer Weg JIT zu tun.

Es gibt eine Lösung von Chromium-Projekt, das für Javascript V8 VM JIT verwendet und die plattformübergreifend. Um plattformübergreifende, die benötigte Funktion in mehreren Dateien implementiert ist, und sie werden bei der Kompilierung ausgewählt.

Linux: (Chrom src / v8 / src / platform-linux.cc) Flag PROT_EXEC von 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 PAGE_EXECUTE_READWRITE von 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;
}

MacOS (src / v8 / src / platform-macos.cc): Flag PROT_EXEC von mmap, genau wie Linux oder anderen 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;
}

Und ich mag auch beachten, dass bcdedit.exe artig verwendet nur für sehr alte Programme werden soll, den neuen ausführbaren Code im Speicher erstellt, aber nicht setzt eine Exec-Eigenschaft auf dieser Seite. Für neuere Programme wie Firefox oder Chrome / Chromium oder jeden moderner JIT sollte DEP aktiv sein, und JIT wird Speicherberechtigungen in feinkörniger Weise verwalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top