Showing posts with label sid. Show all posts
Showing posts with label sid. Show all posts

Oct 9, 2013

Batch code variants: EnumerateProfileSids

No, it is not a verbatim re-post of my older work. GetCurrentSID and EnumerateLoggedOnSIDs are functions that utilize a bit different method from the one I am about to describe. What they all do is guessing, accurate guessing. This function enumerates user profiles' SIDs with lesser uncertainty factor than the former. EnumerateProfileSids retrieves SIDs from the ProfileList registry key. I have worked out two variants, and chose the faster (because both are good and give the same results) one.

First, I am going to present the slower variant. What does it do? It retrieves Sid values from ProfileList subkeys, explodes long hex values properly so that they can later be converted to decimal, thus to concatenate the decimal values into a valid SID.
This slow script also demonstrates a basic cache. When a newly encountered DWORD is converted, it is saved to a variable which is an array. When it encounters a DWORD that had already been converted, it gets the previously converted decimal form of the matching DWORD from that array. This cache takes only three biggest "parts" of an SID into account, because conversion of the latest DWORD (Relative ID) is very fast, hence it is not necessary for it to be saved.
@echo off
call:EnumerateProfileSids var
for %%A in (%var%) do (
 for /f "tokens=1,2,3,4 delims=+" %%B in (%%A) do (
  echo.
  echo  SID                  : %%B
  echo  Logged in            : %%C
  echo  Possible username    : %%D
  echo  Profile storage path : %%E
 )
)
pause
goto:eof
:EnumerateProfileSids
setlocal
set key=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
set pow16_0_=0;0;0;0;0;0;0;0&set pow16_1_=16;256;4096;65536;1048576;16777216;268435456;4294967296
set pow16_2_=32;512;8192;131072;2097152;33554432;536870912;8589934592&set pow16_3_=48;768;12288;196608;3145728;50331648;805306368;12884901888
set pow16_4_=64;1024;16384;262144;4194304;67108864;1073741824;17179869184&set pow16_5_=80;1280;20480;327680;5242880;83886080;1342177280;21474836480
set pow16_6_=96;1536;24576;393216;6291456;100663296;1610612736;25769803776&set pow16_7_=112;1792;28672;458752;7340032;117440512;1879048192;30064771072
set pow16_8_=128;2048;32768;524288;8388608;134217728;2147483648;34359738368&set pow16_9_=144;2304;36864;589824;9437184;150994944;2415919104;38654705664
set pow16_10_=160;2560;40960;655360;10485760;167772160;2684354560;42949672960&set pow16_11_=176;2816;45056;720896;11534336;184549376;2952790016;47244640256
set pow16_12_=192;3072;49152;786432;12582912;201326592;3221225472;51539607552&set pow16_13_=208;3328;53248;851968;13631488;218103808;3489660928;55834574848
set pow16_14_=224;3584;57344;917504;14680064;234881024;3758096384;60129542144&set pow16_15_=240;3840;61440;983040;15728640;251658240;4026531840;64424509440
for /f "tokens=7 delims=\" %%A in ('reg query "%key%"') do (for /f "tokens=1,2,3,4,5,6,7,8,9 delims=.-" %%B in ("%%A") do (if not "%%B"=="" (if not "%%C"=="" (if not "%%D"=="" (if not "%%E"=="" (if not "%%F"=="" (if not "%%G"=="" (if not "%%H"=="" (if not "%%I"=="" (if "%%J"=="" (for /f "tokens=3 skip=2" %%K in ('reg query "%key%\%%A" /v "Sid"') do (call:process_sid %%K))))))))))))
endlocal&set %1=%sids%&exit/b0
:process_sid
set sid=%1
set sid_0=%sid:~-42,2%&set sid_1=%sid:~-40,2%&set sid_2=%sid:~-26,2%%sid:~-28,2%%sid:~-30,2%%sid:~-32,2%&set sid_3=%sid:~-18,2%%sid:~-20,2%%sid:~-22,2%%sid:~-24,2%&set sid_4=%sid:~-10,2%%sid:~-12,2%%sid:~-14,2%%sid:~-16,2%&set sid_5=%sid:~-2,2%%sid:~-4,2%%sid:~-6,2%%sid:~-8,2%
:sid5
if "%sid_5:~0,1%"=="0" (set sid_5=%sid_5:~1%&goto sid5)
set/a iter+=1
set/a sid_0=0x%sid_0%*1
set/a sid_1=0x%sid_1%*1
set sid_2_0=%sid_2%
set sid_3_0=%sid_3%
set sid_4_0=%sid_4%
if defined tokenchain (call:checkifalreadycvted)
if "%sid_2_0%"=="%sid_2%" (call:sid16_10 %sid_2% sid_2)
if "%sid_3_0%"=="%sid_3%" (call:sid16_10 %sid_3% sid_3)
if "%sid_4_0%"=="%sid_4%" (call:sid16_10 %sid_4% sid_4)
if defined tokenchain (
 call:addtoken2ifnotinthetokenlist&call:addtoken3ifnotinthetokenlist&call:addtoken4ifnotinthetokenlist
) else (set tokenchain=%sid_2_0%+%sid_2%;%sid_3_0%+%sid_3%;%sid_4_0%+%sid_4%)
set/a sid_5=0x%sid_5%*1
set sid=S-1-%sid_0%-%sid_1%-%sid_2%-%sid_3%-%sid_4%-%sid_5%
for /f "tokens=3*" %%A in ('reg query "%key%\%sid%" /v "ProfileImagePath"') do (if not "%%B"=="" (set ProfileImagePath=%%A %%B) else (set ProfileImagePath=%%A))
set LoggedIn=False
set reported_username=
reg query "HKU\%sid%\Volatile Environment">nul 2>&1&&set LoggedIn=True&&reg query "HKU\%sid%\Volatile Environment" /v "USERNAME">nul 2>&1&&for /f "tokens=3*" %%A in ('reg query "HKU\%sid%\Volatile Environment" /v "USERNAME"') do (if not "%%B"=="" (set reported_username=%%A %%B) else (set reported_username=%%A))
if "%ProfileImagePath:~-1,1%"=="\" (set ProfileImagePath=%ProfileImagePath:~0,-1%)
if not defined reported_username (call:extract_the_deepest_dir_from_path ProfileImagePath reported_username)
if not defined sids (
 set sids="%sid%+%LoggedIn%+%reported_username%+%ProfileImagePath%"
) else (
 set sids=%sids%;"%sid%+%LoggedIn%+%reported_username%+%ProfileImagePath%"
)
exit/b0
:extract_the_deepest_dir_from_path
::syntax:  call:extract_the_deepest_dir_from_path path_var_name last_token_name
setlocal&set v1=&set v2=&set v0=%%%1%%&for /f "tokens=2 delims=^=" %%A in ('set v0') do (call set v0=%%A)
:etddfp_
set v1=[%v0:~-1,1%]
if not "%v1%"=="[\]" (set v2=%v1:~1,1%%v2%&set v0=%v0:~0,-1%&goto etddfp_) else (endlocal&set %2=%v2%&exit/b0)
:addtoken2ifnotinthetokenlist
for %%A in (%tokenchain%) do (for /f "tokens=1 delims=+" %%B in ("%%A") do (if "%%B"=="%sid_2_0%" (exit/b0)))
set tokenchain=%tokenchain%;%sid_2_0%+%sid_2%&exit/b0
:addtoken3ifnotinthetokenlist
for %%A in (%tokenchain%) do (for /f "tokens=1 delims=+" %%B in ("%%A") do (if "%%B"=="%sid_3_0%" (exit/b0)))
set tokenchain=%tokenchain%;%sid_3_0%+%sid_3%&exit/b0
:addtoken4ifnotinthetokenlist
for %%A in (%tokenchain%) do (for /f "tokens=1 delims=+" %%B in ("%%A") do (if "%%B"=="%sid_4_0%" (exit/b0)))
set tokenchain=%tokenchain%;%sid_4_0%+%sid_4%&exit/b0
:checkifalreadycvted
for /l %%A in (2,1,4) do (for /f "tokens=2 delims=^=" %%B in ('set sid_%%A_0') do (for %%C in (%tokenchain%) do (for /f "tokens=1,2 delims=+" %%D in ("%%C") do (if "%%D"=="%%B" (set sid_%%A=%%E)))))
exit/b0
:sid16_10
setlocal
set var=%1
set sum=0
set exp=-1
set base=16
:loop_
if not defined _var (
 set _var=%var:~-1%
) else (
 set _var=%_var%;%var:~-1%
)
set var=%var:~0,-1%
if defined var (goto loop_)
for %%A in (%_var%) do (call:loop %%A)
set n_=0
for %%A in (%chain%) do (set/a n_+=1)
if %n_% EQU 0 (goto:hextodec_out)
if %n_% LEQ 7 (call:sum_lesser&for /f "tokens=2* delims=^=" %%G in ('set component_') do (set sum=%%G)) else (call:sum_bigger)
:hextodec_out
endlocal&set %2=%sum%&exit/b0
:sum_bigger
call:sum_lesser
set chain=%component_%;%chain%
:sum_bigger_
for /f "tokens=1,2* delims=;" %%A in ("%chain%") do (set component=%%A&if "%%C" =="" (set chain=%%B) else (set chain=%%B;%%C))
if not "%component:~0,1%"=="0" (call:LargeInt_add sum component sum)
if defined chain (goto sum_bigger_)
exit/b0
:sum_lesser
for /f "tokens=1,2,3,4,5,6,7 delims=;" %%A in ("%chain%") do (call:sum_smaller_components %%A %%B %%C %%D %%E %%F %%G)
exit/b0
:sum_smaller_components
set/a component_+=%1
for /f "tokens=2* delims=;" %%H in ("%chain%") do (set chain=%%H;%%I)
shift
if not "%1"=="" (goto sum_smaller_components)
exit/b0
:loop
set num_=%1
if /i "%num_%"=="A" (set num_=10)
if /i "%num_%"=="B" (set num_=11)
if /i "%num_%"=="C" (set num_=12)
if /i "%num_%"=="D" (set num_=13)
if /i "%num_%"=="E" (set num_=14)
if /i "%num_%"=="F" (set num_=15)
set/a exp+=1
if %exp% GTR 0 (
 for /f "tokens=2* delims=^=" %%A in ('set pow16_%num_%_') do (for /f "tokens=%exp% delims=;" %%C in ("%%A;%%B") do (set num=%%C))
) else (set num=%num_%)
if defined chain (
 set chain=%chain%;%num%
) else (set chain=%num%)
exit/b0

