本帖最后由 CrLf 于 2013-1-21 15:08 编辑
这里给出 encode 代码,拖动写好的 com 到 encode.bat 上进行操作: | @echo off&setlocal enabledelayedexpansion | | set compress=true | | ::设置是否压缩 | | | | if "%~1"=="" echo 无文件&pause&exit/b | | set "s1=%~s1" | | | | set list=0123456789JKLMNO | | for %%a in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do ( | | set hb=!list:~0x%%a,1! | | for %%b in (0 1 2 3 4 5 6 7 8 9 A B C D E F) do ( | | set lb=!list:~0x%%b,1! | | set "hex%%a%%b=!hb!!lb!" | | if %compress%==true ( | | if 0x%%a%%b geq 0x50 if 0x%%a%%b leq 0x7e set "hex%%a%%b=" | | for %%c in (5E 7C) do if %%a%%b==%%c set "hex%%a%%b=!hb!!lb!" | | ) | | ) | | ) | | ::获取 hex 表 | | | | for %%a in ("%~1") do cmd/c exit/b %%~za | | if !errorlevel! gtr 0x3030 ( | | echo 文件太长 | | pause&exit/b | | ) | | ::判断文件长度 | | | | set cx=!=exitcode:~-4! | | echo d100l!cx!^&echo q|debug !s1! >"%~n1.bat" | | ::获取文件 hex | | | | set m=0 | | (for /f %%a in ('find /n /v ""^<"%~n1.bat"') do ( | | set "var="&set /p "var=" | | if "!var::=!" neq "!var!" ( | | set "var=!var:-= !" | | set "str=!var:~61!" | | set "var=!var:~11,48!" | | for %%b in (!var!) do ( | | if defined hex%%b (set "com=!com!!hex%%b!") else set "com=!com!!str:~,1!" | | set "str=!str:~1!" | | | | if "!com:~39!" neq "" ( | | set /a m+=1 | | set "com!m!=!com!" | | set "com=" | | ) | | ) | | ) | | ))<%~n1.bat" | | | | if defined com set /a "m+=1"&set "com!m!=!com!" | | | | (echo @echo off | | echo @(echo RQPUWP]UZV_BBBB5``PY(E1(E6^^^)E8^^^)E=(EA^^^)EI= | | echo echo SX3CP^^^<P}pE^^^< ~r%%%%ooQRY2AY0@G uO0EOB?_]XYZ | | for /l %%a in (1 1 !m!) do echo echo !com%%a! | | echo ^)^>"%~n1.com" | | echo ::这个 bat 是生成 "%~n1.com" 的模板,使用时可以直接复制 | | echo pause)>"%~n1.bat" | | | | start notepad "%~n1.bat"COPY |
需注意的地方: | 生成的 com 前两行是解码部分,不能随意改动 | | 支持的加密后的 com 长度上限是 0x6060,也就是 24672 字节(取这个奇怪的数字是因为它既大又不消耗多余指令),超过这一长度将出错,因为解码部分只固定循环 0x6060 次 | | 引用 cs:ff 之后的地址时需注意,代码的真实地址是 cs:150(解码部分的长度),对地址进行绝对引用时要注意判断是否需要加 0x60,比如 cs: mov ax,[120] 就应该写成 cs: mov ax,[170],而 jmp、call、loop 等指令使用的是相对跳转,所以不用修改地址COPY |
当然,解码部分单独运行是没有意义的,还需要用 encode 算法把转换的数据附加到其后。 |