热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

PC微信获取登录二维码

我看到"这篇文章"之后自己尝试了一下还是找不到对应的call,毕竟没有学习过逆向,只是因为一时兴起想逆向一下微信。找到关键CALL不过我找到了一

PC微信获取登录二维码

我看到这篇文章之后自己尝试了一下还是找不到对应的call,毕竟没有学习过逆向,只是因为一时兴起想逆向一下微信。

找到关键CALL

不过我找到了一个投机取巧的办法:因为已经知道了微信的二维码图片是PNG格式的,而PNG有一个通用的文件头,如下

 89 50 4E 47 0D 0A 1A 0A00 00 00 0D49 48 44 52 ; 塒NG........IHDR
 00 00 00 CE 00 00 00 CE 08 02 00 00 00 F9 7D AA ; ...?..?....鶀?
 93 00 00 00 09 70 48 59 73 00 00 0A 75 00 00 0A ; ?...pHYs...u...
75 01 4A 25 DD FD 00 00 0C 91 49 44 41 54 78 9C ; u.J%蔟...慖DATx?
ED 9D D9 96 DC 2A 0C 45 A9 AC FC FF 2F D7 7D 70 ; 頋贃?.E┈?/讅p
C7 97 66 10 9A 98 CF 7E C8 EA 54 95 6D 86 83 24 ; 菞f.殬蟸汝T昺唭$
04 B6 3F DF EF 37 00 D0 9F 3F B3 0B 00 6E 01 52 ; .?唢7.袩??.n.R
03 83 F8 3B BB 00 AB F2 F9 98 0E 47 58 92 01 A9 ; .凐;?鶚.GX??

我们可以利用这个找到内存中的二维码图片,然后对它下内存写入断点就可以找到改写二维码的代码段。首先让微信处于二维码的状态,接着我们用CE附加微信搜索字符串IHDR,也就是上面的文件头格式中的一个最明显的标识。
在这里插入图片描述
然后把上面的地址放下来,绿色的就不用看了肯定不是,从那篇文章可以看出微信中图片二维码存放的是一个结构体,第一个指向的是图片数据的指针,第二个是图片的长度。所有这些地址肯定还有上一级指针,所有我们一个一个的搜索他们的上一级指针(这里需要注意的是我们搜索的地址是(地址-C),而不是地址栏中的地址,这是因为IHDR并不是PNG文件的文件头,它前面还有12个字节(十六进制C)的数据,我们搜的是他的文件头的地址 ),如下:
在这里插入图片描述
找到所有地址的上一级指针的话(没有的可以直接删除),可以直接在OD中dd查看一下这个指针,如图
在这里插入图片描述
也可以dc 0E782C58看一下是不是PNG文件头的格式。另外,搜出来的地址中也有和这个一样的,我们只要长度为E开头的三位十六进制数(图中为E6F)的,对应大小大概是4K小一点。后面只需要对05FD3CC4这个二维码地址下内存写入断点就可以知道是哪里修改了它。下完断点后,扫描二维码在返回二维码登录就会断下,如图:
在这里插入图片描述
把上面的代码扣下来看一下

mov dword ptr ds:[esi],0x0       ;这个时候esi的值就是我们下内存断点的指针(05FD3CC4),将原来图片数据指针指向0x0
mov dword ptr ds:[esi+0x4],0x0   ;而esi+0x4很明显就是图片的长度,这两行代码应该是清空原来的数据
push 0x1
push edi
call WeChatWi.5194B3CC
add esp,0x8
mov dword ptr ds:[esi],eax       ;给图片指针赋值,eax就是新二维码数据的指针,不过此时只是个空指针,图片还没被赋值
xor ecx,ecx
test eax,eax
cmovne ecx,edi
pop edi
mov dword ptr ds:[esi+0x4],ecx   ;给长度赋值

接着我们按F8单步走,一直到走出函数,也就是执行完retn 0x4,如图
在这里插入图片描述
刚才的代码段就是WeChatWi.50D4D5D0中的代码,刚才说了,这个函数只是将原来的数据清空了然后赋值了一个空指针和一个长度,那么图片数据肯定在后面被赋值,也就是在图中的注释那个函数中。当然,我们也可以看一下这个05FD3CC4这个我们一开始找到的地址的偏移。

找到二维码地址的偏移

如果让我看OD里面的汇编代码来找到偏移,恐怕有点困难。所以我还是用一个简单的方法来找偏移:使用CE,首先我们找到二维码的地址指针,右键它点击对这个地址使用指针扫描(可能因为CE翻译版本不同有些差异,大致肯定是指针扫描):
在这里插入图片描述
其中上面的选项都可以默认,扫描线程数可以适当调大,允许最大偏移和最大级别默认即可。如果找不到则需要加大。这两个我先不解释,后面在解释。
在这里插入图片描述
你会得到很多的结果,大概如下:
在这里插入图片描述
怎么过滤呢,我们需要关闭微信,重新打开再找一次二维码的地址。然后在上面的菜单栏选择指针扫描器->重新扫描...,之后输入新找到的地址点确定即可。这时候就剩下几个结果了
在这里插入图片描述
我们可以重复上面的继续刷选,当然这没有必要,9个结果已经很理想了。这里我们可以联想上面OD中找到的汇编代码段,看这篇博客最后一张OD的截图

