中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

中国DOS联盟论坛
现在时间是 2026-09-17 07:19
中国DOS联盟论坛 » DOS开发编程 & 发展交流 (开发室) » 二进制方式处理文件工具 STR (2020.11.16 更新) 查看 42,359 回复 72
楼 主 二进制方式处理文件工具 STR (2020.11.16 更新) 发表于 2008-04-26 21:45 ·  中国 北京 电信
高级用户
★★
流落街头
积分 570
发帖 272
注册 2005-10-17 10:51
20年会员
UID 43609
性别 男
来自 北京
状态 离线
STR
File: A File to be Processed data. //文件
Start: Offset to Process data. //文件中处理数据的起始位置 (文件的开头位置为0)
Bytes: Bytes to Process. //要处理的字节数量 (如果输入0,则表示从Start开始到文件末尾)
/C: Copy Bytes from File to dstFile. //从源文件向目标文件复制数据
/I: Insert Bytes to dstFile from File. //从源文件向目标文件插入数据,插入数据后目标文件增加 Bytes个字节
dstFile: A File to Write Result data. //目标文件
Address: Offset to Write Result data. //目标文件中要复制或插入数据的位置 (如果目标文件不存在,该值被忽略)

STR
/D: Delete Bytes from File & Write Result to dstFile. //从源文件删除数据并结果写入目标文件

STR
/V: View File In Hex Style. //十六进制方式查看文件
/A: Show ASCII Value. //显示ASCII码
/P: Pause Echo Screen. //满屏暂停

STR :
Bytes: Must be 0. //必须为0
/F: Find String in File. //在文件中查找字符串
/Hex: Hex Style. //十六进制方式
/Asc: ASCII Style. //ASCII码方式
Value: Hex_Digital/ASCII String (40 Characters Maximum). //字符传真的值,最长40个字符 (如果是十六进制串长度应为双数)
/I: Ignore Case. //忽略大小写
/A: Process All Value in File. //在文件中查找所有满足要求的字符串(默认查找1次)

STR :
Bytes: Must be 0. //必须为0
/E: Edit File. //编辑文件

STR
Bytes: Must be 0. //必须为0
/R: Relace SrcString with DstString. //字符常替换
SrcString: :. //源串,可以使用十六进制或ASCII码串
DstString: :. //目标串,可以使用十六进制或ASCII码串
/A: Process All SrcString in File. //在文件中查找所有源字符串(默认替换1次)

说明:
1 使用 /C 和 /I 命令时,如果目的文件不存在,Adress 的值将被忽略,直接执行将源文件从 Start 开始的 Bytes 个字节写入到新创建的目的文件中
2 使用 /C 和 /I 命令时,如果目的文件存在,并且不输入 Address,则Address 默认为0,也就是文件的起始位置。
3 目前处理的单个文件大小不超过 2G

例子:

str 1.exe 0x100 0x10 /d 2.bin 执行将文件1.exe 从位置256开始的16个字节删除,并将结果写入到2.bin,文件2.bin的长度将比1.exe长度小16
str 1.exe 0x100 0x10 /c 2.bin 20 执行将文件1.exe 从位置256开始的16个字节写入到2.bin的20位置,也就是文件2.bin从位置20开始的16字节被覆盖
str 1.exe 0x100 0x10 /i 2.bin 20 执行将文件1.exe 从位置256开始的16个字节插入到2.bin的20位置,结果文件2.bin的长度将增加16字节

str 1.exe 0x100 0 /v /p /a 从文件偏移位置256开始在屏幕上显示文件内容,如果Bytes输入为0,则表示从Start开始至文件末尾。

str 1.exe 0x100 0 /e /hex:11223344 将文件偏移位置256开始的4个字节修改为,0x11,0x22,0x33,0x44。
str 1.exe 0x100 0 /e /asc:1234 将文件偏移位置256开始的4个字节修改为,1234, 也就是0x31,0x32,0x33,0x34

