Extract deleted file from NTFS using PowerShell (Preparation)
Here is main part
I implemented PowerShell script that extract file record from NTFS drive.
I coded in PowerShell for following reaseons.
- It is available on standard Windows envirnment.
- It is easy to modify after distribution because it is script.
- Win32 API functions are available.
Folloing 4 Win32 APIs were userd to extract file record.
- CreateFile
- SetFilePointerEx
- ReadFile
- CloseHandle
First I coded a script kernel32.ps to create object to call these Win32 APIs. By creating dinamic module, dynamic types and dynamic methods as assembly, functions on kernel32.dll are invoked via the assembly.
kernel32.ps1
#Win32API Class
$domain = [AppDomain]::CurrentDomain
$dynassembly = new-object system.reflection.assemblyname("DynamicAssembly")
$assemblybuilder = $domain.defineDynamicAssembly(
$dynassembly,
[system.reflection.emit.assemblybuilderaccess]::run
)
$modulebuilder = $assemblybuilder.definedynamicmodule("DynamicModule", $false)
$typebuilder = $modulebuilder.definetype("kernel32", "Public, Class")
#CreateFile
$createfilemethod = $typebuilder.definemethod(
"CreateFile",
[system.reflection.methodattributes] "Public, Static",
[IntPtr],
[Type[]] @(
[string],
[uint32],
[uint32],
[IntPtr],
[uint32],
[uint32],
[IntPtr]
)
)
$createfiledllimport = [system.runtime.interopservices.dllimportattribute].getconstructor(@([string]))
$createfilefieldarray = [system.reflection.fieldinfo[]] @(
[system.runtime.interopservices.dllimportattribute].getfield("EntryPoint"),
[system.runtime.interopservices.dllimportattribute].getfield("PreserveSig"),
[system.runtime.interopservices.dllimportattribute].getfield("SetLastError"),
[system.runtime.interopservices.dllimportattribute].getfield("CallingConvention"),
[system.runtime.interopservices.dllimportattribute].getfield("CharSet")
)
$createfilefieldvaluearray = [object[]] @(
"CreateFile",
$true,
$true,
[system.runtime.interopservices.callingconvention]::winapi,
[system.runtime.interopservices.charSet]::auto
)
$createfilecustomattribute = new-object system.reflection.emit.customattributebuilder(
$createfiledllImport,
@("kernel32.dll"),
$createfilefieldarray,
$createfilefieldvaluearray
)
$createfilemethod.setcustomattribute($createfilecustomattribute)
#SetFilePointerEx
$setfilepointerexmethod = $typebuilder.definemethod(
"SetFilePointerEx",
[system.reflection.methodattributes] "Public, Static",
[uint32],
[Type[]] @(
[IntPtr],
[uint64],
[IntPtr],
[uint32]
)
)
$setfilepointerexdllimport = [system.runtime.interopservices.dllimportattribute].getconstructor(@([string]))
$setfilepointerexfieldarray = [system.reflection.fieldinfo[]] @(
[system.runtime.interopservices.dllimportattribute].getfield("EntryPoint"),
[system.runtime.interopservices.dllimportattribute].getfield("PreserveSig"),
[system.runtime.interopservices.dllimportattribute].getfield("SetLastError"),
[system.runtime.interopservices.dllimportattribute].getfield("CallingConvention"),
[system.runtime.interopservices.dllimportattribute].getfield("CharSet")
)
$setfilepointerexfieldvaluearray = [object[]] @(
"SetFilePointerEx",
$true,
$true,
[system.runtime.interopservices.callingconvention]::winapi,
[system.runtime.interopservices.charSet]::auto
)
$setfilepointerexcustomattribute = new-object system.reflection.emit.customattributebuilder(
$setfilepointerexdllImport,
@("kernel32.dll"),
$setfilepointerexfieldarray,
$setfilepointerexfieldvaluearray
)
$setfilepointerexmethod.setcustomattribute($setfilepointerexcustomattribute)
#ReadFile
$readfilemethod = $typebuilder.definemethod(
"ReadFile",
[system.reflection.methodattributes] "Public, Static",
[uint32],
[Type[]] @(
[IntPtr],
[IntPtr],
[uint32],
[IntPtr],
[IntPtr]
)
)
$readfiledllimport = [system.runtime.interopservices.dllimportattribute].getconstructor(@([string]))
$readfilefieldarray = [system.reflection.fieldinfo[]] @(
[system.runtime.interopservices.dllimportattribute].getfield("EntryPoint"),
[system.runtime.interopservices.dllimportattribute].getfield("PreserveSig"),
[system.runtime.interopservices.dllimportattribute].getfield("SetLastError"),
[system.runtime.interopservices.dllimportattribute].getfield("CallingConvention"),
[system.runtime.interopservices.dllimportattribute].getfield("CharSet")
)
$readfilefieldvaluearray = [object[]] @(
"ReadFile",
$true,
$true,
[system.runtime.interopservices.callingconvention]::winapi,
[system.runtime.interopservices.charSet]::auto
)
$readfilecustomattribute = new-object system.reflection.emit.customattributebuilder(
$readfiledllImport,
@("kernel32.dll"),
$readfilefieldarray,
$readfilefieldvaluearray
)
$readfilemethod.setcustomattribute($readfilecustomattribute)
#CloseHandle
$closehandlemethod = $typebuilder.definemethod(
"CloseHandle",
[system.reflection.methodattributes] "Public, Static",
[uint32],
[Type[]] @(
[IntPtr]
)
)
$closehandledllimport = [system.runtime.interopservices.dllimportattribute].getconstructor(@([string]))
$closehandlefieldarray = [system.reflection.fieldinfo[]] @(
[system.runtime.interopservices.dllimportattribute].getfield("EntryPoint"),
[system.runtime.interopservices.dllimportattribute].getfield("PreserveSig"),
[system.runtime.interopservices.dllimportattribute].getfield("SetLastError"),
[system.runtime.interopservices.dllimportattribute].getfield("CallingConvention"),
[system.runtime.interopservices.dllimportattribute].getfield("CharSet")
)
$closehandlefieldvaluearray = [object[]] @(
"CloseHandle",
$true,
$true,
[system.runtime.interopservices.callingconvention]::winapi,
[system.runtime.interopservices.charSet]::auto
)
$closehandlecustomattribute = new-object system.reflection.emit.customattributebuilder(
$closehandledllImport,
@("kernel32.dll"),
$closehandlefieldarray,
$closehandlefieldvaluearray
)
$closehandlemethod.setcustomattribute($closehandlecustomattribute)
#create kernel32 class
$Kernel32 = $typebuilder.createtype()
And I also implemented utility function. Get-multi-bytes methods (16bit 32bit 64bit) for Marshal buffer only supports signed value, so I add unsigned version to ps object.
psutil.ps1
#My Utility Functions
$myutil = new-object psobject
#properties
#$myutil | Add-Member noteproperty -name hoge -value "hoge"
$myutil | Add-Member noteproperty -name writeoption -value $false
#methods
#$myutil | add-member scriptmethod -name fuga -value { param($fuga) return $fuga }
$myutil | add-member scriptmethod -name ReadByte -value {
param($buffer, $offset)
[byte]$retval = 0
switch($buffer.getType().Name){
"IntPtr"{
$retval = [system.runtime.interopservices.marshal]::ReadByte($buffer, $offset)
}
"byte[]"{
$retval = $buffer[$offset]
}
"Object[]"{
$retval = $buffer[$offset]
}
}
return $retval
}
$myutil | add-member scriptmethod -name ReadUInt16 -value {
param($buffer, $offset)
[uint16]$retval = 0
switch($buffer.getType().Name){
"IntPtr"{
for($i = 0; $i -lt 2; $i++){
$retval += [system.runtime.interopservices.marshal]::ReadByte($buffer, $offset + $i) * [math]::pow(0x0100, $i)
}
}
"byte[]"{
for($i = 0; $i -lt 2; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
"Object[]"{
for($i = 0; $i -lt 2; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
}
return $retval
}
$myutil | add-member scriptmethod -name ReadUInt32 -value {
param($buffer, $offset)
[uint32]$retval = 0
switch($buffer.getType().Name){
"IntPtr"{
for($i = 0; $i -lt 4; $i++){
$retval += [system.runtime.interopservices.marshal]::ReadByte($buffer, $offset + $i) * [math]::pow(0x0100, $i)
}
}
"byte[]"{
for($i = 0; $i -lt 4; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
"Object[]"{
for($i = 0; $i -lt 4; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
}
return $retval
}
$myutil | add-member scriptmethod -name ReadUInt64 -value {
param($buffer, $offset)
[uint64]$retval = 0
switch($buffer.getType().Name){
"IntPtr"{
for($i = 0; $i -lt 8; $i++){
$retval += [system.runtime.interopservices.marshal]::ReadByte($buffer, $offset + $i) * [math]::pow(0x0100, $i)
}
}
"byte[]"{
for($i = 0; $i -lt 8; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
"Object[]"{
for($i = 0; $i -lt 8; $i++){
$retval += $buffer[$offset + $i] * [math]::pow(0x0100, $i)
}
}
}
return $retval
}
$myutil | add-member scriptmethod -name Dump -value {
param($buffer)
$outlen = 16
$linenum = 0
$output = $linenum.tostring("X8") + " : "
$linenum++
for($i = 0; $i -lt $buffer.count; $i++){
$output += (($this.ReadByte($buffer,$i)).tostring("X2") + " ")
if(($i % $outlen) -eq ($outlen - 1)){
write-host $output
$output = $linenum.tostring("X8") + " : "
$linenum++
}
}
write-host $output
}
$myutil | add-member scriptmethod -name write2host -value {
param($msg)
if($this.writeoption){
write-host $msg
}
}
Profile
I have technical job experience in enbedded software development and server side infrastructure/application engineering.
I'm interested in programming and computer security.
Objective
To write down my technical knowledge in the place where I can access from anywhere.
To share my program source code.
To train my writing skill.
New entries