Source: Moeomu’s blog
Introduction to DEP
The root cause of overflow attacks is the failure to accurately distinguish between data and code, but redesigning the computer architecture is unlikely, so various approaches are used to mitigate overflow attacks
Principle
- The memory page where the data is located is marked as non-executable, and the CPU will throw an execution exception when the program successfully overflows into the shellcode
- DEP is divided into software DEP and hardware DEP, while software DEP refers to SafeSEH, hardware DEP is called No-Execute Page-Protection (NX) on AMD platforms and Execute Disable Bit (XD) on Intel platforms
- The operating system indicates that the code cannot be executed from here by setting the NX and XD tags on the memory page, and a tag is inserted in the PageTable to identify whether this page is running execution instructions, with 0 indicating allowed and 1 indicating not allowed
The working status of DEP
- Optin: Allow system components and services to use DEP, other programs will not be protected, and the user can mark the program to use DEP through the ACT tool, this protection can be dynamically closed by the program, mostly used for ordinary user operating systems
- Output: Enable DEP for programs that are excluded from the list, mostly used in server operating systems
- AlwaysOn: DEP protection is applied to all programs and cannot be turned off, only 64-bit operating systems use this mode
- AlwaysOff: not used in general
Compile options
/NXCOMPAT
compile option will setIMAGE_DLLCHARACTERISTICS_ NX_COMPAT
flag in PE header, located inIMAGE_OPTIONAL_HEADER
inDllCharacteristics
, a value of0x100
means DEP is enabled
Challenging DEP with Ret2Libc
Principle
- The reason for overflow failure during DEP protection is that DEP detects that the code is executing on a non-executable page, and if the program is allowed to jump directly to a pre-existing system function, it will necessarily not be intercepted
Ret2Libc
is the abbreviation ofReturn-to-libc
, if each exploit finds a replacement in the system lib, then this exp must be executed correctly, but the problem is that not every instruction does not contain 0, and it is easy to jump to the wrong place constantly- Here are three possible ways
- Jump to
ZwSetinfomationProcess
function to turn off DEP and go to shellcode - Jump to
VirtualProtect
to make the shellcode page executable, then go to shellcode execution - Jump to
VirtualAlloc
to request a piece of executable memory space and then jump to shellcode execution
- Jump to
Try ZwSetinfomationProcess to close DEP
Preceding content
- The DEP identifier of a process is present in the
_KEXECUTE_OPTION
of theKPROCESS
structure and can be modified by the API function
_KEXECUTE_OPTION
structure
|
|
- When the current process DEP is on,
ExecuteDisable
will be set to 1 - When the current process DEP is closed,
ExecuteEnable
will be set to 1. DisableThunkEmulation
is set for ATL compatibilityPermanent
is set to 1 to indicate that none of these flags can be modified- We can set
ExecuteEnable
to 1 by setting the value of_KEXECUTE_OPTIONS
to0x02(00000010)
.
shellcode principle
- The
LdrpCheckNXCompatibility
function checks for DEP compatibility and will turn off DEP if one of the following conditions is met- The DLL is protected by the SafeDisc copyright protection system
- If the DLL contains
.aspack
,.pcle
,.sforce
, etc. bytes - When the DLL exists in a module declared in the registry that does not require DEP to be enabled
HKEY_LOCAL_MACHINE\SOFTWARE \Microsoft\ Windows NT\CurrentVersion\Image File Execution Options\DllNXOptions
Code
Test environment: System: Windows XP SP3, DEP Status: Optout, Compiler: VC6, Compile Options: Disable Optimization, Version: release
|
|
|
|
Technical details
- Need to compare whether al is 1 or not, so the first step retn will return to
mov eax, 1
, the address ofretn
, this address will return to the location of repair ebp - Because before calling the function, the value in ebp will be accessed, but it has been swiped, so ebp will be repaired, here we use
push esp
,pop ebp
,retn
three instructions to assign the address in esp to ebp, because retn is followed by a number, so ebp will add this number, that isebp+8
, at this time ebp is smaller than esp, once the subroutine is called, the stack area will be destroyed, so we still have to add some more ebp, I choose to add 0x24 to esp, and the previous 0x8 to make a stack space of 0x30, so that in the return time will return to the statementretn 0x24
. - The
retn 0x24
statement will return to the place where the functionZwSetInformationProcess
is called to close the DEP, and after that it will use the leave statement and retn, so it will return to the address ofjmp esp
. - Jump from
jmp esp
to the address where\x24\xCD\x93\x7C
data is stored, and this garbage data will not affect the execution of shellcode - Just write a jump after the garbage data, and then jump to the real execution of shellcode