查找替换算法使用的是 KMP 算法,不重复计数,如文件 1.txt 的内容为10个字符0:
0000000000

如执行命令: str 1.txt 0 0 /f /asc:0000 /a
则执行结果为:
Find string At:
0 0x0
4 0x4

不会是:
Find string At:
0 0x0
1 0x1
2 0x2
3 0x3
4 0x4
5 0x5
6 0x6


压缩包中包含DOS版本和Win32版本

2008.12.14 修正替换字符串功能中存在的问题


2008.12.19 修正19楼存在问题

2009.2.15 测试版本在50楼

[ Last edited by 19951001 on 2020-11-16 at 17:01 ]
[已使用 Gemini 解答]
Gemini 解答

这是一个在 DOS / Win32 命令行环境下用于二进制文件切片、检索、原位修补(Patching)与替换的专用工具。在 2000 年代中后期(尤其在维护系统启动盘、修改引导扇区、修改 GRLDR/DOS 扩展器配置或编写自动化装机批处理时),此类命令行 Hex 处理工具非常常见。

核心功能与运行机制

  1. 底层寻址与文件大小限制(2GB 边界)

    • 软件支持十进制与十六进制(0x 前缀)的偏移量(Start/Address)与长度(Bytes)输入。
    • 文档明确指出单文件大小上限为 2GB,这是典型的 32 位有符号整型(signed long / int32_t)限制。在 C 标准 I/O 库中,fseek()ftell() 使用 long 类型记录偏移量,最大寻址范围即为 $2^{31}-1$ 字节(约 2.14GB)。
  2. 数据操作模式的本质差异

    • 覆写操作(Overwrite / Patch)/C(在已有目标上)、/E。这类操作仅改变指定偏移处的字节,不改变目标文件的物理尺寸。
    • 插入/删除操作(Insert / Delete)/I/D。此类操作必须对目标偏移点之后的所有数据进行前移或后移重写(或流式重写到新目标文件),操作完成后目标文件尺寸会发生增减。
    • 就地替换(Replace)/R 模式在二进制修补中的特殊性在于,如果 SrcStringDstString 的长度不一致,会导致文件中后续所有数据的绝对偏移发生移动。在修改诸如 PE/MZ 可执行文件或 GRLDR 等引导镜像时,改变数据长度通常会破坏文件头中的结构体偏移或校验和,因此在引导文件定制场景中,通常要求等长替换。
  3. 检索算法与匹配步进(Non-overlapping Matching)

    • 作者说明中指出查找使用了 KMP 算法,且采用“非重叠匹配(Non-overlapping)”策略。
    • 当在 0000000000(10 个 0)中查找 0000(4 个 0)时,匹配到偏移 0 后,指针直接跳过 4 个字节从偏移 4 开始下一次匹配,因而仅返回 04(第 8、9 字节不足 4 字节被舍弃)。这种设计符合文件内容替换工具的标准逻辑(避免产生自重叠递归替换死循环)。

后续跟帖中暴露的典型历史 Bug 与底层原因

  1. 写空字节(0x00)截断失效问题(第 19 楼)

    • 现象str 1.exe 0x03 0 /e /hex:0011 遇到 00 无法写入。
    • 原因:这是 C/C++ 编写此类工具时最常见的逻辑缺陷——在解析命令行传入的十六进制串转换为二进制字节流时,开发者如果将转换后的二进制缓冲区直接当作 C 风格字符串(以 \0 结尾的 ASCIIZ)进行处理(例如使用了 strlen()strcpy()fprintf("%s") 或基于 char * 的查找函数),0x00 会被判定为字符串结束符(Null Terminator),导致后续的数据解析或文件写入被提前截断。正确的二进制处理必须显式维护 buffer 指针与其对应的 size_t 长度,完全脱离对 Null 字符的依赖。
  2. 字符串转义与长度计算(第 12–14 楼)

    • 在批处理自动化中,直接以 Hex 形式处理控制字符(如换行符 0x0D 0x0A、截断符 0x00)是标准做法。若工具不支持 \r\n\0 等转义序列,可通过将 ASCII 字符与控制字符统一换算为连续的 Hex 字符串(例如将 test + 0x0D + 0x00 写作 /hex:746573740D00)一次性写入,避免分段计算偏移。
  3. 退出码与批处理控制(第 21 楼)

    • 程序通过标准返回值(Exit Code)传递执行状态,在 DOS/Windows 批处理中可通过 %errorlevel% 进行流程分支控制(如 IF ERRORLEVEL 12 GOTO NOT_FOUND,注意 DOS 默认的 ERRORLEVEL 判定是大于等于逻辑)。作者定义的退出码枚举如下:
