使用ADODB更新.ACF文件中的adVarChar字段引发错误多步操作生成错误

时间:2018-11-06 07:00:21

标签: .net powershell adodb

我正在调试一个应用程序,发现它使用了.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

1 个答案:

答案 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更新命令接受。