Sign in to follow this  
Followers 0
Factfinder

Help with converting C to autoit, a DLLCall failes

8 posts in this topic

#1 ·  Posted (edited)

There is an old thread with a code here: http://forum.sysinternals.com/howto-verify-the-digital-signature-of-a-file_topic19247.html

The author has not tried it on all systems.

There is a thread here from a couple of years ego: '?do=embed' frameborder='0' data-embedContent>>

The OP, FredAl seems to have converted the script to autoit with success. But unfortunately he is not logged into the forum since last November.

I have been working on the script but got stuck on the last DLLCall before the final verification. I have tried to reduce the code to the essentials for debugging and added the needed comments to make the job easier for those who are willing to help.

Any advise is greatly appreciated.

;//Get a context for signature verification:
;msdn source: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379889%28v=vs.85%29.aspx
;code: if( !CryptCATAdminAcquireContext(&Context, NULL, 0) ); etc
Local $pContext
$context = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminAcquireContext', 'HANDLE*', $pContext, 'ptr', 0, 'DWORD', 0) ; This looks OK, have tried 'ptr*' instead of 'HANDLE*' still with the same final outcome of 'CryptCATAdminEnumCatalogFromHash'
If Not $context[0] Then Return False
$context = $context[1]

;//Open file
;Code: FileHandle = CreateFileW(FilePath, GENERIC_READ, 7, NULL, OPEN_EXISTING, 0, NULL);
Local $hFile = DllCall('Kernel32.dll', 'HANDLE', 'CreateFileW', 'Wstr', $filepath, 'DWORD', 0x80000000, 'DWORD', 7, 'ptr', 0, 'DWORD', 3, 'DWORD', 0, 'HANDLE', 0); no @error

;//Get the size we need for our hash.
; Code: CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, NULL, 0)
Local $cbHash
$cbHash = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminCalcHashFromFileHandle', 'HANDLE', $hFile, 'DWORD*', $cbHash, 'ptr', 0, 'DWORD', 0)
If Not $cbHash[0] Then Return False
$cbHash = $cbHash[2]

;//Allocate memory.
;code: Buffer = (PBYTE)calloc(HashSize, 1);
;;//Actually calculate the hash
;msdn source: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379891%28v=vs.85%29.aspx
;Code: if( !CryptCATAdminCalcHashFromFileHandle(FileHandle, &HashSize, Buffer, 0) )
Local $Buffer = DllStructCreate('BYTE[' & $cbHash & ']')
$pbHash = DllStructGetPtr($Buffer, 1)

$cbHash = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminCalcHashFromFileHandle', 'HANDLE', $hFile, 'DWORD*', $cbHash, 'ptr', $pbHash, 'DWORD', 0); this gives the desired result.
If Not $cbHash[0] Then Return False
$cbHash = $cbHash[2]

;//Get catalog for our context.
;msdn source: https://www.google.com/search?q=CryptCATAdminEnumCatalogFromHash&ie=UTF-8
;Code: CatalogContext = CryptCATAdminEnumCatalogFromHash(Context, Buffer, HashSize, 0, NULL);
Local $CatalogContext = DllCall('Wintrust.dll', 'Handle', 'CryptCATAdminEnumCatalogFromHash', 'handle', $context, 'ptr*', $pbHash, 'DWORD', $cbHash, 'DWORD', 0, "handle", 0); this one failes to ruturn a handle, returns 0
If not $CatalogContext[0] Then  MsgBox(0,"", "Failed")
Edited by Factfinder

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Your script failed on my PC at CrateFileW function.

I was able to test this successfully on my PC though:

$retVal = testFunc(@WindowsDir & "\notepad.exe")
if NOT @error then
    MsgBox(0, "HCATINFO", "Success: " & @CRLF & @CRLF & $retVal)
Else
    MsgBox(0, "Error", "Error code: " & @error & @CRLF & @CRLF & $retVal)
EndIf

