Board logo

标题: [思路挑战][讨论]批处理做 Base64 编码运算 理论原型 [打印本页]

作者: electronixtar     时间: 2006-11-13 13:07    标题: [思路挑战][讨论]批处理做 Base64 编码运算 理论原型



  Quote:
::base64conv.cmd::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
setlocal enabledelayedexpansion
set code=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
set /A B1=10,B2=0x7f,B3=255
echo %B1% %B2% %B3%
:: byte-triplet to base64-quadruple 第一次echo要encode的几个ASCII字符
set /A Q1=(%B1% "&" 252) ">>" 2
set /A Q2=((%B1% "&" 3) "<<" 4) + ((%B2% "&" 240) ">>" 4)
set /A Q3=((%B2% "&" 15) "<<" 2) + ((%B3% "&" 192) ">>" 6)
set /A Q4=(%B3% "&" 63)
::
echo %Q1% %Q2% %Q3% %Q4% 第二次echo已经encode完毕
echo !code:~%Q1%,1! !code:~%Q2%,1! !code:~%Q3%,1! !code:~%Q4%,1!
:: base64-quadruple to  byte-triplet 第三次echo Base64字符流出来了!
:: yes, I know, to work a loop to find the pos in %code% should be here.
set /A B1=(%Q1% "<<" 2) + ((%Q2% "&" 48) ">>" 4)
set /A B2=((%Q2% "&" 15) "<<" 4) + ((%Q3% "&" 60) ">>" 2)
set /A B3=((%Q3% "&" 3) "<<" 6) + %Q4%
::
echo %B1% %B2% %B3% 第四次echo decode到原来的字符
::base64conv.cmd::::::::::::::::::::::::::::::::::::::::::::::::::::::::

可见 set /a 的位运算的强大了!以上代码我完全没有看懂,详情见

http://groups.google.com/group/a ... =1#b03cb66dd08c2719

各位版主高手潜水的大侠都出来想想怎么实现用纯批处理做BASE64编码/解码?

做Base64的算法理论研究是十分有用的,很简单的例子就是:批处理加密,二进制文件嵌入bat,处理EMail,等等。

[ Last edited by electronixtar on 2006-11-15 at 01:25 AM ]
作者: electronixtar     时间: 2006-11-13 13:23
我先提一个思路,用 fc 命令获得文件流的每一个字节的ASCII码。(其实fc的很多用处被大家忽略了)。但是,用什么来把ASCII码还原成字符呢?包括一些批处理不能处理的 乱码、不可见字符 呢(ASCII码128以后的那些)?

btw,新手们,搞理论研究很枯燥,但是很有用,请你们多多支持,多多理解!其实我们联盟的某些方面的批处理技术已经是世界顶尖水准了。

[ Last edited by electronixtar on 2006-11-13 at 01:27 PM ]
作者: pengfei     时间: 2006-11-15 00:23
electronixtar这个思路非常好, 相信理解这个概念并掌握他以后会有很大用途.
作者: electronixtar     时间: 2006-11-15 01:12
原来没人感兴趣~~~哇啦哇啦哇啦伤心啦
作者: electronixtar     时间: 2006-11-15 01:20
再贴一个世界顶尖级牛人   Herbert Kleebauer   写的 base64.cmd
@echo off
setlocal enabledelayedexpansion


set infile=a.txt
:: set infile=%1


for %%i in (%infile%) do set outfile=%%~ni.b64


echo --->%outfile%
echo Content-Type: application/octet-stream; name="%infile%">>%outfile%
echo Content-Transfer-Encoding: base64>>%outfile%
echo Content-Disposition: inline; filename="%infile%">>%outfile%
echo.>>%outfile%


set t=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/


for %%i in (%infile%) do set n=%%~zi
if [%n%]==[0] goto :eof
set /p=<nul>_.a
set /p=<nul>_.b
set /p=a<nul>_.a1
set /p=b<nul>_.b1
set m=1
set /a i=-2


