首页
社区
课程
招聘
[翻译]Powershell 代码反混淆技术研究
2018-11-28 21:25 13547

[翻译]Powershell 代码反混淆技术研究

2018-11-28 21:25
13547

安全专业人员很早意识到一件令他们头疼的事情,那就是攻击者喜欢让他们的工作变得更加复杂。攻击者们有一系列技术来混淆自己的地理位置,网络流量,原始代码指令。这些行为使得防御者更难以发现并阻止他们,毕竟防御者很难找到攻击痕迹,即使找到了也难以理解那些混淆过后的数据。在编程领域,混淆就是使用语言的特性和技巧来创建一个易于机器读取,但人眼很难识别的命令。

 

混淆技术在不断发展,但幸运的是,防御者也逐渐意识到并发展了与之对应的反混淆技术。正如我今年上半年在BSides Charm上所介绍的,现在有一些令人兴奋的方法可以应用机器学习(ML)来对抗PowerShell的混淆技术。 但是在正式开始之前,让我们先了解一些常见的混淆技术,尤其关注攻击者对于PowerShell的混淆。

PowerShell脚本混淆

PowerShell功能十分强大。它旨在从命令行自动执行任务并解决配置管理的问题,由此创建了许多重要工具。PowerShell有很多优点:例如易于导入模块,能够访问核心API和远程命令,也正是由于这些优点使其成为攻击者执行无文件攻击的首选工具之一。使用本地或预先安装的工具来进行攻击已经越来越受欢迎,至少部分是由于基于文件的AV系统(例如ML引擎)的进步以检测从未见过的攻击。

 

