大灰狼1976 发表于 2021-10-14 21:43

【VBA对二进制数据文件的处理】

本帖最后由 大灰狼1976 于 2021-10-15 22:17 编辑

VBA处理二进制数据文件的实现方法及部分用途
前言    此贴内容和一般办公应用没有关系,仅为自己的兴趣而记录,当然也供其他感兴趣者参考。
用途    修改软件及其他数据文件,以达到某种预期目的,例如软件汉化、更换素材等。高阶者可以用来修改软件的功能、去除一些使用限制。    我一般只是用来做软件汉化(不仅限于PC软件汉化)。
基本功能介绍    非常幸运,VBA可以如同处理文本文件一样方便地读写二进制数据文件,而不需要借助API或其他专用插件来实现,甚至可以凭空创建一个二进制数据文件。    所涉及的VBA语句也很简单,说明如下: 1、提取二进制文件数据:    Dim arrByte() AsByte, fNo#, n As Byte    fNo = FreeFile    OpenFileFullPath For Binary As fNo'打开二进制数据源文件    ReDimarrByte(LOF(fNo) - 1)        '将接收用的数组大小设置成匹配源文件字节数    Get fNo, ,arrByte      '用字节数组接收二进制数据    Close fNo         '关闭二进制数据源文件
    上述语句执行后,可以将一个二进制文件的数据全盘返回给一个同样大小的字节数组,通过修改一些参数,也可以截取一个字节或一段字节返回给数组,如:    ReDimarrByte(99)       '如果想截取100个字节出来,需要先调整数组大小    Get fNo, 100 ,arrByte        '从第100个字节开始截取,返回给数组    Get fNo, 100 ,n        '截取第100个字节返回给一个字节变量n
通过上面示例中的方法,我们可以方便地获取二进制文件中的全部数据、任意位置的部分数据、任意位置的一个字节数据,灵活性还是相当高的,操作也简单。
2、写入二进制文件数据:    写入二进制数据和读取的语句大同小异,基本上只需要将Get改成Put即可    Dim arrByte() AsByte, fNo#, n As Byte    fNo = FreeFile    OpenFileFullPath For Binary As fNo'打开二进制数据源文件    Put fNo, ,arrByte      '假设arrByte内已准备好数据    Close fNo       '关闭二进制数据源文件    上述语句执行后,可以将一个字节数组的数据全部写入二进制数据文件内,如果二进制数据区域比数组大,则只覆盖数组大小的区域;反之,数组数据仍然会全部写入二进制数据文件,二进制数据文件也会相应增大。
    通过修改一些参数,也可以写入一个字节或一段字节给二进制数据文件:    Put fNo, 100 ,arrByte        '从第100个字节开始写入整个数组内的数据    Put fNo, 100 ,n        '在第100个字节处写入变量n的值。    注意:上述Put语句都是数据覆盖而非数据插入。
如果要凭空创建一个二进制数据文件,直接使用上述Open语句会出错,可以用以下两种预处理方法:    1、手工创建一个目标文件,就是生成一个空TXT文档,然后随意改下扩展名就行;    2、使用FileSystemObject来创建一个目标文件,也是空的。然后再使用上述Open等一系列语句来写入内容。
本楼示例:1、提取一个BMP图片的二进制数据,写入单元格区域;2、对图片进行几个简单修改以及还原处理。
以下各楼会贴出一些实际应用,但这些示例的准备都需要时间,所以不定时更新,未完待续......注意:对二进制数据的修改有可能会触发某些杀软或防火墙的异常行为侦测,所以尽量不要在公司里面尝试,我今天就触发了一次,好孩子不要学我。

心正意诚身修 发表于 2021-10-14 23:01

上午还在说这个事呢,晚上就出来了。效率高哈。门槛也高。

大灰狼1976 发表于 2021-10-15 12:45

心正意诚身修 发表于 2021-10-14 23:01
上午还在说这个事呢,晚上就出来了。效率高哈。门槛也高。

效率是高,人气还是一如既往的低哈{:1_1:}

心正意诚身修 发表于 2021-10-15 16:56

就是被那些发广告的给害得。当年论坛和EH不相上下。

大灰狼1976 发表于 2021-10-15 22:22

【实战一】汉化一个英文软件
1、基本知识说明:
虽然我不打算详细讲解字符编码知识,不然会劝退很多萌新,但是最基本的理论还是必须事先简单提一下的,如下:
A) 任何软件及文件在硬盘上以及机器处理中都是以01数据方式存在,并不是我们在显示器上看到的样子,每8个01数据串称为一个字节(Byte);
B) 字符编码种类很多,但半角英文字母和常见半角符号在所有编码系统中都保持其ASCII码值,在某些编码系统中占1个字节,另外一些编码系统中占2个字节;占2个字节时,其中一个字节的值为0。
基本知识只有上面两条,其他知识点在遇到的时候再提一下。
个人建议,不管什么事情,都没必要等万事具备再去做,先动手去做才是最有趣的。前提是留好源文件的备份,然后再怎么弄都不用担心;

2、自制工具的准备
为了方便说明,我使用主楼介绍的方法制作了一个简单的自制工具,它具有以下功能
A) 将源文件二进制数据导入EXCEL表单元格区域内;
B) 将二进制数据根据最简单的ASCII编码规则转换成字符以供观察(不参与处理);
C) 可根据输入的目标字符串找到其在二进制数据内的位置(地址),并生成列表;
D) 截取某段地址并修改相应的值后,再将修改后的数据写入源文件中相应位置;
它的界面如下图所示,等一下讲解的时候会经常用到。

本楼附件先下载,各位可以先熟悉一下界面,下面的楼层开始进行实操演练。

大灰狼1976 发表于 2021-10-15 23:21

【实战一续】汉化一个英文软件

    简单的工具已经准备好了,里面涉及到的知识要点也就是主楼说明过的部分,其他的一些查找等判断都是常规方法不再详述。汉化的目标软件我随便选择了一个“edidw2k.exe”,好像是什么显示器测试软件,但这不重要,和我们接下来的工作没有关系。此软件在本楼的附件压缩包内,请将其和自制工具放到同一路径下。

    先打开自制工具,里面只有一个工作表,点击“导入数据”按钮,将源文件的二进制数据导入到自制工具的A:C列单元格区域内;再打开英文软件,随便选一个界面上能看到的英文字符串,比如菜单最左边的“View”,把它输入到自制工具的黄色单元格(F1)内,注意要区分大小写,然后点击“字符->代码”按钮,会将"View"转成ASCII码输出到“E3:F”单元格区域内,接着点击“查找”按钮,会将该字符串在源文件内的位置(数据地址)输出到“J3:J”单元格区域内,如果有多处出现的话会形成地址列表;双击地址列表中含地址内容的任意一个单元格,会跳转到A列相应位置,我们先双击“017A1C”内容的单元格,跳转到A列对应位置,然后把“View”对应的地址和值单元格(A96798:B96801)复制到“M3:N”单元格处,现在暂停自制工具内的操作,我们要先进行翻译,并将译文转换成编码值后,再输入到“N3:N”单元格中,点击“改写数据”按钮进行写入,这段需要略为详细说明一下:

1、"View"意思是"视图"(这个有点废话),我们目前还没接触汉字编码,所以先不去管编码规则,找一个网站在线转换就行了,我使用的是“http://www.mytju.com/classcode/tools/encode_utf8.asp”,将“视图”字符串输入到网站中进行转换,中文汉字常见的编码有UTF-8和GB2312两种,网址当前状态的是UTF-8编码转换,我们就先转换UTF-8试试,在网站的输入文字框内输入“视图”两字,点击“查看编码”按钮,会逐个字符列出对应的编码值,我们看到“视”的Unicode16进制编码为“89C6”(16进制数),共2个字节,“图”暂时先不管它。


2、将网站转换得到的编码值(16进制数)顺序填到自制工具的“N3:N4”单元格区域内,一个单元格填写一个字节(两位16进制数)。


3、点击“改写数据”按钮,弹出“Done!”对话框说明写入成功。注意点击“改写数据”按钮前要确保英文软件已关闭,不然会报错。