:loop
set /a k="%m%&%n%"
if not [%k%]==[0] copy /b _.a + _.a1>nul
if not [%k%]==[0] copy /b _.b + _.b1>nul
set /a k="%i%&%n%"
if [%k%]==[0] goto :exit


type _.a1>>_.a1
type _.b1>>_.b1
set /a m=m*2
set /a i=i*2
goto :loop
:exit


fc /b %infile% _.a|find ":">_.a1
fc /b %infile% _.b|find ":">>_.a1
sort _.a1>_.b1
set n=
set m=0
set k=0
set q=0
for /f "tokens=1,2" %%i in (_.b1) do (
   if not [!n!]==[%%i] (
        set i=%%j
        call :dig !i:~0,1!
        set /a m=!m!*16+!j!
        call :dig !i:~1,1!
        set /a m=m*16+j
        set /a k=k+1
        if !k!==3 (
           set /a p="m>>18"
           call set x=!x!%%t:~!p!,1%%
           set /a p="(m>>12)&63"
           call set x=!x!%%t:~!p!,1%%
           set /a p="(m>>6)&63"
           call set x=!x!%%t:~!p!,1%%
           set /a p="m&63"
           call set x=!x!%%t:~!p!,1%%
           set /a q=q+1
           if [!q!]==[18] (
                           echo !x!>>%outfile%
                           set x=
                           set q=0)
           set m=0
           set k=0))
   set n=%%i)


if [%k%]==[1] (
           set /a p="m>>2"
           call set x=!x!%%t:~!p!,1%%
           set /a p="(m<<4)&63"
           call set x=!x!%%t:~!p!,1%%==)


if [%k%]==[2] (
           set /a p="m>>10"
           call set x=!x!%%t:~!p!,1%%
           set /a p="(m>>4)&63"
           call set x=!x!%%t:~!p!,1%%
           set /a p="(m<<2)&63"
           call set x=!x!%%t:~!p!,1%%=)


if not [%q%]==[0] echo %x%>>%outfile%


echo.>>%outfile%
echo ----->>%outfile%


del _.a
del _.a1
del _.b
del _.b1


goto :eof


:dig
set j=%1
if [%1]==[A] set j=10
if [%1]==[B] set j=11
if [%1]==[C] set j=12
if [%1]==[D] set j=13
if [%1]==[E] set j=14
if [%1]==[F] set j=15

作者: pengfei     时间: 2006-11-15 01:21
不是不感兴趣, 只是我这样的菜鸟功力不够, 就听你讲课, 多长点见识, 呵呵~
作者: electronixtar     时间: 2006-11-15 01:27
pengfei你都高会了还菜鸟~~~太谦虚了吧,至少也算老鸟~~
作者: pengfei     时间: 2006-11-15 01:35
呵呵~ electronixtar兄过奖了, 我是真不会.
作者: ccwan     时间: 2006-11-15 01:35
electronixtar兄,每一行后都有一个空格,害得我以为代码有问题呢。
作者: lxmxn     时间: 2006-11-15 01:46

  谁说没人感兴趣~~

  这个帖子太好了,值得好好的研究一下~~~顶一个先~

作者: electronixtar     时间: 2006-11-15 04:49
re ccwan:

我是直接复制粘贴的~~汗~~
作者: electronixtar     时间: 2006-11-18 01:29
转一个 Base64 简介

作者:lcother@163.net

  Quote:
奇妙的Base64编码
各位看官应该都是资深的网虫了,小弟斗胆在此问问大家,平时上网时,除了泡MM、到论坛灌水、扔版砖……之外,进行的最多的是什么活动?对了,你一定会说:是收发电子邮件!(谁敢说自己没收/发过电子邮件的?拉出去枪毙了!!)
收/发E-mail的时候有一个安全性的问题--假想一下,你花了一整天时间给系花写的情书,在发送的过程中被隔壁宿舍张三那小子截获了(难道他是黑客??),更糟的是他是你的情敌啊……天,后果不堪设想!!因此,我们必须有一种比较可靠的加密方法,能够对电子邮件的明文进行转换,至少要得出一个无法被别人一眼就看出内容来的东西,而且编码/解码的速度还要足够快。(这时你可以再假想一下啦,张三那家伙截获了你的肉麻情书,可是他一看:“咦?怎么乱七八糟的?垃圾邮件!!”--这样一来你不就逃过大难了?!)

