本帖最后由 无瑕黑心肠 于 2019-9-12 19:37 编辑
1、软件简介
JPEGView是一款小巧快速的全屏图片浏览器和编辑器,支持JPEG,BMP,PNG,GIF和TIFF格式的图像。并支持调整图像锐度、色彩平衡、对比度、局部过渡。
2、回到正题
JPEGView的确是一款非常不错的看图软件,小巧而且打开速度快,但是某些功能不能自定义是用户很苦恼的事情,如下图:
图片100%显示是正常的,但是你一旦放大就会变成:
图片就变模糊了(Windows自带看图放大是不会模糊处理图像的),这对于普通用户可能没什么太大的影响,但是对于设计或在意细节的朋友来说可不太友好,举个例子,你想查看两张图片的不同处,然而两张图片都是模糊的,你炸不楞一看两张图片都是一样的,但实际上两张图片不一样,此时心里会有一万只那啥四条腿的在奔腾。恰巧,这个放大会模糊处理的设置参数里没有,也就是说你不能决定图片放大后进不进行模糊处理,身为一个吾爱3年多的老用户,怎能轻易放过它,于是我操起了我的手术刀(x64dbg、Cheat Engine)
3、手术开始
用x64dbg分析了一下JPEGView,发现使用GDI+绘制图片的,那就好说了,直接Hook GDI的模糊处理不就可以了嘛?(真这么做莫非是个疯子),先从功能找找有没有图片放大后图片不模糊的操作,果不其然:
JPEGView的透视校正不会使用模糊处理,而且不管图片怎么缩放都是很清晰的,那么我们如何知道JPEGView用没有用模糊处理呢?以下是我的思路:
既然透视校正打开后图片不论怎么缩放都不会使用模糊处理,那么我们可以去跟踪一下这个透视校正打开后缩放是如何处理的,然后找到模糊处理的代码,把它修改成我们想要结果。但是如何知道模糊处理的代码是在什么地方呢?一般思路肯定是下个鼠标滚轮的消息断点,然后返回到程序领空,这样肯定就是处理缩放的地方,缩放图片肯定会处理图片的模糊......打住,今天用一种奇葩的方法,用Cheat Engine:
打开Cheat Engine,把透视校正功能打开,用Cheat Engine搜索1,功能关闭搜索0,最后会有两个结果:
但是其中有一个正确的,验证方法也很简单,只要把其中一个数值改成1,另一个改成0,如果缩放不模糊,那就是正确的数值。
找到正确的数值后,我们看看是什么读取了这个内存数据:
发现有两处地方读取了这个值,接下记录这两处的地址,用x64dbg跟一下汇编代码,这两处都这是读取透视校正功能是否打开然后返回给上一层:
最主要知道的还是上一层的代码是用这个值来干了些什么,经过我的一番筛选,果然有一处是与模糊处理相关的:
如果直接把功能判断直接 nop 掉其实我们目的就已经达到了,即使透视校正功能是关闭的,图片缩放也是清晰的,不会进行模糊处理:
但是,再次打开看图会发现:
WTF,bro?这黑丝......这线条是什么个情况?经过一番排查,原来是透视校正功能中显示网格、自动裁剪校正后的图像和保持画面比例裁剪默认是开启的,这相当于我把这些功能全部打开了,但是我就只要它不进行模糊处理就好了,如果要完美实现这个功能,办法只有一个,把它初始化赋值给干掉,也就是把显示网格、自动裁剪校正后的图像和保持画面比例裁剪三个功能关掉,ok,现在要做的就是找到室哪里给这三个功能打开了,以下是我的思路:
要知道功能开是1,功能关是0,用Cheat Engine搜索显示网格功能,搜素一番发现只有一处读取了这个内存数据:
[Asm] 纯文本查看 复制代码 000000013FF86770 | 4C:894C24 20 | mov qword ptr ss:[rsp+20],r9 |
000000013FF86775 | 4C:894424 18 | mov qword ptr ss:[rsp+18],r8 |
000000013FF8677A | 48:895424 10 | mov qword ptr ss:[rsp+10],rdx |
000000013FF8677F | 53 | push rbx |
000000013FF86780 | 56 | push rsi |
000000013FF86781 | 57 | push rdi |
000000013FF86782 | 48:81EC 80000000 | sub rsp,80 |
000000013FF86789 | 4C:8BC2 | mov r8,rdx |
000000013FF8678C | 48:8D5424 60 | lea rdx,qword ptr ss:[rsp+60] |
000000013FF86791 | 48:8BF9 | mov rdi,rcx |
000000013FF86794 | E8 87000000 | call jpegview-js.13FF86820 |
000000013FF86799 | 8BB424 C8000000 | mov esi,dword ptr ss:[rsp+C8] |
000000013FF867A0 | 0FB65F 30 | movzx ebx,byte ptr ds:[rdi+30] | 显示网格
000000013FF867A4 | 48:8BCF | mov rcx,rdi |
000000013FF867A7 | 83E6 FB | and esi,FFFFFFFB |
想要知道初始值是哪里赋值的,则必须要找到显示网格的来源,下面是详细跟踪的汇编代码:
[Asm] 纯文本查看 复制代码 00000000025B0FE0 | 48:B9 F0FB280000000000 | mov rcx,28FBF0 | rcx 来源是 0x28FBF0
00000000025B0FEA | 48:B8 30BCF43F01000000 | mov rax,jpegview-js.13FF4BC30 |
00000000025B0FF4 | FFE0 | jmp rax |
000000013FF4BC67 | 48:8BF9 | mov rdi,rcx | rdi 来源是 rcx
000000013FF4BC94 | 48:8BCF | mov rcx,rdi | rcx 来源是 rdi
000000013FFA89E3 | 4C:8BF1 | mov r14,rcx | r14 来源是 rcx
000000013FFA8E97 | 49:8B8E 20020000 | mov rcx,qword ptr ds:[r14+220] | rcx 来源是 r14
000000013FF86791 | 48:8BF9 | mov rdi,rcx | rdi 来源是 rcx
000000013FF867A0 | 0FB65F 30 | movzx ebx,byte ptr ds:[rdi+30] | 显示网格
可以看出最后 rcx 的来源是 0x28FBF0 但是这个句汇编代码的地址明显不是程序领空,那应该是动态分配的,所以还得往上一层下一个断点然后重载程序,果然每次的内存地址都是不一样的:
[Asm] 纯文本查看 复制代码 00000000002B0FE0 | 48:B9 10FA140000000000 | mov rcx,14FA10 |
00000000002B0FEA | 48:B8 30BC0C3F01000000 | mov rax,jpegview-js.13F0CBC30 |
00000000002B0FF4 | FFE0 | jmp rax |
既然找到了显示网格功能数据的来源(显示网格 = [[[动态分配的RCX基址]+0x220]+0x30]),我们下个写入断点开始追踪就能找到初始赋值的地方了,首先找第一层指针赋值的地方([[动态分配的RCX基址]+0x220]):
找到第一层指针后查看一下内存数据,发现显示网格功能已经被打开了,那么肯定是第一层指针赋值前就已经被初始化了,由于第一层指针是由 rax 赋值的,那么这个 rax 的来源call 就很可疑,跟进去看一哈儿:
[Asm] 纯文本查看 复制代码 000000013F3E65F0 | 48:8BF9 | mov rdi,rcx | rdi 来源是 rcx
000000013F3E6620 | 48:8BC5 | mov rax,rbp |
000000013F3E6623 | 4C:8BC8 | mov r9,rax |
000000013F3E6626 | 4C:8BC3 | mov r8,rbx |
000000013F3E6629 | 48:8BD6 | mov rdx,rsi |
000000013F3E662C | 48:8BCF | mov rcx,rdi |
000000013F3E662F | E8 BC170000 | call jpegview-js.13F3E7DF0 | 关键赋值的call
000000013F3E6759 | 48:8BC7 | mov rax,rdi | rax 来源是 rdi
从汇编代码可以看出,rax 是来自 rdi 的,也就是说,[rdi+0x30] 就是显示网格数据了,把这个地址添加到Cheat Engine列表中,然后步过观察这个地址数据的变化,可以发现,当步过关键赋值的call时,这个地址的数据被改变了,可想而知这就是显示网格数据初始赋值的地方了,跟进去瞧瞧:
终于真相大白了,现在,只要把这三个赋值的地方 nop 掉或者把赋值的值指向一个空值都可以达到默认关闭显示网格、自动裁剪校正后的图像和保持画面比例裁剪功能的目的。
4、手术结束,总结一下
经过近1个小时的跟踪和分析,发现要找到这些功能的关键代码并不难,方法千千万只是方法怎么快怎么来的比较好。需要注意的一点事JPEGView这个软件有重定位,最后用PE工具抹除一下子,不然做了笔记重启软件又得重新跟踪一遍,写了这么多也就只是做了两件事“关闭JPEGView的缩放模糊处理”和“关闭显示网格、自动裁剪校正后的图片和保持画面比例裁剪功能”,软件依旧是可以正常使用的,不会有任何影响!!!
5、成品下载
本想是学术交流,但我想万一有人刚好需要这个功能呢?以下是成品的链接:
JPEGView 1.0.35.1:链接:https://pan.baidu.com/s/15HBbuB9hpGMT-VQrXDg2cg 提取码:jf79
PS:压缩包内“JPEGView.exe.ORG”是原版的 JPEGView。
大家有任何问题欢迎留言探讨!!! |