4、再次打开英文软件,确认原来的“View”现在有何变化,结果没有出现“视”字,说明选择的编码错误,但这个并不是坏事,说明我们找到的地址是正确的。关闭软件后在网站上另选编码GBK(相当于GB2312)后重新走流程,“视”的GBK16进制编码显示为“CAD3”,将此编码值顺序输入“N3:N4”单元格区域内再次点击“改写数据”按钮进行数据写入;


5、不出意外的话,再打开修改版软件后我们可以看到原来“View”变成了“视ew”,第一个字对了,说明编码正确,我们再将“图”的GBK编码“CDBC”也同样顺序往下写入,“View”顺利变成了“视图”。成功了一小步,对初心者来说是一大步!


6、所有菜单项的字符编码规则都是一样的,所以接下来可以用这种方法自行测试,注意这个软件的菜单有点特殊,菜单名称后面跟一个点后面还有内容(这是指二进制数据内),点后面的内容是菜单项的下拉项,需要一起处理。

本楼的附件只有一个供汉化测试的英文软件,上述大部分操作都在自制工具里面完成。下面会进行菜单项以外的汉化测试。


大灰狼1976 发表于 2021-10-16 15:23

【实战一续】汉化一个英文软件
为什么要把菜单项以外的汉化测试单独拿出来说明,因为其中有些不同,等下边测试步骤中进行说明。
继续和上一楼类似的测试,查找目标字符串地址和贴到待写入区域等准备工作就不再详述了:
1、点击“Test”菜单的“EDID”下拉项,会出现一个窗体,先测试汉化窗体标题“Monitor Information”,翻译成“显示器信息”,按上一楼的方法,通过网站进行转换得到编码值“CFD4CABE...”,填写到待写入区域的相应位置,点击按钮进行写入;
2、打开修改后软件,再打开此窗体,出现乱码,说明编码错误,我们换一个编码测试。话不多讲,实际上使用“Unicode编码16进制”就行了,但是注意前后位顺序要调换,比如“显”的编码为“663E”,输入时要把“3E”放在前面变成“3E66”;
3、控件的字符(按钮、框架、Label的Caption等)实际上也是“Unicode编码16进制”编码;
4、再看看哪些功能会弹出对话框,对话框内容也同样进行测试改写,不详述;
5、如果有耐心很快就能汉化完一个软件,至少能看到的地方都可以完成。
为什么要特地提一下菜单项以外的汉化处理呢,原因就是同一个软件里面,并不是处处使用相同的字符编码,有些软件里面甚至会用到三种编码方式,所以尝试->观察结果->猜测原因->改变方法是非常重要的手段,一定要多加利用。等处理的样本数多了,丰富的经验能保证自己处乱不惊。

最后,还有一个建议。有没有发现每步写入时都有点提心吊胆,生怕一个失误又没有保存附本时,前面的工作全部都要重新做一遍,这个确实难受。我们要想个办法把前面的成果保留下来,于是我采取了下面这样的措施:
1、制作一份汉化项清单,里面记录汉化修改处的地址信息、原文、译文、编码规则;
2、找一个转码函数,不用通过网站,直接通过转码函数进行实时转换,我们要做的只是填入译文后点点按钮,自动写入数据;
3、做个需转换项的标记,假设某项汉化失败导致程序错乱的话,只要把原版软件复制过来,把除了错误项以外的汉化项全部打上需转换标记,就能一次性把前面的工作全部恢复;
不卖关子了,本楼把此工具也作为附件发上来,想要研究的话我的代码永远是全公开的。

林木水 发表于 2022-1-12 15:25

不明觉厉

lhj323323 发表于 2022-7-31 20:38

老师:

一楼的附件打不开,能否重发一个
border=0

大灰狼1976 发表于 2022-8-2 20:46

lhj323323 发表于 2022-7-31 20:38
老师:

一楼的附件打不开,能否重发一个

我刚下载测试了一下,可以正常解压的,你用winrar试一下。
页: [1] 2
查看完整版本: 【VBA对二进制数据文件的处理】