Base64就是在这种背景下产生的加密方法。它的特点是:1、速度非常快。2、能够将字符串A转换成字符串B,而且如果你光看字符串B,是绝对猜不出字符串A的内容来的。不信吗?让我们来看看下面这串东西:

xOO6w6Osu7bTrbniwdnAz8LetcTnzbfXzOy12KOh

呵呵,是什么啊?猜出来了吗?其实它就是下面这段文字经过Base64编码产生的东东:

你好,欢迎光临老罗的缤纷天地!

介绍说完啦,让我们开始探讨实质性的东西。

Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,大家可以查看RFC2045~RFC2049,上面有MIME的详细规范。

Base64要求把每三个8Bit的字节转换为四个6Bit的字节(3*8 = 4*6 = 24),然后把6Bit再添两位高位0,组成四个8Bit的字节,也就是说,转换后的字符串理论上将要比原来的长1/3。

这样说会不会太抽象了?不怕,我们来看一个例子:

转换前 aaaaaabb ccccdddd eeffffff
转换后 00aaaaaa 00bbcccc 00ddddee 00ffffff

应该很清楚了吧?上面的三个字节是原文,下面的四个字节是转换后的Base64编码,其前两位均为0。

转换后,我们用一个码表来得到我们想要的字符串(也就是最终的Base64编码),这个表是这样的:(摘自RFC2045)


Table 1: The Base64 Alphabet

value Encoding value Encoding value Encoding value Encoding
0 A 17 R 34 i 51 z
1 B 18 S 35 j 52 0
2 C 19 T 36 k 53 1
3 D 20 U 37 l 54 2
4 E 21 V 38 m 55 3
5 F 22 W 39 n 56 4
6 G 23 X 40 o 57 5
7 H 24 Y 41 p 58 6
8 I 25 Z 42 q 59 7
9 J 26 a 43 r 60 8
10 K 27 b 44 s 61 9
11 L 28 c 45 t 62 +
12 M 29 d 46 u 63 /
13 N 30 e 47 v
14 O 31 f 48 w (pad) =
15 P 32 g 49 x
16 Q 33 h 50 y


让我们再来看一个实际的例子,加深印象!

转换前 10101101 10111010 01110110
转换后 00101011 00011011 00101001 00110110
十进制 43 27 42 54
对应码表中的值 r b q 2


所以上面的24位编码,编码后的Base64值为 rbq2
解码同理,把 rbq2 的二进制位连接上再重组得到三个8位值,得出原码。
(解码只是编码的逆过程,在此我就不多说了,另外有关MIME的RFC还是有很多的,如果需要详细情况请自行查找。)

用更接近于编程的思维来说,编码的过程是这样的:

第一个字符通过右移2位获得第一个目标字符的Base64表位置,根据这个数值取到表上相应的字符,就是第一个目标字符。
然后将第一个字符左移6位加上第二个字符右移4位,即获得第二个目标字符。
再将第二个字符左移4位加上第三个字符右移6位,获得第三个目标字符。
最后取第三个字符的右6位即获得第四个目标字符.

So easy! That’s all!!!

可是等等……聪明的你可能会问到,原文的字节数量应该是3的倍数啊,如果这个条件不能满足的话,那该怎么办呢?

我们的解决办法是这样的:原文的字节不够的地方可以用全0来补足,转换时Base64编码用=号来代替。这就是为什么有些Base64编码会以一个或两个等号结束的原因,但等号最多只有两个。因为:

余数 = 原文字节数 MOD 3