func testFunc($sFile)
    Local $pContext
    $context = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminAcquireContext', 'ptr*', $pContext, 'ptr', 0, 'DWORD', 0)
    If @error Or Not $context[0] Then Return SetError(1, 0, "CryptCATAdminAcquireContext failed to return pContext")
    $context = $context[1]

    Local $a_hCall = DllCall("kernel32.dll", "hwnd", "CreateFileW", _
            "wstr", $sFile, _
            "dword", 0x80000000, _ ; GENERIC_READ
            "dword", 1, _ ; FILE_SHARE_READ
            "ptr", 0, _
            "dword", 3, _ ; OPEN_EXISTING
            "dword", 0, _ ; SECURITY_ANONYMOUS
            "ptr", 0)
    If @error Or $a_hCall[0] = -1 Then Return SetError(2, 0, "CreateFileW function failed")
    Local $hFile = $a_hCall[0]

    Local $cbHash = 0
    $cbHash = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminCalcHashFromFileHandle', 'handle', $hFile, 'DWORD*', $cbHash, 'ptr', 0, 'dword', 0)
    If @error Or Not $cbHash[0] Then
        _WinAPI_CloseHandleEx($hFile)
        Return SetError(3, 0, "CryptCATAdminCalcHashFromFileHandle failed to return cbHash")
    EndIf
    $cbHash = $cbHash[2]

    Local $Buffer = DllStructCreate('BYTE[' & $cbHash & ']')
    $pbHash = DllStructGetPtr($Buffer, 1)

    $cbHash = DllCall('Wintrust.dll', 'BOOL', 'CryptCATAdminCalcHashFromFileHandle', 'handle', $hFile, 'DWORD*', $cbHash, 'ptr', $pbHash, 'DWORD', 0)
    If @error Or Not $cbHash[0] Then
        _WinAPI_CloseHandleEx($hFile)
        Return SetError(4, 0, "CryptCATAdminCalcHashFromFileHandle failed to return cbHash, #2")
    EndIf
    $cbHash = $cbHash[2]

    _WinAPI_CloseHandleEx($hFile)

    Local $CatalogContext = DllCall('Wintrust.dll', 'handle', 'CryptCATAdminEnumCatalogFromHash', 'handle', $context, 'ptr', $pbHash, 'DWORD', $cbHash, 'DWORD', 0, "handle", 0)
    If @error Or not $CatalogContext[0] Then Return SetError(5, 0, "CryptCATAdminEnumCatalogFromHash failed to return HCATINFO")
    $CatalogContext = $CatalogContext[0]

    Return $CatalogContext
EndFunc

; #FUNCTION# ====================================================================================================================
; Author ........: Paul Campbell (PaulIA)
; Modified.......:
; ===============================================================================================================================
Func _WinAPI_CloseHandleEx($hObject)
    Local $aResult = DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hObject)
    If @error Then Return SetError(@error, @extended, False)

    Return $aResult[0]
EndFunc   ;==>_WinAPI_CloseHandle
Edited by dragan

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

    Why "ptr*" and not "ptr"?

 

Thank you for the reply. You are right and it was wrong. I initially used "ptr" following the original c script. But the compiled script used to crash. I followed msdm direction "_In_  BYTE *pbHash," and used "ptr*". The compiled script stopped crashing (of course it was not working). dragan used "ptr" too with success. I know now the script crashed because my system has corrupted catalogs.

@dragan,

Thanks a lot for taking time to build a nice working script. I had tried many things including setting "FILE_SHARE_READ" but it failed on my main system. Thanks to your effort I have now a working script and additionally know my system has some corrupted catalogs to be taken care of. I tested your script on another system and it worked.

 

Edited by Factfinder

Share this post


Link to post
Share on other sites

Hi Factfinder,

Did you get the whole script to work

I see that dragan script returns the context, did you follow up with verifying the file? If so could you share script that you are using?

Thanks,

Stephen

Share this post


Link to post
Share on other sites

Look this example:

;Written by Danyfirex & Dany3j
;Thanks http://forum.sysinternals.com
;10-03-2014

#include <WinAPI.au3>


Opt("MustDeclareVars", 1) ;0=no, 1=require pre-declaration

#Region Constants
Global Const $WTD_STATEACTION_CLOSE = 0x00000002
Global Const $WTD_CHOICE_FILE = 1
Global Const $WTD_CHOICE_CATALOG = 2
Global Const $WTD_UI_NONE = 2
Global Const $WTD_REVOKE_NONE = 0
Global Const $WTD_STATEACTION_IGNORE = 0
Global Const $WTD_STATEACTION_VERIFY = 1
Global Const $WTD_SAFER_FLAG = 256
#EndRegion Constants



#Region Struct
Global Const $tagWINTRUST_DATA = "dword cbStruct;ptr pPolicyCallbackData;ptr pSIPClientData;dword dwUIChoice;dword fdwRevocationChecks;dword dwUnionChoice;" & _
        "dword pPointer;dword dwStateAction;handle hWVTStateData;ptr pwszURLReference;dword dwProvFlags;dword dwUIContext"

Global Const $tagWINTRUST_FILE_INFO = "dword cbStruct;ptr pcwszFilePath;handle hFile;ptr pgKnownSubject"