#define SUCCESS              0  // 执行成功
#define COMMON_USE_ERROR     1  // 常规/通用错误
#define OPEN_FILE_ERROR      2  // 打开源文件失败
#define PRG_MODIFIED         3  // 程序/文件已被修改
#define FILE_READ_ERROR      4  // 读取文件失败
#define PARAMETER_ERROR      5  // 命令行参数格式错误
#define CREATE_FILE_ERROR    6  // 创建目标文件失败
#define FILE_WRITE_ERROR     7  // 写入数据失败
#define SRCFILE_DSTFILE_SAME 8  // 源文件与目标文件相同(冲突)
#define USER_CANCEL          9  // 用户取消操作
#define FILE_NOT_EXIST      10  // 文件不存在
#define FILE_SEEK_ERROR     11  // 文件指针定位(fseek)失败
#define STRING_NOT_FOUND    12  // 未找到目标字符串
附件
str.rar (18.38 KiB, 下载附件所需积分 1 点, 下载次数: 171)
strWin32.rar (20.34 KiB, 下载次数: 11)
2 发表于 2008-04-28 17:29 ·  中国 广东 深圳 电信
高级用户
★★
积分 525
发帖 222
注册 2006-08-28 21:07
20年会员
UID 61476
状态 离线
可能这个东西我用不到,但是我需要一个DOS下查找替换文件中的某个字符串的工具……

不知道 19950101兄能否帮忙写一个?

比如: XXX /rN file "12345,d" "54321,g"

查找到才替换,或替换一次就退出。
替换所有 /r N次 /rN

此文件可能会有 3~10 M

[ Last edited by cchessbd on 2008-4-28 at 05:39 PM ]
3 发表于 2008-05-07 22:52 ·  中国 北京 电信
高级用户
★★
流落街头
积分 570
发帖 272
注册 2005-10-17 10:51
20年会员
UID 43609
性别 男
来自 北京
状态 离线
Originally posted by cchessbd at 2008-4-28 17:29:
可能这个东西我用不到,但是我需要一个DOS下查找替换文件中的某个字符串的工具……

不知道 19950101兄能否帮忙写一个?

比如: XXX /rN file "123 ...


