加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

另一种修改在线SWF的方法

发布时间:2020-12-15 19:57:00 所属栏目:百科 来源:网络整理
导读:这次公开的这种方式有一定的局限性,通过努力可以克服。它也有一定的优越性。与以前所用的内存搜索和局部修改不同,这种方式不仅可以局部修改,也可以完全重新编译而不受文件大小的限制。推而广之,这种方法可以替换很多东西而不仅限于SWF,凡是从服务器

  这次公开的这种方式有一定的局限性,通过努力可以克服。它也有一定的优越性。与以前所用的内存搜索和局部修改不同,这种方式不仅可以局部修改,也可以完全重新编译而不受文件大小的限制。推而广之,这种方法可以替换很多东西而不仅限于SWF,凡是从服务器申请来的都可以。当然,缓存是一个问题,前面也说过,通过努力都可以克服。这种方式基于对网络请求和文件下载API的HOOK,在下面的范例中HOOK本进程的WEBBROWSER控件的调用的两个WININET.DLL的API函数即可达到目的:

    <DllImport("wininet.dll",SetLastError:=True)>
    Public Shared Function InternetReadFile(ByVal hFile As IntPtr,ByVal lpBuffer As IntPtr,ByVal dwNumberOfBytesToRead As Integer,ByRef lpdwNumberOfBytesRead As Integer) As Boolean
    End Function

以及

    <DllImport("wininet.dll")>
    Public Shared Function HttpOpenRequestW(hConnect As IntPtr,szVerb As IntPtr,szURI As IntPtr,szHttpVersion As IntPtr,szReferer As IntPtr,accetpType As IntPtr,dwflags As Integer,dwcontext As IntPtr) As IntPtr
    End Function

  其实,HOOK?internetreadfile 就可以达成目标。但是有一个问题,从hfile难于识别正在下载的文件是哪一个,而从lpbuffer来识别需要大量对比。所以,我们来查看一下hfile的来源,它可以由好几个API获得,而httpopenrequest正是webbrowser所使用的那个。通过HOOK 就可以得到szuri,它就是请求的文件,而函数返回值就是hfile这个家伙。所以,HOOK这两个API看起来是不错的做法。

  然后,让我们分析一下具体实现过程:我们知道,HOOK internetreadfile之后,这个API被调用时会进入我们的自定义函数,而在自定义函数中会调用真正的API来填充其传入的lpbuffer所指向的数组。那么机会来了,如果我们识别到一个hfile,它恰好是我们想要替换掉的那个请求来的文件,这时我们不调用真正的API而自己填充lbuffer就把请求的文件换成了本地文件。而这时服务器和webbrowser还蒙在鼓里。当然,真正实施之前,我们还需要的理解一下internetreadfile的调用方法,否则一切都是空谈。可以在网上找一些使用这个API的代码来查看一下,很容易得到这样的结论:这个API被循环调用,直到lpdwnumberofbytesread为0且返回值为true。此时,将历次读取的缓冲区内容放在一起,就是整个文件。

  于是,我们替换时,无需担心调用多少次,webbrowser会不断调用,每调用一次我们就写入一次数据,并模仿API的其他行为:设置真实写入字节数,如此直到数据被完全写入。此时,该API还会被调用,因为我们从来都设置lpdwnumberofbytesread为写入lpbuffer的字节数,那么现在没有数据写了,所以实际写入数据数为0,亦即lpdwnumberofbytesread为0时,调用者认为文件传输完成。这与我们用这个API去编写程序的思路是完全一样的。

  因为今天看了看easyhook,所以当作练习就直接用了这个第三方库。如果想自己完成hook部分,可以参考我cnblogs的博客。在x64上,这两个API中至少有一个前面没有90的,所以自己实现的话,简单起见还是使用EATIAT HOOK。而直接使用easyhook或者微软库都没有这些问题,虽然它们也都采用inlinehook。所以,下面的代码都是基于easyhook的,使用前先下载这个库并放置easyhook.dll,easyhook32.dll,easyhook64.dll到程序目录。

1、hook httpopenrequestw

Imports System.Runtime.InteropServices

