我如何确定这个字符串是如何编码的,以便我可以复制它?

逆向工程 加密 编码 字符串 视觉基础 VB6
2021-07-05 15:45:53

一家朋友公司使用旧的 VB6 应用程序生成编码字符串,然后在他们同样陈旧和过时的数据库系统中使用。

他们让应用程序在独立模式下运行,因此我可以测试输入并让它生成编码输出,但他们希望将其迁移到基于 Web 的系统中以构建请求字符串,以防止有人必须在本地访问旧桌面。

Input: AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz
Output: ~^}]|\sSrRqQpPwWvVuUtTkKjJiIhHoOnNmMlLcCbBaA`@gGfFeE

Input: 1234567890
Output: 4=<3210765

Input: 1
Output: 5

Input: 12
Output: 65

Input: 123
Output: 765

关于我可以从哪里开始解决这个问题的任何想法?看起来它进行了单个字符编码,然后反转了字符串。

编辑:看起来有点复杂……如果输入交叉到一个新列中,它似乎减去 4?

Input: ?
Output: ;

Input: 789:;<=>?
Output: ;:98?>=<3

看起来应用程序可能正在使用多个定义?或者做某种类型的数学范围来确定加减?

ASCII 表

对我来说意义不大的反编译代码。

Private Sub CommandButton_Click() '408C90
  Dim var_44 As TextBox
  Dim var_48 As TextBox
  loc_00408CB5: var_8 = &H4010C0
  loc_00408D16: Set var_44 = Me
  loc_00408D25: var_28 = password.Text
  loc_00408D6D: Set var_44 = Len(var_28)
  loc_00408D7C: var_28 = password.Text
  loc_00408DBE: 
  loc_00408DC5: If Len(var_28) < 0 Then GoTo loc_00408EDA
  loc_00408DE5: var_54 = Me
  loc_00408DF2: var_64 = 1
  loc_00408DF9: var_6C = 2
  loc_00408E00: var_44 = 0
  loc_00408E07: var_5C = 9
  loc_00408E1C: var_28 = CStr(Mid$(vbObject, Len(var_28), 1))
  loc_00408E34: call __vbaStrI2(Asc(var_28) xor eax, Me, var_28, var_44, 0040856Ch, 000000A0h, 000000A0h, 000000A0h, 000000A0h)
  loc_00408E70: var_84 = var_24
  loc_00408E76: var_8C = 8
  loc_00408E81: Var_Ret_1 = CLng(__vbaStrI2(Asc(var_28) xor eax, Me, var_28, var_44, 0040856Ch, 000000A0h, 000000A0h, 000000A0h, 000000A0h))
  loc_00408E8C: var_5C = Chr(Var_Ret_1)
  loc_00408EA1: var_6C = var_24 & var_24
  loc_00408EC5: eax = var_5C Or FFFFFFFFh
  loc_00408ECB: var_5C Or FFFFFFFFh = var_5C Or FFFFFFFFh + Len(var_28)
  loc_00408ED5: GoTo loc_00408DBE
  loc_00408EDA: 
  loc_00408EF0: var_A0 = vbEmpty
  loc_00408F04: Set var_44 = Me
  loc_00408F0F: var_28 = ip.Text
  loc_00408F3B: Set var_48 = var_28
  loc_00408F4A: var_30 = User.Text
  loc_00408FC0: var_40 = "http://" & var_28 & "/login?name=" & var_30 & "&password=" & var_24
  loc_00408FCA: Me.MousePointer = var_40
  loc_0040902F: GoTo loc_00409081
  loc_00409080: Exit Sub
  loc_00409081: 
  loc_00409091: Exit Sub
End Sub
2个回答

编辑加密是与密钥 0x04 的按位异或(请参阅此答案的底部)

该应用程序使用一个简单的替换密码(或者,确切地说是带有移位 4 的凯撒密码),然后对函数执行 reverse()。

我们可以使用 python 的maketrans方法来控制它

方法 maketrans() 返回一个转换表,该表将 intabstring 中的每个字符映射到 outtab 字符串中相同位置的字符。然后这个表被传递给 translate() 函数。

例如,这是一个快速脚本,可以证明这是使用的加密:

from string import maketrans

# Define list of characters
chars = "AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz1234567890"  

# Perform Caesar Cipher on our string
cipher_chars = ""
for c in chars:
    cipher_chars+= chr(ord(c)+4)

# Create a translation table
transition = maketrans(chars, cipher_chars)

# We use "[::-1]" to reverse the string
def encrypt (plaintext):
    return plaintext.translate(transition)[::-1] 

让我们试试看:

encrypt("1")
'5'

encrypt ("12")
'65'

encrypt("123")
'765'

反之亦然:

encrypt("65")
'12'

encrypt("765")
'123'

编辑:

根据您添加的反编译代码以及@Ilmari 的精彩评论和回复,正确指出了以下发现:加密是与“0x04”的异或

这是更新后的encrypt功能:

def encrypt (plaintext):
    return ''.join(chr(ord(c) ^ 4) for c in plaintext)[::-1]

根据您的示例,看起来字符串是颠倒的,并且每个字节都与字节 4进行异或运算。这是一个快速的 Perl 单行代码来演示这一点:

perl -lne 'print reverse($_) ^ ("\x04" x length($_))'

以及将其应用于测试字符串时会发生什么:

$ cat test.txt
AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz
1234567890
1
2
123
?
789:;<=>?

$ perl -lne 'print reverse($_) ^ ("\x04" x length($_))' test.txt 
~^}]|\sSrRqQpPwWvVuUtTkKjJiIhHoOnNmMlLcCbBaA`@gGfFeE
4=<3210765
5
6
765
;
;:98?>=<3

如果你比较的加密,输入字符串被逆转的事实是很明显的1526123765

在弄清楚这一点并猜测其余部分只是一个字节替换密码之后,您可以通过查看字母的加密来找出替换的模式。具体来说,我们可以看到(忽略反转),字母:

ABCDEFGHIJKLMNOPQRSTUVWXYZ

加密为:

EFG@ABCLMNOHIJKTUVWPQRS\]^

注意到ASCII 中的@就在 之前A`同样在 之前a),我们可以看到加密的字母表以 4 个字母为一组进行混洗:

Input:  ABC DEFG HIJK LMNO PQRS TUVW XYZ
Output: EFG @ABC LMNO HIJK TUVW PQRS \]^

我们还可以看到映射是自逆的:HIJK加密到LMNOLMNO加密回HIJK这与字母位置交换的常规模式一起,应该是一个非常强烈的暗示,表明我们可能正在处理按位异或。比较任何一对明文/密文字母的 ASCII 码就足以揭示常量密钥字节(然后我们可以在其他已知输入字符串上测试以确认我们的猜测)。