我正在调试一个应用程序,发现它使用了.ACF文件中“ Db”字段中加密的数据库连接字符串。在确定如何编写解密/加密例程的过程中,我无法写回新值。
PowerShell代码片段示例:
Add-Type -Path C:\app\adodb.dll
Add-Type -TypeDefinition $decryptCode
$recordSet = New-Object ADODB.RecordsetClass
$recordSet.Open("c:\app\connectionstring.acf",[Type]::Missing,[ADODB.CursorTypeEnum]::adOpenKeySet,[ADODB.LockTypeEnum]::adLockBatchOptimistic)
$dbEncrypted = $recordSet.Fields["Db"].Value
"Current Connection String: $([Decryptor.NativeMethods]::Decrypt($dbEncrypted))"
# update connection string
$newConnectionString = "<blah blah blah>"
$recordSet.Fields["Db"].Value = [Decryptor.NativeMethods]::Encrypt($newConnectionString)
$recordSet.Save()
此代码读取连接字符串并解密。 IT还可以很好地加密新的连接字符串。但是,当尝试更新“ Db”字段时会引发错误:
异常设置“值”:“多步操作生成错误。 检查每个状态值。“在C:\ debugging \ Decryptor.ps1:329 char:1 + $ recordSet.Fields [“ Db”]。Value = [Decryptor.NativeMethods] :: Encrypt($ n ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~ + CategoryInfo:未指定:(:) [],SetValueInvocationException + FullyQualifiedErrorId:ExceptionWhenSetting
[Decryptor.NativeMethods] :: Encrypt返回一个字符串,尽管并非所有字符都是可打印的,并且该字符串比原始字符串长。
我可以将DB值设置为普通字符串,或者我刚刚从数据库中读取的字符串:
$recordSet.Fields["Db"].Value = $dbEncrypted
我认为可能是大小,因为原始的加密字符串为147个字符,但新的为179个字符。因此,我将新字符串切成147个字符,甚至更少,但仍然无法设置。所以我怀疑这是由于字符串的内容所致。
我要设置的字符串如下:
£àÌóÓàù:ÒJ·DµÕ1R |SÀgÐqíÀZ(Lá2!’'B $Rä!kýÈg\ ISXêmh®¾oÔçþOZißlß%¼ù@ ÆÿeæB¦vpâNÉoSÆ!fZÆÿ²ÔFôóóvºä2øg ¹¼
àU¸ÏAß0g§ÿ¨brÁƾ('îÙ2ÿééµHãhû
=¿6Å=#´ú½¬ö
$ recordSet显示以下值:
Properties : {IAccessor, IChapteredRowset, IColumnsInfo, IColumnsRowset...}
AbsolutePosition : 1
ActiveConnection :
BOF : False
Bookmark : 1
CacheSize : 1
CursorType : adOpenStatic
EOF : False
Fields : {DB}
LockType : adLockBatchOptimistic
MaxRecords : 0
RecordCount : 5
Source : c:\app\connectionstring.acf
AbsolutePage : 1
EditMode : adEditNone
Filter : 0
PageCount : 1
PageSize : 10
Sort :
Status : 8
State : 1
CursorLocation : adUseClient
MarshalOptions : adMarshalAll
DataSource : ADODB.RecordsetClass
ActiveCommand :
StayInSync : True
DataMember :
Index :
recordset.Fields [“ db”]的当前设置显示:
$ recordSet.Fields [“ Db”]
Status : 0
ActualSize : 147
Attributes : 4
DataFormat :
DefinedSize : 255
Name : DB
NumericScale : 0
OriginalValue :
Precision : 0
Properties : {BASECOLUMNNAME, BASETABLENAME, BASECATALOGNAME, BASESCHEMANAME...}
Type : adVarChar
UnderlyingValue :
Value : £àöÌóÓà™ù:Ò¡J·DµÕ1R|SÀgÐqíÀZ(Lá2 !¯'B$Rä\!kýȘg\ISX ê‰mh®¾ oÔçþOZißlß%¼ù€@Š˜ ÕeæB¦ëvpâNÉ
oSÆ!fZ–Æÿ²ÔFôó Ûvºä2øÀü"ëöÑ@Õ k§«üdÊ'Ó‹Û§1j©
$ recordSet.Fields [“ Db”]。属性包含
Attributes Name Type Value
---------- ---- ---- -----
1 BASECOLUMNNAME adVarWChar
1 BASETABLENAME adVarWChar
1 BASECATALOGNAME adVarWChar
1 BASESCHEMANAME adVarWChar
1 KEYCOLUMN adBoolean False
1 ISAUTOINCREMENT adBoolean False
1 RELATIONCONDITIONS adVarBinary
1 CALCULATIONINFO adVarBinary
1 OPTIMIZE adBoolean False
在进一步测试不同的字符串时,发现此字符串有效:
$recordSet.Fields["Db"].Value = "£àöÌóÓà"
但是此字符串不起作用:
$recordSet.Fields["Db"].Value = "£àöÌóÓà"
Exception setting "Value": "Multiple-step operation generated errors. Check each status value."
At line:1 char:1
+ $recordSet.Fields["Db"].Value = "£àöÌóÓà"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], SetValueInvocationException
+ FullyQualifiedErrorId : ExceptionWhenSetting
进一步的测试表明:
$broken = "£àöÌóÓà"
$working = "£àöÌóÓà"
# $broken.Length = 9
# $working.Length = 7
[System.Text.UTF8Encoding]::UTF8.GetBytes($working)
194
163
195
160
195
182
195
140
195
179
195
147
195
160
[System.Text.UTF8Encoding]::UTF8.GetBytes($broken)
194
163
195
160
195
182
195
140
195
179
195
147
195
160
194
129
194
153
答案 0 :(得分:0)
此问题是由加密例程中的一个缺陷引起的,该缺陷产生的外观看上去与正确的加密相同,但是结果字符串的字节表示形式有所不同。
已从反编译的DLL复制加密例程,并利用该函数将Byte数组转换为字符串:
private static string ByteArrayToString(byte[] Buffer)
{
StringBuilder builder = new StringBuilder(Buffer.Count);
foreach (byte num in Buffer)
{
builder.Append(Convert.ToString((char)num));
}
return builder.ToString();
}
我使用.NET内置转换方法替换了代码:
private static string ByteArrayToString(byte[] Buffer)
{
return Encoding.Default.GetString(Buffer.ToArray());
}
后一种方法生成的字符串在外观上相同,但逐字节不同,并且被ADODB更新命令接受。