Sign in to follow this  
Followers 0
ECHAIGNE

Use of DllStruct and byte[xxx]

16 posts in this topic

Hi,

excuse me for my bad English.

With an aim of writing programs of migration, I try to find the SID binary of a user starting from his account, to transform this SID into format text then to return in arrear, i.e. to find the account starting from the conversion of the SID text into binary SID then to find the account to use associated with the binary SID (I need the binary SID to treat the SID history)

The program listed below functions but, so that the late return functions, I must carry out the conversion of a field of structure of the type byte [256] which is not useful to me then any more in string (line surrounded by ***)

Do you have an idea on the fact of converting a value which is not useful any more after transformation, in order to make function the code located apart from the function?

Thank you by advance

AutoItSetOption("MustDeclareVars", 1)

AutoItSetOption("RunErrorsFatal", 0)

AutoItSetOption("TrayIconDebug", 1)

; src of include under http://www.autoitscript.com/forum/index.php?showtopic=33677

#include <A3LLibrary.au3>

#include <A3LSecurity.au3>

Const $Debug = 0

Test()

Exit

Func Test()

Local $TestSID

$TestSID = TrouveSID(@computername & "\eric")

MsgBox(4096, "Trouve SID", "SID trouvé=" & $TestSID)

If $TestSID <> "" Then

MsgBox(4096, "Account trouvé", AccountFromSID($TestSID))

EndIf

_DllClose ()

EndFunc ;==>Test

; Trouve le SID texte d'un compte

; Entrée : Compte à décomposer (Domaine\Compte)

; Retourne une chaine contenant le SID au format texte (de type : S-1-5-21-1960408961-583907252-839522115-26511)

Func TrouveSID($AccountATrouver)

Local $SIDstr = ""

Local $Result = _LookupAccountName ($AccountATrouver)

Local $OK = DllStructGetData($Result, 1)

Local $pSID = DllStructGetPtr($Result, 2)

Local $Domain = DllStructGetData($Result, 3)

Local $SIDtype = DllStructGetData($Result, 4)

If IsValidSID(DllStructGetPtr($Result, 2)) Then

If $Debug Then

MsgBox(4096, "_LookupAccountName", "OK=" & $OK & @LF & "Domain=" & $Domain & @LF & "Type de SID=" & $SIDtype & @LF & "SID binaire=" & String(DllStructGetData($Result, 2)) & @LF & "Longueur du SID=" & LngSID(DllStructGetPtr($Result, 2)))

EndIf

$SIDstr = SIDtoStr($pSID)

; ****************************************************************************************************

*****************

; Si cette ligne n'est pas présente (ou si la valeur $Debug est à 0), le code inverse ne fonctionne pas (récupération du compte à partir du SID) ???????

; If this line is not present (or if the value $Debug is with the 0), the opposite code does not function (recovery of the account starting from the SID)???????

; ****************************************************************************************************

*****************

Local $BinSID = String(DllStructGetData($Result, 2))

; ****************************************************************************************************

*****************

$Result = 0

Return $SIDstr

Else

SetError(1)

Return ""

EndIf

EndFunc ;==>TrouveSID

; Trouve le compte lié à un SID texte

; Entrée : SID au format texte (ex : S-1-5-21-1960408961-583907252-839522115-26511)

; Retourne une chaine contenant Domaine\Compte

Func AccountFromSID($SID)

Local $pSIDbin = TrouveSIDbin($SID)

If $pSIDbin <> "" Then

Local $Result = _LookupAccountSid ($pSIDbin)

Local $OK = DllStructGetData($Result, 1)

Local $Account = DllStructGetData($Result, 2)

Local $Domain = DllStructGetData($Result, 3)

Local $SIDtype = DllStructGetData($Result, 4)

If $Debug Then

MsgBox(4096, "_LookupAccountSid", "OK=" & $OK & @LF & "Domain=" & $Domain & @LF & "Type SID=" & $SIDtype & @LF & "Account=" & $Account)

EndIf

Return $Domain & "\" & $Account

Else

SetError(1)

Return ""

EndIf

EndFunc ;==>AccountFromSID

