is there some way to start a program with ASLR disabled on Windows? like on Posix one would do
posix_spawnattr_t attrs={0};
posix_spawnattr_setflags(&attrs, _POSIX_SPAWN_DISABLE_ASLR);
posix_spawnp(NULL, "./program.exe", NULL, &attrs,...);
and then program.exe would be started without ASLR.. but i have no idea how to do it on Windows (couldn't find any relevant info when looking through CreateProcessW docs either)
this SO post suggest that Microsoft's Enhanced Mitigation Experience Toolkit (EMET)
could indeed disable ASLR on a per-process basis, which suggest that it is possible (or at the very least, it was possible on Windows 7)
(also this is not a duplicate of how to disable ASLR on Windows
because i don't want to disable ASLR globally, but i know there is a registry key that can globally disable ASLR)
I don't know how Microsoft managed to it on Windows 7 (Evidently it IS possible to do it Win7, Microsoft did with their EMET after all. MSFT probably used some un-documented win7 apis),
But Windows 8 got new Process Attributes to disable ASLR on a per-process-invocation basis:
It's not trivial to use them. Here is a small example, written with help from ChatGPT, and tested with Visual Studio 2022 on Windows 10:
#include <windows.h>
#include <iostream>
int wmain()
{
// 1) Prepare STARTUPINFOEX and attribute list
STARTUPINFOEXW si{ { sizeof(si) } };
SIZE_T attrSize = 0;
// Get required buffer size
InitializeProcThreadAttributeList(nullptr, 1, 0, &attrSize);
si.lpAttributeList = static_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(
HeapAlloc(GetProcessHeap(), 0, attrSize));
if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attrSize)) {
std::cerr << "InitAttribList failed: " << GetLastError() << "\n";
return 1;
}
// 2) Disable all ASLR modes
DWORD64 policy =
PROCESS_CREATION_MITIGATION_POLICY_FORCE_RELOCATE_IMAGES_ALWAYS_OFF |
PROCESS_CREATION_MITIGATION_POLICY_BOTTOM_UP_ASLR_ALWAYS_OFF |
PROCESS_CREATION_MITIGATION_POLICY_HIGH_ENTROPY_ASLR_ALWAYS_OFF;
if (!UpdateProcThreadAttribute(
si.lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY,
&policy,
sizeof(policy),
nullptr,
nullptr))
{
std::cerr << "UpdateAttrib failed: " << GetLastError() << "\n";
return 1;
}
// 3) Launch the child process
PROCESS_INFORMATION pi{};
BOOL ok = CreateProcessW(
L"C:\\tcc\\aslr_test.exe", // Application name
nullptr, // Command-line (NULL = same as app name)
nullptr, nullptr, // Process & thread security
FALSE, // Inherit handles?
EXTENDED_STARTUPINFO_PRESENT, // Use our STARTUPINFOEX
nullptr, // Environment
nullptr, // Current directory
&si.StartupInfo, // Pointer to STARTUPINFOEX
&pi // Receives PROCESS_INFORMATION
);
if (!ok) {
std::cerr << "CreateProcess failed: " << GetLastError() << "\n";
}
else {
std::wcout << L"Launched with PID " << pi.dwProcessId << L"\n";
// Optionally wait for the child to exit:
// WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
// 4) Clean up
DeleteProcThreadAttributeList(si.lpAttributeList);
HeapFree(GetProcessHeap(), 0, si.lpAttributeList);
return ok ? 0 : 1;
}