QQ交流群:753894145
9102年了,我想大部分人使用微信的频率应该都会高于QQ了吧。
以前在QQ传文件的时候,哪里会想到会有文件大小限制,几G、几十G的文件随意传。
而现在,用微信传文件,很尴尬,只能传100M或更小的文件。
为什么做这个限制?我想可能是因为微信一开始就是手机应用。
- 最初手机存储空间并不像电脑那么大,所以微信可能认为手机存不下(而现在256G是标配了)。
- 更重要的是,手机使用流量,大文件消耗流量更多,用户肯定受不了(现在流量也不贵了,再说还有WIFI呢)。
所以限制文件大小,合情合理。
但是,现在微信也出了PC版本了,也有很多用户在使用PC版本微信,还在限制100M就有点说不过去了。
你说怕手机收到后下载耗流量,确实有点浪费,那你服务端可以区分一下嘛,用户也可以自己确认是否下载啊。
但是,微信并没有做什么,这就很影响PC上微信的使用体验了。
我要用微信传大文件啊(100M以上),因为我QQ密码忘了,因为我朋友QQ密码忘了…
好,既然如此,你不做…还是…你不做,那就我来做!
1、突破本地100M限制
下载最新的PC微信(当时2.6.8.65),开始分析微信对文件大小限制是如何做的,然后一一突破。
在选择文件过程中就做了100M限制。
嗯,文件大小首先就想到了GetFileSize
,下个断点看看。
1 | bp KERNEL32!GetFileSize |
艾玛啊,触发有点多啊,头疼。算了,换个思路。点击发送文件按钮,会弹出文件选择对话框,这是微软提供的。
写过win32 gui或者mfc程序的同学应该想到了,对弹出文件选择对话框的函数下断点。
不是~bp shell32!SHBrowseForFolderW这是目录选择~,也不是~bp shell32!SHFileOperationW~,而是这个:bp comdlg32!GetOpenFileNameW
1 | Breakpoint 5 hit |
根据返回地址7908eac2
计算到在IDA中地址100deac2
,用IDA翻看一下函数怎么做的。
微信可以同时选择多个文件,这里循环获取到路径,限制最多10个,然后进入sub_100DEED0处理。
1 | v24 = -GetOpenFileNameW(&v44); |
进入函数sub_100DEED0
之后,一下就看到获取文件大小的函数,然后是判断文件是否大于100M。
1 | v16 = f_FileUtils::fileSize_10475050(&path); |
先手工windbg修改一下指令,验证是否正确。把0x6400000改为0,jl改成jge即可。篇幅原因,不展开了。
通过调试确认,100M以上文件绕过这个限制。
1 | .text:100DF347 07C cmp esi, 6400000h |
但是还没完,依然会弹框,居然还有二次验证。
调试函数sub_100DEED0
,单步继续往下走,看看是哪里弹框。最终找到在sub_10099D70
这个函数里还有校验。
1 | v33 = sub_104FF8F0(v7 + 337); |
同样进入sub_10099D70
,找到校验代码。
1 | v7 = f_FileUtils::fileSize_10475050(a2); |
windbg修改一下指令,验证是否正确。把0x6400000改为0,jle改成jge即可,调试确认绕过检查。
1 | .text:1009A34C 0AC cmp esi, 6400000h |
过了这两处检查后,文件成功显示在输入框中。
不过直接发送依然失败,显示“上传文件大小不能大于100M”,应该是服务器做了检查。
另外,微信还支持拖动文件发送,经过前面两步的突破,此时拖入文件依然提示“发送的文件大小不能大于100M”。
那继续把这个干掉吧。拖动文件首先想到的就是DragQueryFileW
,加上断点试试。
1 | bp shell32!DragQueryFileW |
确实拖动中会断下,但经过分析并不是关键代码,没有对文件进行处理,另外断下后,再跑起来,拖动文件失败。
所以另想他法。又想到了前面没有用处的getfilesizeex
,再来尝试一下。
1 | 0:004> bp kernel32!getfilesizeex |
嘿嘿,没想到一下子找到了关键位置,getfilesizeex
建了一功。
1 | filesize = f_FileUtils::fileSize_10475050(v52); |
同样的方式,把0x6400000改为0,ja改成jbe,绕过这个校验。
1 | .text:101FA196 078 81 7D C0 00 00 40 06 cmp dword ptr [ebp+filesize], 6400000h |
OK,到这里,本地100M限制就成功突破,下面继续看看如何绕过服务器限制。
2、突破服务器100M限制
前面提到,能够选择大于100M文件之后,点击发送依然会失败,提示“上传文件大小不能大于100M”。
很明显服务器做了上传文件限制。
所以如何突破这个限制呢?
额,动不了服务器代码啊…
能够想到的就是在文件发送前,自动分割文件为小于100M的多个文件,然后将分割的文件自动发送出去,在接收方,把收到的每个文件再自动合并。
如此服务器也不会说文件大于100M了,对于用户来说,体验也是一致的。
是的,我就是这么实现的。
首先,找到发送文件的函数。
由于之前分享过如何找到发送消息的函数,详情请看文章微信PC端技术研究(3)-如何找到消息发送接口,所以这里不详细分析如何找到发送文件的函数了。
直接拿来用,就是这个函数sub_102382E0
。
1 | .text:100CC124 DE0 83 EC 14 sub esp, 14h |
接口大概是这个样子的。
1 | void __stdcall fakeWechatSendMsg1(int unk, wchar_t* wxid, int len1, int maxlen1, int unk1, int unk2, wchar_t* path, int len2, int maxlen2, int unk3, int unk4, int a1, int a2, int a3, int a4, int a5, int a6) |
然后hook sub_102382E0,拿到path文件路径后,获取文件大小,如果大于100M,则分割文件,然后重新调用sub_102382E0把分割文件发送出去。大概代码如下:
1 | bool fakeWechatSendMsgInternal(DWORD dwEcx, wchar_t* wxid, wchar_t* filepath) |
OK,突破服务器100M限制也完成了(详细实现代码请移步SuperWeChatPC开源项目)。
不过在测试中,发现bug多多(说的是微信)。
- 经测试自带单文件发送功能,100M,甚至99M、或者更小点的文件,发送到最后都没成功,微信bug or 网络问题?
- 96M左右可以成功,55M左右文件可以妙传,不稳定,这个可能网络问题,但是我怎么也是100M宽带啊。
- 自带多个文件同时发送,40M都无法发送成功。
- 有时还会提示:文件无法发送,已超过今日发送限制。
- 而此时选择10M以内文件依然能够发送成功。
所以最后,我不得不面对现实,把文件分割成了每个10M大小的文件进行尝试,终于一个大于100M的文件发送成功了,并且非常稳定!
3、总结
简单总结一下,我是如何让微信发送成功100M以上文件的。
- 首先、突破本地100M限制,也就是选择100M文件限制,最终patch三个点绕过判断即可。
- 然后,hook发送文件接口,把大于100M文件分割,然后自动发送小文件。
- 最后,接收方自动合并文件(并没有做,哈哈)
因为接收方并没有做自动合并的功能,所以需要自己合并一下,也很简单。
1 | //使用windows原生命令合并文件 |
让这个功能更完美,还需要做:
- 删除分割的小文件
- 接收方自动合并文件
- 微信修复bug,能够100M分割(@tencent @weixin)
最后,想试用大文件传输功能,请下载最新的https://github.com/anhkgg/SuperWeChatPC。
欢迎PR、star、试用。
欢迎关注技术公众号:汉客儿
转载请注明出处:https://anhkgg.com/anti-call/