Updated go-winpmem to use the latest test driver (#61)

Updated binary to:
1. save function allows to save the actual driver
2. install/uninstall commands allow the driver to be installed and left
in background
This commit is contained in:
Mike Cohen
2024-11-25 10:10:29 +10:00
committed by GitHub
parent 57f829bc00
commit a1e0b1f5ab
8 changed files with 160 additions and 14 deletions
+1
View File
@@ -2,5 +2,6 @@ all:
GOOS=windows GOARCH=amd64 go build -o ./winpmem.exe -ldflags="-w -s " ./cmd/
assets:
rm -f embed/winpmem*
cp ../src/binaries/winpmem_*.sys embed
gzip -9 embed/*
+5 -1
View File
@@ -1,6 +1,7 @@
package main
import (
"fmt"
"io/ioutil"
"os"
"time"
@@ -74,6 +75,9 @@ func doAcquire() error {
logger.Info("Writing driver to %v", *driver_path)
err = winpmem.InstallDriver(*driver_path, *service_name, logger)
if err != nil {
return err
}
defer winpmem.UninstallDriver(
*driver_path, *service_name, logger)
@@ -107,7 +111,7 @@ func doAcquire() error {
out_fd, err := winpmem.CreateFileForWriting(!*nosparse, *filename)
if err != nil {
return err
return fmt.Errorf("Creating sparse file error: %w. Disable sparse support with --nosparse flag.", err)
}
defer out_fd.Close()
+90
View File
@@ -0,0 +1,90 @@
package main
import (
"io/ioutil"
"os"
"github.com/Velocidex/WinPmem/go-winpmem"
"github.com/alecthomas/kingpin"
)
var (
install = app.Command("install", "Install the driver and exit")
install_driver_path = install.Flag("driver_path", "Where to store the driver").
String()
install_service_name = install.Flag("service_name", "Name of the service to create").
Default("winpmem").String()
uninstall = app.Command("uninstall", "Uninstall the driver and exit")
uninstall_driver_path = uninstall.Flag("driver_path", "Where to store the driver").
String()
uninstall_service_name = uninstall.Flag("service_name", "Name of the service to create").
Default("winpmem").String()
)
func doInstall() error {
logger := winpmem.NewLogger(*verbose)
var err error
var fd *os.File
if *driver_path == "" {
fd, err = ioutil.TempFile("", "*.sys")
if err != nil {
return err
}
*install_driver_path = fd.Name()
} else {
fd, err = os.OpenFile(*install_driver_path,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
}
driver_code, err := winpmem.Winpmem_x64()
if err != nil {
return err
}
fd.Write([]byte(driver_code))
fd.Close()
logger.Info("Writing driver to %v", *install_driver_path)
err = winpmem.InstallDriver(*install_driver_path, *install_service_name, logger)
if err != nil {
return err
}
return nil
}
func doUninstall() error {
logger := winpmem.NewLogger(*verbose)
winpmem.UninstallDriver(*uninstall_driver_path, *uninstall_service_name, logger)
return nil
}
func init() {
command_handlers = append(command_handlers, func(command string) bool {
switch command {
case install.FullCommand():
kingpin.FatalIfError(doInstall(), "install")
case uninstall.FullCommand():
kingpin.FatalIfError(doUninstall(), "uninstall")
default:
return false
}
return true
})
}
+47
View File
@@ -0,0 +1,47 @@
package main
import (
"os"
"github.com/Velocidex/WinPmem/go-winpmem"
"github.com/alecthomas/kingpin"
)
var (
save = app.Command("save", "Save the driver and exit")
save_driver_path = save.Arg("driver_path", "Where to store the driver").
String()
)
func doSave() error {
logger := winpmem.NewLogger(*verbose)
logger.Info("Writing driver to %v", *save_driver_path)
fd, err := os.OpenFile(*save_driver_path,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
if err != nil {
return err
}
driver_code, err := winpmem.Winpmem_x64()
if err != nil {
return err
}
fd.Write([]byte(driver_code))
fd.Close()
return nil
}
func init() {
command_handlers = append(command_handlers, func(command string) bool {
switch command {
case save.FullCommand():
kingpin.FatalIfError(doSave(), "save")
default:
return false
}
return true
})
}
Binary file not shown.
+12 -8
View File
@@ -5,6 +5,7 @@ import (
"context"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
"sync"
@@ -80,18 +81,21 @@ func (self *Imager) readAt(buf []byte, offset int64) (int, error) {
_, err := windows.Seek(self.fd, int64(offset), os.SEEK_SET)
if err != nil {
return 0, err
return 0, fmt.Errorf("windows.Seek: seeking to %v %w", offset, err)
}
actual_read := uint32(0)
err = windows.ReadFile(self.fd, buf[:to_read], &actual_read, nil)
if err != nil {
// Large Read failed, read in pages and pad any failed pages
for i := 0; i < to_read; i += PAGE_SIZE {
pages_read := int(actual_read) / PAGE_SIZE
// Large Read failed, read in pages from the last successful
// place and pad any failed pages
for i := pages_read * PAGE_SIZE; i < to_read; i += PAGE_SIZE {
_, err = windows.Seek(self.fd, int64(i)+offset, os.SEEK_SET)
if err != nil {
return 0, err
return 0, fmt.Errorf("windows.Seek: to %v %w", int64(i)+offset, err)
}
err := windows.ReadFile(self.fd, buf[:PAGE_SIZE], &actual_read, nil)
@@ -105,7 +109,7 @@ func (self *Imager) readAt(buf []byte, offset int64) (int, error) {
return to_read, nil
}
return int(actual_read), err
return int(actual_read), fmt.Errorf("readAt: %w", err)
}
func (self *Imager) ReadAt(buf []byte, offset int64) (int, error) {
@@ -235,7 +239,7 @@ func (self *Imager) copyRange(
self.logger.Debug("Reading %#x from %#x", to_read, offset)
_, err := windows.Seek(self.fd, int64(offset), os.SEEK_SET)
if err != nil {
return err
return fmt.Errorf("windows.Seek: ro %v %w", offset, err)
}
err = windows.ReadFile(self.fd, buff[:to_read], &actual_read, nil)
@@ -245,13 +249,13 @@ func (self *Imager) copyRange(
_, err = windows.Seek(self.fd, int64(i), os.SEEK_SET)
if err != nil {
return err
return fmt.Errorf("windows.Seek: ro %v %w", offset, err)
}
err := windows.ReadFile(self.fd, buff[:PAGE_SIZE], &actual_read, nil)
if err != nil {
_, err := w.Write(pad)
if err != nil {
return err
return fmt.Errorf("write: %w", err)
}
continue
}
+1 -1
View File
@@ -4,7 +4,7 @@
// Contains all the data shared between the driver and the usermode part.
#define PMEM_DRIVER_VERSION "4.0.1"
#define PMEM_DRIVER_VERSION "4.1"
#define PMEM_DEVICE_NAME_ASCII "pmem" // the name for normal userspace usage.
#define PMEM_DEVICE_NAME L"pmem" // preferred by the driver.
#define PMEM_SERVICE_NAME TEXT("winpmem") // and this is finally the service/display name.
+4 -4
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
@@ -44,7 +44,7 @@
<!-- <TargetVersion>Windows10</TargetVersion> -->
<!-- Wdk11 can only compile for minimum OS Win10, this covers only Win10-Win11. -->
<!-- If you want Windows 7 support, too, you need the WDK10. -->
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
@@ -56,7 +56,7 @@
<PropertyGroup Label="Configuration" Condition="'$(Configuration)'=='Release'">
<UseDebugLibraries>False</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Label="Configuration" Condition="'$(Configuration)'=='Debug'">
<UseDebugLibraries>True</UseDebugLibraries>
</PropertyGroup>
@@ -105,4 +105,4 @@
<Message Text="OutDir = $(OutDir)" />
<Message Text="TargetPath = $(TargetPath)" />
</Target>
</Project>
</Project>