Global Const $tagWINTRUST_CATALOG_INFO = "dword cbStruct;dword dwCatalogVersion;ptr pcwszCatalogFilePath;ptr pcwszMemberTag;ptr pcwszMemberFilePath;dword hMemberFile"

Global Const $tagCATALOG_INFO = "dword cbStruct;byte wszCatalogFile[520]"
#EndRegion Struct




Global Const $sWinTrust = "wintrust.dll"
Global $hWinTrustDll = 0


$hWinTrustDll = DllOpen($sWinTrust)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hWinTrustDll = ' & $hWinTrustDll & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console


;check
SignV(@WindowsDir & "\explorer.exe")




Func SignV($sFilePath)


    Local $bRet = False
    Local $hCatAdmin = 0
    Local $bRet = 0
    Local $hFile = 0
    Local $hr = 0
    Local $pszMemberTag = ""
    Local $iHashLen = 100
    $iHashLen
    Local $dw = 0
    Local $hCatInfo = 0
    Local $tagbyHash = "byte byHash[100]"
    ;Structures
    Local $tbyHash = DllStructCreate($tagbyHash)
    Local $tWINTRUST_DATA = DllStructCreate($tagWINTRUST_DATA)
    Local $tWINTRUST_FILE_INFO = DllStructCreate($tagWINTRUST_FILE_INFO)
    Local $tWINTRUST_CATALOG_INFO = DllStructCreate($tagWINTRUST_CATALOG_INFO)
    Local $tCATALOG_INFO = DllStructCreate($tagCATALOG_INFO)


    ;Debug Structures
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tbyHash = ' & IsDllStruct($tbyHash) & " Size= " & DllStructGetSize($tbyHash) & @CRLF) ;### Debug Console

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tWINTRUST_DATA = ' & IsDllStruct($tWINTRUST_DATA) & " Size= " & DllStructGetSize($tWINTRUST_DATA) & @CRLF) ;### Debug Console

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tWINTRUST_FILE_INFO = ' & IsDllStruct($tWINTRUST_FILE_INFO) & " Size= " & DllStructGetSize($tWINTRUST_FILE_INFO) & @CRLF) ;### Debug Console

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $tWINTRUST_CATALOG_INFO = ' & IsDllStruct($tWINTRUST_CATALOG_INFO) & " Size= " & DllStructGetSize($tWINTRUST_CATALOG_INFO) & @CRLF) ;### Debug Console

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') :  $tCATALOG_INFO = ' & IsDllStruct($tCATALOG_INFO) & " Size= " & DllStructGetSize($tCATALOG_INFO) & @CRLF) ;### Debug Console




    Local $Ret = DllCall($hWinTrustDll, "bool", "CryptCATAdminAcquireContext", "handle*", 0, "ptr", 0, "dword", 0)
    ConsoleWrite("+ CryptCATAdminAcquireContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)
    $hCatAdmin = $Ret[1]

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hCatAdmin = ' & ($hCatAdmin) & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console




    $hFile = _WinAPI_CreateFile($sFilePath, 2, 2, 2)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hFile = ' & $hFile & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console

    If $hFile = $INVALID_HANDLE_VALUE Then
        $Ret = DllCall($hWinTrustDll, "bool", "CryptCATAdminReleaseContext", "handle", $hCatAdmin, "dword", 0)
        ConsoleWrite("+ CryptCATAdminReleaseContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)
        ConsoleWrite("! $INVALID_HANDLE_VALUE" & ">Error code: " & @error & @CRLF)
    EndIf








    $Ret = DllCall($hWinTrustDll, "bool", "CryptCATAdminCalcHashFromFileHandle", "handle", $hFile, "dword*", 0, "ptr", 0, "dword", 0)
    ConsoleWrite("+ CryptCATAdminCalcHashFromFileHandle Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)
    $iHashLen = $Ret[2]
    ConsoleWrite(">> $iHashLen= " & $iHashLen & @CRLF)



    $Ret = DllCall($hWinTrustDll, "bool", "CryptCATAdminCalcHashFromFileHandle", "handle", $hFile, "dword*", $iHashLen, "ptr", DllStructGetPtr($tbyHash), "dword", 0)
    ConsoleWrite("+ CryptCATAdminCalcHashFromFileHandle Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)




    If $hFile Then _WinAPI_CloseHandle($hFile)


    For $i = 1 To $iHashLen
        $pszMemberTag &= Hex(DllStructGetData($tbyHash, 1, $i), 2)
    Next
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pszMemberTag = ' & $pszMemberTag & " Len= " & StringLen($pszMemberTag) & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console


    $Ret = DllCall($hWinTrustDll, "handle", "CryptCATAdminEnumCatalogFromHash", "handle", $hCatAdmin, "ptr", DllStructGetPtr($tbyHash), "dword", $iHashLen, "dword", 0, "ptr", 0)
    ConsoleWrite("+ CryptCATAdminEnumCatalogFromHash Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)
    $hCatInfo = $Ret[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $hCatInfo = ' & $hCatInfo & @TAB & '>Error code: ' & @error & @CRLF) ;### Debug Console


    If $hCatInfo = 0 Then
        ConsoleWrite("CryptCATAdminEnumCatalogFromHash failed, verifying embedded signature." & @CRLF)

    Else

        $Ret = DllCall($hWinTrustDll, "bool", "CryptCATCatalogInfoFromContext", "handle", $hCatInfo, "ptr", DllStructGetPtr($tCATALOG_INFO), "dword", 0)
        ConsoleWrite("+ CryptCATCatalogInfoFromContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

        If Not $Ret[0] Then
            ConsoleWrite("CryptCATCatalogInfoFromContext failed" & @CRLF)
            $Ret = DllCall($hWinTrustDll, "bool", "CryptCATAdminReleaseCatalogContext", "handle", $hCatAdmin, "handle", $hCatInfo, "dword", 0)
            ConsoleWrite("+ CryptCATAdminReleaseCatalogContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

        EndIf



        ConsoleWrite("!wszCatalogFile 67 = " & DllStructGetData($tCATALOG_INFO, "wszCatalogFile", 1) & @CRLF)
        Local $tFile = DllStructCreate("wchar[" & StringLen($sFilePath) + 2 & "]")
        DllStructSetData($tFile, 1, $sFilePath)
        Local $pFile = DllStructGetPtr($tFile)
        ConsoleWrite("!tFileData = " & DllStructGetData($tFile, 1) & @CRLF)

        DllStructSetData($tWINTRUST_CATALOG_INFO, "cbStruct", DllStructGetSize($tWINTRUST_CATALOG_INFO))
        DllStructSetData($tWINTRUST_CATALOG_INFO, "pcwszCatalogFilePath", DllStructGetPtr($tCATALOG_INFO, "wszCatalogFile"))
        ConsoleWrite("wszCatalogFile Ptr = " & DllStructGetPtr($tCATALOG_INFO, "wszCatalogFile") & @CRLF)



        ConsoleWrite("pcwszCatalogFilePath Data = " & DllStructGetData($tWINTRUST_CATALOG_INFO, "pcwszCatalogFilePath") & @CRLF)

        DllStructSetData($tWINTRUST_CATALOG_INFO, "pcwszMemberFilePath", $pFile)
        ConsoleWrite("pcwszMemberFilePath Ptr = " & DllStructGetData($tWINTRUST_CATALOG_INFO, "pcwszMemberFilePath") & @CRLF)


        Local $tpszMemberTag = DllStructCreate("wchar[" & StringLen($pszMemberTag) + 2 & "]")
        DllStructSetData($tpszMemberTag, 1, $pszMemberTag)
        Local $ptpszMemberTag = DllStructGetPtr($tpszMemberTag)
        ConsoleWrite("!tpszMemberTag  Data = " & DllStructGetData($tpszMemberTag, 1) & @CRLF)

        DllStructSetData($tWINTRUST_CATALOG_INFO, "pcwszMemberTag", $ptpszMemberTag)


        DllStructSetData($tWINTRUST_DATA, "cbStruct", DllStructGetSize($tWINTRUST_DATA))
        DllStructSetData($tWINTRUST_DATA, "dwUnionChoice", $WTD_CHOICE_CATALOG)
        DllStructSetData($tWINTRUST_DATA, "pPointer", DllStructGetPtr($tWINTRUST_CATALOG_INFO))
        DllStructSetData($tWINTRUST_DATA, "dwUIChoice", $WTD_UI_NONE)
        DllStructSetData($tWINTRUST_DATA, "fdwRevocationChecks", $WTD_REVOKE_NONE)
        DllStructSetData($tWINTRUST_DATA, "dwStateAction", $WTD_STATEACTION_VERIFY)
        DllStructSetData($tWINTRUST_DATA, "dwProvFlags", 0)
        DllStructSetData($tWINTRUST_DATA, "hWVTStateData", 0)
        DllStructSetData($tWINTRUST_DATA, "pwszURLReference", 0)

    EndIf


    Local $taction = _GUIDStruct("{00AAC56B-CD44-11D0-8CC200C04FC295EE}")
    ConsoleWrite("Structura action=" & IsDllStruct($taction) & " Valor=" & Hex(DllStructGetData($taction, 1), 8) & " Error= " & @error & @CRLF)


    $Ret = DllCall($hWinTrustDll, "long", "WinVerifyTrust", "long", $INVALID_HANDLE_VALUE, "ptr", DllStructGetPtr($taction), "ptr", DllStructGetPtr($tWINTRUST_DATA))
    ConsoleWrite("+ WinVerifyTrust Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

    ConsoleWrite("WinVerifyTrust Retorno= " & ($Ret[0]) & @CRLF)

    Local $hr = $Ret[0]


    If $hCatInfo <> 0 Then
        $Ret = DllCall($hWinTrustDll, "long", "CryptCATAdminReleaseCatalogContext", "long", $hCatAdmin, "long", $hCatInfo, "long", 0)
        ConsoleWrite("+ CryptCATAdminReleaseCatalogContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

    EndIf


    $Ret = DllCall($hWinTrustDll, "long", "CryptCATAdminReleaseContext", "int", $hCatAdmin, "long", 0)
    ConsoleWrite("+ CryptCATAdminReleaseContext Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Ret = ' & $Ret[0] & @CRLF & '>Error code: ' & @error & @CRLF)

    If $hr = 0 Then
        DllStructSetData($tWINTRUST_DATA, "dwStateAction", $WTD_STATEACTION_CLOSE)

        $Ret = DllCall($hWinTrustDll, "long", "WinVerifyTrust", "long", $INVALID_HANDLE_VALUE, "ptr", DllStructGetPtr($taction), "ptr", DllStructGetPtr($tWINTRUST_DATA))
        ConsoleWrite("+ WinVerifyTrust Ret= " & $Ret[0] & @TAB & '>Error code: ' & @error & @CRLF)

    EndIf



    If $hWinTrustDll Then DllClose($hWinTrustDll)

EndFunc   ;==>SignV



;Prog@ndy
Func _GUIDStruct($IID)
    $IID = StringRegExpReplace($IID, "([}{])", "")
    $IID = StringSplit($IID, "-")
    Local $_GUID = "DWORD Data1;  ushort Data2;  ushort Data3;  BYTE Data4[8];"
    Local $GUID = DllStructCreate($_GUID)
    If $IID[0] = 5 Then $IID[4] &= $IID[5]
    If $IID[0] > 5 Or $IID[0] < 4 Then Return SetError(1, 0, 0)
    DllStructSetData($GUID, 1, Dec($IID[1]))
    DllStructSetData($GUID, 2, Dec($IID[2]))
    DllStructSetData($GUID, 3, Dec($IID[3]))
    DllStructSetData($GUID, 4, Binary("0x" & $IID[4]))
    Return $GUID
EndFunc   ;==>_GUIDStruct

Need some adjustments but look debug console There is everything you need.

 

Saludos


 

venezuela.png Would you like to say thank to Danyfirex using a warmy way?  offer me a cup of coffee... coffee.png

autoit_scripter_blue_userbar.png

       AutoIt...

 

 

Share this post


Link to post
Share on other sites

thanks Dany, it helped me out.
I modified '?do=embed' frameborder='0' data-embedContent>> and used code posted here to come up this 

#include "_WinTrust.au3"
$filepath = FileOpenDialog("pick a file",@ScriptDir, "All Files (*.*)")
If Not FileExists($filepath) Then 
    MsgBox(16, '', $filepath & ' does not exist.')
    Exit
EndIf
$retval = _Verify($filepath)
If $retval[0] Then
    MsgBox(64,'Verified', $filepath & ' is verified.' & @crlf & $retval[0] & @CRLF & $retval[1] & @CRLF & $retval[2])
    ConsoleWrite($filepath & ' is verified.' & @CRLF & $retval[0] & @CRLF & $retval[1] & @CRLF & $retval[2] & @CRLF)
Else
    MsgBox(032,'Unverified',$filepath & ' is not verified.')
    ConsoleWrite($filepath & ' is not verified.' & @CRLF)
EndIf

I have tested on win 7 64 bit, win 8 32bit, win 8.1 64 bit and xp sp3

and it worked. 

_WinTrust.au3

1 person likes this

Share this post


Link to post
Share on other sites

Sorry for being late. In fact this script gives additional information while the script I made just verfies the signature. I had to use a modfied short version of _WinTrust.Au3 too.

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