所以余数任何情况下都只可能是0,1,2这三个数中的一个。如果余数是0的话,就表示原文字节数正好是3的倍数(最理想的情况啦)。如果是1的话,为了让Base64编码是4的倍数,就要补2个等号;同理,如果是2的话,就要补1个等号。

讲到这里,大伙儿应该全明白了吧?如果还有不清楚的话就返回去再仔细看看,其实不难理解的。


作者: ccwan     时间: 2006-11-18 01:43
好东西。泡妞密文。
作者: redtek     时间: 2006-11-18 02:06
欣赏~~
作者: vkill     时间: 2006-11-18 02:25
我还是没有看到具体怎么“加密”
作者: electronixtar     时间: 2006-11-18 02:29
不是 加密 ,是编码/解码。用纯文本来传输二进制文件的方法——Base64
作者: hxuan999     时间: 2006-11-23 04:51
牛人还真是多呀,努力!
作者: lxmxn     时间: 2006-11-23 05:20

  electronixtar 兄发的关于base64的第一个批处理基本看懂了,但是第二个怎么也搞不懂,严重打击了自信心,汗一个先。

作者: tao0610     时间: 2006-11-23 06:06
位运算反向倒回去果然复杂。
作者: redtek     时间: 2006-11-25 03:05
精彩的好贴,欣赏~:)
作者: zqygsd     时间: 2006-12-20 23:04
泡妞密文一定要好好看看。。。
哈哈 !!
作者: vptdosme     时间: 2006-12-23 07:49
此时不应有 ]==[0]。
作者: 0401     时间: 2007-1-11 01:01
发个编码解码的例子,局限性很大。因为我不知道如何将解码后的数转换为原来的字符。这个例子只是简单地通过查表来确定几个字符数字,像汉字就没办法了。还有就是我不懂怎么处理特殊字符,所以会出现很多错误的地方(当然是含有特殊字符的时候了。)
如果生成文件时用echo应该可以减少些特殊字符输入时的错误,但却还要判断0D0A(回车换行)这两个数,晕啊,随便了。
::code by 0401

@echo off
setlocal
set ASCII= !"#$%%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
setlocal enabledelayedexpansion
set B64CODE=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
set str=
set/p "str=请输入需要编码的字符串:"
if not defined str exit/b

call :enc
call :dec
exit/b

:enc
rem 两个比较的文件名为:[.str] [.cmp]
rem 将字符串放到文件中等待比较(fc)并求字符串长度
set/p=%str%<nul>.str
for %%f in (.str) do set strlen=%%~zf
echo 原始字符串长度为: %strlen% 字节

rem 生成fc用来与字符串比较的文件
for /l %%l in (0,1,%strlen%) do >>.cmp set/p= <nul

rem 将比较后得到的字符串的16进制存储到变量
for /f "tokens=3" %%i in ('fc/b .cmp .str^|find "A1"') do (set strhex=!strhex!%%i)
del .cmp .str
echo 转换后的16进制为: %strhex%

:encloop
if not defined strhex goto :encbreak
set chr1=0x!strhex:~0,2!
set chr2=0x!strhex:~2,2!
set chr3=0x!strhex:~4,2!
set strhex=%strhex:~6%
for %%i in (chr1 chr2 chr3) do if "!%%i!"=="0x" set %%i=0
set/a enc1=%chr1%">>"2
set/a enc2=((%chr1%"&"3)"<<"4)"|"(%chr2%">>"4)
set/a enc3=((%chr2%"&"15)"<<"2)"|"(%chr3%">>"6)
set/a enc4=%chr3%"&"63
::echo 移位后得到的数据:%enc1% %enc2% %enc3% %enc4%
if %chr3% equ 0 if %chr2% equ 0 (set enc4=64& set enc3=64) else (set enc4=64)
::echo 移位后的数据编码为:!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
set encstr=!encstr!!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
goto :encloop
:encbreak
echo 字符串[%str%]编码后的数据为[%encstr%]
goto :eof