:LargeInt_add
setlocal
set left=%% %1 %%
set left=%left: =%
call set left=%left%
set right=%% %2 %%
set right=%right: =%
call set right=%right%
if defined left (if defined right (goto lrgintadd))
set exitcode=1
goto lrgintadd_endproc
:lrgintadd
set buff=
set lastchar_l=
set lastchar_r=
if defined left (set lastchar_l=%left:~-1%)
if defined right (set lastchar_r=%right:~-1%)
if defined carry (set/a buff+=%carry%&set carry=)
if defined lastchar_l (set/a buff+=%lastchar_l%)
if defined lastchar_r (set/a buff+=%lastchar_r%)
if %buff% GTR 9 (
 set outvar=%buff:~-1%%outvar%
 set carry=%buff:~0,1%
) else (
 set outvar=%buff%%outvar%
)
if defined left (set left=%left:~0,-1%)
if defined right (set right=%right:~0,-1%)
if not defined left (if not defined right (set outvar=%carry%%outvar%&goto lrgintadd_opsucc))
goto lrgintadd
:lrgintadd_opsucc
set exitcode=0
:lrgintadd_endproc
call:ThrowErrorLevel exitcode %exitcode%
endlocal&set %3=%outvar%&exit/b%errorlevel%
:ThrowErrorLevel
if defined %1 set %1=
exit/b%2
The above variant is just a theoretical example, as it is terribly slow: it needs over 3 times (333%) the time the next one. The aim of writing it was to show that it is possible to handle hex values, plus properly converting them to decimal (this script can cope with DWORDs decimal value of which exceeds 2^31-1). It is slow, but it works, and is possible.
This one also gets data from the ProfileList key, but acts more lazily. It just gets user name from ProfileImagePath value of each existing key of the pattern of a "typical" SID, and takes the subkey name, which is believed to be always equal with what's in Sid value in that subkey.