50C5E27E    57              push edi
50C5E27F    8D8E 54060000   lea ecx,dword ptr ds:[esi+0x654]    
50C5E285    E8 46F33600     call WeChatWi.50FCD5D0                   ; 重新赋值图片
50C5E28A    57              push edi
50C5E28B    53              push ebx
50C5E28C    FFB6 54060000   push dword ptr ds:[esi+0x654]
50C5E292    E8 1954F500     call WeChatWi.51BB36B0                   ; 图片数据赋值
50C5E297    83C4 0C         add esp,0xC

注意第二行和第六行,第二行的ecx其实就是我们要的二维码结构体指针。它是esi+0x654的偏移得到的,我们再看CE扫描出的结果。有两个地址的偏移最后一位是0x654,我们将所有地址双击一遍到地址栏中,重点关注这两个地址。接着关闭微信在打开,观察这9个地址的改变,你会发现有一个地址在微信启动之后就没变化过,而其他的会改变。而这个地址正好是上面提到的两个中的一个,不过这个地址虽然能拿到二维码的数据但是却不能用,因为在登录界面没出现二维码的时候(比如确定登录的时候)这个地址也是有数据的,也是能读出二维码的图片,当然这个图片是失效的。所以正常来说,除了这个地址其他应该都能使用。看来开始关注的点不对。

通过上面的步骤就可以不用hook注入写dll这么麻烦了,直接读找到的地址偏移就可以得到二维码了。

aardio保存二维码

使用aardio将地址中的图片保存下来,代码有点神奇,我开始还不知道。原先我一直在找怎么用aardio读字节,后面发现读字符串保存到文件也行,因为string.save本来保存的就是字节数据。

import process;
import console;
 
prcs = process.find("WeChat.exe")
数据指针 = 0x05FD3CC4  //二维码的结构体的地址,既然已经找到了偏移,将这个地址改成偏移对应的地址就行
数据地址 = prcs.readNumber(数据指针)
长度 = prcs.readNumber(数据指针 + 0x4)
数据 = prcs.readString(数据地址, 长度)
string.save("E:二维码.png", 数据)
  

找二维码字符串地址偏移

一开始提到的那篇文章还介绍了如何获取二维码字符串的数据,既然知道了结果,我觉得步骤可以简化一下。我们在CE中搜索字符串找到一部分地址,然后等待刷新排除一部分,应该只剩下几个了,而我们可以通过那篇博客看出这个地址还有上一级指针,而且上一级指针正好是dll地址加偏移,所以我们直接在CE中搜索四字节的地址,找到有个绿色的就是二维码字符的基址了。

我的当前版本(2.8.0.121)的基址:WeChatWin.dll+0x1635C58

接着我们就可以直接通过这个字符拼接出登录的链接,然后利用某些网站的API就可以将这个链接转换为二维码,效果和上面绕了一大圈还要hook是一样的。


推荐阅读
  • 本文详细介绍了Java中vector的使用方法和相关知识,包括vector类的功能、构造方法和使用注意事项。通过使用vector类,可以方便地实现动态数组的功能,并且可以随意插入不同类型的对象,进行查找、插入和删除操作。这篇文章对于需要频繁进行查找、插入和删除操作的情况下,使用vector类是一个很好的选择。 ... [详细]
  • vue使用
    关键词: ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • JVM 学习总结(三)——对象存活判定算法的两种实现
    本文介绍了垃圾收集器在回收堆内存前确定对象存活的两种算法:引用计数算法和可达性分析算法。引用计数算法通过计数器判定对象是否存活,虽然简单高效,但无法解决循环引用的问题;可达性分析算法通过判断对象是否可达来确定存活对象,是主流的Java虚拟机内存管理算法。 ... [详细]
  • 006_Redis的List数据类型
    1.List类型是一个链表结构的集合,主要功能有push,pop,获取元素等。List类型是一个双端链表的结构,我们可以通过相关操作进行集合的头部或者尾部添加删除元素,List的设 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • python中安装并使用redis相关的知识
    本文介绍了在python中安装并使用redis的相关知识,包括redis的数据缓存系统和支持的数据类型,以及在pycharm中安装redis模块和常用的字符串操作。 ... [详细]
  • 文章目录题目:二叉搜索树中的两个节点被错误地交换。基本思想1:中序遍历题目:二叉搜索树中的两个节点被错误地交换。请在不改变其结构的情况下 ... [详细]
  • loader资源模块加载器webpack资源模块加载webpack内部(内部loader)默认只会处理javascript文件,也就是说它会把打包过程中所有遇到的 ... [详细]
author-avatar
OutMan王
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有