对分析师和防御者来说,可以通过记录PowerShell命令并捕获脚本文件以进行分析。这使安全人员有机会在系统被入侵后取证,以了解攻击者的行为以及获取的成果(是否攻击成功。不过,攻击者可不喜欢这样做(this 代指上文取证工作,是说不会让安全人员轻易进行有效取证),所以他们经常会对命令进行模糊处理和编码,以阻止和减慢分析人员的速度。

 

每种语言都有自己的混淆方法,其中有许多都是通用的。对于PowerShell而言,以下是一些常见的方法:


  • PS(PowerShell)中一些变量/名称不区分大小写
  • 将单词进行分割。分割后的每个部分可能是也可能不是一个单词。
    将单词进行分割,分割后的每个部分可能是也可能不是一个单词
  • 通常用于将变量插入到命令语句中,在这种情况下,它用于打乱字符串。
    通常用于将变量插入到命令语句中,在这种情况下,它用于打乱字符串

  • 反引号可以用作连接字符,有时也可以表示特殊字符。但是,如果在变量的中间使用反引号,它会连接同一行的前后连个字符

  • 将字符串转换为命令操作

  • 空格在某些操作中无关紧要,因此添加它只是为了使阅读变得更麻烦

  • 用代表特定字符的ascii码的值替换字符

还有更复杂的混淆方法,如变量创建和替换。混淆器将随机变量定义为字符串的全部或部分,并通过文件在该字符串的位置插入/替换它的地方。 有许多方法可以实现替换。以下是几个例子:

  • 格式化操作符
    输入:
    {1}PSScriptRoot{0}..{0}PSVersionCompare.psd1 -F  ‘\’,’$’
    
    输出:
    $PSScriptRoot\..\PSVersionCompare.psd1
    
  • 替换功能
    输入:
    (pZyPSScriptRoot\Add-LTUser.ps1).replace('pZy',’$’)
    
    输出:
    $PSScriptRoot\Add-LTUser.ps1
    

还有更多的例子我们没有详细列举,由于篇幅有限这里只能列举一部分,但是它们都是可以解决的。

 

使用Daniel Bohannon的Invoke-Obfuscation模块可以轻松使用以上列出的和更多没有列出的混淆方法。它是我们研究中所有混淆和编码工作的首选来源。

 

使用Invoke-Obfuscation,我们可以同时使用多个模糊处理方式,例如:
混淆之前:

$packageName = 'kvrt'
$url = 'http://devbuilds.kaspersky-labs.com/devbuilds/KVRT/latest/full/KVRT.exe'
$checksum = '8f1de79beb31f1dbb8b83d14951d71d41bc10668d875531684143b04e271c362'
$checksumType = 'sha256'
$toolsPath = "$(Split-Path -parent $MyInvocation.MyCommand.Definition)"
$installFile = Join-Path $toolsPath "kvrt.exe"
try {
  Get-ChocolateyWebFile -PackageName "$packageName" `
                        -FileFullPath "$installFile" `
                        -Url "$url" `
                        -Checksum "$checksum" `
                        -ChecksumType "$checksumType"

  # create empty sidecars so shimgen only creates one shim
  Set-Content -Path ("$installFile.ignore") `
              -Value $null

  # create batch to start executable
  $batchStart = Join-Path $toolsPath "kvrt.bat"
  'start %~dp0\kvrt.exe -accepteula' | Out-File -FilePath $batchStart -Encoding ASCII
  Install-BinFile "kvrt" "$batchStart"
} catch {
  throw $_.Exception
}

图表1:原始Powershell脚本示例

 

混淆之后:

${P`ACka`Ge`NAMe} = ("{0}{1}" -f 'kv','rt')
${U`RL} = ("{4}{11}{0}{6}{10}{3}{7}{2}{13}{15}{1}{16}{5}{8}{9}{14}{12}"-f'persky-','il','com/dev','bs','http:/','/','l','.','KVR','T/late','a','/devbuilds.kas','T.exe','b','st/full/KVR','u','ds')
${Check`s`UM} = ("{15}{16}{10}{3}{11}{6}{14}{9}{4}{5}{13}{1}{8}{7}{12}{2}{0}"-f 'c362','84143b0','71','79beb31f1d','1','bc','495','e','4','d71d4','e','bb8b83d1','2','10668d8755316','1','8f','1d')
${C`HE`cksu`m`TYpe} = ("{1}{0}" -f'56','sha2')
${T`Ool`s`PATH} = "$(Split-Path -parent $MyInvocation.MyCommand.Definition) "
${instALL`F`i`Le} = .("{0}{2}{1}{3}" -f'J','-Pa','oin','th') ${tOO`lSP`ATh} ("{0}{1}{2}" -f 'k','vrt.e','xe')
try {
&("{2}{5}{0}{4}{3}{1}" -f'colateyWe','e','Ge','Fil','b','t-Cho') -PackageName "$packageName" `
-FileFullPath "$installFile" `
-Url "$url" `
-Checksum "$checksum" `
-ChecksumType "$checksumType"

&("{2}{3}{0}{1}"-f '-','Content','Se','t') -Path ("$installFile.ignore") `
-Value ${nu`Ll}

${B`At`C`HSTart} = &("{0}{2}{1}{3}"-f 'J','i','o','n-Path') ${TOol`s`patH} ("{0}{2}{1}" -f 'k','.bat','vrt')
((("{1}{2}{3}{4}{5}{7}{0}{6}"-f'ce','start ','%','~dp0{0','}k','vrt','pteula','.exe -ac'))-f [CHar]92) | .("{0}{1}{2}"-f 'Out-','Fi','le') -FilePath ${BA`T`c`hstARt} -Encoding ("{0}{1}"-f 'AS','CII')
&("{1}{0}{3}{2}"-f'l-','Instal','nFile','Bi') ("{0}{1}"-f 'k','vrt') "$batchStart"
} catch {
throw ${_}."E`X`CEPtiOn"
}

图表2:通过Invoke-Obfuscation进行模糊处理后的Powershell脚本示例

编码技术

文本也可以转换为其他字符映射方案,进一步模糊。本文我们只关注两种方案:ascii转成hex以及ascii转成decimal。例如,'A'可以用十六进制表示为'41',用十进制表示为'65','['用十六进制表示为'5B',用十进制表示为'91'。

 

对PowerShell脚本进行完全编码需要一些额外的逻辑,解释器可以使用这些逻辑来解码文本。使用十进制编码的示例脚本如下所示:

.((gET-varIAble '*MDR*').nAME[3,11,2]-JoiN'')([chAR[]] ( 36,112, 97, 99,107, 97 ,103, 101 , 78 , 97 ,109, 101 ,32 ,61 ,32 , 39 , 107 , 118,114 , 116 ,39 , 10 , 36 ,117 ,114 ,108 , 32 ,61 , 32,39,104 , 116, 116, 112,58,47 , 47 , 100 , 101 ,118, 98, 117 , 105, 108, 100 , 115,46, 107 , 97 , 115,112, 101,114,115, 107, 121,45,108,97, 98 , 115, 46 , 99 , 111 , 109 , 47, 100 ,101, 118 , 98 ,117,105, 108 , 100,115,47 ,75 , 86 ,82, 84,47 ,108 , 97, 116 ,101, 115 ,116,47 ,102 ,117, 108,108,47, 75 , 86,82 , 84 ,46, 101 ,120 ,101, 39, 10 , 36,99 , 104,101 ,99 , 107 ,115,117 , 109, 32 ,61,32, 39 , 56, 102, 49,100 ,101, 55,57 , 98, 101 , 98,51, 49 , 102,49, 100, 98 ,98,56,98 , 56,51,100, 49, 52, 57, 53 ,49,100,55, 49,100,52 , 49 , 98,99,49 ,48 , 54, 54, 56 , 100 , 56, 55, 53 ,53 , 51,49 , 54 , 56 , 52,49, 52 ,51 ,98, 48 , 52 , 101 ,50 , 55 , 49, 99 , 51 ,54, 50, 39 , 10 ,36, 99,104 , 101, 99 ,107, 115 ,117 , 109,84,121, 112, 101,32, 61,32 ,39, 115 , 104 , 97 , 50, 53,54 ,39 , 10 ,36 , 116 ,111 ,111 , 108 , 115, 80 ,97,116 ,104, 32, 61 , 32 ,34, 36,40 , 83 , 112 ,108, 105 , 116 , 45 , 80,97, 116 ,104, 32,45 ,112, 97 , 114 , 101, 110 ,116 ,32 , 36, 77 ,121 ,73 , 110, 118 ,111, 99 ,97, 116 , 105 ,111,110, 46, 77, 121 ,67 , 111,109, 109, 97, 110 , 100 ,46 , 68, 101 ,102,105 ,110, 105 , 116 , 105, 111, 110,41,34 ,10 , 36,105,110 , 115 , 116 , 97 ,108 ,108, 70 , 105, 108 ,101,32, 61 ,32, 74,111 , 105 ,110 ,45 , 80 ,97, 116, 104, 32 ,36, 116 , 111,111,108, 115 , 80 , 97,116,104,32 ,34,107, 118,114, 116 , 46,101,120,101, 34, 10, 116 , 114 , 121, 32,123 ,10 , 32,32, 71 ,101 , 116, 45, 67,104, 111 , 99 , 111 , 108,97, 116,101 , 121, 87, 101, 98, 70,105, 108,101 , 32 ,45 ,80, 97, 99,107,97, 103 , 101,78,97, 109, 101 , 32,34, 36, 112,97 ,99, 107, 97,103 , 101 , 78 , 97 , 109 ,101,34 , 32 , 96,10,32, 32,32 ,32 ,32 ,32,32,32 , 32, 32,32, 32 ,32,32, 32,32 , 32 ,32, 32 ,32 ,32, 32,32,32, 45,70,105 ,108 , 101, 70,117 , 108 ,108 ,80,97,116 ,104, 32, 34, 36,105 ,110 , 115 , 116 , 97,108, 108 , 70 ,105 ,108, 101 ,34, 32,96 ,10 , 32, 32,32 , 32 ,32,32,32 ,32 , 32,32, 32 ,32,32 , 32 , 32,32, 32,32 , 32, 32 ,32 ,32 , 32 ,32 ,45,85 , 114, 108, 32 , 34,36, 117, 114 , 108,34 ,32 ,96,10 , 32,32,32,32,32 , 32 , 32 ,32 ,32 ,32 ,32 ,32,32 , 32, 32,32 , 32,32, 32 ,32 ,32, 32 ,32 , 32,45,67 ,104 ,101, 99 , 107 , 115 , 117, 109 ,32 , 34 , 36 ,99,104,101, 99 , 107,115, 117 , 109 ,34,32, 96,10,32,32, 32 ,32, 32,32 ,32 , 32 , 32 ,32 , 32 , 32,32 , 32, 32, 32 ,32 ,32 , 32, 32 ,32, 32,32, 32,45,67,104 , 101 , 99 , 107,115 ,117 , 109 , 84 , 121 , 112, 101, 32 ,34,36, 99, 104,101, 99,107,115 , 117 , 109, 84, 121,112, 101, 34 , 10, 10, 32 ,32 , 35 , 32, 99 ,114 ,101 , 97 ,116 ,101 , 32 ,101,109, 112,116 , 121,32, 115 ,105 ,100 , 101 ,99 ,97, 114 ,115 ,32 ,115 ,111 ,32, 115 ,104 ,105 ,109,103 , 101 , 110 ,32,111 ,110,108 , 121,32,99 ,114 ,101 ,97 , 116 , 101, 115 , 32, 111 ,110 , 101 , 32,115 , 104 ,105 ,109, 10,32 , 32,83 , 101 , 116 , 45 ,67,111, 110 ,116 ,101,110 , 116, 32 ,45 ,80 , 97, 116 ,104, 32, 40 ,34,36,105,110, 115,116,97, 108,108, 70 ,105, 108,101 , 46 , 105 ,103, 110,111 , 114 , 101 , 34 ,41, 32, 96 , 10 , 32,32 , 32, 32,32 , 32,32 , 32, 32 ,32, 32,32,32 , 32 , 45,86,97, 108 ,117 ,101 , 32 , 36 , 110 , 117 , 108, 108 , 10, 10 ,32, 32, 35,32 , 99 , 114,101 , 97 ,116 ,101 , 32 , 98 ,97 ,116 , 99,104 , 32 ,116 , 111 ,32,115, 116, 97,114, 116, 32 , 101, 120 , 101 ,99 , 117 , 116, 97 ,98 , 108 ,101, 10,32 , 32 , 36 ,98 ,97, 116 , 99 , 104, 83,116, 97 ,114 , 116 ,32,61, 32 ,74,111,105, 110, 45, 80, 97, 116 , 104,32, 36 , 116 , 111,111,108,115, 80,97 , 116,104,32 , 34 ,107 , 118, 114,116 , 46 , 98 ,97 , 116 , 34 ,10,32, 32 , 39,115 ,116,97 , 114, 116,32,37, 126,100, 112, 48 ,92, 107,118 ,114, 116, 46 , 101, 120,101 , 32 , 45 ,97, 99, 99 ,101 , 112 , 116 ,101 ,117 ,108, 97 ,39 , 32,124, 32 ,79 , 117, 116, 45,70, 105 , 108, 101 , 32 , 45, 70 ,105 ,108 ,101 ,80, 97 ,116,104, 32 ,36,98, 97, 116,99 ,104, 83 ,116, 97 ,114 , 116 ,32, 45 , 69, 110 , 99 ,111 , 100 , 105,110, 103 ,32 ,65 , 83,67, 73,73, 10 ,32, 32 ,73,110, 115, 116 ,97 , 108,108 , 45 , 66,105 , 110,70,105, 108 , 101 , 32,34 , 107,118 ,114, 116 , 34 , 32 ,34,36, 98 , 97 , 116, 99 , 104, 83 , 116 ,97, 114,116 ,34,10, 125 ,32 ,99,97 , 116,99,104 ,32, 123,10 , 32 , 32 ,116 , 104, 114 , 111 , 119 ,32 , 36 , 95, 46, 69 ,120 , 99, 101 ,112 ,116 ,105 ,111 , 110 , 10,125 )-jOIN'')

图3:通过Invoke-Obfuscation进行编码后的Powershell脚本示例

 

您可能会注意到,在此示例中,甚至用于解码序列的逻辑也会被混淆。Invoke-Obfuscation真正做到了在脚本中执行数字。

如何反混淆

为了解决这个问题,我们创建了一系列操作来解决出现的每个问题。

 

首先,我们收集数据并构建分类器以确定样本是否经过编码,模糊处理,或者未经混淆。样本可能同时经过了模糊处理和编码,因此我们需要重复使用此分类器以确保我们的最终结果是有效的。然后我们迭代地调用解码和反混淆逻辑,同时检查每个应用程序的输出以查看是否需要更多工作。最后,我们实现了一个清理神经网络,一种新的反混淆方法,以修复一些在混淆中出现的仅靠简单逻辑无法处理的比特位。
图4:反混淆逻辑流程
图4:反混淆逻辑流程

如何实现

我们的第一个任务是创建一些可以确定样本是编码,混淆还是未经混淆的普通文本。为此,我们构建了一个机器学习分类器来自动识别。

构建状态分类器

用于构建和训练分类器的典型机器学习方法是:

 

1.使用标签收集大量标记好的样本(例如十六进制编码,混淆,纯文本)
2.采集样本的数字特征
3.使用选择好的算法进行训练

图5:分类器流程

 

通常,构建分类器最困难的部分是获取样本和标签。收集样本的方法可以从文件共享服务下载或从Github上去查找来解决。幸运的是,在我们拥有PowerShell脚本示例语料库之后,我们可以使用Invoke-Obfuscation按需生成模糊和编码的样本。

 

接下来是为我们的样品提取特征。对于分类器来说,文本可能有点棘手。 经典的机器学习方法(例如,训练逻辑回归模型)是手工定义和生成样本的摘要统计和其他相关特征,例如:

  • 字符
  • 元音
  • `标记
  • 数字

但是,这些特征往往不能很好地表达字符之间的关系。

 

于是,我们将使用一种称为LSTM的神经网络。

 

LSTM(长短期记忆)网络是专门的RNN(循环神经网络)。这些网络非常有用,因为它们保留了先前状态的存储器,并将其与当前输入结合使用以确定下一个状态。 这里有一个很好的解释性博客,介绍LSTM是什么以及它们是如何运作的,或者也可以看看我们之前关于构建LSTM以检测域生成算法的一些研究

图6:LSTM图

 

上来就接触神经网络似乎有点令人生畏,但是高级管理框架使初始应用程序非常容易,并不是那么困难。

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20)
model = Sequential()
model.add(Embedding(num_encoder_tokens, embedding_vector_length, input_length=sample_len))
model.add(LSTM(100))
model.add(Dropout(0.2))
model.add(Dense(len(classes), activation='sigmoid'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
print(model.summary())
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)

可以看到,使用短短不到十行代码,我们就可以获取输入数据,创建一个简单的网络并进行训练。

解码


图7 通过Invoke-Obfuscation进行编码后的Powershell脚本示例

 

如果你了解编码映射关系并知道何时应用逻辑,则解码可能是一个相对简单的过程。这正是PowerShell解释器所做的,重新实现是上面示例的有效方法。

 

但是,我作为一名数据科学家,在这里看到了一种特定格式。你知道用什么做格式匹配最好吗,肯定是正则表达式!

ascii_char_reg = r'([0-9]{1,3})[, \)]+'
ascii_chars = re.findall(ascii_char_reg, file_text)
chars = [chr(int(ac)) for ac in ascii_chars]
file_text = ''.join(chars)

使用基于正则表达式的的解决方案,我们只需几行代码即可创建解码器。它在样本的开头和结尾处对编码器逻辑的混淆也很稳健,并且它可以PowerShell脚本之外运行,因此它是可推广的。

反混淆

大部分的反混淆可以通过简单的逻辑来处理:连接字符串,删除`s,替换变量等。
其中一些转换很容易:

def remove_ticks(line):
line = line[:-1].replace('`', '') + line[-1]
return line
def splatting(line):
splat_reg = r"""(&\( *['"]{1}(.+)?['"]{1} *?\))"""
matches = re.findall(splat_reg, line)
for match in matches:
line = line.replace(match[0], match[1])
return line
def string_by_assign(line):
match_reg = r'(?:(\[[sS][tT][rR][iI][nN][gG]\])([\[\]A-Za-z0-9]+)[\)\,\.]+)'
matches = re.findall(match_reg, line)
for match in matches:
replace_str = match[0] + match[1]
line = line.replace(replace_str, "'" + match[1] + "'")
return line

有些就会变得复杂一些。对于基于'-f'(格式运算符)的字符串乱序,我们如下操作:

 

1.通过char字符串处理来查找'-f'或'-F'
2.在'-f'之前找到所有{[0-9] +}类型的占位符
3.找到所有字符串和有效的非字符串值
4.用值替换占位符
5.迭代,因为你可以在同一行中多次这样做。

 

这有点单调乏味,并且有多种方法可以做到这种效果。但是总的技术是有限的,所以即使我们没有在我们的实现中枚举每个解决方案,它肯定是一个可解决的问题。

 

在集成了所有这些反混淆技术并按顺序应用它们之后,我们可以看到代码的执行情况。

 

反混淆之前:

param
(
[Parameter(MANdAtORy=${FA`L`SE})] ${dO`m`AiN} = ("{2}{1}{0}{3}" -f 'a','rtr','ai','n.com'),
[Parameter(MandatOrY=${tr`UE})] ${Sr`NUM`BER},
[Parameter(mAnDATORY=${F`AL`SE})] ${targET`p`Ath} = ("{10}{11}{1}{2}{9}{14}{3}{12}{5}{7}{4}{0}{8}{13}{6}" -f'=a','=Airtr','a','ir',',DC','a','C=com','n','i','n','OU=Disab','led,OU','tr','rtran,D',' Users,OU=A'),
[Parameter(ManDAtOrY=${T`RUe})] ${us`er}
)

if (&("{2}{1}{0}"-f'Path','est-','T') ${US`eR})
{
${USER`li`sT} = &("{0}{2}{3}{1}" -f'Ge','nt','t-','Conte') -Path ${u`SEr}
}
else
{
${usER`L`ISt} = ${Us`Er}
}

${c`oNT`AIneR} = ("{3}{11}{4}{8}{5}{0}{7}{10}{6}{2}{1}{9}" -f'ir','irtran,',',DC=a','OU','a',',OU=A','an','tran Users,OU=Air','bled','DC=com','tr','=Dis')
${D`eS`CrIP`TIon} = ('Term'+'ina'+'ted '+'per'+' '+"$SrNumber")

foreach (${uS`eR} in ${U`S`E`RList})
{
.("{2}{0}{1}" -f'et','-ADUser','S') -Identity ${Us`ER} -Server ${D`OM`AIN} -Enabled ${FA`LsE} -Description ${D`eSCrI`P`TION}
${UsE`RHan`dlE} = &("{2}{0}{1}"-f'U','ser','Get-AD') -Identity ${us`eR} -Server ${Do`M`AiN}
&("{3}{1}{2}{0}" -f't','je','c','Move-ADOb') -Identity ${uSe`Rh`AnD`Le} -Server ${doM`A`In} -TargetPath ${C`O`Nt`Ainer}
}

图8:混淆的样本

 

反混淆之后:

param
(
[Parameter(MANdAtORy=${FALSE})] ${dOmAiN} = "airtran.com",
[Parameter(MandatOrY=${trUE})] ${SrNUMBER},
[Parameter(mAnDATORY=${FALSE})] ${targETpAth} = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com",
[Parameter(ManDAtOrY=${TRUe})] ${user}
)
if ("Test-Path" ${USeR})
{
${USERlisT} = "Get-Content" -Path ${uSEr}
}
else
{
${usERLISt} = ${UsEr}
}
${coNTAIneR} = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com"
${DeSCrIPTIon} = ('Terminated per $SrNumber")
foreach (${uSeR} in ${USERList})
{
"Set-ADUser" -Identity ${UsER} -Server ${DOMAIN} -Enabled ${FALsE} -Description ${DeSCrIPTION}
${UsERHandlE} = "Get-ADUser" -Identity ${useR} -Server ${DoMAiN}
"Move-ADObject" -Identity ${uSeRhAnDLe} -Server ${doMAIn} -TargetPath ${CONtAiner}
}

图9:部分反混淆之后的样本

 

效果不算太差!但是仍然存在一些错误,并且大多数都很相似,看起来像:

(MAndatoRy = $ {fAlSe})] $ {dOMAiN}

这种随机化情形是一种与我们之前看到的不同类型的问题。它使代码更难阅读,但不能将PowerShell函数应用为混淆。 虽然我们讨论的所有先前技术都可以向后运行以获得原始输入,但随机方案却不能。 为此,我们需要一种不同的技术。

逆向不可逆函数

这是事情变得有趣的地方。为了更进一步,我们将使用神经网络来学习,有时记住变量应该是什么样子。
如果您看到了示例:

MOdULEDiRectORy

根据您的英语和编程知识,您可能会拼接出一个有具体含义的例子。也许是以下其中一个:

  • ModuleDirectory
  • moduleDirectory
  • moduledirectory

为了模仿这种认知,我们将训练一个Seq2Seq网络。Seq2Seq代表序列到序列。它是一种经常用于机器翻译的网络。

 

Seq2Seq使用LSTM(参见我们之前的文本分类器)来创建编码器网络以转换起始文本,并使用解码器网络来使用编码器输出和解码器存储器。结合这些,我们能够按字符输入输入字符并预测输出。 Keras有一个很好的博客,解释如何创建和训练其中一个网络。我们的代码通常都是参考他们的示例。

 

我们最初尝试使用此网络来翻译整行。由于Seq2Seq网络根据输入字符和最后预测的输出字符逐字符构建输出字符,因此我们可以看到测试如何与输入一起进行。它开始效果很好:
输入:

变成(看起来不错):

然后(开始出错):

最后(彻底跑偏):

 

一旦开始出错,它就会彻底失控。

 

为了解决错误的预测,我们对这个问题进行限制,并在每一行中选择“单词”作为最小单位。

 

1.在混淆和未混淆文件中找到相应的单词
2.获取可以被随机混淆的大多数变量和关键字
3.使用混淆的单词作为输入,使用未混淆的单词作为所需输出
4.使用先前的预测和新的输入数据预测下一个字符

 

重新训练的网络偶尔有一些有趣的问题:

但一般情况下表现得相当不错:

汇总

现在我们有了文件状态分类器,解码器,反混淆器和清理网络,我们已准备好将它们一起打包成一个功能并进行测试。

 

我们的总体流程如下:

图10:反混淆逻辑流程

 

让我们从一个非混淆的文件开始:

param
(
[Parameter(Mandatory=$false)] $Domain = 'airtran.com',
[Parameter(Mandatory=$true)] $SrNumber,
[Parameter(Mandatory=$false)] $TargetPath = 'OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com',
[Parameter(Mandatory=$true)] $User
)

if (Test-Path $User)
{
$UserList = Get-Content -Path $User
}
else
{
$UserList = $User
}

$Container = 'OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com'
$Description = "Terminated per $SrNumber"

foreach ($User in $UserList)
{
Set-ADUser -Identity $User -Server $Domain -Enabled $false -Description $Description
$UserHandle = Get-ADUser -Identity $User -Server $Domain
Move-ADObject -Identity $UserHandle -Server $Domain -TargetPath $Container
}

图表11:原始样本

 

我们使用一组随机技术对其进行混淆处理:

param
(
[Parameter(MANdAtORy=${FA`L`SE})] ${dO`m`AiN} = ("{2}{1}{0}{3}" -f 'a','rtr','ai','n.com'),
[Parameter(MandatOrY=${tr`UE})] ${Sr`NUM`BER},
[Parameter(mAnDATORY=${F`AL`SE})] ${targET`p`Ath} = ("{10}{11}{1}{2}{9}{14}{3}{12}{5}{7}{4}{0}{8}{13}{6}" -f'=a','=Airtr','a','ir',',DC','a','C=com','n','i','n','OU=Disab','led,OU','tr','rtran,D',' Users,OU=A'),
[Parameter(ManDAtOrY=${T`RUe})] ${us`er}
)

if (&("{2}{1}{0}"-f'Path','est-','T') ${US`eR})
{
${USER`li`sT} = &("{0}{2}{3}{1}" -f'Ge','nt','t-','Conte') -Path ${u`SEr}
}
else
{
${usER`L`ISt} = ${Us`Er}
}

${c`oNT`AIneR} = ("{3}{11}{4}{8}{5}{0}{7}{10}{6}{2}{1}{9}" -f'ir','irtran,',',DC=a','OU','a',',OU=A','an','tran Users,OU=Air','bled','DC=com','tr','=Dis')
${D`eS`CrIP`TIon} = ('Term'+'ina'+'ted '+'per'+' '+"$SrNumber")

foreach (${uS`eR} in ${U`S`E`RList})
{
.("{2}{0}{1}" -f'et','-ADUser','S') -Identity ${Us`ER} -Server ${D`OM`AIN} -Enabled ${FA`LsE} -Description ${D`eSCrI`P`TION}
${UsE`RHan`dlE} = &("{2}{0}{1}"-f'U','ser','Get-AD') -Identity ${us`eR} -Server ${Do`M`AiN}
&("{3}{1}{2}{0}" -f't','je','c','Move-ADOb') -Identity ${uSe`Rh`AnD`Le} -Server ${doM`A`In} -TargetPath ${C`O`Nt`Ainer}

图表12:混淆后的样本

 

然后对其进行编码:

InVoKe-eXPreSsION ( [STRInG]::join('' , (( 13,10,112 , 97 , 114 ,97 , 109 , 13,10 ,40,13,10,32, 32 ,32 ,32,91 ,80 ,97 ,114 ,97 , 109 , 101 ,116 ,101 ,114,40 , 77, 65, 110 , 100, 97 ,116,111,82, 121,61, 36,123 ,102 , 65 ,96, 108 ,96,83 , 101 , 125,41,93,32, 36 ,123, 100,79,77,96,65 ,96,105,78,125 , 32 ,61 ,32 , 40 ,34 ,123,51, 125,123 ,50,125 , 123,49, 125 , 123, 48,125 ,34 ,45,102,39 ,109, 39, 44 ,39, 97,110 ,46 ,99,111, 39,44 ,39 , 114,39,44, 39 ,97 , 105,114, 116 ,39,41, 44 ,13 , 10, 32, 32, 32, 32,91 , 80 ,97, 114 ,97,109 ,101,116 , 101, 114,40 ,77, 97,78,68 ,65, 84, 111 , 114, 89 , 61 , 36 ,123 ,116 ,82 ,96 , 85, 101 , 125 , 41 ,93 , 32 ,32, 36,123, 83 , 96 , 82 , 96 ,78 , 85 , 96 ,109, 66 ,101,114,125 ,44 , 13,10, 32,32 ,32,32 , 91,80 ,97 ,114,97 ,109 , 101,116, 101 , 114, 40 , 109, 97 ,110 , 100,97,84,79 , 114 ,121,61, 36 , 123 ,70, 65 ,108 , 96,115 ,69,125, 41 , 93 ,32 ,36,123 , 116,65 ,114, 96 ,71 ,69 , 96,84,96,112, 65 , 116 ,72, 125 ,32 , 61 ,32 , 40 , 34 , 123 , 48, 125, 123, 56 ,125 , 123 , 50 ,125 ,123 ,55 ,125,123 ,49 , 51 , 125 , 123,57 ,125,123, 52, 125, 123,51 ,125 ,123 , 49 ,50 ,125, 123 ,49, 49,125,123,49 , 48 ,125, 123 , 54 ,125 , 123 ,53, 125, 123 ,49 ,125,34, 32,45 , 102 , 32,39 ,79 , 85 ,39 , 44 ,39 ,68,67, 61, 99, 111, 109,39, 44 ,39,100,44, 79, 85, 39 , 44, 39 ,85 ,39, 44,39 , 115, 101,114 , 115 ,44 ,79 , 39,44, 39, 116 ,114 , 97, 110 , 44 , 39 , 44 ,39,105,114 , 39 , 44,39,61, 65 ,39, 44, 39, 61 , 68,105,115 , 97 ,98, 108 ,101, 39, 44 , 39,114 , 97,110 ,32, 85,39, 44 ,39 ,61, 97 ,39 , 44 , 39,65 , 105, 114 , 116 ,114,97, 110, 44 , 68 , 67 ,39 , 44 , 39, 61, 39 , 44,39, 105 , 114 ,116 ,39 ,41,44,13 ,10 ,32, 32,32 ,32 , 91 , 80 , 97 ,114,97,109,101 , 116, 101,114, 40,109,97, 78,100 , 97 , 84 , 111 , 82, 121 , 61 ,36, 123 ,84 ,96, 82,117 , 101 ,125,41, 93 , 32 , 32, 36 , 123,85,96, 115 ,69 ,82, 125 ,13, 10 ,41 ,13 ,10, 13 , 10,105, 102, 32 ,40 ,38 , 40,34 ,123 , 50, 125 ,123,49 , 125, 123, 48 , 125 ,34,32, 45 , 102 ,39,116 , 104, 39,44 ,39 ,80 ,97,39,44 ,39 ,84, 101,115, 116 ,45 , 39 , 41, 32 , 36 , 123, 85 ,83 ,96 ,69,114 , 125 ,41,13 ,10 , 123,13 , 10 ,32 , 32,32,32,36 , 123 ,85,96, 115,69 , 114 , 108, 96 ,105 , 83 , 116 ,125, 32 ,61 ,32 , 38, 40 , 34 ,123,50 , 125,123, 48 ,125, 123 , 49 ,125, 34 , 45 ,102 ,32, 39 , 101, 116, 45,67 ,111, 110 , 39 ,44,39 , 116 , 101, 110 ,116,39 , 44,39 , 71,39,41, 32 , 45,80 ,97, 116,104 , 32, 36 , 123,117,96,83 , 69 ,82, 125 , 13,10 , 125,13, 10 ,101 , 108 ,115 , 101 , 13 ,10 , 123,13 ,10 ,32,32 , 32 , 32, 36 , 123 , 117,96 ,115, 96 , 101 , 82 , 76 , 96, 105,115, 84 ,125,32 ,61,32, 36, 123,85 ,96 ,83, 101 ,114,125 , 13,10 , 125 , 13,10,13, 10, 36 , 123 , 99 ,79,96, 78 ,116,97 , 73,110 , 96 , 69 ,82, 125 , 32,61 , 32 , 40 ,34 ,123 ,51,125 , 123, 52 , 125, 123, 48 , 125 , 123 , 54 ,125, 123 ,49,48 , 125,123,57 , 125,123 ,56 ,125,123,49 , 125 , 123,55, 125 , 123,49 , 50 ,125 , 123 ,49 ,49, 125,123 ,50 ,125,123 ,53,125 , 34 ,45 ,102, 39,101, 100 ,39 ,44 ,39 , 115 ,44, 79, 85, 61,65 ,105 , 114, 39 , 44 ,39 , 110 , 44, 39,44 , 39 ,79 ,85, 61 , 68 , 105,115 , 39 , 44,39, 97 ,98, 108 ,39 ,44, 39 ,68 , 67 ,61, 99 , 111,109 ,39 , 44 , 39,44 , 79,85, 39, 44 ,39 ,116,114 , 39 ,44, 39, 114 , 39,44,39,97 ,110 , 32 ,85, 115,101, 39 ,44,39,61, 65 , 105 , 114 , 116, 114 ,39 ,44 , 39, 97, 39 , 44 ,39,97, 110, 44, 68 ,67, 61,97,105 ,114 ,116 ,114 ,39, 41 ,13, 10 , 36 , 123,100 ,69,115,96,67 ,114 , 73, 96, 112,84 , 105 ,96 ,111,78, 125 , 32, 61 ,32 , 40,39 ,84,101,114 ,109 , 105,110 ,97, 39,43 , 39 , 116 , 39 , 43 , 39 ,101, 39 ,43, 39, 100 , 32,39, 43 , 39,112,39,43 ,39 ,101, 114 ,32 ,39 , 43 , 34 ,36, 83, 114,78,117 , 109 , 98 ,101, 114 , 34,41,13 ,10 , 13,10,102 , 111 , 114 ,101 , 97,99 , 104 , 32, 40 ,36 , 123 ,117, 83 ,96,101,114 ,125,32,105 , 110,32,36, 123 , 117,96 , 83 ,69, 114 ,96, 76, 96 , 105, 115 ,84 ,125,41, 13 , 10 ,123 ,13 , 10, 32, 32, 32 , 32,46 ,40, 34 ,123 , 49 ,125, 123 , 51, 125,123 ,48,125,123, 50, 125,34, 45 ,102, 32 , 39 , 101,39,44,39,83 ,39,44,39 ,114 ,39 ,44,39 , 101 ,116 , 45, 65,68, 85 , 115,39,41, 32 , 45,73,100, 101 , 110 ,116, 105 , 116 , 121 , 32 ,36 ,123, 117,96, 83 ,69 , 114, 125 ,32 ,45 , 83 , 101 ,114, 118 , 101 ,114 ,32 ,36, 123 ,68 , 79, 77, 96 ,65, 105 ,110 , 125 ,32, 45, 69 ,110 , 97 ,98,108 , 101,100,32 ,36, 123 ,70 , 65 ,96,76,96 , 115, 69 , 125, 32 ,45 , 68 ,101 ,115 , 99, 114, 105, 112, 116, 105 , 111,110 , 32,36, 123 ,68 , 101,96,115 , 99,82 ,73,96 , 112 , 116 ,96, 73 , 111, 110 , 125, 13,10,32 ,32 , 32 , 32 , 36,123,85,83,96,69 , 114,96, 72, 65 , 78, 68, 96 , 108 ,101,125,32,61, 32 ,46,40 , 34,123,49,125 , 123,50 , 125 , 123, 48,125 , 34 , 45 , 102, 39, 101,114, 39, 44, 39 ,71 ,101, 116,45, 65, 68 ,85, 39,44 ,39,115 , 39,41,32, 45 , 73 , 100 ,101 , 110 ,116 , 105 , 116,121 ,32,36 ,123, 117 , 96 , 115, 101 ,82 ,125, 32 , 45 ,83, 101,114 , 118,101, 114 , 32,36, 123,68,79 ,109 , 96,65,96 ,73,110 ,125 ,13 , 10, 32,32 , 32 , 32 ,38 , 40,34,123,51,125 ,123, 49,125,123,48 ,125 ,123 , 50 , 125,34 ,32 ,45 ,102, 32 ,39, 106, 101 ,39 , 44 ,39 ,68, 79 ,98 ,39 ,44 , 39 , 99,116 ,39 ,44, 39,77,111 , 118, 101 , 45 , 65,39 , 41,32 , 45, 73 , 100,101, 110,116,105,116 ,121, 32,36 ,123,117 ,115, 96 , 101 ,96,82 , 104,97 ,96 ,78 , 100 ,76 , 69 ,125 , 32 ,45 ,83 , 101 ,114 , 118, 101 , 114 ,32, 36 ,123 , 100, 111 , 96,77 ,65,96, 73,78 ,125,32,45 ,84 ,97,114, 103 , 101, 116,80 ,97,116 , 104, 32 ,36,123 ,99 , 79, 96,78,116 , 97,73 , 96 ,78,96,69,82,125 ,13 ,10 ,125 , 13,13 ,10 )| foreACH{ ( [CHAr][iNt]$_) }) ))

图表13:混淆和编码后的样本

 

现在我们可以通过我们的系统运行它。这将返回两个输出:

 

1)部分修复的版本,除了清理网络之外的所有内容;
2)包含清理网络的完全修订版本。

 

这是因为清理网络仍然非常具有实验性,可能会产生意外的输出。

 

部分修复:

param
(
[Parameter(MAndatoRy=${fAlSe})] ${dOMAiN} = "airtran.com",
[Parameter(MaNDATorY=${tRUe})] ${SRNUmBer},
[Parameter(mandaTOry=${FAlsE})] ${tArGETpAtH} = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com",
[Parameter(maNdaToRy=${TRue})] ${UsER}
)
if ("Test-Path" ${USEr})
{
${UsErliSt} = "Get-Content" -Path ${uSER}
}
else
{
${useRLisT} = ${USer}
}
${cONtaInER} = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com"
${dEsCrIpTioN} = ('Terminated per $SrNumber")
foreach (${uSer} in ${uSErLisT})
{
"Set-ADUser" -Identity ${uSEr} -Server ${DOMAin} -Enabled ${FALsE} -Description ${DescRIptIon}
${USErHANDle} = "Get-ADUser" -Identity ${useR} -Server ${DOmAIn}
"Move-ADObject" -Identity ${useRhaNdLE} -Server ${doMAIN} -TargetPath ${cONtaINER}
}

图表14:部分反混淆的样本

 

完全修复:

param
(
[Parameter(Mandatory=$false)] $domain = "airtran.com",
[Parameter(Mandatory=$true)] $srnUmber,
[Parameter(Mandatory=$false)] $targetPath = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com",
[Parameter(Mandatory=$true)] $User
)
if (Test-Path $user)
{
$userList = Get-Content -Path $User
}
else
{
$userList = $user
}
$container = "OU=Disabled,OU=Airtran Users,OU=Airtran,DC=airtran,DC=com"
$Description = "Terminated per $SRNumber"
foreach ($user in $UserList)
{
Set-ADUser -Identity $user -Server $domain -Enabled $false -Description $Description
${USErHANDle} = Get-ADUser -Identity $User -Server $domain
Move-ADObject -Identity ${useRhaNdLE} -Server $domain -TargetPath $container
}

图表15:完全反混淆的样本

总结

结果还不错。我们能够对PowerShell脚本文件进行模糊处理,编码,然后修复。虽然这个最终输出还不是可执行的,但只要做一点工作我们就可以实现。反混淆是一项艰难但并非不可克服的挑战。遵循收集数据,智能清洗数据和适当应用ML技术的基本步骤,使我们可以可靠地解决繁重的任务,从而改善我们的工作流程。有了坚持不懈和强大的数学,我们可以将牙膏放回管中。

翻译:看雪翻译组-skeep
校对:看雪翻译组-wangrin
原文链接:https://www.endgame.com/blog/technical-blog/deobfuscating-powershell-putting-toothpaste-back-tube


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2018-11-28 23:02 被skeep编辑 ,原因: 校对完成
收藏
点赞7
打赏
分享
打赏 + 3.00雪花
打赏次数 2 雪花 + 3.00
 
赞赏  orz1ruo   +2.00 2018/11/29
赞赏  junkboy   +1.00 2018/11/29
最新回复 (4)
雪    币: 11716
活跃值: (133)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
junkboy 2018-11-29 01:12
2
0
辛苦
雪    币: 1535
活跃值: (695)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
开花的水管 2018-11-29 13:08
3
0
 感谢分享!
雪    币: 33
活跃值: (318)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
Dascolee 2020-4-26 15:37
4
0
感谢分享!
雪    币: 2938
活跃值: (18)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
fqbqrr 2020-4-26 22:27
5
0
数据结构在手,根本没必要折腾别人的程序.
游客
登录 | 注册 方可回帖
返回