:dec
rem 并求编码字符串长度
set/p=%encstr%<nul>.str
for %%f in (.str) do set strlen=%%~zf
echo 编码后的字符串长度为: %strlen% 字节
del .str

rem 从编码的字符串encstr中求出编码时偏移的数量
set str=
for /l %%l in (0,1,%strlen%) do (
        for /l %%m in (0,1,64) do (
                if "!encstr:~%%l,1!"=="!B64CODE:~%%m,1!" (
                        set str=!str!/%%m
                )
        )
)
set a=1&set b=4

:decloop
if %strlen% equ 0 goto :decbreak
for /f "tokens=%a%-%b% delims=/" %%i in ("%str%") do set enc1=%%i&set enc2=%%j&set enc3=%%k&set enc4=%%l
::echo 4个字节的偏移分别为: %enc1% %enc2% %enc3% %enc4%
set/a a+=4&set/a b+=4
set/a strlen-=4
set/a chr1=((%enc1%"<<"2)"|"(%enc2%">>"4))-32
set/a chr2=(((%enc2%"&"15)"<<"4)"|"(%enc3%">>"2))-32
set/a chr3=(((%enc3%"&"3)"<<"6)"|"%enc4%)-32
::echo 4个字节解码后再减去32得到的十进制为: %chr1% %chr2% %chr3%
if %enc4% equ 64 if %enc3% equ 64 (set chr3=107&set chr2=107) else (set chr3=107)
::echo 解码后的数据为:!ASCII:~%chr1%,1!!ASCII:~%chr2%,1!!ASCII:~%chr3%,1!
set decstr=!decstr!!ASCII:~%chr1%,1!!ASCII:~%chr2%,1!!ASCII:~%chr3%,1!
goto :decloop

:decbreak
echo 编码的数据[%encstr%]解码后为[%decstr%]
goto :eof

作者: electronixtar     时间: 2007-1-11 03:05
0401兄十分厉害,佩服
作者: vkill     时间: 2007-1-11 07:09
0401兄 厉害
作者: chenall     时间: 2007-1-25 07:05
学习了.
试着将0401的代码修改了一下,利用DEBUG将结果得到的16进制写入到文件.
就可以得到原来的字符了.

将0401另外发了一个十进制转十六进制的批处理整进来了.
这个解码长度有限制的.我对DEBUG不熟.
debug这一段是抄 redtek 的 QQ密码转PwdHash的批处理
::code by 0401

@echo off
setlocal
setlocal enabledelayedexpansion
set B64CODE=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
set str=
set/p "str=请输入需要编码的字符串:"
if not defined str exit/b

call :enc
call :dec
exit/b

:enc
rem 两个比较的文件名为:[.str] [.cmp]
rem 将字符串放到文件中等待比较(fc)并求字符串长度
set/p=%str%<nul>.str
for %%f in (.str) do set strlen=%%~zf
echo 原始字符串长度为: %strlen% 字节
set str_len=%strlen%

rem 生成fc用来与字符串比较的文件
for /l %%l in (0,1,%strlen%) do >>.cmp set/p= <nul

rem 将比较后得到的字符串的16进制存储到变量
for /f "tokens=3" %%i in ('fc/b .cmp .str^|find "A1"') do (set strhex=!strhex!%%i)
del .cmp .str
echo 转换后的16进制为: %strhex%

:encloop
if not defined strhex goto :encbreak
set chr1=0x!strhex:~0,2!
set chr2=0x!strhex:~2,2!
set chr3=0x!strhex:~4,2!
set strhex=%strhex:~6%
for %%i in (chr1 chr2 chr3) do if "!%%i!"=="0x" set %%i=0
set/a enc1=%chr1%">>"2
set/a enc2=((%chr1%"&"3)"<<"4)"|"(%chr2%">>"4)
set/a enc3=((%chr2%"&"15)"<<"2)"|"(%chr3%">>"6)
set/a enc4=%chr3%"&"63
::echo 移位后得到的数据:%enc1% %enc2% %enc3% %enc4%
if %chr3% equ 0 if %chr2% equ 0 (set enc4=64& set enc3=64) else (set enc4=64)
::echo 移位后的数据编码为:!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
set encstr=!encstr!!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
goto :encloop
:encbreak
echo 字符串[%str%]编码后的数据为[%encstr%]
goto :eof