只需要对文本文件处理吗?
4 发表于 2008-11-14 21:20 ·  中国 北京 电信
高级用户
★★
流落街头
积分 570
发帖 272
注册 2005-10-17 10:51
20年会员
UID 43609
性别 男
来自 北京
状态 离线
2008.11.14 更新
5 发表于 2008-11-15 00:01 ·  中国 江苏 苏州 电信
银牌会员
★★★
积分 2,227
发帖 790
注册 2005-01-27 00:00
21年会员
UID 35703
性别 男
状态 离线
好工具,但.rar 解压时报错:文件"WIN"头被损坏!
请重新上传!!!
my major is english----my love is dos----my teacher is the buddha----my friends--how about U
6 发表于 2008-11-15 08:07 ·  中国 浙江 台州 温岭市 电信
管理员
★★★★
DOS非常爱好者
积分 6,215
发帖 2,601
注册 2006-01-20 13:00
20年会员
UID 49256
状态 离线
报错后win32文件夹是空的!
7 发表于 2008-11-15 11:13 ·  中国 江苏 苏州 电信
银牌会员
★★★
积分 2,227
发帖 790
注册 2005-01-27 00:00
21年会员
UID 35703
性别 男
状态 离线
文件WIN在根目录。
my major is english----my love is dos----my teacher is the buddha----my friends--how about U
8 发表于 2008-11-15 11:42 ·  中国 北京 电信
高级用户
★★
流落街头
积分 570
发帖 272
注册 2005-10-17 10:51
20年会员
UID 43609
性别 男
来自 北京
状态 离线
已经修复破损的压缩包
9 发表于 2008-11-24 21:25 ·  中国 广东 东莞 电信
银牌会员
★★★
积分 1,284
发帖 538
注册 2002-11-02 00:00
23年会员
UID 129
性别 男
状态 离线
因需修改二进制文件,这种小软件我以前寻找过,只找到纯DOS下的FH,现在这个应该不错。
10 发表于 2008-12-13 11:07 ·  中国 广西 河池 电信
中级用户
★★
积分 252
发帖 97
注册 2006-09-17 12:00
19年会员
UID 62869
性别 男
状态 离线
坚决支持,!!
找了好久,请楼主将标题改改,可好,方便其他人搜索,谢谢!
11 发表于 2008-12-13 18:10 ·  中国 福建 泉州 电信
银牌会员
★★★
积分 1,276
发帖 469
注册 2002-12-23 13:00
23年会员
UID 586
性别 男
来自 福建泉州
状态 离线
好东西,收下了,谢谢!
QQ:366840202
http://chenall.net
12 发表于 2008-12-13 19:10 ·  中国 福建 泉州 电信
银牌会员
★★★
积分 1,276
发帖 469
注册 2002-12-23 13:00
23年会员
UID 586
性别 男
来自 福建泉州
状态 离线
可不可以再加个功能"字符转义"
比如\0 就是ASCII码00
比如
strw test.bin 0x10 0 /e /asc:test\13\0
会写入test和0X0D和0X00
QQ:366840202
http://chenall.net
13 发表于 2008-12-13 22:28 ·  中国 北京 电信
高级用户
★★
流落街头
积分 570
发帖 272
注册 2005-10-17 10:51
20年会员
UID 43609
性别 男
来自 北京
状态 离线
Originally posted by chenall at 2008-12-13 19:10:
可不可以再加个功能"字符转义"
比如\0 就是ASCII码00
比如
strw test.bin 0x10 0 /e /asc:test\13\0
会写入test和0X0D和0X00


理论上可以实现,不过我近些日子比较忙,暂时没有时间修改


其实也可以这样实现
strw test.bin 0x10 0 /e /asc:test
strw test.bin 0x14 0 /e /hex:1300
上述两条命令可以实现你要的功能

[ Last edited by 19951001 on 2008-12-13 at 23:18 ]
14 发表于 2008-12-14 09:43 ·  中国 福建 泉州 电信
银牌会员
★★★
积分 1,276
发帖 469
注册 2002-12-23 13:00
23年会员
UID 586
性别 男
来自 福建泉州
状态 离线
嗯,上面是可以实现,只是如果放在批处理里面要计算字符长度会比较麻烦.

另一个问题,不知程序有没有返回errorleve值?
比如查找,成功返回?失败返回?
QQ:366840202
http://chenall.net
15 发表于 2008-12-14 10:14 ·  中国 福建 泉州 电信
银牌会员
★★★
积分 1,276
发帖 469
注册 2002-12-23 13:00
23年会员
UID 586
性别 男
来自 福建泉州
状态 离线
查找替换功能好像有些问题..
文件A.TXT内容

Exe =$1\TEST
Exe =$1\TEST2

strw a.txt 0 0 /r /asc:$1 /asc:j: /a
得到的结果为乱码,而且丢失字符

正确的结果

Exe =J:\TEST
Exe =J:\TEST2
QQ:366840202
http://chenall.net
论坛跳转: