使用VB.NET通过代码注入实现的PC微信消息撤回提醒及修改DLL文件实现消息禁止撤回

查看 141|回复 9
作者:LaoDan   

注1:本文代码部分实现的只有撤回提醒功能,无防撤回功能。
注2:本文所实现的防撤回功能没有提醒功能。
注3:微信使用最新版本 3.9.2.23,版本不正确基址也会不同。

找CALL
首先打开Cheat Engine,选择WeChat.exe并打开。


1.png (120.25 KB, 下载次数: 0)
下载附件
2023-4-21 13:39 上传

打开一个微信好友,向微信好友发送消息,建议数字形式。便于查找。
数值填写自己发送的数值,扫描类型为搜索字串符,进行搜索。


2.png (111.44 KB, 下载次数: 0)
下载附件
2023-4-21 13:42 上传

扫描到结果,然后撤回消息。


3.png (120.88 KB, 下载次数: 0)
下载附件
2023-4-21 13:43 上传

可以看到有一个包含22字符的内存地址,记录下来。
内存地址为:131FFF90
再接着打开OD,打开文件,附加,选中WeChat。


4.png (69.9 KB, 下载次数: 0)
下载附件
2023-4-21 13:45 上传

附加结束,点击OD里的E按钮,打开WeChatWin.dll文件


5.png (62.11 KB, 下载次数: 0)
下载附件
2023-4-21 13:45 上传

打开之后CTRL+G,搜索CE里面保存的撤回消息的内存地址


6.png (60.95 KB, 下载次数: 0)
下载附件
2023-4-21 13:53 上传

给我指向了131FFF90内存地址。
然后再次在微信窗体中发送一条消息。


7.png (90.08 KB, 下载次数: 0)
下载附件
2023-4-21 13:53 上传

在131FFF90设置断点>内存写入断点


8.png (55.98 KB, 下载次数: 0)
下载附件
2023-4-21 13:54 上传

此时将消息撤回,程序会被断下,这个时候,在堆栈中往下寻找相应的值,找到用户ID、撤回消息、撤回的内容,都均在一个子程序内的位置。
注:找到之后,记得在地址处,右键>断点>删除内存断点,避免调试的时候再次中断。


9.png (40.03 KB, 下载次数: 0)
下载附件
2023-4-21 13:54 上传

找到之后,在堆栈中返回调用,点击右键>反汇编窗口中跟随


10.png (50.13 KB, 下载次数: 0)
下载附件
2023-4-21 13:54 上传

返回到了52CF1AC4内存地址处,其中52CF1ABE,为调用的关键CALL。在52CF1ABE处F2下断点。
再发一次消息并撤回消息,可以看到在52CF1ABE处断掉。


11.png (111.76 KB, 下载次数: 0)
下载附件
2023-4-21 14:01 上传

在堆栈中可以看到撤回的消息,在堆栈中右键>地址>相对于ESP。可以看到:


13.png (34.03 KB, 下载次数: 0)
下载附件
2023-4-21 14:06 上传



14.png (17.23 KB, 下载次数: 0)
下载附件
2023-4-21 14:06 上传

ESP+5C:用户ID
ESP+84:撤回提示
ESP+1C4:撤回的内容
由此成功找到关键的CALL:
CALL地址:52CF1ABE,我们是知道52CF1ABE内存地址是不断变动的, 那么则需要找到基址,这样每次打开微信都可以定位到关键的CALL。
可以使用CE来寻找52CF1ABE所对应的基址。


150.png (103.48 KB, 下载次数: 0)
下载附件
2023-4-21 14:23 上传

点击手动添加地址>输入52CF1ABE,点击确定。


15.png (254.46 KB, 下载次数: 0)
下载附件
2023-4-21 14:24 上传

然后右键>反汇编此内存区域,可以看到基址为:WeChatWin.dll+CB1ABE。
添加至CE地址栏。


16.png (97.13 KB, 下载次数: 0)
下载附件
2023-4-21 14:27 上传

退出微信,重新打开,使用CE再次打开WeChat。


17.png (103.19 KB, 下载次数: 0)
下载附件
2023-4-21 14:28 上传

可以看到地址已经变动,在内存区域可以准确定位至这个消息撤回的关键CALL。
到目前思路已经很清晰了,在基址WeChatWin.dll+CB1ABE处,获取寄存器ESP的内存地址的值,然后将内存地址的值进行偏移获取数据。
ESP+5C:用户ID
ESP+84:撤回提示
ESP+1C4:撤回的内容
VB.NET实现撤回弹窗
在上一部分已经知道了CALL的基址为WeChatWin.dll+CB1ABE,但因为VB.NET写HOOK真的太特娘的扯淡,所以我的想法是先申请出来一块内存,然后将WeChatWin.dll+CB1ABE基址处改为JMP跳转至新申请的内存,新申请的内存处调用弹窗,然后再将CALL的汇编指令补全,再JMP跳转回下一指令,但是我测试将CALL写至申请内存,微信会崩,没办法,也不想继续研究了,所以在下一基址处写跳转,基址为:WeChatWin.dll+CB1AC4


18.png (52.86 KB, 下载次数: 0)
下载附件
2023-4-21 15:38 上传



基址.png (54.63 KB, 下载次数: 0)
下载附件
2023-4-21 15:48 上传

最终结果


11.gif (578.12 KB, 下载次数: 0)
下载附件
2023-4-21 15:50 上传

导入
Imports System.Runtime.InteropServices
Imports System.Text
定义
  
    Private Shared Function OpenProcess(ByVal dwDesiredAccess As UInteger, ByVal bInheritHandle As Boolean, ByVal dwProcessId As Integer) As IntPtr
    End Function
   
    Private Shared Function WriteProcessMemory(ByVal hProcess As IntPtr, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As Byte(), ByVal nSize As Integer, ByRef lpNumberOfBytesWritten As Integer) As Boolean
    End Function
   
    Private Shared Function VirtualAllocEx(ByVal hProcess As IntPtr, ByVal lpAddress As IntPtr, ByVal dwSize As UInteger, ByVal flAllocationType As UInteger, ByVal flProtect As UInteger) As IntPtr
    End Function
   
    Shared Function ReadProcessMemory(ByVal hProcess As UInteger, ByVal lpBaseAddress As IntPtr, ByVal lpBuffer As IntPtr, ByVal nSize As UInteger, ByRef lpNumberOfBytesRead As UInteger) As Boolean
    End Function
    Dim TranAddress As IntPtr '全局变量
    Dim offset As Integer  '全局变量
分配内存及跳转至分配内存处
Dim processName As String = "WeChat" '替换为目标进程的名称
        Dim process1 As Process() = Process.GetProcessesByName(processName)
        Dim 基址 As Integer
        基址 = getMoudleAddress("WeChat", "WeChatWin.dll")
        If (process1.Length > 0) Then
            Dim entry As Int32 = &HCB1AC4  '偏移地址
            Dim processHandle As IntPtr = OpenProcess(&H1F0FFF, False, process1(0).Id) '打开目标进程的句柄
            TranAddress = VirtualAllocEx(processHandle, IntPtr.Zero, 1024, &H1000, &H40) '在目标进程中申请内存
            Dim TranBytes As Byte() = {&HE9, &H0, &H0, &H0, &H0} 'JMP指令的机器码
            offset = CInt(TranAddress.ToInt64() - (基址 + entry)) '计算申请的空间偏移量
            BitConverter.GetBytes(offset - 5).CopyTo(TranBytes, 1) '将跳转偏移量写入JMP指令中
            Dim entryPoint As IntPtr = 基址
            entryPoint += entry '替换为目标进程代码中的一个位置,以便进行测试,此处为基址,需要修改的汇编语句在这里。
            Dim bytesWritten As Integer = 0
            'Dim originalBytes As Byte() = New Byte(TranBytes.Length - 1) {} '保存被覆盖的原始指令
            'ReadProcessMemory(processHandle, entryPoint, originalBytes, originalBytes.Length, bytesWritten)
            WriteProcessMemory(processHandle, entryPoint, TranBytes, TranBytes.Length, bytesWritten) '将JMP指令插入到目标进程代码中
            TextBox2.Text = "内存:[" & Hex(基址 + entry) & "]=>写入跳转指令成功,跳转地址:[" & Hex(CLng(TranAddress)) & "]"
        Else
            MsgBox("没有找到句柄")
        End If
插入汇编语句
Dim processName As String = "WeChat" '替换为目标进程的名称
        Dim process1 As Process() = Process.GetProcessesByName(processName)
        Dim vBuffer(10) As Byte
        Dim vBytesAddress As IntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0)
        Dim vNumberOfBytesRead As UInteger = 0
        If (process1.Length > 0) Then
            Dim processHandle As IntPtr = OpenProcess(&H1F0FFF, False, process1(0).Id) '打开目标进程的句柄
            Dim bytesWritten As Integer = 0
            Dim 基址 As Integer
            基址 = getMoudleAddress("WeChat", "WeChatWin.dll")
            Dim jmpBytes As Byte() = {&H89, &H25, &H0, &H0, &H0, &H0,
                                      &H6A, &H00,
                                      &H68, &H00, &H00, &H00, &H00,
                                      &H68, &H00, &H00, &H00, &H00,
                                      &H6A, &H00,
                                      &HFF, &H15, &H00, &H00, &H00, &H00, 'call地址的值需要找到
                                      &H8D, &H8D, &H24, &HFD, &HFF, &HFF,
                                      &HE9, &H00, &H00, &H00, &H00} 'JMP指令的机器码
            BitConverter.GetBytes(CInt(TranAddress) + 39).CopyTo(jmpBytes, 2) '从第2个字节开始插入,使用汇编的MOV将ESP地址写入到分配的内存地址+39
            BitConverter.GetBytes(CInt(TranAddress) + 48).CopyTo(jmpBytes, 9) '从第6个字节开始插入,使用汇编的MOV将ESP地址写入到分配的内存地址+48
            BitConverter.GetBytes(CInt(TranAddress) + 48).CopyTo(jmpBytes, 14) '从第6个字节开始插入,使用汇编的MOV将ESP地址写入到分配的内存地址+48
            ReadProcessMemory(processHandle, CLng(基址) + &H1F91A4D, vBytesAddress, 4, vNumberOfBytesRead) '读取基址的4字节值
            Dim vInt As Integer = Marshal.ReadInt32(vBytesAddress)
            BitConverter.GetBytes(CInt(vInt.ToString)).CopyTo(jmpBytes, 22)   '将字节值放到jmpbytes以便调用CALLMessagebox函数
            Dim offset1 As Integer = CInt((TranAddress - offset) - (TranAddress) - 31) '分配的内存地址:(1670000-1248A1D)- 1670000 + 5
            BitConverter.GetBytes(offset1).CopyTo(jmpBytes, 33) '从第33个字节开始插入,进行汇编指令组合
            Dim bSuccess As Boolean = WriteProcessMemory(processHandle, TranAddress, jmpBytes, jmpBytes.Length, bytesWritten) '将JMP指令写入目标进程内存中
            If bSuccess Then
                ' 写入成功
                MsgBox("插入汇编指令成功,准备写入弹窗标题!")
                Dim MessageBytes As Byte() = {&H09, &H67, &H28, &H75, &H37, &H62, &H28, &H57, &HA4, &H64, &HDE, &H56, &H88, &H6D, &H6F, &H60} 'Messagebox标题与文本的存储内容
                Dim m_bytesWritten As Integer = 0
                Dim mSuccess As Boolean = WriteProcessMemory(processHandle, CInt(TranAddress) + 48, MessageBytes, MessageBytes.Length, m_bytesWritten) '将JMP指令写入目标进程内存中
                If mSuccess Then
                    TextBox5.Text = CInt(TranAddress) + 39
                    TextBox6.Text = CInt(TranAddress) + 48
                    MsgBox("标题与内容写入成功")
                Else
                    MsgBox("写入失败")
                End If
            Else
                ' 写入失败
                MsgBox("汇编指令插入失败")
            End If
        Else
            MsgBox("没有找到句柄")
        End If
取ESP的值
Dim processName As String = "WeChat" '替换为目标进程的名称
        Dim process1 As Process() = Process.GetProcessesByName(processName)
        If (process1.Length > 0) Then
            Dim vBuffer(3) As Byte
            Dim vBytesAddress As IntPtr = Marshal.UnsafeAddrOfPinnedArrayElement(vBuffer, 0)
            Dim vNumberOfBytesRead As UInteger = 0
            Dim processHandle As IntPtr = OpenProcess(&H1F0FFF, False, process1(0).Id) '打开目标进程的句柄
            ReadProcessMemory(processHandle, CLng(TranAddress) + CLng(39), vBytesAddress, 4, vNumberOfBytesRead)
            Dim vInt1 As Integer = Marshal.ReadInt32(vBytesAddress)
            If vInt1.ToString = 0 Then
                MsgBox("请让其它微信好友撤回消息一下,让汇编指令访问到跳转处,再点击此按钮可获取到ESP保存的值")
            Else
                TextBox3.Text = vInt1.ToString
                TextBox4.Text = Hex(vInt1.ToString)
            End If
        End If
最终实现的汇编指令修改


19.png (75.36 KB, 下载次数: 0)
下载附件
2023-4-21 15:57 上传



20.png (178.82 KB, 下载次数: 0)
下载附件
2023-4-21 15:57 上传

代码还需要继续开发,但是不大想继续研究了。这些代码相信针对学VB.NET或C#的有一些比较好的启发。
修改十六进制增加防撤回的功能(无提醒)
首先依旧是OD附加或打开WeChat,然后选择E按钮,选择WeChatWin.dll文件。
然后右键>中文搜索引擎>搜索UNICODE,WeChatWin.dll文件有些大,可能要卡一会。


21.png (143.27 KB, 下载次数: 0)
下载附件
2023-4-21 16:05 上传

出来中文搜索引擎,然后按CTRL+F弹出搜索框,搜索特征码:revokemsg。


22.png (92.64 KB, 下载次数: 0)
下载附件
2023-4-21 16:08 上传

搜索结果会有很多,找到之后按B键,继续找下一个,找到下面图片中的特征,就是跳转位置了。


23.png (40.97 KB, 下载次数: 0)
下载附件
2023-4-21 16:11 上传

然后点进去,将上面的JE条件跳改为JNZ即可。


24.png (51.52 KB, 下载次数: 0)
下载附件
2023-4-21 16:35 上传



25.png (11.03 KB, 下载次数: 0)
下载附件
2023-4-21 16:22 上传

然后自己PC端向其它好友发一条消息,自己进行撤回,发现无反应,说明修改完成。
然后看上面的两张图片找到特征码:83 C4 10 84 C0 74 0A
这个特征码可能搜索的时候比较多。
发散思维,自己可以使用CE来手动添加地址:WeChatWin.dll,右键反汇编此内存区域,在弹出的内存浏览器中点击搜索>查找内存>选择字节(数组),填入:C7 00 ?? ?? ?? ?? C7 40 ?? ?? ?? ?? ?? E8 ?? ?? ?? ?? 83 C4 10 84 C0 74 0A,动态汇编地址使用??问题模糊查找。
不出意外的话在地址栏中第一行就是搜索到的地址。
其中74 0A代表je咱们改为75 0A即可,或者改为90 90直接NOP掉都可以。
打开微信的目录文件夹>3.9.2.23文件夹,找到WeChatWin.dll文件拖到桌面,使用C32Asm工具打开。
按CTRL+F,类型选为十六进制,输入特征码。点击下一个。


27.png (113.6 KB, 下载次数: 0)
下载附件
2023-4-21 16:35 上传

成功搜索到,将74改为75,保存WeChatWin.dll文件。


28.png (15.64 KB, 下载次数: 0)
下载附件
2023-4-21 16:37 上传

将保存的WeChatWin.dll文件拖到3.9.2.23文件夹即可实现防撤回,但可惜的是没有撤回提示的。
文中所有工具下载
VB.NET 代码

微信撤回提示VB.NET代码.rar
(77.19 KB, 下载次数: 12)
2023-4-21 16:49 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB

C32Asm十六进制编辑器

C32Asm十六进制编辑器.rar
(1.03 MB, 下载次数: 6)
2023-4-21 17:18 上传
点击文件名下载附件
下载积分: 吾爱币 -1 CB

Cheat Engine 7.1
https://400.lanzout.com/iSdIf0tlnjve
OD
https://down.52pojie.cn/Tools/Debuggers/%E5%90%BE%E7%88%B1%E7%A0%B4%E8%A7%A3%E4%B8%93%E7%94%A8%E7%89%88Ollydbg.rar

下载次数, 基址

LaoDan
OP
  


Light紫星 发表于 2023-4-21 18:14
不错的文章,.net用easyhook可以很方便的进行hook

其实当初我想用easehook实现,结果研究不透,资料太少。想找一个例子,用代码注入的方式实现还是局限太多了。
Light紫星   

不错的文章,.net用easyhook可以很方便的进行hook
wtujoxk   

自己写,牛!!!!
apull   

这个太牛了。。
renpeng009   

牛逼啊,这是真正的技术贴。详细又实用
Patches   

今天刚刚更新WeChat3.9.5.17  不知道新版适不适用   一会我去试试看
ps122   

谢谢分享,有些高深了。
lduml   

学习学习
壹嘢笃呱沵   

外行看热闹,内行看门道!我是来看热闹的那个~~~
您需要登录后才可以回帖 登录 | 立即注册

返回顶部