My objective opinion on why did Microsoft decide to store SID in one place in two forms
I think it is that it could be faster for the OS to grab "raw" SID (in hexadecimal form) from a REG_BINARY value rather than to convert string SID (included in the key name) to hexadecimal form each time it's needed.

Here is the faster one.
@echo off
call:EnumerateProfileSids var
for %%A in (%var%) do (
 for /f "tokens=1,2,3,4 delims=+" %%B in (%%A) do (
  echo.
  echo  SID                  : %%B
  echo  Logged in            : %%C
  echo  Possible username    : %%D
  echo  Profile storage path : %%E
 )
)
pause
goto:eof
:EnumerateProfileSids
setlocal
set key=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
for /f "tokens=7 delims=\" %%A in ('reg query "%key%"') do (for /f "tokens=1,2,3,4,5,6,7,8,9 delims=.-" %%B in ("%%A") do (if not "%%B"=="" (if not "%%C"=="" (if not "%%D"=="" (if not "%%E"=="" (if not "%%F"=="" (if not "%%G"=="" (if not "%%H"=="" (if not "%%I"=="" (if "%%J"=="" (call:process_sid %%B-%%C-%%D-%%E-%%F-%%G-%%H-%%I)))))))))))
endlocal&set %1=%sids%&exit/b0
:process_sid
for /f "tokens=3*" %%A in ('reg query "%key%\%1" /v "ProfileImagePath"') do (if not "%%B"=="" (set ProfileImagePath=%%A %%B) else (set ProfileImagePath=%%A))
set LoggedIn=False
set reported_username=
reg query "HKU\%1\Volatile Environment">nul 2>&1&&set LoggedIn=True&&reg query "HKU\%1\Volatile Environment" /v "USERNAME">nul 2>&1&&for /f "tokens=3*" %%A in ('reg query "HKU\%1\Volatile Environment" /v "USERNAME"') do (if not "%%B"=="" (set reported_username=%%A %%B) else (set reported_username=%%A))
if "%ProfileImagePath:~-1,1%"=="\" (set ProfileImagePath=%ProfileImagePath:~0,-1%)
if not defined reported_username (call:extract_the_deepest_dir_from_path ProfileImagePath reported_username)
if not defined sids (
 set sids="%1+%LoggedIn%+%reported_username%+%ProfileImagePath%"
) else (
 set sids=%sids%;"%1+%LoggedIn%+%reported_username%+%ProfileImagePath%"
)
exit/b0
:extract_the_deepest_dir_from_path
::syntax:  call:extract_the_deepest_dir_from_path path_var_name last_token_name
setlocal&set v1=&set v2=&set v0=%%%1%%&for /f "tokens=2 delims=^=" %%A in ('set v0') do (call set v0=%%A)
:etddfp_
set v1=[%v0:~-1,1%]
if not "%v1%"=="[\]" (set v2=%v1:~1,1%%v2%&set v0=%v0:~0,-1%&goto etddfp_) else (endlocal&set %2=%v2%&exit/b0)