; Trouve le SID binaire d'un SID texte

; Entrée : SID au format texte (ex : S-1-5-21-1960408961-583907252-839522115-26511)

; Retourne un pointeur sur le SID binaire

Func TrouveSIDbin($SID)

Local $SIDstr = _DllStructCreate ("ptr;byte[256];char[256]")

Local $pSID = _DllStructGetPtr ($SIDstr, 1)

Local $pSIDbin = _DllStructGetPtr ($SIDstr, 2)

Local $pSIDstr = _DllStructGetPtr ($SIDstr, 3)

_DllStructSetData ($SIDstr, 3, $SID)

Local $hAdvAPI32 = _DllOpen ("AdvAPI32.dll")

Local $aResultinv = DllCall($hAdvAPI32, "int", "ConvertStringSidToSid", "ptr", $pSIDstr, "ptr", $pSID)

_Check ("ConvertStringSidToSid:DllCall", @error, @error)

Local $ppSIDstr = DllStructGetData($SIDstr, 1)

CopyMemory($ppSIDstr, $pSIDbin, 256)

If IsValidSID($pSIDbin) Then

If $Debug Then

MsgBox(4096, "ConvertStringSidToSid", "SID binaire=" & String(DllStructGetData($SIDstr, 2)) & @LF & "Longueur du SID=" & LngSID($pSIDbin))

EndIf

If $aResultinv[0] <> 0 Then

Return $pSIDbin

Else

Return ""

EndIf

Else

Return ""

EndIf

EndFunc ;==>TrouveSIDbin

; Trouve la longueur d'un SID binaire

; Enrée : Pointeur sur le SID binaire

; Retourne la longueur du SID

Func LngSID($pBinSID)

Local $hAdvAPI32 = _DllOpen ("AdvAPI32.dll")

Local $LngSID = DllCall($hAdvAPI32, "int", "GetLengthSid", "ptr", $pBinSID)

_Check ("GetLengthSid:DllCall", @error, @error)

Return $LngSID[0]

EndFunc ;==>LngSID

; Vérifie si un SID binaire est valide

; Enrée : Pointeur sur le SID binaire

; Retourne True ou False

Func IsValidSID($pBinSID)

Local $hAdvAPI32 = _DllOpen ("AdvAPI32.dll")

Local $ValidSID = DllCall($hAdvAPI32, "int", "IsValidSid", "ptr", $pBinSID)

_Check ("IsValidSid:DllCall", @error, @error)

Return $ValidSID[0] <> 0

EndFunc ;==>IsValidSID

; Copie un emplacement mémoire à un autre emplacement

; Entrée : Pointeur sur la source, pointeur sur la destination, longueur à déplacer

Func CopyMemory(ByRef $Source, ByRef $Destination, $Lng)

Local $hKernel32 = _DllOpen ("kernel32.dll")

DllCall($hKernel32, "none", "RtlMoveMemory", "long", $Destination, "ptr", $Source, "long", $Lng)

_Check ("RtlMoveMemory:DllCall", @error, @error)

If Not @error Then

Return 1

Else

Return 0

EndIf

EndFunc ;==>CopyMemory

; Converti un SID binaire en un SID texte

; Enrée : Pointeur sur le SID binaire

; Retourne le SID au format texte (ex: S-1-5-21-1960408961-583907252-839522115-26511)

Func SIDtoStr($pBinSID)

Local $Result = ""

Local $SIDstr = _DllStructCreate ("ptr;char[256]")

Local $pSID = _DllStructGetPtr ($SIDstr, 1)

Local $pSIDstr = _DllStructGetPtr ($SIDstr, 2)

Local $hAdvAPI32 = _DllOpen ("AdvAPI32.dll")

Local $aResult = DllCall($hAdvAPI32, "int", "ConvertSidToStringSid", "ptr", $pBinSID, "ptr", $pSID)

_Check ("ConvertSidToStringSid:DllCall", @error, @error)

Local $ppSIDstr = DllStructGetData($SIDstr, 1)

CopyMemory($ppSIDstr, $pSIDstr, 256)

If $aResult[0] <> 0 Then

$Result = DllStructGetData($SIDstr, 2)

