ADS batch extension/api v1.0

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
KKZiomek
Posts: 7
Joined: 27 Mar 2017 17:57

ADS batch extension/api v1.0

#1 Post by KKZiomek » 05 Apr 2017 20:08

Hello, batch hackers. I have been playing a lot with Alternate Data Streams on windows recently. ADSs are hidden streams in a file, therefore it is hidden data in a file. The ADSs are not visible when accessing the file containing them normally. It is easy to write to them and read them, but Windows lacks an API that allows to do other things with the streams such as renaming, deleting, copying between streams, etc..

To read more about ADSs, google "Alternate Data Streams" and you will find information about it.

I created an API in batch to manipulate the ADSs easily. It was not very easy to write this extension because most commands in windows either don't support ADSs, or the ADSs use is limited. That's why the code can seem sometimes messy and unreadable, because I had to use different tricks that I could come up with to achieve different tasks.

All functions of the api are described inside the code. If anyone finds any bugs or suggests something for the code, write it under this topic.

ads.cmd:

Code: Select all

:ADS function args...
::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: ADS batch extension v1.0
:: By KKZiomek (c) 2017
::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: The first most complete API written using pure
:: batch for manipulation of Alternate Data Streams
:: and files that are containing them. Feel free to
:: use this code in any project, private or commercial,
:: but always keep this information box attached
:: with the code.
::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: To use any of the functions in this API, just
:: use "call :ADS function args...", where 'function'
:: is the name of API function, and 'args...' are
:: arguments specific to the function. The current
:: functions in this API are: clear, echo, write,
:: readToFile, appendToFile, readToVar, copy,
:: move, append, moveAppend, delete, rename.
:: DO NOT use "call :ADS_function rest..." but
:: "call :ADS function rest...". Notice that there is
:: a space instead of the '_' character. It is intended
:: even though function definitions have this character
:: in them. Specific arguments to a function can be
:: found with the label/function declaration.
:: The API doesn't support putting or reading binary
:: files to or from ADS's yet, but it will in future versions.
::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: YOU CAN DELETE THE REST OF THIS INFORMATION
:: BOX. IT IS JUST FOR REFERENCE FOR DEVELOPERS!
:: Function 'clear' clears a stream in a file.
:: Function 'echo' inputs a text to a stream.
:: Function 'write' inputs contents of a file into a stream.
::     The contents already in the stream are NOT overriden.
:: Function 'readToFile' outputs contents of a stream into
::     an outside file. Contents of the outside file are overriden.
:: Function 'appendToFile' appends contents of a stream into
::     an outside file. Contents of the outside file are NOT overriden.
:: Function 'readToVar' puts contents of a stream into
::     a variable of specified name. Newline characters are
::     ommited because there isn't a way to store a newline
::     character in batch in a variable, only to output it.
:: Function 'copy' copies contents from one stream to
::     another stream in the same file. The contents already
::     in the second stream are overriden.
:: Function 'move' moves contents from one stream to
::     another stream in the same file. The contents already
::     in the second stream are overriden.
:: Function 'append' appends contents of one stream to
::     another stream in the same file. The contents already
::     in the second stream are NOT overriden.
:: Function 'moveAppend' moves contents of one stream
::     to another stream by appending it. The contents already
::     in the second stream are NOT overriden.
:: Function 'delete' deletes a stream from a file completely.
::     Other streams in the same file are unaffected.
:: Function 'rename' renames a stream in a file to a new
::     name, but keeping the contents. Other streams in the
::     same file are unaffected.
::::::::::::::::::::::::::::::::::::::::::::::::::::::
set "$=goto:eof"
call:ADS_%*&%$%
:ADS_clear file streamname
if not exist %1 echo nul>%1
type nul>"%~1:%~2"&%$%
:ADS_echo file streamname content
if not exist %1 echo nul>%1
echo:%~3>>"%~1:%~2"&%$%
:ADS_write file streamname inputfile
if not exist %1 echo nul>%1
for /f usebackq %%# in ("%~3") do echo:%%#>>"%~1:%~2"
%$%
:ADS_readToFile file streamname outputfile
if not exist %3 echo nul>%3
more<"%~1:%~2">%3&%$%
:ADS_appendToFile file streamname outputfile
if not exist %3 echo nul>%3
more<"%~1:%~2">>%3&%$%
:ADS_readToVar file streamname variable_name
set %~3=
call:ADS_readToFile %1 %2 `
for /f usebackq %%# in ("`") do call set %~3=%%%~3%%%%#
del /q "`"&%$%
:ADS_copy file streamname1 streamname2
call:ADS_readToFile %1 %2 `
call:ADS_clear %1 %3
call:ADS_write %1 %3 `
del /q "`"&%$%
:ADS_move file streamname1 streamname2
call:ADS_copy %1 %2 %3
call:ADS_clear %1 %2
%$%
:ADS_append file streamname1 streamname2
call:ADS_readToFile %1 %2 `
call:ADS_write %1 %3 `
del /q "`"&%$%
:ADS_moveAppend file streamname1 streamname2
call:ADS_append %1 %2 %3
call:ADS_clear %1 %2
%$%
:ADS_delete file streamname
for /f "tokens=2 delims=: usebackq" %%# in (`dir /r ^| find "%~1:" ^| find ":$DATA" ^| find /v "%~2"`) do echo %%#>>`
if exist "`" (
md `strs`
waitfor /t 1 shortPause >nul 2>&1
for /f usebackq %%# in ("`") do call:ADS_readToFile %1 "%%#" "`strs`\%%#" )
for /f usebackq %%# in ("%~1") do echo:%%#>>"``"
del /q %1
waitfor /t 1 shortPause >nul 2>&1
for /f usebackq %%# in ("``") do echo:%%#>>"%~1"
del /q "``"
if exist "`" (
for /r `strs` %%# in (*) do call:ADS_write %1 "%%~nx#" "`strs`\%%~nx#"
del /q "`strs`\*"
rmdir "`strs`"
del /q "`" )
%$%
:ADS_rename file streamname newStreamname
call:ADS_readToFile %1 %2 ```
call:ADS_delete %1 %2
call:ADS_write %1 %3 ```
del /q "```"&%$%


KKZiomek

Aacini
Expert
Posts: 1914
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: ADS batch extension/api v1.0

#2 Post by Aacini » 06 Apr 2017 00:32

I reviewed your code. I realized that several modifications may be done in order to made it simpler or better.

All the functions ("API's") that use "echo:%%#>>file" will fail if the last character in the line is a digit. You should put the redirection at beginning: ">>file echo:%%#".

Function 'write' may be implemented in this simpler way: type "%~3">>"%~1:%~2"

Function 'readToVar' may be implemented in a much simpler way. You may directly read from an ADS via FOR /F command: for /f usebackq %%# in ("%1:%2") do call set %~3=%%%~3%%%%#

IMHO Function 'delete' is too much complicated. I don't understand what is the purpose of WAITFOR command in this function. Such a code may be implemented in this much simpler way:

Code: Select all

:ADS_delete file streamname
type "%~1" > "%~1.tmp"
for /F "tokens=3 delims=: " %%a in ('dir /R "%~1" ^| find ":$DATA" ^| find /V "%~2"') do (
   < "%~1:%%a" more > "%~1.tmp:%%a"
)
move /Y "%~1.tmp" "%~1" > NUL
goto :EOF


Perhaps you may be interested in this topic that describe some uses of ADS's...

Antonio

KKZiomek
Posts: 7
Joined: 27 Mar 2017 17:57

Re: ADS batch extension/api v1.0

#3 Post by KKZiomek » 06 Apr 2017 07:19

You're right I could do better on the delete function. And thank you for reviewing. I will update my code as soon as I get access to my computer.

By the way I didn't know you could do '>file command'. I learn something about batch every week.

Post Reply