Page 1 of 1 1
Topic Options
#128970 - 2004-11-03 04:58 PM Using ADO to convert to / from BYTE arrays.
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4945
Loc: Leatherhead, Surrey, UK
As you will know, KiXtart does not handle bytes which mean that manipulating binary objects (and/or files) is a bit of a problem.

Specifically I needed to convert a binary SID to it's string value.

To this end, I've created a series of UDFs which will allow the manipulation of byte arrays.

These UDFs require ADO 2.5 - I think that this is ubiquitous for Windows installations now, but if this is not the case then please let me know.

This example displays all groups and user with their associated SID:
Code:
Break ON

$=SetOption("Explicit","ON")
$=SetOption("WrapAtEOL","ON")

Dim $sDomain,$oDomain,$oGroup,$sGroupPath,$avSID,$aiBinarySID,$i

$sDomain="YOUR_DOMAIN_HERE"
$oDomain=GetObject("WinNT://"+$sDomain)
$oDomain.Filter="group",""
"GROUP SIDS: " ?
For Each $oGroup In $oDomain
$avSID=$oGroup.GetEx("objectSID")
$aiBinarySID=udfBytes2Array($avSID[0])
$oGroup.Name+", SID="+udfSID2String($aiBinarySID) ?
Next

$oDomain.Filter="user",""
"USER SIDS: " ?
For Each $oGroup In $oDomain
$avSID=$oGroup.GetEx("objectSID")
$aiBinarySID=udfBytes2Array($avSID[0])
$oGroup.Name+", SID="+udfSID2String($aiBinarySID) ?
Next

$oDomain=0
$oGroup=0
Exit 0

; Convert a SID in binary format to SDDL format
; Note, I cheat here with the 48 bit authority value.
; It works though ;)
Function udfSID2String($aiSID)
Dim $i,$dAuth

$udfSID2String="S-"+$aiSID[0]+"-"+$aiSID[1]+"-"+$aiSID[8]
For $i = 12 To UBound($aiSID) Step 4
$dAuth=CDbl($aiSid[$i+3])
$dAuth=$dAuth*256+CDbl($aiSid[$i+2])
$dAuth=$dAuth*256+CDbl($aiSid[$i+1])
$dAuth=$dAuth*256+CDbl($aiSid[$i+0])
$udfSID2String=$udfSID2String+"-"+CStr($dAuth)
Next
EndFunction



These are the binary / int conversion routines:
Code:
; Convert an array of bytes to an array of integers

Function udfBytes2Array($abBytes)
Dim $oStream,$adTypeBinary,$adTypeText,$i

$adTypeBinary=1

$oStream=CreateObject("ADODB.Stream")
If @ERROR Exit @ERROR EndIf

$oStream.Type=$adTypeBinary
$oStream.Open

$oStream.Write($abBytes)
$oStream.Position=0

Redim Preserve $udfBytes2Array[$oStream.Size-1]

For $i = 0 To UBound($udfBytes2Array)
$udfBytes2Array[$i]=Asc($oStream.Read(1))
Next

$oStream=0

Exit 0
EndFunction

; Convert an array of integers to an array of bytes
Function udfArray2Bytes($aiBytes,Optional $iBytesToConvert)
Dim $oStream,$adTypeBinary,$adTypeText,$i

$adTypeBinary=1
$adTypeText=2

If Not $iBytesToConvert $iBytesToConvert=UBound($aiBytes)+1 EndIf

$oStream=CreateObject("ADODB.Stream")
If @ERROR Exit @ERROR EndIf

$oStream.Type=$adTypeBinary
$oStream.Open

For $i = 1 To $iBytesToConvert
$oStream.Write(udfIntToByte($aiBytes[$i-1]))
Next

$oStream.Position=0
$oStream.Type=$adTypeBinary
$udfArray2Bytes=$oStream.Read($iBytesToConvert)

Exit 0
EndFunction

; Convert a single integer to a byte array
Function udfIntToByte($i)
Dim $oStream,$adTypeBinary,$adTypeText

$adTypeBinary=1
$adTypeText=2

$oStream=CreateObject("ADODB.Stream")
If @ERROR Exit @ERROR EndIf

$i=CInt($i) & 255

$oStream.Type=$adTypeText
$oStream.CharSet="unicode"
$oStream.Open
$oStream.WriteText(" "+Chr($i))
$oStream.Position=0
$oStream.Type=$adTypeBinary

If $i
$oStream.Position=$oStream.Size-2
Else
$oStream.Position=$oStream.Size-1
EndIf
$udfIntToByte=$oStream.Read(1)
Exit 0

EndFunction


Top
#128971 - 2004-11-03 05:46 PM Re: Using ADO to convert to / from BYTE arrays.
Les Offline
KiX Master
*****

Registered: 2001-06-11
Posts: 12734
Loc: fortfrances.on.ca
Have you looked at my GetSID() UDF? It converts a binary SID to it's string value.
_________________________
Give a man a fish and he will be back for more. Slap him with a fish and he will go away forever.

Top
#128972 - 2004-11-04 09:43 AM Re: Using ADO to convert to / from BYTE arrays.
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4945
Loc: Leatherhead, Surrey, UK
Yes I did and the Google trail that it started led to information that I used to create these UDFs , however your UDF requires a DLL from one of the SDKs and I was keen to avoid that.

The ADO requirement is more easy to fulfil.

Additionally, these routines allow the manipulation of any binary data in KiXtart - binary files, network IO and so-on. Anything that can be presented as a byte array.

Top
#195054 - 2009-07-27 10:03 AM Re: Using ADO to convert to / from BYTE arrays. [Re: Richard H.]
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4945
Loc: Leatherhead, Surrey, UK
Don't use these routines at present, one of them has a bug.