Rarely do I recommend others' work, but in this case that page assured me about my guesses.
A bit off-topic: I overtook the future a bit, because the slower variant of the function I described uses Hex2Dec procedure I am going to release. I have it ready, and I will publish it soon so please hold on from using sid16_10 because it is truncated for needs of the script. The original ("full") one supports numbers greater than 2^64.

Oct 7, 2013

Function: EnumerateLoggedOnSIDs

Bases on GetCurrentUserSID; retrieves SIDs of logged on users by matching their usernames to corresponding HKU registry subkeys. Testing in progress, confirmed working on XP and Windows 7. Code below may not be final.
@echo off
:: works globally; uses vars: sids, opsys, ocparam, skip, var, var0, var1, retv, username_for_sid, appdata_username, userprofile_username
:: contains GTweak procedures: OsCheck (modified); RegQueryValue (modified); IsReadable; IsRunWithElevatedRights, TruncateTrailingSpaces, MakeSemicolonSeparatedVariable (modified)
:: requires reg.exe; find.exe and OS >= Windows 2000
call:EnumerateLoggedOnSIDs securityid
for %%A in (%securityid%) do (for /f "tokens=1,2 delims=+" %%B in ('echo %%A') do (echo %%C = %%B))
pause
exit
:EnumerateLoggedOnSIDs
if not exist "%windir%\system32\reg.exe" (exit/b1)
reg add "HKLM\SOFTWARE\Microsoft\WBEM" /v "" /d "" /f>nul 2>&1||exit/b1
if not exist "%windir%\system32\find.exe" (exit/b1)
set sids=
call:OsCheck
set opsys=%errorlevel%
set ocparam=
for /f "tokens=2* delims=\" %%G in ('reg query HKU') do (call:checkifsid %%G)
set %1=%sids%
for %%A in (opsys sids skip var var1) do set %%A=
exit/b0
:checkifsid
set var0=%*
if not "%var0:~0,1%"=="S" (goto checkifsid_out)
if /i "%var0:~-8%"=="_Classes" (goto checkifsid_out)
for /f "tokens=1-8 delims=-" %%G in ('echo %var0%') do (
 if not "%%G"=="" (
  if not "%%H"=="" (
   if not "%%I"=="" (
    if not "%%J"=="" (
     if not "%%K"=="" (
      if not "%%L"=="" (
       if not "%%M"=="" (
        if not "%%N"=="" (
         call:assignsidtousername
        )
       )
      )
     )
    )
   )
  )
 )
)
:checkifsid_out
set var0=
exit/b0
:RegQueryValue
call:IsReadable %1 %2||exit/b1
for /f "%skip%*" %%G in ('reg query %1 /v %2') do (
 set retv=%%G %%H
)
call:TruncateTrailingSpaces retv
exit/b0
:IsReadable
reg query %1 /v %2>nul 2>&1&&exit/b0
exit/b1
:assignsidtousername
call:RegQueryValue "HKU\%var0%\Volatile Environment" "APPDATA"
set username_for_sid=
if %opsys% GEQ 4 (
 call:CompareUserNameCandidates
) else (
 call:ExtractUserName retv username_for_sid
 set retv=
)
if defined username_for_sid (echo.>nul) else (set username_for_sid=???)
call:MakeSemicolonSeparatedVariable "%username_for_sid%" "%var0%" sids
set username_for_sid=
exit/b0
:CompareUserNameCandidates
set appdata_username=%retv%
call:RegQueryValue "HKU\%var0%\Volatile Environment" "USERPROFILE"
set userprofile_username=%retv%&set retv=
call:ExtractUserName appdata_username appdata_username
call:ExtractUserName userprofile_username userprofile_username
if /i "%appdata_username%"=="%userprofile_username%" (set username_for_sid=%appdata_username%)
set userprofile_username=
set appdata_username=
exit/b0
:ExtractUserName
for /f "tokens=3 delims=\" %%G in ('set %1') do set %2=%%G
exit/b0
:OsCheck
for /f "tokens=3*" %%G in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v "ProductName"^|find "ProductName"') do set ocparam=%%G %%H
echo.%ocparam%|find "Windows 7">nul 2>&1&&set skip= tokens=3&&exit/b6
echo.%ocparam%|find "XP">nul 2>&1&&set skip=skip=4 tokens=3&&exit/b2
echo.%ocparam%|find "Vista">nul 2>&1&&set skip= tokens=3&&exit/b4
echo.%ocparam%|find "2003">nul 2>&1&&set skip= tokens=3&&exit/b3
echo.%ocparam%|find "2000">nul 2>&1&&set skip=skip=4 tokens=3&&exit/b1
echo.%ocparam%|find "2008">nul 2>&1&&set skip= tokens=3&&exit/b5
set skip= tokens=3
exit/b6
:TruncateTrailingSpaces
set var=[%% %1:~-1 %%]
set var=%var: =%
call set var=%var%
if not "%var%"=="[ ]" (set var=&set var1=&exit/b0) else (call:TruncateTrailingSpaces_2 %1&goto TruncateTrailingSpaces)
:TruncateTrailingSpaces_2
set var1=%% %1:~0,-1 %%
set var1=%var1: =%
call set %1=%var1%
exit/b0
:MakeSemicolonSeparatedVariable
set var=%% %3 %%
set var=%var: =%
if defined %3 (call set %3=%var%;%1+%2) else (set %3=%1+%2)
set var=
exit/b0

