DOS命令之批处理注册表Word文档格式.docx
《DOS命令之批处理注册表Word文档格式.docx》由会员分享,可在线阅读,更多相关《DOS命令之批处理注册表Word文档格式.docx(34页珍藏版)》请在冰豆网上搜索。
mini_
delmini_
pause
find反过滤的例子
它的优势在于可以通过find过滤嵌入多个脚本
@find"
@"
/v<
%0|debug>
@mini_
@delmini_
@pause
传统的echo大法
通过echo命令重定向标准输出到临时文件,然后用debug执行这个临时文件里的命令,这个方法比较通用,批处理输出文件都是用的这个方法,不足是需要产生临时文件论坛讨论
(-
echoDC000:
000>
v.dat
echoD>
>
v.dat
echoQ>
Debug.exe<
v.dat>
info.txt
echoo7017>
tmp.txt
echoo71ff>
echoQ>
deltmp.txt
方便的prompt大法
prompt命令支持一个特殊的参数$_,改参数表示换行,所以在批处理中灵活应用可以写出紧凑的汇编代码论坛讨论
echoexit|%ComSpec%/kprompte100B400B012CD10B003CD10CD20$_g$_q$_|debug>
经典的more大法
more支持一个+n参数,表示从文件的指定行开始输出,我们利用这个参数把批处理本身尾部的一些汇编代码直接通过|管道直接输出到debug命令,该方法最早可能是论坛网友上[doscc
(-论坛讨论
<
"
%~f0"
more+2|debug&
goto:
eof
e100B013CD10C42FAA11F86413066C04EBF6
rbx
rcx
10
n
强悍的ASCode
ASCode论坛讨论
chcp437>
nul&
graftabl936>
echohP1X500P[PZBBBfh#b##fXf-V@`$fPf]f3/f1/5++u5x>
set/ppassword=请输入密码:
for/f"
tokens=*"
%%iin('
'
)dosetpassword=%%i
del
echo.
echoThePasswordis:
%password%"
这类汇编程序的特殊性在于,所有的代码全部分布于ASCII码表的可显示字符范围中,当然这样的程序不是碰巧得到的,而是人为的构造出来的,其中需要用到许多技巧。
比如最常见的中断调用代码int21(CD21),因为不在ASCII可显示字符范围内,所以用到许多压栈、出栈、增减代码来构造,所以它的代码段是动态变化的。
这样的代码被叫做ASCODE,这样的技术被称作ASCIIAssemble,一门即将消失的技术,可想而知,这样的代码构造起来是困难的,在网上流传的ASCODE只有很少量的是人为构造的,因为已经有成熟的技术可以将任何二进制文件转变为ASCODE,这样的过程叫encode。
而ASCODE执行的过程需要decode,合称codec,codec的算法已知的超过4种,比较有名的应该是HerbertKleebauer的算法,不过它要求原程序必须有org170H的类似标记,因为前面的文件头被用来存放decode代码。
巧妙的.com文件头
据说这个是袁哥写的病毒天极网的分析资料
(
0jeX4e-005POP]hWeX5ddP^1,FFFFF1,FFF1,4rP^P_jeX4aPY-x-AAR`0`*=00uPBOIAAAAFKAOBPIDMCBALEAJMNCBJALIAAEMMNCBFEGIGFCAENGBGDHCGPHGGJHCHFHDCAGJHDCAGDGPGNGJGOGHCACOCOCOCOCOCOANAKCEAAqqqq
@ECHOOFF
COPY%0/BC:
\BATVIR.COM/B/Y
C:
\BATVIR.COM
DELC:
这段代码有什么巧妙指出呢?
第一句的开头,
冒号告诉cmd.exe,这句是个GOTO语句的标识符,cmd.exe会直接跳过这一句,也就是当作注释了,但是,后面的批处理把自身copy为,这就很讲究了,.com文件是以
开头的一段ASCode代码!
所以这种ASCode比上一种更加高级,因为必须以
作为ASCode的开头。
与VBS集成
在命令行下调用VBS/JS用cscript命令,由于cscript只能读取文件,不接受重定向和管道的输入,所以只能用echo或者more来生成一个临时脚本文件
与批处理不同的是,VBS有很多特殊字符,例如>
在批处理中代表重定向输出,在VBS语法里代表大于,所以使用echo需要用^来转义特殊符号
echomsgbox3^>
2>
v.vbs
cscriptv.vbs
国外的find大法
利用find命令过滤出VBS代码的一个特定'
VBS,这样可以嵌入多段VBS代码到bat里,例如:
@echooff&
setlocalenableextensions
Makeatemporaryfolder
ifnotexistc:
\mytempmkdirc:
\mytemp
BuildaVisualBasicScript
findstr"
%skip%VBS"
"
>
c:
\mytemp\tmp$$$.vbs
RunitwithMicrosoftWindowsScriptHostVersion5.6
cscript//nologoc:
Callthecommandlinescriptthescripthostbuilt
callc:
\mytemp\tmp$$$.cmd
Cleanup
for%%fin(c:
\mytemp\tmp$$$.vbsc:
\mytemp\tmp$$$.cmd)doifexist%%fdel%%f
rmdirc:
Showtheresult
echoDayNumberdn_=%dn_%
endlocal&
goto
EOF
TheVisualBasicScript
ConstForReading=1,ForWriting=2,ForAppending=8'
VBS
DimDateNow,fso,f'
DateNow=Date'
Setfso=CreateObject("
Scripting.FileSystemObject"
)'
Setf=fso.OpenTextFile("
c:
\mytemp\tmp$$$.cmd"
ForWriting,True)'
f.Write"
@setdn_="
&
DatePart("
y"
DateNow)'
f.Close'
同上面的more大法,优点是不需要考虑特殊字符的问题,缺点是代码灵活性不高,添加了代码就需要修改+n的值
more+3>
cscript//nologov.vbs
msgboxnow
wscript.echo"
CN-DOS<
wscript.stdin.readline
Vacum的方法
最近在写几个Bat,在Google上找到这里,顺便把我的方法也贴到这里来,和上面的Find、more方法原理差不多。
但感觉灵活方便许多。
代码如下,不是很复杂,就不多说明了。
Makeallthecodeintoonebatfile
@echoOFF
IF"
%1"
=="
_GET_LINES_"
GOTO
_GET_LINES_
REMYourcodehere
REMExample
(CALL%0
_GET_LINES_############)|MORE
_GET_LINES___SQLPLUS__)|MORE
REM这一部分用来取数据。
goto
SETLOCALENABLEDELAYEDEXPANSION
SETLINE_TAG=%2
SETBEGIN_LINE=0
SETTOTAL_LINE=0
SETCURLINE=0
usebackqdelims=:
tokens=1"
%%iin(`findstr/N/R/C:
^^^^%LINE_TAG%%0`)DOsetBEGIN_LINE=%%i&
goto__GET_BEGIN_LINE_OK
__GET_BEGIN_LINE_OK
%%iin(`(for/f"
skip=!
BEGIN_LINE!
tokens=*"
%%jin(%0^)do@echo%%j^)^|findstr/N/R/C:
^^^^%LINE_TAG%`)DOsetTOTAL_LINE=%%i&
goto__GET_END_LINE_OK
__GET_END_LINE_OK
skip=%BEGIN_LINE%tokens=*"
%%iIN(%0)DO((SET/ACURLINE+=1)&
(if
!
CURLINE!
LSS%TOTAL_LINE%(ifnot"
A%%i"
A"
@echo%%i)))
ENDLOCAL
GOTO
REM下面是数据部分的内容
############
HelloThisJustaTest
限制,前导空格、空行会被过滤掉,可以在上面的for语句中增加delims=选项来解决,但同时会带来新的问题
__SQLPLUS__
SELECT*FROMDUAL;
select*fromdual;
方便的mshta大法
该方法由est首创,巧妙利用了Windows系统里自带的javascript:
和vbscript:
协议使得在批处理中能够在一行的狭小空间里插入简短的VBS/JS代码论坛讨论
mshta"
javascript:
newActiveXObject('
SAPI.SpVoice'
).Speak('
Hi,CN-DOSguys!
);
window.close();
事实上使用iexplore.exe和Helpctr.exe也可以,不过mshta.exe的权限相对要高一点
让WSH直接解析bat
这个方法也是est首创论坛讨论
OnErrorResumeNext
Subbat
echooff&
cls
echoBatching_codez_here_following_vbs_rules&
pause
startwscript-e:
vbs"
ExitSub
EndSub
MsgBox"
Thisisvbs"
代码解释
cmd.exe识别成一段注释
wscript.exe这样识别,
在vbs语法里代表分行,然后OnErrorResumeNext,也就是让WSH忽略一些错误
cmd.exe识别成:
启动wscript.exe,其参数是:
①-e:
vbs设定以vbs解析文件自身②"
指这个批处理本身。
wscript.exe把这句识别成:
调用一个叫start的函数,函数参数是wscript这个变量,然后用这个函数的结果来减去e。
接下来是又是一个
,分行,然后又是调用一个名叫vbs的函数,参数是字符:
这句是最为精巧的,因为它成功的让vbs引擎解释了一段批处理,而且没有错误!
当然这些start()、vbs()函数是不存在的,但是会被cmd.exe当成命令执行。
为什么不用wscript//e:
来执行呢?
vbs解析会出错的
这段代码的核心思想已经介绍完毕了。
下面,为了让批处理以vbs调用其自身后,马上退出,我们需要exit或者goto
eof,但是gotocallexit在vbs又是一个关键词,所以我们只能用符合vbs语法的exitsub,所以我们在第二句加一个subbat,其实cmd.exe寻找了一个叫sub.exe的命令,但是这个命令是不存在的,cmd.exe跳过。
然后在6、7句加一个exitsub以及endsub,让批处理结束,同时又符合vbs的语法
那个echooff&
cls,批处理的意思就是相当于@echooff,但是vbs不认@符号,所以改成echooff&
cls,vbs可以解析为,调用一个叫echo()的函数,参数为off&
cls,也就是两个字符串off和cls相加
这段代码的好处是:
不用生成临时文件。
其实用echo或者more或者find来生成临时vbs很浪费系统资源的,用我写的这段代码,就完全免去了这些麻烦。
直接混合编程,以startwscript-e:
为界限,上面写批处理,下面写vbs,并行不悖!
与.NET语言集成
安装了.NETFramework之后,系统就多了一个强势语言的编译工具,在C:
\Windows\Microsoft.NET\Framework\v*\下,我们可以在批处理中输出代码然后调用这些编译器来现场生成exe让批处理调用。
这些编译器有,C#的csc.exe,VB.NET的vbc.exe,JScript.NET的jsc.exe,VJ#的vjc.exe,这里给出C#的例子,由于C#是一种语法严格的语言,所以推荐用more直接生成源代码并且编译论坛讨论
set"
dnfpath=C:
\Windows\Microsoft.NET\Framework"
est=DO_NOT_ZT_WITHOUT_PERMISSION"
delims="
%%vin('
dir/ad/b%dnfpath%\v?
.*'
)do(
ifexist"
%dnfpath%\%%v\csc.exe"
set"
cscpath=%dnfpath%\%%v\csc.exe"
)
more+17>
%temp%\estTrayTip.cs"
%cscpath%"
/out:
%cd%\estTrayTip.exe"
estTrayTip.exeC:
\Windows\System32\acwizard.ico看什么看没见过批处理啊?
没见过任务栏的汽泡信息啊?
见过了吧?
见过了顶electronixtar的帖子。
2
exe的参数解释:
estTrayTip.exe图标路径 标题 内容 提示图标类型Error、Info、None、Warning,这里取2=Info。
每个参数都必须正确填写
nulping127.1-n1
delestTrayTip.exe
estTrayTip
usingSystem;
usingSystem.Windows.Forms;
usingSystem.Drawing;
namespaceestTrayTip
{
classProgram
staticvoidMain(string[]args)
NotifyIconestIcon=newNotifyIcon();
estIcon.Icon=newIcon(args[0]);
estIcon.Visible=true;
ToolTipIconestToolTipIcon=newToolTipIcon();
switch(args[3])
case"
1"
estToolTipIcon=ToolTipIcon.Error;
break;
2"
estToolTipIcon=ToolTipIcon.Info;
3"
estToolTipIcon=ToolTipIcon.None;
4"
estToolTipIcon=ToolTipIcon.Warning;
}
estIcon.ShowBalloonTip(1,args[1],args[2],estToolTipIcon);
与其他语言集成
其他语言,例如Python,Perl等和批处理集成,方法和上面的都大同小异
ruby和CMD脚本的混杂编写示例
#!
/usr/bin/ruby
@rem=<
CMDSHELL
for%%?
in(ruby.exe)doifnot*%%~$PATH:
?
==*ruby.exe"
%*
exit/b
#rubycode
print"
rubyruninshellbash/cmd,参数:
;
$*.each{|i|print'
+i+'
'
__END__
*注释*
可运行在win/unixshell
让同一个文件,被cmd.exe识别成批处理,让ruby.exe识别成ruby脚本
可以直接在cmd中编写ruby脚本
如只想运行在win可以把第一行"
/usr/bin/ruby"
删除,再把"
cls"
删除就好
附加信息
本wiki持续更新中,转载请注意版本更新,不要误人之弟
作者:
est,联系方式:
(Email&
MSN)electronicstar@
最后更新:
2007-1-1717:
22感谢lxmxn的支持,感谢ccwan帮助测试代码
080807补充FORtokens和delims的应用
delims是指分割符,tokens是指选取分割后得到的字符串片断。
以下面这段代码为例:
FOR/F"
eol=;
tokens=2,3*delims=,"
%iin("
a,bc,def,ghij,jklmn"
)do@echo%i%j%k
其中Delims是“,”,所以"
a,bc,def,ghij,klmn"
)被分隔成了abcdefghijklmn这5段。
tokens=2,3*表示取第2个片段、第3个片段以及第3个片段以后的所有片段,亦即:
%i=bc
%j=def
%k=ghij,klmn(此处“*”表示从第4个片段开始就不用再分割了,统统赋给%k)
所以如果你代码中用“tokens=*”的话,就表示不进行任何分割,直接把当前行赋给循环变量。
内容如下
helloworld
thankyouvery
youareverygood
这三行内容
%ain(a.txt)do@echo%a