Das kann ich eigentlich ausschliessen. Nachdem ich meine INI Überarbeitet hatte (wie oben erwähnt) ist da kein einziges unnötiges Leerzeichen mehr vorhanden.
Variable als INI behandeln?
-
Lottich -
15. April 2015 um 20:50 -
Erledigt
-
-
Nach einigem herum experimentieren hab ich das für mich nun doch noch lösen können, ohne dass die INI in irgendeiner Form entschlüsselt irgendwo abgelegt wird.
Hab mich dabei von @Kanashius inspirieren lassen. Dabei bin ich von einer INI-typischen Syntax abgewichen. JA, das hab ich nach @Andy s Anregung zu verdanken.CodeSektionsname1 ø Adresse der Website1 ø Anmeldename1 ø Passwort1 Sektionsname2 ø Adresse der Website2 ø Anmeldename2 ø Passwort2 ... ...
Die Funktionen lassen sich beinahe genauso verwenden, wie die herkömmlichen INI Befehle. Als UDF ists aber noch nicht tauglich, da so gut wie kein Errorhandling eingebaut ist.
Doch falls es trotzdem jemanden interessiertist hier der Code
AutoIt
Alles anzeigenGlobal $Splitter = "ø" Func _Mem_TextToArray($DataHandle) ; wandelt die Datei in ein 2D Array Local $aRet[0][5], $split_1, $split_2, $count = 0 $split_1 = StringSplit($DataHandle, @CRLF, 1) For $i = 1 To $split_1[0] If StringLeft($split_1[$i], 1) <> ";" Then If StringInStr($split_1[$i], $Splitter) Then $split_2 = StringSplit($split_1[$i], $Splitter) $count += 1 ReDim $aRet[$count + 1][5] $aRet[0][0] += 1 $aRet[$count][0] = $split_2[1] ;=> Sektion $aRet[$count][1] = $split_2[2] ;=> Adresse $aRet[$count][2] = $split_2[3] ;=> Username $aRet[$count][3] = $split_2[4] ;=> Passwort $aRet[$count][4] = $split_2[5] ;=> Datum EndIf EndIf Next Return $aRet EndFunc ;==>_Mem_TextToArray Func _Mem_ArrayToText($aArray) ; wandelt das Array in einen String Local $string = "" For $i = 1 To $aArray[0][0] $string &= $aArray[$i][0] & $Splitter & $aArray[$i][1] & $Splitter & $aArray[$i][2] & $Splitter & $aArray[$i][3] & $Splitter & $aArray[$i][4] If $i < $aArray[0][0] Then $string &= @CRLF Next Return $string EndFunc ;==>_Mem_ArrayToText Func _Mem_IniDelete(ByRef $aArray, $Section) $index = _ArraySearch($aArray, $Section) If $index = -1 Then Return SetError(-1, 0, "Funktion:" & @TAB & "_Mem_IniDelete ==> _ArraySearch" & @CRLF & "Fehler:" & @TAB & @error) Else _ArrayDelete($aArray, $index) $aArray[0][0] -= 1 EndIf EndFunc ;==>_Mem_IniDelete Func _Mem_IniWrite(ByRef $aArray, $Section, $Key, $Value) If $Key = "Adresse" Then $Key = 1 ElseIf $Key = "Username" Then $Key = 2 ElseIf $Key = "Passwort" Then $Key = 3 ElseIf $Key = "Datum" Then $Key = 4 Else Return SetError(-1, 0, "Funktion:" & @TAB & "_Mem_IniWrite" & @CRLF & "Fehler:" & @TAB & "3" & @CRLF & "Falscher Schlüssel") EndIf $index = _ArraySearch($aArray, $Section) If $index <> -1 Then $aArray[$index][$Key] = $Value $aArray[$index][4] = @MDAY & "." & @MON & "." & @YEAR Else ReDim $aArray[$aArray[0][0] + 2][5] $aArray[0][0] += 1 $aArray[$aArray[0][0]][0] = $Section $aArray[$aArray[0][0]][$Key] = $Value $aArray[$aArray[0][0]][4] = @MDAY & "." & @MON & "." & @YEAR EndIf EndFunc ;==>_Mem_IniWrite Func _Mem_IniWriteSection(ByRef $aArray, $Section, $Adresse = "", $Username = "", $Userpasswort = ""); auf mich zugeschnitten If $Adresse <> "" Then _Mem_IniWrite($aArray, $Section, "Adresse", $Adresse) If $Username <> "" Then _Mem_IniWrite($aArray, $Section, "Username", $Username) If $Userpasswort <> "" Then _Mem_IniWrite($aArray, $Section, "Passwort", $Userpasswort) EndFunc ;==>_Mem_IniWriteSection Func _Mem_IniRenameSection(ByRef $aArray, $Section_Alt, $Section_Neu) $index = _ArraySearch($aArray, $Section_Alt) If $index <> -1 Then $aArray[$index][0] = $Section_Neu $aArray[$index][4] = @MDAY & "." & @MON & "." & @YEAR Else SetError(-1, 0, "Funktion:" & @TAB & "_Mem_IniRenameSection" & @CRLF & "Fehler:" & @TAB & "3" & @CRLF & "Sektion nicht vorhanden!") EndIf EndFunc ;==>_Mem_IniRenameSection Func _Mem_IniRead($aArray, $Section, $Key) If $Key = "Adresse" Then $Key = 1 ElseIf $Key = "Username" Then $Key = 2 ElseIf $Key = "Passwort" Then $Key = 3 ElseIf $Key = "Datum" Then $Key = 4 Else Return SetError(-1, 0, "Funktion:" & @TAB & "_Mem_IniRead" & @CRLF & "Fehler:" & @TAB & "3" & @CRLF & "Falscher Schlüssel") EndIf $index = _ArraySearch($aArray, $Section) If $index <> -1 Then Return $aArray[$index][$Key] Else Return SetError(-1, 0, "Funktion:" & @TAB & "_Mem_IniRead ==> _ArraySearch" & @CRLF & "Fehler:" & @TAB & @error) EndIf EndFunc ;==>_Mem_IniRead Func _Mem_IniReadSection($aArray, $Section) Local $aRet[1] $index = _ArraySearch($aArray, $Section) If $index <> -1 Then ReDim $aRet[5] $aRet[0] = 4 For $i = 1 To $aRet[0] $aRet[$i] = $aArray[$index][$i] Next Return $aRet EndIf SetError(-1, 0, -1) EndFunc ;==>_Mem_IniReadSection Func _Mem_IniReadSectionNames($aArray) Local $aRet[$aArray[0][0] + 1] $aRet[0] = $aArray[0][0] For $i = 1 To $aArray[0][0] $aRet[$i] = $aArray[$i][0] Next Return $aRet EndFunc ;==>_Mem_IniReadSectionNames
@Andy: ich bin mir beinahe sicher, dass du mich für diese Vorgehensweise und diesem Code mit sofortiger Wirkung aus deiner Firma rauswerfen würdest
-
Nur als Info:
Hab vor geraumer Zeit eine ArrayToStringExUDF geschrieben. Die sollte 1D und 2D Arrays mit beliebigem Inhalt in Text und umgekehrt verwandeln können. Und zwar OHNE Split Zeichen und damit MIT vollem Asc Umfang. (Da es keinen Seperator gibt können im Array beliebige Zeichen auftreten ohne das es Probleme gibt).Spoiler anzeigen
[autoit]
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
#include-once
;~ #include 'StringPop.au3'; Anmerkung zur UDF =============================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Nicht Implementiert: Map, DllStruct, Object
; - Map: wird nachgereicht, sobald die nächste Stable Maps unterstützt und ich genug Zeit und Lust habe
; - DllStruct: Problemkind, da es keine Möglichkeit gibt anhand einer Structvariable auf die eigentliche Struktur zu schließen (z.B. 'int abc[2]')
; - Object: Da Objekte grundsätzlich "Alles" sein können ist es unmöglich sie als Ganzes (vorallem Zeitunabhängig) in einem String zu speichern.
; ===============================================================================================================================; #INDEX# =======================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Title .........: ArrayToStringEx
; AutoIt Version : 3.3.12.0
; Date ..........: 21.08.2014
; Language ......: Deutsch
; Description ...: Funktion um 1D oder 2D Arrays in Strings umzuwandeln incl. Umkehrfunktion
; Author(s) .....: Mars
; ===============================================================================================================================; #CURRENT# =====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; _ArrayToStringEx
; _StringToArrayEx
; ===============================================================================================================================; #INTERNAL_USE_ONLY# ===========================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; __ArrayToString1D
; __Double
; __StringToArray1D
; ===============================================================================================================================Global Const $___HexLen_UBound = 6 ; Maximal mögliche Arrayelemente = 2^24
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Global Const $___HexLen_ArraySubscripts = 2 ; Maximal 64 Stück
Global Const $___HexLen_Empty = 0 ; Wird nicht verwendet
Global Const $___HexLen_uInt8 = 2 ; Nur interne Benutzung
Global Const $___HexLen_uInt16 = 4 ; Nur interne Benutzung
Global Const $___HexLen_Int32 = 8
Global Const $___HexLen_Int64 = 16
Global Const $___HexLen_Double = 16
Global Const $___HexLen_Ptr = 16 ; Mit 64 Bit sind in jedem Fall x86 und x64 Systeme abgesichert
Global Const $___HexLen_Bool = 2 ; Eigentlich nur 1 Bit, wir nehmen aber 1 Byte !
Global Const $___HexLen_Keyword = 2 ; Wird nicht verwendet
Global Const $___MaxLen_String = 8 ; 2^32 Zeichen
Global Const $___MaxLen_Binary = 8 ; 2^32 Zeichen
Global Const $___MaxLen_FuncName = 2 ; 256 Zeichen
Global Const $___MaxLen_ArrayString = $___MaxLen_String
Global Const $___MaxLen_MapString = $___MaxLen_String
Global Const $___MaxLen_DllStructString = $___MaxLen_StringGlobal Const $___HexLen_ID = 2
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Global Const $___ID_Empty = '00'
Global Const $___ID_uInt8 = '01' ; Nur interne Benutzung
Global Const $___ID_uInt16 = '02' ; Nur interne Benutzung
Global Const $___ID_Int32 = '03'
Global Const $___ID_Int64 = '04'
Global Const $___ID_Double = '05'
Global Const $___ID_String = '06'
Global Const $___ID_Binary = '07'
Global Const $___ID_Ptr = '08'
Global Const $___ID_Bool = '09'
Global Const $___ID_Array = '0A'
Global Const $___ID_Function = '0B'
Global Const $___ID_Map = '0C'
Global Const $___ID_DllStruct = '0D'
Global Const $___ID_Keyword = '0E'; #FUNCTION# ====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Wandelt ein 1D oder 2D Array in einen String um
; ===============================================================================================================================
Func _ArrayToStringEx($aArray) ; Für 1D und 2D Arrays
If Not IsArray($aArray) Then Return
Local $iDim = UBound($aArray, 0)
If $iDim = 1 Then
Return BinaryToString('0x' & Hex($iDim, $___HexLen_ArraySubscripts) & StringTrimLeft(StringToBinary(__ArrayToString1D($aArray)), 2))
Else ; 2D
Local $aSub[2] = [UBound($aArray, 1), UBound($aArray, 2)], $sTmp = ''
Local $sRet = Hex($iDim, $___HexLen_ArraySubscripts) & Hex($aSub[0], $___HexLen_UBound) & Hex($aSub[1], $___HexLen_UBound)
For $i = 0 To $aSub[0] - 1 Step 1
$sTmp = StringTrimLeft(StringToBinary(__ArrayToString1D($aArray, $i)), 2)
$sRet &= Hex(StringLen($sTmp), $___MaxLen_ArrayString) & $sTmp
Next
Return BinaryToString('0x' & $sRet)
EndIf
EndFunc ;==>_ArrayToStringEx; #FUNCTION# ====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Wandelt einen String in ein 1D oder 2D Array um
; ===============================================================================================================================
Func _StringToArrayEx($sString)
If $sString = '' Then Return
__ValidString($sString)
Local $iDim = StringPopInt($sString, $___HexLen_ArraySubscripts)
If $iDim = 1 Then
Return __StringToArray1D($sString)
Else ; 2D
Local $aSub[2] = [StringPopInt($sString, $___HexLen_UBound), StringPopInt($sString, $___HexLen_UBound)]
Local $aRet[$aSub[0]][$aSub[1]], $iLen
For $i = 0 To $aSub[0] - 1 Step 1
$iLen = StringPopInt($sString, $___MaxLen_ArrayString)
Local $a = __StringToArray1D(StringPop($sString, $iLen))
For $o = 0 To $aSub[1] - 1 Step 1
$aRet[$i][$o] = $a[$o]
Next
Next
Return $aRet
EndIf
EndFunc ;==>_StringToArrayEx#Region - Internal
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]; #INTERNAL_USE_ONLY# ===========================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Hilfsfunktion für _ArrayToStringEx
; ===============================================================================================================================
Func __ArrayToString1D($aArray, $iIndex = 0)
If Not IsArray($aArray) Then Return
Local $iUBound
If UBound($aArray, 0) = 2 Then ; 2D Array
$iUBound = UBound($aArray, 2)
Local $aLinear[$iUBound]
For $i = 0 To $iUBound - 1 Step 1
$aLinear[$i] = $aArray[$iIndex][$i]
Next
$aArray = $aLinear
Else
$iUBound = UBound($aArray)
EndIf
Local $sTmp = '', $sRet = Hex($iUBound, $___HexLen_UBound)
For $i = 0 To $iUBound - 1 Step 1
Switch VarGetType($aArray[$i])
Case 'Int32'
If $aArray[$i] >= 0 And $aArray[$i] < 256 Then
$sRet &= $___ID_uInt8 & Hex($aArray[$i], $___HexLen_uInt8)
ElseIf $aArray[$i] >= 0 And $aArray[$i] < 65536 Then
$sRet &= $___ID_uInt16 & Hex($aArray[$i], $___HexLen_uInt16)
Else
$sRet &= $___ID_Int32 & Hex($aArray[$i], $___HexLen_Int32)
EndIf
Case 'Int64'
$sRet &= $___ID_Int64 & Hex($aArray[$i], $___HexLen_Int64)
Case 'Double'
$sRet &= $___ID_Double & Hex($aArray[$i], $___HexLen_Double)
Case 'String'
$sRet &= ($aArray[$i] = '' ? $___ID_Empty : $___ID_String & Hex(StringLen($aArray[$i]), $___MaxLen_String) & StringTrimLeft(StringToBinary($aArray[$i]), 2))
Case 'Binary'
$sRet &= $___ID_Binary & Hex(BinaryLen($aArray[$i]), $___MaxLen_Binary) & StringTrimLeft($aArray[$i], 2)
Case 'Ptr'
$sRet &= $___ID_Ptr & Hex($aArray[$i], $___HexLen_Ptr)
Case 'Bool'
$sRet &= $___ID_Bool & Hex($aArray[$i], $___HexLen_Bool)
Case 'Array'
$sTmp = _ArrayToStringEx($aArray[$i])
$sRet &= $___ID_Array & Hex(Int(StringLen($sTmp)), $___MaxLen_ArrayString) & StringTrimLeft(StringToBinary($sTmp), 2)
$sTmp = ''
Case 'Function'
$sRet &= $___ID_Function & Hex(StringLen(FuncName($aArray[$i])), $___MaxLen_FuncName) & StringTrimLeft(StringToBinary(FuncName($aArray[$i])), 2)
Case 'Map' ; ########## Nicht Implementiert ##########
Case 'DLLStruct' ; ########## Nicht Implementiert ##########
Case 'Keyword'
$sRet &= $___ID_Keyword & ($aArray[$i] = Default ? '01' : '00')
Case Else
ConsoleWrite('! Error: Unbekannter Variablentyp: ' & VarGetType($aArray[$i]) & @CRLF)
EndSwitchNext
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
Return BinaryToString('0x' & $sRet)
EndFunc ;==>__ArrayToString1D; #INTERNAL_USE_ONLY# ===========================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Hilfsfunktion für _StringToArrayEx
; ===============================================================================================================================
Func __StringToArray1D($sString)
If $sString = '' Then Return
__ValidString($sString)
Local $iUBound = StringPopInt($sString, $___HexLen_UBound)
Local $aRet[$iUBound], $sTmp = ''
For $i = 0 To $iUBound - 1 Step 1
$sTmp = StringPop($sString, $___HexLen_ID)
Switch $sTmp
Case $___ID_Empty
; Hier muss nichts gemacht werden
Case $___ID_uInt8
$aRet[$i] = StringPopInt($sString, $___HexLen_uInt8)
Case $___ID_uInt16
$aRet[$i] = StringPopInt($sString, $___HexLen_uInt16)
Case $___ID_Int32
$aRet[$i] = StringPopInt($sString, $___HexLen_Int32)
Case $___ID_Int64
$aRet[$i] = StringPopInt($sString, $___HexLen_Int64)
Case $___ID_Double
$aRet[$i] = __Double(StringPop($sString, $___HexLen_Double))
Case $___ID_String
$aRet[$i] = BinaryToString('0x' & StringPop($sString, 2 * StringPopInt($sString, $___MaxLen_String)))
Case $___ID_Binary
$aRet[$i] = Binary('0x' & StringPop($sString, 2 * StringPopInt($sString, $___MaxLen_Binary)))
Case $___ID_Ptr
$aRet[$i] = Ptr('0x' & StringPop($sString, $___HexLen_Ptr))
Case $___ID_Bool
$aRet[$i] = StringPopInt($sString, $___HexLen_Bool) = 1
Case $___ID_Array
$sTmp = _StringToArrayEx(StringPop($sString, 2 * StringPopInt($sString, $___MaxLen_ArrayString)))
$aRet[$i] = $sTmp
$sTmp = ''
Case $___ID_Function
$aRet[$i] = Execute(BinaryToString('0x' & StringPop($sString, 2 * StringPopInt($sString, $___MaxLen_FuncName))))
Case $___ID_Map ; ########## Nicht Implementiert ##########
Case $___ID_DllStruct ; ########## Nicht Implementiert ##########
Case $___ID_Keyword
$aRet[$i] = (StringPopInt($sString, 2) = 1 ? Default : Null)
Case Else
ConsoleWrite('! Error: Unbekannter Variablentyp: ID = ' & $sTmp & @CRLF)
EndSwitch
Next
Return $aRet
EndFunc ;==>__StringToArray1D; #INTERNAL_USE_ONLY# ===========================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Hilfsfunktion für _StringToArrayEx und __StringToArray1D
; ===============================================================================================================================
Func __ValidString(ByRef $sString)
If Not StringIsXDigit($sString) Then
If IsBinary($sString) Then
$sString = StringTrimLeft($sString, 2)
Else
$sString = StringTrimLeft(StringToBinary($sString), 2)
EndIf
EndIf
EndFunc ;==>__ValidString; #INTERNAL_USE_ONLY# ===========================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Description ...: Cast Hex64-String -> Double | _Double('400921F9F01B866E') = 3.14159
; ===============================================================================================================================
Func __Double($sHex64)
Local $vInt64 = DllStructCreate('INT64'), $nRet
DllStructSetData($vInt64, 1, '0x' & $sHex64)
Local $vDouble = DllStructCreate('Double', DllStructGetPtr($vInt64))
$nRet = DllStructGetData($vDouble, 1)
Return $nRet
EndFunc ;==>__Double#EndRegion - Internal
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
;EndRegion - Internal#Region - StringPop
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]; #INDEX# =======================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Title .........: StringPop
; AutoIt Version : 3.3.12.0
; Date ..........: 18.07.2014
; Language ......: Deutsch
; Description ...: Funktion um das Ende (links oder rechts) eines Strings abzuschneiden und zurückzugeben
; Author(s) .....: Mars
; ===============================================================================================================================; #CURRENT# =====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; StringPop
; StringPopInt
; ===============================================================================================================================; #FUNCTION# ====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Example .......: $s = '01234' | $sRet = __StringPopInt($s, 3) -> $s = '34' | $sRet = '012'
; ===============================================================================================================================
Func StringPop(ByRef $sString, $iCount = 1)
If $iCount > 0 Then
Local $sLeft = StringLeft($sString, $iCount)
$sString = StringTrimLeft($sString, $iCount)
Return $sLeft
Else
Local $sRight = StringRight($sString, -$iCount)
$sString = StringTrimRight($sString, -$iCount)
Return $sRight
EndIf
EndFunc ;==>StringPop; #FUNCTION# ====================================================================================================================
[/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]
; Author ........: Mars
; Example .......: $s = '01234' | $iRet = __StringPopInt($s, 2) -> $s = '234' | $iRet = Int(0x01) = 1
; ===============================================================================================================================
Func StringPopInt(ByRef $sString, $iCount = 1)
Return Int('0x' & StringPop($sString, $iCount))
EndFunc ;==>StringPopInt#EndRegion - StringPop
[/autoit]
;EndRegion - StringPop -
Ich habe das jetzt noch nicht getestet. Aber wenn es funzt, ist das eine ganz tolle UDF für mich, dieich häufiger benutzen werde. Vielen Dank mars
-
Andy: ich bin mir beinahe sicher, dass du mich für diese Vorgehensweise und diesem Code mit sofortiger Wirkung aus deiner Firma rauswerfen würdest
quatsch, gerade im Gegenteil! Sobald du erkennst, dass etwas nicht funktioniert und es daraufhin änderst, beweist du doch, dass dir etwas an der Lösung dieses Problems liegt!
Um noch eine weitere Anregung zu geben:
Erstelle eine einfache DLL mit einer simplen Funktion, welche dir einen bestimmten Wert (String) zurückgibt. Damit verifizierst du diese DLL als valide.
Nun schreibst du in das Codesegment, in dem irgendwelcher Mumpitz stehen kann, deine "Variablen", XORed mit dem zurückgegebenen "String" . Da du weißt, an welcher Position diese Daten stehen, kommst du über ein einfaches Fileread("blablub.dll") mit einigen Stringmid() an deine Daten.Wieso du Arrays für die Daten verwendest, verstehe ich nicht, aber naja, ich muss auch nicht alles verstehen
Anbei ein kurzes Script, wie man Daten aus einer DLL ausliest...
Die *.ASM-Datei einfach in FASMW.EXE laden. mit CTRL+F9 compilieren, die DLL ist aber auch angehängt.
Ist die DLL einmal erstellt, kann man simpelst die darin enthaltenen Daten per Stringreplace() ändern!So sind die Daten in einer "echten" DLL versteckt
Damit diese wirklich "unsichtbar" werden, könnte/sollte man sie bspw. per Base64 verschlüsseln, oder mit dem "Passwort" XORen, s.oben -
Danke Andy!
Ich habe bisher noch nie mit DLLs gearbeitet, weil ich es bis heute nur 1x gebraucht hatte und bei diesem einen mal konnte ich das (natürlich) umständlich umgehen.
Ist die DLL einmal erstellt, kann man simpelst die darin enthaltenen Daten per Stringreplace() ändern!
Verstehe ich das richtig? Ich kann dann Daten INNERHALB dieser DLL ändern, sodass beim nächsten Programmaufruf die geänderten/neuen Daten vorhanden sind?
Wenn das möglich ist, werde ich mich doch mal mit DLLs auseinander setzen. -
Verstehe ich das richtig? Ich kann dann Daten INNERHALB dieser DLL ändern, sodass beim nächsten Programmaufruf die geänderten/neuen Daten vorhanden sind?
Eine Datei ist eine Datei ist eine Datei.
Der Inhalt einer Datei besteht aus Bytes. Je nachdem, in welcher Folge diese Bytes angeordnet sind und je nach Struktur, kann man diese Bytes auslesen um Musik zu hören, Bilder anzuschauen oder Text zu lesen.
Im umgekehrten Weg muss man sich nur überlegen, in welcher Struktur diese Bytes vorliegen müssen, um ein bestimmtes Ergebnis zu erzielen.
Dann schreibt man einige Handvoll Bytes in eine Datei, vergibt eine "passende" Dateiendung und ein Programm kann diese Dateiinhalte darstellen.Meistens besteht die Struktur des Dateiinhalts aus einer Dateikennung, einem sog. "Header" mit der Beschreibung der Daten und den Daten selbst.
Bei einer Bitmap besteht der Dateiinhalt bspw. aus der Kennung BM, dann folgen 52 Bytes der Beschreibung des Bildes (Breite, Höhe, Farbtiefe usw) und dann die einfach nacheinander die "Pixelfarben". Die Dateiendung lautet dann .BMP
Nun kann dich niemand daran hindern, diese Daten so zu schreiben wie es dir passt. In der Bitmapdatei kannst du natürlich statt der "Pixelfarben" einfach Text oder "Musik" reinschreiben. Das sieht dann, wenn ein Bildanzeigeprogramm diese Datei öffnet, etwas seltsam aus, aber was solls...
Wichtig ist nur, die "Struktur" nicht zu überschreiben bzw. auch an die ggf. hinzugefügten Daten anzupassen.Eine Textdatei ist das einfachste lesbare Dateiformat, da stehen einfach nur Buchstaben, also "lesbare Bytes" hintereinander...
Allerdings kann jeder "Depp" diese Daten auch lesen, um "geheime" Daten dort abzuspeichern, sollten diese dann (mehr oder weniger kompliziert) verschlüsselt werden. Oder man "versteckt" diese Daten einfach innerhalb einer bestehenden, unschuldig ausssehenden Datei.Wenn man sich eine eigene Struktur überlegt, kann man ein eigenes Dateiformat erstellen, eine passende Dateiendung zur Kennzeichnung vergeben und hat ein eigenes Dateiformat kreiert! Wenn du ein Programm mit einigen Dateien weitergibst, deren Dateiendung .lottich oder .lot lautet, dann macht das eher Eindruck als ein schnödes .txt oder .bmp
In der oben angesprochenen DLL sind 10000 Bytes an "Nullbytes" enthalten. Das sind die Platzhalter um deine Daten zu verstecken.
Die Anfangsposition dieser Daten kann man sich entweder über eine Funktion in der DLL zurückgeben lassen, oder per stringinstr() suchen.
Am Anfang dieses Datenbereichs habe ich das Passwort (eigentlich Startwort) "Hallo AutoIt!" geschrieben. Dort dahinter hast du 10000 Bytes zum "rumspielen".
Du könntest auch einfach eine Datei mit 13649 Bytes "Müll" (zufällige Bytes ohne Sinn) erstellen und deine Daten hintendranhängen und dort hintendran nochmal 23814 Bytes "Müll", der Effekt wäre derselbe, allerdings sieht die Verwendung einer DLL schon "cool" aus. Obwohl sie nur ein "Textcontainer" ist.Per Fileread() den Inhalt der Datei lesen und mit stringinstr() die Startkennung ("Hallo AutoIt!") und Endekennung (das nächste Nullbyte) suchen ist im Script gezeigt.
Du kannst diese Daten einfach per Stringreplace() mit neuen oder anderen Daten ersetzen. Allerdings sollte die Anzahl der Bytes innerhalb der Datei konstant bleiben, sicher ist sicher.
Also die Bytes der DLL bis zum Start, dann deine Daten, dann "Müll"-Bytes bis 10000 Bytes erreicht sind, dann den "Rest" der DLL. Stringleft(), Stringmid() und Stringright() sind hervorragend dafür geeignet
Voila, wenn du nun die 10000 Bytes aus deinen Daten und darauffolgenden zufälligen Bytes erstellst, wird es auch "Profis" sehr schwer, deine Daten zu lesen.Zzt. ist das einfach, lade doch mal die lottich.dll in Scite
Wie man die "Nutzdaten" simpelst per XOR (und mit dem "Passwort" aus der DLL) in 3 Zeilen verschlüsselt, kannst du selbst rausfindenJetzt höre ich wieder das Gejaule derjenigen die rumheulen "Sowas braucht heutzutage kein Mensch mehr, nimm ne Datenbank oder verschlüssele mit ACE2048, DAS ist professionell!"
Das sind aber auch seltsamerweise genau diejenigen die dumm durch die Finger schauen wenn irgendetwas mit der DB oder ACE2048 nicht funktioniert. DANN muss ein anderer kommen und das Problem lösen, während Lottich mit einem Blatt Papier und einem Bleistift in der Hand in 10 Minuten an seine Daten kommt
Indem er eine DLL "knackt". Stimmt, "professionell" ist das nicht... -
OMG, ganz offensichtlich bin ich meinen ehemaligen DAU - Status doch noch nicht los. Bisher bin ich immer davon ausgegangen, das DLLs unveränderlich wären
und "nur" Funktionen enthalten, die Programme benötigen, damit sie funktionieren. Programmbibliothek eben.Das Paket, was ich von dir erhalten hab, wurde natürlich schon ausführlich von mir begutachtet und als fantastisch eingestuft. Jetzt heisst es für mich Infos
einzuziehen, was der DLL Code genau bedeutet und was du mit XOR meinst Man muss ja erstmal verstehen, was da passiert, bevor man anfangen kann,
vernünftig damit zu arbeiten. Dann werd ich jetzt mal anfangen Onkel Google zu nervenDanke Andy
(wärst du eine Frau, würd ich jetzt sagen: "Du bist ein Schatz!" ) -
Lottich:
letztendlich hat Andy einfach die Dateiendung DLL genommen... Es ist keine Bibliothek, sondern täuscht nur vor, eine zu sein.
Die zufälligen Bytes verstärken den eindrück noch. Wer rechnet denn auch damit, dass da die Infos nur mittendrin irgendwo stehen -
letztendlich hat Andy einfach die Dateiendung DLL genommen... Es ist keine Bibliothek, sondern täuscht nur vor, eine zu sein.
FALSCH!
Einmal in das AutoIt-Script geschaut wüßtest du das.....
Die DLL ist beigelegt, auch der Sourcecode der DLL.@Lottich,
das Knowhow kommt von alleine, learning by doing!
Und wenn du etwas nicht verstehst, frage nach! Wer hier im Forum ordentlich fragt, bezeugt sein Interesse sich weiterzuentwicken, solche Leute können wir hier brauchen! -
- Offizieller Beitrag
Lottich:
Hier mal ein Bsp., wie man ein eigenes Dateiformat aufbauen kann, mit allen Lese- und Schreibfunktionen. Für den 'Normaluser' sicher nicht zu lesen.CodeBeschreibung Byte Nr. Kurzname Inhalt Bedeutung 1 bis 3 TYP hex: 42 46 46 B F F - Dateityp (BugFix File Format) 4 bis 9 OPL 000000 - 999999 Länge einer folgenden optionalen Beschreibung (OPtional Length) 10 bis (9 + OPL) OPT beliebig optionale Beschreibung (OPtional Text) 10 + OPL bis (10 + OPL + nnn) SPM Random SPaM Bytes (beliebige Länge, durch min/max Konstanten bestimmt) ab 1. Trenner +3 STF verschieden STuFf - DER Inhalt der Datei, erkennbar durch Trennzeichenfolge
Um wirklich jede Form von Inhalten speichern zu können (auch Null-Bytes) ist das Verwenden eines einzelnen Zeichens zum Trennen problematisch.
Ich verwende einen 5-Byte Trenner: hex: 00 10 00 1A 00Um etwas Verwirrung zu stiften lasse ich meine Daten mit zusätzlichen 3 Bytes beginnen, die aus 2-mal '00' und 1-mal '20' kombiniert werden. ('00 00 20', '00 20 00', '20 00 00')
Somit kann ich beliebig viele "Spam-Blöcke" dazwischen setzen. Meine gesuchten Inhalte sind nur dort, wo nach dem Trenner eine Kombination der 3 Bytes zu finden ist.Es liesse sich noch zusätzlich ein Markersystem integrieren, indem ich festlege dass das erste Daten-Byte Auskunft über den folgenden Inhalt gibt. Z.B.
0E - Text jeder Art
0F - Icon
10 - BMP etc.
Dann könnte man ganz fix alle Daten eines Typs auslesen.
Alternativ kann man natürlich auch ausschliesslich mit einem identifizierenden Namen für die
Folgedaten arbeiten ('main.ico' etc.), den man dann mit einem Null-Byte von den eigentlichen Daten trennt.Hier nun das Bsp.:
AutoIt
Alles anzeigenGlobal Const $SPAM_MIN_LEN = 500 ; Mindestlänge für Spam Global Const $SPAM_MAX_LEN = 800 ; Maximallänge für Spam Global Const $DELIM = '0010001A00' ; Trenner zwischen Blöcken (Data-Spam) Global Const $PREFIX_1 = '000020' ; folgt dem Trenner als Kennung für Echtdaten Global Const $PREFIX_2 = '002000' ; ~"~ Global Const $PREFIX_3 = '200000' ; ~"~ ; Dateiname Local $sFile = 'MeinTest.BFF' ; Dateiendung nicht zwingend, funktioniert auch ohne oder mit irgendeiner anderen Endung. ; die zu schreibenden Daten Local $aText[] = ['Das ist ein Text.','Und hier ist noch ein Text.','Ein dritter Block.'] ; erstelle Datei (überschreibt Datei, falls sie existiert) _WriteBFF($sFile, $aText, 'Ein optionaler Kommentar beliebiger Länge') ; optionalen Text ausgeben $OptionalerText = _CheckBFF($sFile) ConsoleWrite('Optionaler Text: ' & $OptionalerText & @CRLF) ; Dateninhalte lesen $aData = _GetData($sFile) If IsArray($aData) Then For $data In $aData ConsoleWrite($data & @LF) Next ConsoleWrite(@CRLF) Else ConsoleWrite('Keine Daten!' & @CRLF) EndIf ; Inhalte ersetzen If Not _ReplaceData($sFile, 'Und hier ist noch ein Text.', 'NOW REPLACED') Then ConsoleWrite('Gesuchte Daten nicht enthalten' & @CRLF) Else $aData = _GetData($sFile) If IsArray($aData) Then For $data In $aData ConsoleWrite($data & @LF) Next ConsoleWrite(@CRLF) Else ConsoleWrite('Keine Daten!' & @CRLF) EndIf EndIf ; neue Inhalte hinzufügen _AddData($sFile, 'NEW_DATA') $aData = _GetData($sFile) If IsArray($aData) Then For $data In $aData ConsoleWrite($data & @LF) Next ConsoleWrite(@CRLF) Else ConsoleWrite('Keine Daten!' & @CRLF) EndIf ; ============================================================================ S C H R E I B E N === ; Alle Inhalte werden Zeichen für Zeichen als 2er Hex-String dargestellt ; ================================================================================================== Func _WriteBFF($sFile, $aData, $sOptText='') If Not IsArray($aData) Then $aData = StringSplit($aData, '__$STR_TO_ARRAY$__', 3) ; einzelnen String in Array stecken Local $iLenOpt = StringLen($sOptText) Local $sWrite = _ToHex('BFF' & StringFormat('%06i', $iLenOpt)) & ($iLenOpt ? _ToHex($sOptText) : '') & _Spam() For $i = 0 To UBound($aData) -1 ; jedem Daten-Block folgt ein Spam-Block $sWrite &= $DELIM & _Prefix() & _ToHex($aData[$i]) & $DELIM & _Spam() ; hier könnte man auch zusätzlich eine zufällige Anzahl von Spam-Blöcken (1 bis .. ) folgen lassen Next Local $fH = FileOpen($sFile, 2+8+16) FileWrite($fH, $sWrite) FileClose($fH) EndFunc ; ============================================================================ S C H R E I B E N === ; Return 1 wenn OK, 0 wenn $sSearch nicht gefunden ; ================================================================================================== Func _ReplaceData($sFile, $sSearch, $sReplace) $sSearch = _ToHex(_ToHex($sSearch) & $DELIM) Local $fH = FileOpen($sFile, 16) Local $sContent = FileRead($fH) FileClose($fH) Local $iPos = StringInStr($sContent, $sSearch) If $iPos Then $sContent = StringReplace($sContent, $sSearch, _ToHex(_ToHex($sReplace) & $DELIM)) $fH = FileOpen($sFile, 2+16) FileWrite($fH, $sContent) Return FileClose($fH) Else Return 0 EndIf EndFunc ; ============================================================================ S C H R E I B E N === ; Neue Daten hinzufügen ; ================================================================================================== Func _AddData($sFile, $sData) Local $fH = FileOpen($sFile, 1+16) FileWrite($fH, $DELIM & _Prefix() & _ToHex($sData) & $DELIM & _Spam()) FileClose($fH) EndFunc ; ==================================================================================== L E S E N === ; Prüfen ob Typ BFF stimmt ; wenn ja: Rückgabe optionaler Text (Text oder '') ; wenn nein: Rückgabe -1 ; $fGetOpenHwd=True: Rückgabe Array [$fH,Länge opt. Text] FileHandle mit Leseposition hinter Längenangabe ; ================================================================================================== Func _CheckBFF($sFile, $fGetOpenHwnd=False) Local $fH = FileOpen($sFile, 16) $sStart = _ToStr(_ToStr(Hex(FileRead($fH, 18)))) If StringLeft($sStart, 3) <> 'BFF' Then FileClose($fH) Return -1 Else Local $iLen = Int(StringRight($sStart, 6))*2 If $fGetOpenHwnd Then Local $aOut[2] = [$fH, $iLen] Return $aOut EndIf Local $sOut = $iLen > 0 ? _ToStr(_ToStr(Hex(FileRead($fH, $iLen)))) : '' FileClose($fH) Return $sOut EndIf EndFunc ; ==================================================================================== L E S E N === ; Alle Daten in einem Array ausgeben ; Erfolg: Rückgabe Array ; Fehler: Leersting, @error = 1 ; ================================================================================================== Func _GetData($sFile) ; Lesen starten an Position: hinter Längenangabe + min-Länge-Spam Local $aCheck = _CheckBFF($sFile, True) If Not IsArray($aCheck) Then Return SetError(1,0,$aCheck) Local $fH = $aCheck[0] FileSetPos($fH, $aCheck[1]+$SPAM_MIN_LEN*2, 1) ; akt.Pos=hinter Längenangabe --> +Länge opt.Text +min.LängeSpam Local $sContent = FileRead($fH) ; lesen bis zum Ende FileClose($fH) Local $aSplit = StringSplit($sContent, _ToHex($DELIM), 1) Local $iLenP = StringLen(_ToHex($PREFIX_1)), $aData[$aSplit[0]], $iIndex = 0 For $i = 2 To $aSplit[0] -1 Switch StringMid($aSplit[$i], 1, $iLenP) Case _ToHex($PREFIX_1), _ToHex($PREFIX_2), _ToHex($PREFIX_3) $aData[$iIndex] = _ToStr(_ToStr(StringTrimLeft($aSplit[$i], $iLenP))) $iIndex += 1 EndSwitch Next If $iIndex > 0 Then ReDim $aData[$iIndex] Else $aData = '' EndIf Return $aData EndFunc ; damit beginnt jeder echte Datenblock Func _Prefix() Local $aStart[3] = [$PREFIX_1, $PREFIX_2, $PREFIX_3] Return $aStart[Random(0, 2, 1)] EndFunc Func _ToHex($s) Local $sOut = '' For $char In StringSplit($s, '', 2) $sOut &= Hex(Asc($char), 2) Next Return String($sOut) EndFunc Func _ToStr($sHex) Local $sOut = '', $n = 1 While $n < StringLen($sHex) $sOut &= Chr(Dec(StringMid($sHex, $n, 2))) $n += 2 WEnd Return String($sOut) EndFunc Func _Spam() ; alle ASCII/ANSI Zeichen Local $sOut = '', $iRnd For $i = 1 To Random($SPAM_MIN_LEN, $SPAM_MAX_LEN, 1) $iRnd = Random(0, 255, 1) $sOut &= Hex(($iRnd <> 127 ? $iRnd : 0), 2) Next ; ausschliessen, dass Spam mit Datenkennung beginnt Switch StringLeft($sOut, 6) Case $PREFIX_1, $PREFIX_2, $PREFIX_3 $sOut = StringLeft($sOut, 4) & '7E' & StringTrimLeft($sOut, 6) EndSwitch Return String($sOut) EndFunc
-
Du meine Fresse, dass muss ich erstmal sacken lassen!
OFFTOPIC: Woher zum Henker weiss man sowas?!BugFix, ich werde diese Variante garantiert ausprobieren. Leider werde ich dabei vermutlich den oberen Code von dir 1:1 übernehmen müssen, denn für mich ist das "gehobene Klasse".
Ganz ehrlich, ich weiss grad nicht, was ich schreiben soll. Es ist ziemlich spät, bin müde und fühl mich grad von dieser Informationsflut ziemlich erschlagen und ein wenig gedemütigt -
- Offizieller Beitrag
Woher zum Henker weiss man sowas?!
Programmiertechnisch ist an dem Skript eigentlich nichts aussergewöhnlich. Ausschliesslich native AutoIt-Funktionen. Das einzige Wissen hierbei ist, wie Zeichen beim Wandeln von String zu Hex und umgekehrt aussehen. Dass man die Ascii 0-31 u. 127 (bis auf Tab und CR/LF) nicht für eine Konsolenausgabe verwenden kann, sollte auch bekannt sein. MIt solchen Zeichen also kein herkömmliches Debugging versuchen.
Und die Programmlogik ist dann das Umsetzen der Idee des Dateiaufbaus.
Wie Andy treffend bemerkte, besteht eine Datei doch eigentlich immer nur aus Strings. Man muss sie nur in zugriffsbereite Form bringen (binäres Lesen/Schreiben).Das schöne an einem eigenen Dateiformat: Du kannst es dir so stricken und so optimieren, dass es genau für deinen Bedarf passt. Hier ging es ja darum ein klein wenig Versteck zu spielen. Wenn es um schnelle Zugriffe geht, kannst du die Datei anders gestalten um z.B. mit gespeicherten Positionen ausschliesslich den gesuchten Inhalt zu lesen (und nicht erst die ganze Datei und dann mit StrInString die Position finden), wobei wir dann wieder bei einem Indexing sind. Es gibt also viele Möglichkeiten. Darum sollte man vor einem Projekt feststellen, welche Anforderungen bestehen.
Viel Spaß beim Probieren. -