Seite 1 von 1

C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 11:24
von tschaka81
Hallo,

ich habe derzeit folgenden abgekürzten C# Code:

Code: Alles auswählen

        [DllImport("PxCrypto.dll", CharSet = CharSet.Ansi,
        EntryPoint = "_MakeHash@8")]
        private static extern int MakeHash(string password, ref object Hash);

	...
	object var_CryptoPass = "";
        MakeHash("", ref var_CryptoPass);
diesen wollte ich nach Python übersetzen. (Einen Großteil habe ich hier https://stackoverflow.com/questions/252 ... rom-python entnommen ohne wirklich zu verstehen wie das Ganze funktioniert...)

Code: Alles auswählen

hllDll = ctypes.WinDLL (r"PxCrypto.dll")
hllApiProto = ctypes.WINFUNCTYPE (
    ctypes.c_int,      # Return type.
    ctypes.c_void_p,   # string password
    ctypes.c_void_p)   # object Hash

hllApiParams = (1, "p1", 0), (1, "p2", 0),
hllApi = hllApiProto (("_MakeHash@8", hllDll), hllApiParams)
p1 = ctypes.c_char
p2 = ctypes.c_char_p
a = hllApi (ctypes.byref (p1), p2)
print(a)

Ich bin jetzt was C# und generell DLLs anbelangt nicht wirklich gut und komme hier nicht weiter.
Ich verstehe noch nicht, wie ich die p1, p2 Parameter richtig setzen muss, ob c_char das Richtige ist?

Derzeit bekomme ich den Fehler in python:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\mwagner\AppData\Local\Programs\Python\Python310-32\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 11, in <module>
TypeError: byref() argument must be a ctypes instance, not '_ctypes.PyCSimpleType'

Weiß jemand, was ich falsch mache und würde es mir erklären?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 11:52
von __blackjack__
@tschaka81: Warum hast Du Dir gerade *das* Beispiel ausgesucht, bei dem das so umständlich über einen Funktionsprototypen gemacht wird?

Wobei die wichtigste Frage wohl ist, ob das überhaupt mit `ctypes` geht, denn das ist für native DLLs und nicht für C#-DLLs. Oder enthalten die nativen Code über den dann der .NET-Code aufgerufen wird?

Ansonsten ist die Fehlermeldung recht offensichtlich und erwartbar, weil Du versuchst die Datentypen als Werte zu übergeben, statt Objekte mit einem Wert davon zu erstellen, und die dann zu übergeben. So wie das im Beispiel ja auch gemacht wird.

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 11:52
von Sirius3
Woher kommt dieses PxCrypto.dll? Oder anders gefragt, welche Hash-Funktion steckt dahinter? Es gibt für alle relevanten Hash-Funktionen auch Python-Implementierungen.

Ein Passwort mit einer normalen Hash-Funktion zu bearbeiten, ist ein großes Sicherheitsproblem. Neben dem Algorithmus hat man noch die Anzahl der Iterationen, einen Salt oder weitere Parameter. Übliche Methoden sind bcrypt, PBKDF2 oder Argon2.

Das Password soll als ANSI-codierter c_char_p übergeben werden. ctypes kann ByteStrings automatisch konvertieren. Was da als object Hash zurückkommt, kann man schlehct sagen, das ist ein simpler Pointer, den Du per byref übergeben mußt. Du dagegen übergibst keine Werte, sondern die Typen.

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 11:56
von tschaka81
Nach ein wenig hin und her, habe ich auch gemerkt, dass das Ganze ein wenig umständlich ist:

Mittels:

Code: Alles auswählen

hllDll = ctypes.WinDLL (r"PxCrypto.dll")
a = ctypes.c_char()
hllDll.MakeHash("Hallo", ctypes.byref(a))
print(a)
bekomme ich schonmal das erste Zeichen zurück. (Glaube ich, zumindest keinen Fehler).

Wie kann ich den Datentyp von c_Char in String ändern?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:03
von __blackjack__
@tschaka81: String gibt es in C nicht als Datentyp. Das sind in C Zeiger auf Char. Das heisst Du musst hier ein Zeichen-Array anlegen das gross genug ist um das Ergebnis aufzunehmen, und dann einen Zeiger darauf übergeben.

An der Stelle kann man übrigens auch ganz gut sehen wie gefährlich C ist. Du übergibst da gerade einen Zeiger auf Speicherplatz für *ein* Zeichen, der Aufruf schreibt aber mehr als ein Zeichen dort hin und überschreibt irgendwelche Daten die dahinter im Speicher liegen. Das kann gut gehen, weil der Speicherplatz nicht (mehr) verwendet wird, das kann aber auch katastrophale Folgen haben. Von verfälschten Daten, bis zu harten Programmabstürzen.

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:16
von tschaka81
__blackjack__ hat geschrieben: Donnerstag 24. März 2022, 12:03 @tschaka81: String gibt es in C nicht als Datentyp. Das sind in C Zeiger auf Char. Das heisst Du musst hier ein Zeichen-Array anlegen das gross genug ist um das Ergebnis aufzunehmen, und dann einen Zeiger darauf übergeben.

An der Stelle kann man übrigens auch ganz gut sehen wie gefährlich C ist. Du übergibst da gerade einen Zeiger auf Speicherplatz für *ein* Zeichen, der Aufruf schreibt aber mehr als ein Zeichen dort hin und überschreibt irgendwelche Daten die dahinter im Speicher liegen. Das kann gut gehen, weil der Speicherplatz nicht (mehr) verwendet wird, das kann aber auch katastrophale Folgen haben. Von verfälschten Daten, bis zu harten Programmabstürzen.
Das gebe ich dir recht mit dem Speicher.

Wie macht man das konkret mit dem Zeichen Array per ctypes?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:34
von tschaka81
Ich habe jetzt mal folgendes versucht:

Code: Alles auswählen

import ctypes
hllDll = ctypes.WinDLL (r"C:\Canberra\Apex\Exefiles\PxCrypto.dll")
length_str = 20
a = [ctypes.create_string_buffer(length_str) for i in range(length_str)]
pointers = (ctypes.c_char_p*length_str)(*map(ctypes.addressof, a))
hllDll.MakeHash("Hallo", ctypes.byref(pointers))
print([k.value for k in a])
Das gibt mir zwar keinen Fehler zurück, aber auch nur ein bytearray mit lauter

Code: Alles auswählen

[b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'', b'']

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:38
von __deets__
Eh. Das ist doch komplett geraten. Wieso produzierst du denn ploetzlich eine Liste von Pointern? Das hat doch niemand irgendwo gefordert.

Mir fehlt hier vor allem die Angabe, was die Funktion als "Hash"-Objekt haben will. Ein void_p ist ja schoen und gut, aber der muss schon auf eine gewisse Menge Speicher zeigen. Wie sieht den die C++(!) Deklaration der Funktion aus? Und die all ihrer Argumente?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:48
von tschaka81
__deets__ hat geschrieben: Donnerstag 24. März 2022, 12:38 Eh. Das ist doch komplett geraten. Wieso produzierst du denn ploetzlich eine Liste von Pointern? Das hat doch niemand irgendwo gefordert.

Mir fehlt hier vor allem die Angabe, was die Funktion als "Hash"-Objekt haben will. Ein void_p ist ja schoen und gut, aber der muss schon auf eine gewisse Menge Speicher zeigen. Wie sieht den die C++(!) Deklaration der Funktion aus? Und die all ihrer Argumente?
Die Declaration habe ich leider nicht. Ich bin davon ausgegangen, dass ein String am Schluss ein Zeiger auf einzelne Positionen im String zeigt. Scheinbar aber nicht^^

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:51
von __deets__
Ich weiss nicht, was "ein String am Schluss ein Zeiger auf einzelne Positionen im String" sein soll. Das zweite Argument ist aus C++-Sicht "nur" ein Pointer, aber eben auf einen unbekannten Typ - Hash.

Bist du sicher, dass du keine Deklaration hast? Irgendwo in der Dokumentation der DLL muss das doch stehen, der Hersteller gibt die ja nicht ohne alles raus. Und dann gibt es ein "ref object Hash" im C#, wie sieht denn das aus?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:57
von tschaka81
Wie gesagt, dass habe ich nicht. Müsste ich erstmal nachfragen beim Hersteller.

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 12:58
von __deets__
Und den C# Code hast du auch nicht? Dann hilft nur die Nachfrage, ja.

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 13:22
von tschaka81
alles klar, ich werde mal den Kontakt suchen. Vielen Dank schonmal für die Hilfe

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 15:08
von Sirius3
Woher kommt die PxCrypto.dll? Was ist das für eine Bibliothek? Was wird weiter in dem C#-Programm mit dem Ergebnis gemacht?

Re: C# DLL to Python

Verfasst: Donnerstag 24. März 2022, 18:00
von tschaka81
Die Cryptodll gehört zu einem speziellen Programm und sorgt für die Anmeldung an diesem. Ich habe jetzt den Part mit dem MakeHash hinbekommen:
daraufhin sollte ich mich mit Authenticate einloggen können. Hier scheitere ich wieder an secman. secman kommt aus sessions.Properties("SecMgr") und ist der gleiche datentyp wie secman2 (Hab ich geprüft. es sind zumindest die gleichen Methoden verbaut)

Wenn ich jetzt

Code: Alles auswählen

hllDll.Authenticate(secman, facility, user, automation.byref(a))
ausführe, dann bekomme ich:

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Users\mwagner\AppData\Local\Programs\Python\Python310-32\lib\code.py", line 90, in runcode
    exec(code, self.locals)
  File "<input>", line 14, in <module>
ctypes.ArgumentError: argument 1: <class 'TypeError'>: Don't know how to convert parameter 1
Laut Hersteller ist der datentyp ein SecMgr, d.h. vom typ secman2 (in meinem Code als Beispiel)

Wie bekomme ich Python das nun beigebracht?

Hier ist der Code den ich derzeit habe:

Code: Alles auswählen

password = ""
user = "Administrator"
facility = "Default"
import ctypes
from comtypes import automation
import win32com.client
sessions = win32com.client.Dispatch("Canberra.SessionMgr.1")
secman = sessions.Properties("SecMgr")
secman2 = win32com.client.Dispatch("Canberra.SecMan.SecMgr.1")
hllDll = ctypes.WinDLL (r"C:\Canberra\Apex\Exefiles\PxCrypto.dll")
a = automation.VARIANT()
hllDll.MakeHash(password, automation.byref(a))
hllDll.Authenticate.restype = ctypes.c_long
hllDll.Authenticate(secman, facility, user, automation.byref(a))
sessions.BeginSession("localhost")

Parallel habe ich einen Code für VBA bekommen:

Code: Alles auswählen

Private Declare Function MakeHash Lib "PxCrypto" Alias "_MakeHash@8" (ByVal password As String, ByRef Hash As Variant) As Boolean
Private Declare Function Authenticate Lib "PxCrypto" Alias "_Authenticate@16" (ByVal SecurityManager As SecMgr, ByVal Facility As String, ByVal UserName As String, ByRef PasswordHash As Variant) As Long
Dim var_CryptoPass                      As Variant
Dim obj_SecMgr                          As SecMgr
Dim obj_SM                              As SessionMgr

Set obj_SM = New SessionMgr
MakeHash "", var_CryptoPass
Set obj_SecMgr = obj_SM.Properties("SecMgr")
Authenticate obj_SecMgr, FACILITY_NAME, USER_NAME, var_CryptoPass
Ich verstehe noch nicht was die Aliasse machen?