Update (October the 7th, 2013): I enhanced this script, as I did with GetCurrentUserSID. Tested/working in Windows XP and Windows 7.
@echo off
:: requires reg.exe and OS >= Windows 2000
call:EnumerateLoggedOnSIDs securityid_container
if %errorlevel%==0 (for %%A in (%securityid_container%) do (for /f "tokens=1,2 delims=+" %%B in (%%A) do (echo %%C = %%B)))
if %errorlevel%==1 (echo Required component missing.)
if %errorlevel%==2 (echo Required registry writes could not be performed or insufficient privileges.)
if %errorlevel%==3 (echo Unknown error, SIDs not found?)
pause
exit
:EnumerateLoggedOnSIDs
setlocal
if not exist "%windir%\system32\reg.exe" (set err=1&goto elosids_endproc)
reg add "HKLM\SOFTWARE\Microsoft\WBEM" /v "" /d "" /f>nul 2>&1||set err=2&&goto elosids_endproc
for /f "tokens=2* delims=\" %%G in ('reg query HKU') do (call:checkifsid %%G)
if defined sids (set err=0) else (set err=3)
:elosids_endproc
endlocal&set %1=%sids%&exit/b%err%

:checkifsid
set var0=%*
if "%var0:~0,1%"=="S" (if not "%var0:~-8%"=="_Classes" (for /f "tokens=1-8 delims=-" %%G in ("%var0%") do (if not "%%G"=="" (if not "%%H"=="" (if not "%%I"=="" (if not "%%J"=="" (if not "%%K"=="" (if not "%%L"=="" (if not "%%M"=="" (if not "%%N"=="" (for /f "tokens=3*" %%O in ('reg query "HKU\%var0%\Volatile Environment" /v "APPDATA"') do (if "%%P"=="" (for /f "tokens=3 delims=\" %%Q in ("%%O") do (call:makesidsvar %var0% %%Q)) else (for /f "tokens=3 delims=\" %%Q in ("%%O %%P") do (call:makesidsvar %var0% %%Q))))))))))))))
exit/b0
:makesidsvar
for /f "tokens=1,2*" %%A in ("%*") do (if "%%C"=="" (set sid=%%A&set usrname=%%B) else (set sid=%%A&set usrname=%%B %%C))
if defined sids (set sids=%sids%;"%usrname%+%sid%") else (set sids="%usrname%+%sid%")
exit/b0

Oct 6, 2013

Function: GetCurrentUserSID

Concept of getting the SID: write to HKCU, then crawl through HKU subkeys consisting of 8 tokens not ending with "_Classes", in search of a "test value", just see below.
Tested on Windows 2000, XP SP3, 2003, Vista SP2, Windows 7 SP0 x64.
There is one parameter to be given - name of the variable to which the SID will be written (name of the variable can not be one of these mentioned being used by the code).
@echo off
:: works globally; uses vars: sid; ocparam; buff; skip; var0; retv
:: contains GTweak procedures: OsCheck (modified); RegQueryValue; IsReadable; IsRunWithElevatedRights
:: requires reg.exe; find.exe and OS >= Windows 2000
call:GetCurrentUserSID securityid
echo CurrentUserSID = [%securityid%]
pause
exit
:GetCurrentUserSID
if not exist "%windir%\system32\reg.exe" (exit/b1)
reg add "HKLM\SOFTWARE\Microsoft\WBEM" /v "" /d "" /f>nul 2>&1||exit/b1
if not exist "%windir%\system32\find.exe" (exit/b1)
set sid=
call:OsCheck
set buff=%RANDOM%%RANDOM%%RANDOM%
reg add "HKCU" /v "removeme_markerval" /t "REG_SZ" /d "%buff%" /f>nul 2>&1||exit/b1
for /f "tokens=2* delims=\" %%G in ('reg query HKU') do (call:checkifsid %%G&&goto gcusid_0)
:gcusid_0
set %1=%sid%
for %%A in (buff sid skip) do set %%A=
exit/b0
:checkifsid
set var0=%*
if not "%var0:~0,1%"=="S" (goto checkifsid_out)
if /i "%var0:~-8%"=="_Classes" (goto checkifsid_out)
for /f "tokens=1-8 delims=-" %%G in ('echo %var0%') do (
 if not "%%G"=="" (
  if not "%%H"=="" (
   if not "%%I"=="" (
    if not "%%J"=="" (
     if not "%%K"=="" (
      if not "%%L"=="" (
       if not "%%M"=="" (
        if not "%%N"=="" (
         call:testsid
        )
       )
      )
     )
    )
   )
  )
 )
)
:checkifsid_out
set var0=
if defined sid (exit/b0) else (exit/b1)
:RegQueryValue
call:IsReadable %1 %2||exit/b1
for /f "%skip%" %%G in ('reg query %1 /v %2') do (
 set retv=%%G
)
exit/b0
:IsReadable
reg query %1 /v %2>nul 2>&1&&exit/b0
exit/b1
:testsid
call:RegQueryValue "HKU\%var0%" "removeme_markerval"
if "%retv%"=="%buff%" (
 reg delete "HKU\%var0%" /v "removeme_markerval" /f>nul 2>&1
 set sid=%var0%
)
set retv=
exit/b0
:OsCheck
for /f "tokens=3*" %%G in ('reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion" /v "ProductName"^|find "ProductName"') do set ocparam=%%G %%H
echo.%ocparam%|find "Windows 7">nul 2>&1&&set skip= tokens=3&&exit/b0
echo.%ocparam%|find "XP">nul 2>&1&&set skip=skip=4 tokens=3&&exit/b0
echo.%ocparam%|find "Vista">nul 2>&1&&set skip= tokens=3&&exit/b0
echo.%ocparam%|find "2003">nul 2>&1&&set skip= tokens=3&&exit/b0
echo.%ocparam%|find "2000">nul 2>&1&&set skip=skip=4 tokens=3&&exit/b0
echo.%ocparam%|find "2008">nul 2>&1&&set skip= tokens=3&&exit/b0
set skip= tokens=3
set ocparam=
exit/b0

Update (October the 6th, 2013): I enhanced the script. You needn't worry about variables - now the script works locally. Tested/working in Windows 2000, Windows XP, Windows 7 and Windows 8.
@echo off
:: requires reg.exe and OS >= Windows 2000
call:GetCurrentUserSID securityid
if %errorlevel%==0 (echo CurrentUserSID = [%securityid%])
if %errorlevel%==1 (echo Required component missing.)
if %errorlevel%==2 (echo Required registry writes could not be performed or insufficient privileges.)
if %errorlevel%==3 (echo Unknown error, SID not found?)
pause
goto:eof
:GetCurrentUserSID
setlocal
if not exist "%windir%\system32\reg.exe" (set err=1&goto gcusid_endproc)
reg add "HKLM\SOFTWARE\Microsoft\WBEM" /v "" /d "" /f>nul 2>&1||set err=2&&goto gcusid_endproc
set buff=%RANDOM%%RANDOM%%RANDOM%
reg add "HKCU" /v "removeme_markerval" /t "REG_SZ" /d "%buff%" /f>nul 2>&1||set err=2&&goto gcusid_endproc
for /f "tokens=2* delims=\" %%G in ('reg query HKU') do (if not defined sid_found (call:checkifsid %%G))
if defined sid (set err=0) else (set err=3)
:gcusid_endproc
endlocal&set %1=%sid%&exit/b%err%

:checkifsid
set var0=%*
if "%var0:~0,1%"=="S" (if not "%var0:~-8%"=="_Classes" (for /f "tokens=1-8 delims=-" %%G in ("%var0%") do (if not "%%G"=="" (if not "%%H"=="" (if not "%%I"=="" (if not "%%J"=="" (if not "%%K"=="" (if not "%%L"=="" (if not "%%M"=="" (if not "%%N"=="" (for /f "tokens=3" %%O in ('reg query "HKU\%var0%" /v "removeme_markerval"') do (if "%%O"=="%buff%" (set sid=%var0%&set sid_found=1&reg delete "HKU\%var0%" /v "removeme_markerval" /f>nul 2>&1)))))))))))))
exit/b0