Public Class HookHttpOpenRequest

    <DllImport("wininet.dll")>
    Public Shared Function HttpOpenRequestW(hConnect As IntPtr,dwcontext As IntPtr) As IntPtr
    End Function

    Private Delegate Function HttpOpenRequestDelegate(hConnect As IntPtr,dwcontext As IntPtr) As IntPtr
    Private Shared hook As EasyHook.LocalHook = Nothing

    Friend Shared Sub Install()
        Using hook
            If EasyHook.NativeAPI.GetModuleHandle("wininet.dll") = IntPtr.Zero Then
                EasyHook.NativeAPI.LoadLibrary("wininet.dll")
            End If
            hook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("wininet.dll","HttpOpenRequestW"),New HttpOpenRequestDelegate(AddressOf sendProc),Nothing)
            hook.ThreadACL.SetInclusiveACL(New Integer() {0})
        End Using
    End Sub

    Friend Shared Sub UnInstall()
        Using hook
            If hook IsNot Nothing Then
                hook.ThreadACL.SetExclusiveACL(New Integer() {0})
            End If
        End Using
    End Sub

    Private Shared Function sendProc(hConnect As IntPtr,dwcontext As IntPtr) As IntPtr
        Dim uri As String = Marshal.PtrToStringUni(szURI)
        Dim result As IntPtr = HttpOpenRequestW(hConnect,szVerb,szURI,szHttpVersion,szReferer,accetpType,dwflags,dwcontext)
        If uri.Contains("bd_logo1_31bdc765.png") Then   '根据名称区分要替换的图片.
            HookInternetReadFile.CheatFileHandle = result
        End If
        Return result
    End Function

End Class

这个非常简单,没有什么好说的。哦对了,那个替换函数的名就不用关心了,代码是在工程中另外一个类sendhook.vb里面复制的,忘了改名。然后是另一个:

2、hook internetreadfile

Imports System.IO
Imports System.Runtime.InteropServices

Public Class HookInternetReadFile
    <DllImport("wininet.dll",ByRef lpdwNumberOfBytesRead As Integer) As Boolean
    End Function

    Private Delegate Function InternetReadFileDelegate(ByVal hFile As IntPtr,ByRef lpdwNumberOfBytesRead As Integer) As Boolean
    Private Shared hook As EasyHook.LocalHook = Nothing

    Friend Shared CheatFileHandle As IntPtr = IntPtr.Zero   '要替换的文件的句柄,来源于HttpOpenRequest的返回值。
    Friend Shared CheatFile() As Byte = File.ReadAllBytes(My.Application.Info.DirectoryPath & "abc.jpg")    '用于替换的文件
    Private Shared curcnt As Integer = 0

    Friend Shared Sub Install()
        Using hook
            If EasyHook.NativeAPI.GetModuleHandle("wininet.dll") = IntPtr.Zero Then
                EasyHook.NativeAPI.LoadLibrary("wininet.dll")
            End If
            hook = EasyHook.LocalHook.Create(EasyHook.LocalHook.GetProcAddress("wininet.dll","InternetReadFile"),New InternetReadFileDelegate(AddressOf sendProc),Nothing)
            hook.ThreadACL.SetInclusiveACL(New Integer() {0})
        End Using
    End Sub

    Friend Shared Sub UnInstall()
        Using hook
            If hook IsNot Nothing Then
                hook.ThreadACL.SetExclusiveACL(New Integer() {0})
            End If
        End Using
    End Sub

    Private Shared Function sendProc(ByVal hFile As IntPtr,ByRef lpdwNumberOfBytesRead As Integer) As Boolean
        If hFile = CheatFileHandle Then
            If curcnt = CheatFile.Length Then                   
                CheatFileHandle = IntPtr.Zero
                curcnt = 0
                lpdwNumberOfBytesRead = 0                       
            Else                                            
                If curcnt + dwNumberOfBytesToRead <= CheatFile.Length Then            
                    lpdwNumberOfBytesRead = dwNumberOfBytesToRead                     
                    Marshal.Copy(CheatFile,curcnt,lpBuffer,lpdwNumberOfBytesRead)  
                    curcnt += dwNumberOfBytesToRead                                  
                Else                                                                 
                    lpdwNumberOfBytesRead = CheatFile.Length - curcnt                 
                    Marshal.Copy(CheatFile,lpdwNumberOfBytesRead)   
                    curcnt = CheatFile.Length                                        
                End If
            End If
            Return True
        Else
            Return InternetReadFile(hFile,dwNumberOfBytesToRead,lpdwNumberOfBytesRead)
        End If
    End Function

End Class

作为一个demo,还需要一个窗体:

Public Class Form1

    Private Sub Form1_Load(sender As Object,e As EventArgs) Handles MyBase.Load
        wb.Navigate("http://images2015.cnblogs.com/blog/56896/201702/56896-20170216102630488-270057596.jpg")
    End Sub

    Private Sub butRef_Click(sender As Object,e As EventArgs) Handles butRef.Click
        wb.Refresh()
    End Sub

    Private Sub chkCheat_CheckedChanged(sender As Object,e As EventArgs) Handles chkCheat.CheckedChanged
        If chkCheat.Checked Then
            HookHttpOpenRequest.Install()
            HookInternetReadFile.Install()
        Else
            HookHttpOpenRequest.UnInstall()
            HookInternetReadFile.UnInstall()
        End If
    End Sub

End Class
各个名称都可以顾名思义,具体就不说了。怎么样,这个还算是一个比较好玩的玩具吧。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读