$SIDstr = ""

Return $Result

Else

Return ""

EndIf

EndFunc ;==>SIDtoStr

Share this post


Link to post
Share on other sites



Since you're using code from Auto3Lib, I might be able to help you. Unfortunately, your English is so broken that I can't understand what you need help with. Is the problem you are having that you don't understand how to convert the SID into a string?


Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

Since you're using code from Auto3Lib, I might be able to help you. Unfortunately, your English is so broken that I can't understand what you need help with. Is the problem you are having that you don't understand how to convert the SID into a string?

If you to test the code by remplacant the line "$TestSID = TrouveSID(@computername & "\eric")" by $TestSID = TrouveSID(@computername & "\Your account") under 3 tests:

1: Just as it is ==> OK

2: To comment on the line "Local $BinSID = String(DllStructGetData($Result, 2))" ==> KO

3: To place $Debug at 1 (what amounts using the order used by the line "Local $BinSID = String(DllStructGetData($Result, 2))" ==> OK

Conclusion: I do not understand why the fact of placing the code "Local $BinSID = String(DllStructGetData($Result, 2))" allows to make function the remainder of the program correctly whereas the structure is not used elsewhere than in the function ?

Thank you for your answer

Eric

Share this post


Link to post
Share on other sites

Ok, I think I see what the problem is. The Auto3Lib functions are returning structures and I've had problems in the past with doing this. I've converted the calls so that they return arrays and that seems to fix the problem. The new functions will be released in the next day or two.


Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Ok, I think I see what the problem is. The Auto3Lib functions are returning structures and I've had problems in the past with doing this. I've converted the calls so that they return arrays and that seems to fix the problem. The new functions will be released in the next day or two.

Thank you, I await your new version in order to update my code but you could perhaps include the functions of transformation of SID text --> binary and vice versa in your librairy.

I believe that these functions could be useful to several people?

Edited by ECHAIGNE

Share this post


Link to post
Share on other sites

Thank you, I await your new version in order to update my code but you could perhaps include the functions of transformation of SID text --> binary and vice versa in your librairy.

I believe that these functions could be useful to several people?

A new release is out with the features that you requested.

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

A new release is out with the features that you requested.

Thank youPaul, I tested and your new code functions with wonder.

I will have some ideas on functions to add to your librairie, which exists in VBS but not in AutoIt, for example ==>

- TypeName (the type of value of a variable returns)

- IsEmpty (Indicates if a variable is empty)

- Data conversion resulting from requests LDAP i.e. $objUser.SIDhistory: I manage to treat the result via code VBS integrated in my AutoIt script but not in pure AutoIt. there must be method which I do not manage to find

...

Bye

Eric

Share this post


Link to post
Share on other sites

Thank youPaul, I tested and your new code functions with wonder.

I will have some ideas on functions to add to your librairie, which exists in VBS but not in AutoIt, for example ==>

- TypeName (the type of value of a variable returns)

- IsEmpty (Indicates if a variable is empty)

- Data conversion resulting from requests LDAP i.e. $objUser.SIDhistory: I manage to treat the result via code VBS integrated in my AutoIt script but not in pure AutoIt. there must be method which I do not manage to find

...

Bye

Eric

Hey guy ! i'm happy to see another man playing with SIDs ^^

but like you, i had to pass by vbs script to convert sid to text

I've already asked PaulIA if it would be possible to this with some APIs, but at this time, he couldn't

but now, if he can, retrieve the sid history would be really good, for migration purpose, or token group, for "group of group" dependency

for now, i'm really waiting for paulIA solution, i will take a look at his last AutoItLib

this man is a genius, you know ?


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

I put the Sid --> Text and Text --> Sid in the latest release along with a few of the other Sid functions. There are a ton of security functions, so I doubt I'll get around to coding them all right away. However, if you have a need for some of the other ones, just PM or email me and I'll see what I can do to help you out.


Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

I put the Sid --> Text and Text --> Sid in the latest release along with a few of the other Sid functions. There are a ton of security functions, so I doubt I'll get around to coding them all right away. However, if you have a need for some of the other ones, just PM or email me and I'll see what I can do to help you out.

Hi,

I still subject a problem of conversion: When one carries out requests LDAP to recover, for example, the SID or SIDhistory, the type of turned over value is Byte().

How used this type of value directly in AutoIt, without passing by routines of binary conversion towards string then string towards structures (see TestConversion function)

AutoItSetOption("MustDeclareVars", 1)

AutoItSetOption("RunErrorsFatal", 0)

AutoItSetOption("TrayIconDebug", 1)

; src : http://www.autoitscript.com/forum/index.php?showtopic=33677

#include <A3LLibrary.au3>

#include <A3LSecurity.au3>

Const $Debug = 0

Global $vbs

DeclareFuncVBS()

Test()

Exit

Func Test()

Local $TestSID, $pSID

Local $objUser = ObjGet("LDAP://cn=CHAIGNE Eric,ou=users,ou=test,dc=Domaine,dc=fr")

Local $arrbytSids, $arrbytSidsHist

$arrbytSids = $objUser.objectSid

$arrbytSidsHist = $objUser.SIDHistory

TestSID($arrbytSids)

TestSID($arrbytSidsHist)

EndFunc ;==>Test

Func TestSID($arrbytSids)

If IsEmpty($arrbytSids) Then

MsgBox(0, "Test", "Pas de SID")

Else

If TypeName($arrbytSids) = "Byte()" Then

TestConversion($arrbytSids)

Else

For $j = 0 To UBound($arrbytSids) - 1

TestConversion($arrbytSids[$j])

Next

EndIf

EndIf

EndFunc ;==>TestSID

Func TestConversion($arrbytSids)

; Essai avec des fonctions de conversion

MsgBox(0, "Test conversion", OctetToHexStr($arrbytSids) & @LF & HexStrToDecStr(OctetToHexStr($arrbytSids)) & @LF & AccountFromSID(HexStrToDecStr(OctetToHexStr($arrbytSids))))

; Essai avec des structures et des appels de fonctions

Local $BinSID = OctetToHexStr($arrbytSids)

; How to use the value arrbytSids directly for creating structure ?????????????????????????????????????????

Local $rSID = DllStructCreate("byte[" & StringLen($BinSID) / 2 & "]")

Local $pSID = DllStructGetPtr($rSID)

Local $j = 1

For $i = 1 To StringLen($BinSID) Step 2

DllStructSetData($rSID, 1, Dec(StringMid($BinSID, $i, 2)), $j)

$j += 1

Next

MsgBox(0, "Test structures", _ConvertSidToStringSid ($pSID))

EndFunc ;==>TestConversion

; Trouve le SID texte d'un compte

; Entrée : Compte à décomposer (Domaine\Compte)

; Retourne une chaine contenant le SID au format texte (de type : S-1-5-21-1960408961-583907252-839522115-26511)

Func TrouveSID($AccountATrouver)

Local $SIDstr = ""

Local $Result = _LookupAccountName ($AccountATrouver)

Local $OK = $Result[0]

If $OK Then

Local $SID = $Result[1]

Local $Domain = $Result[2]

Local $SIDtype = _ConvertSidTypeToStr ($Result[3])

If $Debug Then

MsgBox(4096, "_LookupAccountName", "OK=" & $OK & @LF & "Domain=" & $Domain & @LF & "Type de SID=" & $SIDtype & @LF & "SID=" & $SID)

EndIf

Return $SID

Else

SetError(1)

Return ""

EndIf

EndFunc ;==>TrouveSID

; Trouve le compte lié à un SID texte

; Entrée : SID au format texte ou pointeur sur une structure binaire

; Retourne une chaine contenant Domaine\Compte

Func AccountFromSID($SID)

Local $Result = _LookupAccountSid ($SID)

Local $OK = $Result[0]

If $OK Then

Local $Account = $Result[1]

Local $Domain = $Result[2]

Local $SIDtype = _ConvertSidTypeToStr ($Result[3])

If $Debug Then

MsgBox(4096, "_LookupAccountSid", "OK=" & $OK & @LF & "Domain=" & $Domain & @LF & "Type SID=" & $SIDtype & @LF & "Account=" & $Account)

EndIf

Return $Domain & "\" & $Account

Else

SetError(1)

Return ""

EndIf

EndFunc ;==>AccountFromSID

Func DeclareFuncVBS()

Local $s_Quotes = '"'

Local $code

$code = "Function vbsOctetToHexStr(arrbytOctet)"

$code = $code & @CRLF & "Dim k"

$code = $code & @CRLF & "OctetToHexStr = """""

$code = $code & @CRLF & "For k = 1 To LenB(arrbytOctet)"

$code = $code & @CRLF & "vbsOctetToHexStr = vbsOctetToHexStr & Right(""0"" & Hex(Ascb(Midb(arrbytOctet, k, 1))), 2)"

$code = $code & @CRLF & "Next"

$code = $code & @CRLF & "end Function"

$vbs = ObjCreate("ScriptControl")

$vbs.language = "vbscript"

$vbs.addcode ($code)

$code = "Function vbsTypeName(VarName)"

$code = $code & @CRLF & "vbsTypeName = TypeName(VarName)"

$code = $code & @CRLF & "end Function"

$vbs.addcode ($code)

$code = "Function vbsIsEmpty(VarName)"

$code = $code & @CRLF & "vbsIsEmpty = IsEmpty(VarName)"

$code = $code & @CRLF & "end Function"

$vbs.addcode ($code)

$code = "Function vbsLenB(VarName)"

$code = $code & @CRLF & "vbsLenB = LenB(VarName)"

$code = $code & @CRLF & "end Function"

$vbs.addcode ($code)

EndFunc ;==>DeclareFuncVBS

Func OctetToHexStr($arrbytOctet)

Local $retour = $vbs.run ("vbsOctetToHexStr", $arrbytOctet)

Return $retour

EndFunc ;==>OctetToHexStr

Func TypeName($VarName)

Local $retour = $vbs.run ("vbsTypeName", $VarName)

Return $retour

EndFunc ;==>TypeName

Func IsEmpty($VarName)

Local $retour = $vbs.run ("vbsIsEmpty", $VarName)

Return $retour

EndFunc ;==>IsEmpty

Func LenB($VarName)

Local $retour = $vbs.run ("vbsLenB", $VarName)

Return $retour

EndFunc ;==>LenB

Func HexStrToDecStr($strSid)

Local $Return = ""

; Function to convert Sid value in hex format

; to decimal display format.

Dim $arrbytSid[1], $lngTemp, $j

ReDim $arrbytSid[stringLen($strSid) / 2 - 1]

For $j = 0 To UBound($arrbytSid) - 1

$arrbytSid[$j] = Number("0x" & StringMid($strSid, 2 * $j + 1, 2))

Next

$Return = "S-" & $arrbytSid[0] & "-" & $arrbytSid[1] & "-" & $arrbytSid[8]

$lngTemp = $arrbytSid[15]

$lngTemp = $lngTemp * 256 + $arrbytSid[14]

$lngTemp = $lngTemp * 256 + $arrbytSid[13]

$lngTemp = $lngTemp * 256 + $arrbytSid[12]

$Return = $Return & "-" & String($lngTemp)

$lngTemp = $arrbytSid[19]

$lngTemp = $lngTemp * 256 + $arrbytSid[18]

$lngTemp = $lngTemp * 256 + $arrbytSid[17]

$lngTemp = $lngTemp * 256 + $arrbytSid[16]

$Return = $Return & "-" & String($lngTemp)

$lngTemp = $arrbytSid[23]

$lngTemp = $lngTemp * 256 + $arrbytSid[22]

$lngTemp = $lngTemp * 256 + $arrbytSid[21]

$lngTemp = $lngTemp * 256 + $arrbytSid[20]

$Return = $Return & "-" & String($lngTemp)

$lngTemp = $arrbytSid[25]

$lngTemp = $lngTemp * 256 + $arrbytSid[24]

$Return = $Return & "-" & String($lngTemp)

Return $Return

EndFunc ;==>HexStrToDecStr

Share this post


Link to post
Share on other sites

What you need to do is "map" the DllStruct over the top of the returned value. An example of this can be found in the EventLog.au3 file where I map a structure over the top of the event record to read the binary data. When using DllStructCreate, the second parameter (which is optional) is a pointer to where the struct will be mapped.


Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

What you need to do is "map" the DllStruct over the top of the returned value. An example of this can be found in the EventLog.au3 file where I map a structure over the top of the event record to read the binary data. When using DllStructCreate, the second parameter (which is optional) is a pointer to where the struct will be mapped.

But, in your example, you master keys a structure in parameter, with the result that you can use the functions to find the pointer.

In my case, the type of value indicated (by functions VBS) by TypeName is Byte () and I do not see how to convert this data of structure ;)

Share this post


Link to post
Share on other sites

But, in your example, you master keys a structure in parameter, with the result that you can use the functions to find the pointer.

In my case, the type of value indicated (by functions VBS) by TypeName is Byte () and I do not see how to convert this data of structure ;)

Your problem is that you're converting the binary array to a string (using OctetToHexStr). _ConvertSidToStringSid($pSID) expects a pointer to a binary array, not a pointer to a string.

What exactly are you trying to do? Maybe if you gave me some clue as to what the end result of this is suppose to be, I could help you out more.


Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

Your problem is that you're converting the binary array to a string (using OctetToHexStr). _ConvertSidToStringSid($pSID) expects a pointer to a binary array, not a pointer to a string.

What exactly are you trying to do? Maybe if you gave me some clue as to what the end result of this is suppose to be, I could help you out more.

Precisely, I do not want to pass by OctetToHexStr ==>

; Essai avec des structures et des appels de fonctions

Local $BinSID = OctetToHexStr($arrbytSids)

; How to use the value arrbytSids directly for creating structure ?????????????????????????????????????????

Local $rSID = DllStructCreate("byte[" & StringLen($BinSID) / 2 & "]")

Local $pSID = DllStructGetPtr($rSID)

Local $j = 1

For $i = 1 To StringLen($BinSID) Step 2

DllStructSetData($rSID, 1, Dec(StringMid($BinSID, $i, 2)), $j)

$j += 1

Next

MsgBox(0, "Test structures", _ConvertSidToStringSid ($pSID))

I want suppress all this lines and replace by

MsgBox(0, "Test structures", _ConvertSidToStringSid ($pSID)) where $pSID is a pointer on arrbytSids (arrbytSids = $objUser.objectSid or $objUser.SIDhistory according to the cases)

Share this post


Link to post
Share on other sites

Precisely, I do not want to pass by OctetToHexStr ==>

You're really starting to drive me insane (I know, it's a short drive) ;) I am missing why you're not just passing $arrbyteSids (or a pointer that points to it) to _ConvertSidToStringSid. Something like:

$rSID = DllStructCreate("byte[256]"), $arrbyteSids)
_ConvertSidToStringSid(DllStructGetPtr($rSID))

Auto3Lib: A library of over 1200 functions for AutoIt

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

You're really starting to drive me insane (I know, it's a short drive) ;) I am missing why you're not just passing $arrbyteSids (or a pointer that points to it) to _ConvertSidToStringSid. Something like:

$rSID = DllStructCreate("byte[256]"), $arrbyteSids)
_ConvertSidToStringSid(DllStructGetPtr($rSID))
My problem has this level.

$arrbyteSids is not a pointer ==> How to create a pointer on a variable which is not a structure?

I want :

Local $objUser = ObjGet("LDAP://cn=CHAIGNE Eric,ou=users,dc=MyDomain,dc=fr")

Local $arrbytSids = $objUser.objectSid

Local $arrbytSidsHist = $objUser.SIDHistory

$rSID = DllStructCreate("byte[256]", a pointer on $arrbytSids (or on $objUser.objectSid) ==> How create it ?????)

$rSIDhist = DllStructCreate("byte[256]", a pointer on $arrbytSidsHist (or on $objUser.SIDHistory) ==> How create it ?????)

_ConvertSidToStringSid(DllStructGetPtr($rSID)

_ConvertSidToStringSid(DllStructGetPtr($rSIDhist )

Edited by ECHAIGNE

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0