zoukankan      html  css  js  c++  java
  • 爆破内存中的SWF文件

    因为最近有一点需要,所以想提取打开的网页里面的SWF文件出来,其实以前也做过,用个游戏修改器,搜索一下FWS然后挨个检查一下结果,手工复制一下内存数据。这次的却比较多,挨个弄比较麻烦还容易出错。于是写了一小段程序。只是需要注意的是,很多浏览器并不是那个有启动窗口的进程是我们要的……哎……不提这个,只是提一下这个实现。其实嘿嘿,前面那个从OFFICE中提取的,也可以考虑一下用这个代替?~咕~~(╯﹏╰)b~速度,速度……慢点点而已了

    1、枚举进程,列表以供选择

    2、枚举所选进程内存块,搜索FWS字样……貌似叫暴力……(其实只需稍加修改源程序就可以连同CWS一起搜索)

    3、筛选,依据被定为这样几个:

    A、版本(第四字节)为,7,8,9,10的

    B、文件大小大于0(5-8字节)

    C、文件结尾为0X40,0X00,0X00,0X00的

    第一部分,枚举进程其实没什么好说的,Process类就可以了。

    第二部分,其实就是核心内容了:内存检索,一般来说,应该先枚举进程所用的内存块及其属性,这样可以通过属性进行筛选,但实际在实现时,我是用ReadProcessMemory函数是否出错来决定是否继续搜索本块内存的……真是懒人啊~~~~

    代码
    Public Structure MEMORY_BASIC_INFORMATION
            
    Dim BaseAddress As Integer        
            
    Dim AllocationBase As Integer     
            
    Dim AllocationProtect As Integer  
            
    Dim RegionSize As Integer         
            
    Dim State As Integer              
            
    Dim Protect As Integer            
            
    Dim lType As Integer              
        
    End Structure
    ‘出处http://www.cnblogs.com/zcsor/
        
    Private Declare Function VirtualQueryEx Lib "kernel32" (ByVal hProcess As Int32, ByVal lpAddress As IntPtr, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As Int32) As Int32
        
    Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As IntegerByVal lpBaseAddress As IntegerByVal lpBuffer() As ByteByVal nSize As IntegerByRef lpNumberOfBytesWritten As IntegerAs Integer
        
    Private Shared m_phandle As Integer

    这样就声明了所用的API函数,接下来是枚举过程:

    代码
    Private Shared Function GetMemoryInfo(ByVal pHandle As IntegerAs ArrayList
            
    Dim Infs As New ArrayList
            
    Dim pAddr As Integer, dwTotalCommit As Integer, ret As Integer, miLen As Integer
            
    Dim mi As New MEMORY_BASIC_INFORMATION
            miLen 
    = Len(mi)
            dwTotalCommit 
    = 0 '这是结果
            pAddr = 0  '这个时查询起始地址,设为0,即进程虚拟地址开始处。
            ret = VirtualQueryEx(pHandle, pAddr, mi, miLen) '从起始地址开始查询
            Infs.Add(mi)
            
    Do While (ret = miLen)
                dwTotalCommit 
    = dwTotalCommit + mi.RegionSize
                pAddr 
    = mi.BaseAddress + mi.RegionSize '跳过已经查询过的内存块,到未被查询的内存地址起始处
                ret = VirtualQueryEx(pHandle, pAddr, mi, miLen) '再次查询,直到查询失败(所有可查询地址都已经查过了)
                If mi.State = &H1000 Then Infs.Add(mi)
            
    Loop
            
    Return Infs
        
    End Function

     很简单,相信大家一看就懂~~~~~~~~~~接下来,就是读内存数据了,这里需要考虑这样一个问题:有些内存块大的……可怜的VB溢出了咋办……前几天绘制一个几十万像素宽的图像就……咕~~(╯﹏╰)b,其实解决办法很简单的,分块即可,这里读写内存我们就分1024字节吧~~当然有一定原因了~~分4096也许你喜欢?O(∩_∩)O~其实编码起来都差不多,只要你知道~~~原因

     出处:http://www.cnblogs.com/zcsor/

    代码

        
    Public Shared Function Scan(ByVal pHandle As IntegerAs ArrayList
            m_phandle 
    = pHandle
            
    If Not ToKen.ToKenPrivileges() Then MsgBox("提升权限失败,扫描结果可能有遗漏")
            
    Dim Ret As New ArrayList
            
    Dim int As ArrayList = GetMemoryInfo(pHandle)
            
    For Each mi As MEMORY_BASIC_INFORMATION In int
                
    Dim bLen As Integer = mi.RegionSize
                
    Dim rLen As Integer
                
    Dim mBaseAddr As Integer = mi.BaseAddress
                
    Dim mStep As Integer = 1024
                
    Dim test(3As Byte
                
    Do While bLen > 0
                    
    If bLen > mStep Then rLen = mStep Else rLen = bLen
                    bLen 
    -= mStep
                    
    Dim Bytes(rLen - 1As Byte
                    
    Dim read As Integer = ReadProcessMemory(pHandle, mBaseAddr, Bytes, rLen, 0)
                    
    If read = 0 Then Exit Do
                    
    For mIndex = 0 To mStep - 3 Step 4
                        
    If Bytes(mIndex) = &H46 AndAlso Bytes(mIndex + 1= &H57 AndAlso Bytes(mIndex + 2= &H53 Then  'just FWS
                            Dim f As New Flash
                            f.addr 
    = mIndex + mBaseAddr
                            f.ver 
    = Bytes(mIndex + 3)
                            f.size 
    = System.BitConverter.ToInt32(Bytes, 4)
                            
    If f.size > 0 AndAlso f.ver > 6 AndAlso f.ver < 11 Then
                                read 
    = ReadProcessMemory(pHandle, mBaseAddr + mIndex + f.size - 4, test, 40)
                                
    If read = 0 Then
                                    
    Exit Do
                                
    Else
                                    
    If test(0= &H40 AndAlso test(1= 0 AndAlso test(2= 0 AndAlso test(3= 0 Then Ret.Add(f)
                                
    End If
                            
    End If
                        
    End If
                    
    Next
                    mBaseAddr 
    += mStep
                
    Loop
            
    Next
            
    Return Ret
        
    End Function

        
    Structure Flash
            
    Public addr As Integer
            
    Public ver As Integer
            
    Public size As Integer
            
    Public Overrides Function ToString() As String
                
    Return "addr: " & Hex(addr) & vbCrLf & _
                
    "ver:  " & ver & vbCrLf & _
                
    "size: " & Format(size, "#,0."& vbCrLf
            
    End Function
        
    End Structure

    这样,大功告成了啊~得到了可读的内存空间内的全部貌似SWF文件的信息,接下来……保存它们吧!

    代码
        Shared Function Save2File(ByVal Pid As IntegerByVal addr As IntegerByVal size As IntegerAs Boolean
            
    Dim bs(size - 1As Byte
            
    Dim read As Integer = ReadProcessMemory(m_phandle, addr, bs, size, 0)
            
    If read = 0 Then
                
    Return False
            
    Else
                My.Computer.FileSystem.WriteAllBytes(
    "c:\" & Hex(Pid) & "_" & Hex(addr) & ".swf", bs, False)
            
    End If
        
    End Function

    呃,发现我确实很懒了吧……其实也检测了一下,当读内存失败的时候不保存(也没法保存嘛~),这是防止FWS字样出现的位置后面的字节数不够SIZE(超出内存段)时的错误,换句话说,就是如果代码没写错,那这个FWS一定不是一个FLASH文件~

    ’出处http://www.cnblogs.com/zcsor/

    最后附上,成品~呃,其实你自己写一下修改修改我的代码,才真的是成品,这个里面不识别压缩的~~其实压缩的和这个一样的~~~~如果你愿意解压,那就解压吧~几句代码的事……不过我懒

    /Files/zcsor/FLASH提取工具.7z

    今天换了笔记本测试的时候发现了一个API调用的问题,重新修改如下:

        Structure MEMORY_BASIC_INFORMATION ' 28 bytes
            Dim BaseAddress As Integer
            Dim AllocationBase As Integer
            Dim AllocationProtect As Integer
            Dim RegionSize As Integer
            Dim State As Integer
            Dim Protect As Integer
            Dim lType As Integer
        End Structure

        Private Declare Function VirtualQueryEx Lib "kernel32" (ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByRef lpBuffer As MEMORY_BASIC_INFORMATION, ByVal dwLength As UInteger) As Integer
       

    原来的代码在笔记本上运行昨天还可以,今天却出现错误,原因尚未查明。改成以上声明形式工作正常。

    又详细的查了一下SWF加载的特征,确定其按一定特征的基地址加载(&HXXXXX000)于是优化查找逻辑如下:


        Public Shared Function Scan(ByVal pHandle As Integer) As ArrayListm_phandle = pHandle
            Dim Ret As New ArrayList
            Try
                Dim int As ArrayList = GetMemoryInfo(pHandle)
                For Each mi As MEMORY_BASIC_INFORMATION In int
                    Dim bLen As Integer = mi.RegionSize
                    'Dim lOldProtect, LOL As Integer
                    Dim mBaseAddr As Integer = mi.BaseAddress
                    Dim mStep As Integer = 4096
                    Dim test(3) As Byte
                    'lOldProtect = VirtualProtectEx(pHandle, mi.BaseAddress, 1, &H40, lOldProtect)
                    Do While bLen >= 0
                        bLen -= mStep
                        Dim Bytes(7) As Byte
                        Dim read As Integer = ReadProcessMemory(pHandle, mBaseAddr, Bytes, 8, 0)
                        If read = 0 Then Exit Do
                        If Bytes(0) = &H46 AndAlso Bytes(1) = &H57 AndAlso Bytes(2) = &H53 Then  'just FWS
                            Dim f As New Flash
                            f.addr = mBaseAddr
                            f.ver = Bytes(3)
                            f.size = System.BitConverter.ToInt32(Bytes, 4)
                            If f.size > 0 AndAlso f.ver > 8 AndAlso f.ver < 11 AndAlso (Integer.MaxValue - mBaseAddr - f.size >= 0) Then
                                read = ReadProcessMemory(pHandle, mBaseAddr + f.size - 4, test, 4, 0)
                                If read = 0 Then
                                    Exit Do
                                Else
                                    If test(0) = &H40 AndAlso test(1) = 0 AndAlso test(2) = 0 AndAlso test(3) = 0 Then Ret.Add(f)
                                End If
                            End If
                        End If
                        mBaseAddr += mStep
                    Loop
                    ' LOL = VirtualProtectEx(pHandle, mi.BaseAddress, 1, lOldProtect, LOL)
                Next
                Return Ret
            Catch ex As Exception
                MsgBox(ex.Message & vbCrLf & ex.Source & vbCrLf & ex.GetBaseException.ToString)
            End Try
            Return Ret
        End Function

    可能还存在一些问题,以后发现会继续修正的。

    补充两点内容,有朋友问这个软件的适用范围和一些更新的查找函数,并说不太喜欢我写东西时留下一些已经被我修复或优化的过程不发出来而是发原始代码。说实在的,只要更新了后来的查找函数,就可以找到全部SWF(只要时机是恰当的,我还是不想说明什么叫恰当的时机,事实上,加载完并播放的时候,时机就很恰当,具体原因非常繁杂,不要太过深究了):

    首先,不管是加密也好,不加密也好,压缩也好,不压缩也好(我的代码没有处理压缩的,实际上只需要了解压缩的是以什么开头,是以什么结尾,大小如何计算——这里有些人是误导的,第4-8字节,是压缩后的大小,而不是压缩前。即4-8字节总是指示文件所占的实际字节数。),鉴于FLASH最终只能执行顺序且连续的文件流,所以在某一时刻(这就是你的恰当时机),SWF文件一定是以未加密的形式出现在FLASH虚拟机面前!

    其次,在后来的代码中(其实前面我写的时候确实留下这个问题给细心的朋友,但也是一种误导,在此表示歉意。因为那是原来的是个带有内存搜索和代码调试功能的游戏修改器中的部分代码,最初我未经修改就进行了使用——虽然注意到了步长问题,但当时没有明确提出而是使用未经修改和优化的代码进行的4字节对齐搜索)使用的步长是4096字节——每隔4096字节(&H1000)去搜索一次是否为FWS,这是完全合理的,关于这一点可以参考ADOBE的关于AS3内存管理那部分内容,它每当需要新内存时首先尝试回收旧的然后申请新的,并以&H1000为单位进行申请。结合其对齐内存的原因,可以断定,SWF就出现在我后来代码所搜索的位置,而不是其他位置。

    今天进行了一些思考,主要是我们的代码的搜索方式,其实还可以优化,一方面,我们首先枚举进程,在这之后就进入了搜索,实际上完全可以进一步枚举每进程是否含有FLASHXX.OCX,而断定是否对进程内存进行搜索,这将提高效率。另一方面,我们进行全内存的搜索,这也是一个低效的做法——虽然代码加以优化后速度快了一些,但更有效的做法是改变思路……暴力搜索只在需要时才用……例如还不清楚这些SWF是被如何的过程存放的,例如想获取一些“私有”的东东时……………………也就是说我们对FLASH存储SWF的表进行解析,完全可以直接得到内存地址,我还没有找到相关资料——我确信这种门牌号技术被应用到这里,但可以确定的是我在内存中确实发现了这样的存储结构(表),虽然有些结构内容还不清楚,而且在我进行一些注入和对指针的探索之后发现——表消失了……嘎嘎,被摆了一道,下次一定要把各个线程搞挺再干。去查查相关资料吧,不然只好自己动手丰衣足食了,不过OD到现在还不咋地,嘿~开工去

  • 相关阅读:
    CentOS下网卡启动、配置等ifcfg-eth0教程(转)
    device eth0 does not seem to be present, delaying initialization(转)
    MicroPython TPYBoard v201 简易家庭气象站的实现过程
    micropython TPYBoard v201 简易的web服务器的实现过程
    使用Visual Studio Code进行MicroPython编程
    PyCharm安装MicroPython插件
    基于MicroPython:TPYBoard心率监测器
    CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-7主节点CM安装子节点Agent配置
    CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-6CM安装前环境检查
    CentOS7+CDH5.14.0安装全流程记录,图文详解全程实测-5安装JDK及安装mysql数据库
  • 原文地址:https://www.cnblogs.com/zcsor/p/1915972.html
Copyright © 2011-2022 走看看