:dec
rem 并求编码字符串长度
set/p=%encstr%<nul>.str
for %%f in (.str) do set strlen=%%~zf
echo 编码后的字符串长度为: %strlen% 字节
del .str

rem 从编码的字符串encstr中求出编码时偏移的数量
set str=
for /l %%l in (0,1,%strlen%) do (
        for /l %%m in (0,1,64) do (
                if "!encstr:~%%l,1!"=="!B64CODE:~%%m,1!" (
                        set str=!str!/%%m
                )
        )
)
set a=1&set b=4

:decloop
if %strlen% equ 0 goto :decbreak
for /f "tokens=%a%-%b% delims=/" %%i in ("%str%") do set enc1=%%i&set enc2=%%j&set enc3=%%k&set enc4=%%l
::echo 4个字节的偏移分别为: %enc1% %enc2% %enc3% %enc4%
set/a a+=4&set/a b+=4
set/a strlen-=4
set/a chr1=((%enc1%"<<"2)"|"(%enc2%">>"4))
set/a chr2=(((%enc2%"&"15)"<<"4)"|"(%enc3%">>"2))
set/a chr3=(((%enc3%"&"3)"<<"6)"|"%enc4%)
::echo 4个字节解码后再减去32得到的十进制为: %chr1% %chr2% %chr3%
call :_d2h chr1 %chr1%
call :_d2h chr2 %chr2%
call :_d2h chr3 %chr3%
::echo 4个字节解码后再减去32得到的十进制为: %chr1% %chr2% %chr3%
::if %enc4% equ 64 if %enc3% equ 64 (set chr3=107&set chr2=107) else (set chr3=107)
::echo 解码后的数据为:!ASCII:~%chr1%,1!!ASCII:~%chr2%,1!!ASCII:~%chr3%,1!
set decstr=!decstr! %chr1% %chr2% %chr3%
goto :decloop

:decbreak
pause
set /a str_len+=1
echo exit|%ComSpec%/kprompt e 100 $_%decstr%$_rcx$_%str_len%$_n tmp.tmp$_w$_q$_|debug>nul
chcp 936>nul
set/p=编码的数据[%encstr%]解码后为:<nul
type tmp.tmp
del tmp.tmp>nul
echo.
pause
goto :eof

:_d2h
set hex=
set hexstr=0 1 2 3 4 5 6 7 8 9 A B C D E F
set d=0
for %%i in (%hexstr%) do (set d!d!=%%i&set/a d+=1)
set scanf=%2
set tscanf=
call :d2h
if not defined hex set hex=0
set %1=%hex%
goto :eof

:d2h
if %scanf% equ 0 goto :eof
set/a tscanf=%scanf%"&"15
set/a scanf">>="4
set hex=!d%tscanf%!!hex!
goto :d2h

作者: 0401     时间: 2007-1-25 09:13
呵呵,漂亮。讨论又有进展了。不过我对Debug也很陌生,看来得补补了。
作者: chenall     时间: 2007-1-25 23:56
再贴一个比较完美一点的.
接下去将这个再修改一下就可以做成一个
将指定文件用BASE64编码/解码的工具