I just created a test suite which converts all 0-255 bytes to a byte array and then back again to a standard KiXtart integer arrary to make sure that the functions still work OK.

There is a problem with integers 128 - 159.

I'm not sure yet which of the routines is failing, though I've got a pretty good idead which one and why. I'll work on them as soon as I get some free time.

Top
#204505 - 2012-03-16 07:53 PM Re: Using ADO to convert to / from BYTE arrays. [Re: Richard H.]
Lonkero Administrator Offline
KiX Master Guru
*****

Registered: 2001-06-05
Posts: 22335
Loc: OK
int to byte?
_________________________
!

download KiXnet

Top
#204507 - 2012-03-17 12:40 PM Re: Using ADO to convert to / from BYTE arrays. [Re: Lonkero]
It_took_my_meds Offline
Hey THIS is FUN
*****

Registered: 2003-05-07
Posts: 273
Loc: Sydney, Australia
Please check out Extract icon from resource file. There is a bytes.bin file that I created attached that you can use to convert int to byte using Adodb.Stream.
Top
#209578 - 2014-10-23 04:19 PM Re: Using ADO to convert to / from BYTE arrays. [Re: It_took_my_meds]
PapaZod Offline
Fresh Scripter

Registered: 2006-07-07
Posts: 5
Loc: Ottawa, Canada
This is a great thread and thanks for the ideas. One thing I noted is that often the token list is used for comparison to a group objectSID. This being the case, and that arrays are difficult to compare, I rewrote the udfs to produce strings and not arrays. This way you can simply do a single conversion, and compare the HEX strings instead of having to convert all the way to the standard SID format before comparison.

I've included the full script which uses the new "string" routines. This *should* run "As Is":

 Code:
$ADS_NAME_TYPE_NT4 = 3
$ADS_NAME_TYPE_1779 = 1

$rootDSE = GetObject("LDAP://RootDSE")
$DomainContainer = $rootDSE.Get("defaultNamingContext")
$DomainShortName = Split(Split($DomainContainer,",")[0],"=")[1]
$CurrentUser = @USERID
$NameTrans = CreateObject("nametranslate")
$NameTrans.set($ADS_NAME_TYPE_NT4, $DomainShortName + "\" + $CurrentUser)
$DN = $NameTrans.get($ADS_NAME_TYPE_1779)
$oUser = GetObject("LDAP://" + $DN)
$oUser.GetInfo
$arrTG = "tokengroups",""
$oUser.GetInfoEx($arrTG, 0)
$GroupList = $oUser.GetEx("tokengroups")

? "" + (ubound($GroupList)+1) + " entries returned"
?"Listing groups"?
For $i = 0 to ubound($GroupList)
	$hexSID = OctetToHexStr($GroupList[$i])
	$sSID = HexSID2DecString($hexSID)
	$bindSID = "LDAP://<SID=" + $sSID + ">"
	$oObject = GetObject($bindSID)
	if not @ERROR
		$Pad = ""
		if len($sSID) < 47
			for $j = 1 to (47 - len($sSID))
				$Pad = $Pad + " "
			Next
		endif
		$CN = $oObject.Get("cn")
		? $sSID + " " + $Pad + $CN
	endif
Next
?
Exit 0

Function HexSID2DecString($sSID)
	; Convert a Hex string SID to the Decimal String representation
	; S-1-5-21-....
	Dim $i, $j, $arrbytSID[], $lngTemp
	
	ReDim $arrbytSID[(Len($sSID)/2) - 1]
	For $j = 0 To UBound($arrbytSID)
		$arrbytSID[$j] = Val("&" + Substr($sSID, (2 * $j) + 1, 2))
	Next
	
	$HexSID2DecString = "S-" + CStr($arrbytSID[0]) + "-" + CStr($arrbytSID[1]) + "-" + CStr($arrbytSID[8])
	For $i = 12 To UBound($arrbytSID) Step 4
		$lngTemp = CDbl($arrbytSID[$i + 3])
		$lngTemp = $lngTemp * 256 + CDbl($arrbytSID[$i + 2])
		$lngTemp = $lngTemp * 256 + CDbl($arrbytSID[$i + 1])
		$lngTemp = $lngTemp * 256 + CDbl($arrbytSID[$i])
		$HexSID2DecString = $HexSID2DecString + "-" + CStr($lngTemp)
	Next

EndFunction

Function OctetToHexStr($abBytes)
	; Convert the SID byte array to a HEX
	; string representation of the SID
	;
	; Uses ADO.Stream for data type conversion
	; because kiXtart can't handle typed arrays
	
	Dim $oStream,$adTypeBinary,$i

	$adTypeBinary = 1
	$oStream = CreateObject("ADODB.Stream")

	If @ERROR 
		? "error creating stream"
		Exit @ERROR
	EndIf
	$oStream.Type = $adTypeBinary
	$oStream.Open

	$oStream.Write($abBytes)
	$oStream.Position=0
	
	$OctetToHexStr = ""
	For $i = 0 To $oStream.size - 1
		$OctetToHexStr = $OctetToHexStr + Right("0" + CStr(DecToHex(CDbl(Asc($oStream.Read(1))))),2)
	Next

	$oStream=0
EndFunction



Edited by Mart (2014-10-23 04:30 PM)
Edit Reason: Please use code tags when posting code.
_________________________
Tim

Life is pleasant, death is peacful.
It's the transition that's troublesome.
-- Isaac Azimov

Top
Page 1 of 1 1


Moderator:  Shawn, ShaneEP, Arend_, Jochen, Radimus, Glenn Barnas, Allen, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 180 anonymous users online.
Newest Members
diefnet, Arogya, gkustra, emnipetro, Hirze
17644 Registered Users

Generated in 0.056 seconds in which 0.016 seconds were spent on a total of 13 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org