代码应该还可以再精简一下.

  Quote:

  1. ::code by 0401
  2. ::chenall 修改于 2007.01.25
  3. @echo off
  4. setlocal
  5. setlocal enabledelayedexpansion
  6. set B64CODE=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
  7. set str=
  8. set/p "str=请输入需要编码的字符串:"
  9. if not defined str exit/b

  10. call :enc
  11. call :dec
  12. exit/b

  13. :enc
  14. rem 两个比较的文件名为:[.str] [.cmp]
  15. rem 将字符串放到文件中等待比较(fc)并求字符串长度
  16. set/p=%str%<nul>.str
  17. for %%f in (.str) do set strlen=%%~zf
  18. echo 原始字符串长度为: %strlen% 字节
  19. set str_len=%strlen%

  20. rem 生成fc用来与字符串比较的文件
  21. del _*.cmp 2>nul
  22. for /l %%l in (1,1,%strlen%) do (
  23.         >>_a.cmp set/p=a<nul
  24.         >>_b.cmp set/p=b<nul
  25. )
  26. fc/b _a.cmp .str|find ":">tmp.str
  27. fc/b _b.cmp .str|find ":">>tmp.str
  28. sort tmp.str>_a.cmp

  29. rem 将比较后得到的字符串的16进制存储到变量
  30. for /f "tokens=1,3" %%i in (_a.cmp) do (
  31.         if not "!n!"=="%%i" set strhex=!strhex!%%j
  32.         set n=%%i
  33. )
  34. ::for /f "tokens=3" %%i in ('fc/b .cmp .str^|find ":"') do (set strhex=!strhex!%%i)
  35. del *.cmp *.str 2>nul
  36. echo 转换后的16进制为: %strhex%

  37. :encloop
  38. if not defined strhex goto :encbreak
  39. set chr1=0x!strhex:~0,2!
  40. set chr2=0x!strhex:~2,2!
  41. set chr3=0x!strhex:~4,2!
  42. set strhex=%strhex:~6%
  43. for %%i in (chr1 chr2 chr3) do if "!%%i!"=="0x" set %%i=0
  44. set/a enc1=%chr1%">>"2
  45. set/a enc2=((%chr1%"&"3)"<<"4)"|"(%chr2%">>"4)
  46. set/a enc3=((%chr2%"&"15)"<<"2)"|"(%chr3%">>"6)
  47. set/a enc4=%chr3%"&"63
  48. ::echo 移位后得到的数据:%enc1% %enc2% %enc3% %enc4%
  49. if %chr3% equ 0 if %chr2% equ 0 (set enc4=64& set enc3=64) else (set enc4=64)
  50. ::echo 移位后的数据编码为:!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
  51. set encstr=!encstr!!B64CODE:~%enc1%,1!!B64CODE:~%enc2%,1!!B64CODE:~%enc3%,1!!B64CODE:~%enc4%,1!
  52. ::for %%i in (enc1 enc2 enc3 enc4) do (
  53. ::        if !%%i! lss 10 (set/p=0!%%i!<nul>>tmp.bb) else (set/p=!%%i!<nul>>tmp.bb)
  54. ::)
  55. goto :encloop
  56. :encbreak
  57. echo 字符串[%str%]编码后的数据为[%encstr%]
  58. ::echo 字符串[%str%]编码后的数据为[%encstr%] >>tmp.aa
  59. goto :eof

  60. :dec
  61. rem 并求编码字符串长度
  62. set/p=%encstr%<nul>.str
  63. for %%f in (.str) do set strlen=%%~zf
  64. echo 编码后的字符串长度为: %strlen% 字节
  65. del .str

  66. rem 从编码的字符串encstr中求出编码时偏移的数量
  67. set str=
  68. for /l %%l in (0,1,%strlen%) do (
  69.         for /l %%m in (0,1,64) do (
  70.                 if "!encstr:~%%l,1!"=="!B64CODE:~%%m,1!" (
  71.                         if %%m lss 10 (
  72.                                 set str=!str!0%%m
  73.                         ) else (
  74.                                 set str=!str!%%m
  75.                         )
  76.                 )
  77.         )
  78. )
  79. set a=1&set b=4&set e=0
  80. del debug.src 2>nul

  81. :decloop
  82. if not defined str goto :decbreak
  83. set /a enc1=1!str:~0,2!-100
  84. set /a enc2=1!str:~2,2!-100
  85. set /a enc3=1!str:~4,2!-100
  86. set /a enc4=1!str:~6,2!-100
  87. set str=%str:~8%
  88. for %%i in (enc1 enc2 enc3 enc3 enc4) do (
  89.         if !%%i! leq 0 set %%i=0
  90.         if !%%i! equ 64 set %%i=0
  91. )
  92. ::echo 4个字节的偏移分别为: %enc1% %enc2% %enc3% %enc4%
  93. set/a chr1=((%enc1%"<<"2)"|"(%enc2%">>"4))
  94. set/a chr2=(((%enc2%"&"15)"<<"4)"|"(%enc3%">>"2))
  95. set/a chr3=(((%enc3%"&"3)"<<"6)"|"%enc4%)
  96. ::echo 4个字节解码后再减去32得到的十进制为: %chr1% %chr2% %chr3%
  97. call :_d2h chr1 %chr1%
  98. call :_d2h chr2 %chr2%
  99. call :_d2h chr3 %chr3%
  100. ::echo 4个字节解码后再减去32得到的十六进制为: %chr1% %chr2% %chr3%
  101. ::echo 解码后的数据为:!ASCII:~%chr1%,1!!ASCII:~%chr2%,1!!ASCII:~%chr3%,1!
  102. set /a ee=0x100+3*e
  103. call :_d2h ee %ee%
  104. >>debug.src echo e %ee% %chr1% %chr2% %chr3%
  105. ::set/p=%chr1%%chr2%%chr3%<NUL >>BB.TXT
  106. set /a e+=1
  107. goto :decloop

  108. :decbreak
  109. pause
  110. set /a str_len+=1
  111. >>debug.src echo rcx
  112. >>debug.src echo %str_len%
  113. >>debug.src echo n tmp.tmp
  114. >>debug.src echo w
  115. >>debug.src echo q
  116. debug<debug.src
  117. del debug.src
  118. chcp 936>nul
  119. echo 编码的数据[%encstr%]
  120. echo.
  121. set/p=解码后为:<nul
  122. type tmp.tmp
  123. del tmp.tmp>nul
  124. echo.
  125. pause
  126. goto :eof

  127. :_d2h
  128. set hex=
  129. set hexstr=0 1 2 3 4 5 6 7 8 9 A B C D E F
  130. set d=0
  131. for %%i in (%hexstr%) do (set d!d!=%%i&set/a d+=1)
  132. set scanf=%2
  133. set tscanf=
  134. call :d2h
  135. if not defined hex set hex=0
  136. set %1=%hex%
  137. goto :eof

  138. :d2h
  139. if %scanf% equ 0 goto :eof
  140. set/a tscanf=%scanf%"&"15
  141. set/a scanf">>="4
  142. set hex=!d%tscanf%!!hex!
  143. goto :d2h
        chenall 发表于:  2007-01-25  15:35

[ Last edited by chenall on 2007-1-26 at 04:37 AM ]
作者: 0401     时间: 2007-1-26 03:03
to chenall兄:

确实已经可以写个BASE64编码/解码的工具了,我也有此打算了,不过不知道时间允不允许。呵呵
顺便提一下,兄为了用fc比较文件,使用fsutil file createnew命令创建一个等大的文件,但这样fsutil只能是管理员组的成员才能使用,适用性打了点折扣。何不试试5楼的方法,或者用debug的f子命令来填充一个二进制全为0的等大文件。
-------------------------------------------------
补充的:如果用f子命令来填充也得填充2个不同内容的文件,因为如果处理的是一个文件,就不保证不碰到二进制为0的字节。

[ Last edited by 0401 on 2007-1-28 at 01:09 PM ]
作者: chenall     时间: 2007-1-26 04:38
参考了5楼的代码已修改.
作者: fastslz     时间: 2007-10-16 11:03
谢谢,0401、chenall
灵活运用这些代码、真的很强,用debug写文件或第3方程序(debug执行比较慢命令复杂),这样加密的文件很难破,之前我一直用第3方程序转换和写入很容易破解,只是CMD处理字符串有局限性,处理大文件要copy /b *+* 要产生太多临时文件了。

继续研究...