├── .gitignore
├── KsDumper.sln
├── KsDumperClient
├── App.config
├── Driver
│ ├── DriverInterface.cs
│ └── Operations.cs
├── Dumper.Designer.cs
├── Dumper.cs
├── Dumper.resx
├── KsDumperClient.csproj
├── PE
│ ├── 32
│ │ ├── PE32File.cs
│ │ └── PE32Header.cs
│ ├── 64
│ │ ├── PE64File.cs
│ │ └── PE64Header.cs
│ ├── DOSHeader.cs
│ ├── NativePEStructs.cs
│ ├── PEFile.cs
│ └── PESection.cs
├── ProcessDumper.cs
├── ProcessSummary.cs
├── Program.cs
├── Properties
│ ├── AssemblyInfo.cs
│ ├── Resources.Designer.cs
│ ├── Resources.resx
│ ├── Settings.Designer.cs
│ └── Settings.settings
├── Utility
│ ├── Logger.cs
│ ├── MarshalUtility.cs
│ ├── ProcessListView.cs
│ └── WinApi.cs
└── app.manifest
├── KsDumperDriver
├── Driver.c
├── KsDumperDriver.vcxproj
├── KsDumperDriver.vcxproj.filters
├── NTUndocumented.h
├── ProcessLister.c
├── ProcessLister.h
├── UserModeBridge.h
├── Utility.c
└── Utility.h
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Build results
17 | [Dd]ebug/
18 | [Dd]ebugPublic/
19 | [Rr]elease/
20 | [Rr]eleases/
21 | x64/
22 | x86/
23 | [Aa][Rr][Mm]/
24 | [Aa][Rr][Mm]64/
25 | bld/
26 | [Bb]in/
27 | [Oo]bj/
28 | [Ll]og/
29 |
30 | # Visual Studio 2015/2017 cache/options directory
31 | .vs/
32 | # Uncomment if you have tasks that create the project's static files in wwwroot
33 | #wwwroot/
34 |
35 | # Visual Studio 2017 auto generated files
36 | Generated\ Files/
37 |
38 | # MSTest test Results
39 | [Tt]est[Rr]esult*/
40 | [Bb]uild[Ll]og.*
41 |
42 | # NUNIT
43 | *.VisualState.xml
44 | TestResult.xml
45 |
46 | # Build Results of an ATL Project
47 | [Dd]ebugPS/
48 | [Rr]eleasePS/
49 | dlldata.c
50 |
51 | # Benchmark Results
52 | BenchmarkDotNet.Artifacts/
53 |
54 | # .NET Core
55 | project.lock.json
56 | project.fragment.lock.json
57 | artifacts/
58 |
59 | # StyleCop
60 | StyleCopReport.xml
61 |
62 | # Files built by Visual Studio
63 | *_i.c
64 | *_p.c
65 | *_h.h
66 | *.ilk
67 | *.meta
68 | *.obj
69 | *.iobj
70 | *.pch
71 | *.pdb
72 | *.ipdb
73 | *.pgc
74 | *.pgd
75 | *.rsp
76 | *.sbr
77 | *.tlb
78 | *.tli
79 | *.tlh
80 | *.tmp
81 | *.tmp_proj
82 | *_wpftmp.csproj
83 | *.log
84 | *.vspscc
85 | *.vssscc
86 | .builds
87 | *.pidb
88 | *.svclog
89 | *.scc
90 |
91 | # Chutzpah Test files
92 | _Chutzpah*
93 |
94 | # Visual C++ cache files
95 | ipch/
96 | *.aps
97 | *.ncb
98 | *.opendb
99 | *.opensdf
100 | *.sdf
101 | *.cachefile
102 | *.VC.db
103 | *.VC.VC.opendb
104 |
105 | # Visual Studio profiler
106 | *.psess
107 | *.vsp
108 | *.vspx
109 | *.sap
110 |
111 | # Visual Studio Trace Files
112 | *.e2e
113 |
114 | # TFS 2012 Local Workspace
115 | $tf/
116 |
117 | # Guidance Automation Toolkit
118 | *.gpState
119 |
120 | # ReSharper is a .NET coding add-in
121 | _ReSharper*/
122 | *.[Rr]e[Ss]harper
123 | *.DotSettings.user
124 |
125 | # JustCode is a .NET coding add-in
126 | .JustCode
127 |
128 | # TeamCity is a build add-in
129 | _TeamCity*
130 |
131 | # DotCover is a Code Coverage Tool
132 | *.dotCover
133 |
134 | # AxoCover is a Code Coverage Tool
135 | .axoCover/*
136 | !.axoCover/settings.json
137 |
138 | # Visual Studio code coverage results
139 | *.coverage
140 | *.coveragexml
141 |
142 | # NCrunch
143 | _NCrunch_*
144 | .*crunch*.local.xml
145 | nCrunchTemp_*
146 |
147 | # MightyMoose
148 | *.mm.*
149 | AutoTest.Net/
150 |
151 | # Web workbench (sass)
152 | .sass-cache/
153 |
154 | # Installshield output folder
155 | [Ee]xpress/
156 |
157 | # DocProject is a documentation generator add-in
158 | DocProject/buildhelp/
159 | DocProject/Help/*.HxT
160 | DocProject/Help/*.HxC
161 | DocProject/Help/*.hhc
162 | DocProject/Help/*.hhk
163 | DocProject/Help/*.hhp
164 | DocProject/Help/Html2
165 | DocProject/Help/html
166 |
167 | # Click-Once directory
168 | publish/
169 |
170 | # Publish Web Output
171 | *.[Pp]ublish.xml
172 | *.azurePubxml
173 | # Note: Comment the next line if you want to checkin your web deploy settings,
174 | # but database connection strings (with potential passwords) will be unencrypted
175 | *.pubxml
176 | *.publishproj
177 |
178 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
179 | # checkin your Azure Web App publish settings, but sensitive information contained
180 | # in these scripts will be unencrypted
181 | PublishScripts/
182 |
183 | # NuGet Packages
184 | *.nupkg
185 | # The packages folder can be ignored because of Package Restore
186 | **/[Pp]ackages/*
187 | # except build/, which is used as an MSBuild target.
188 | !**/[Pp]ackages/build/
189 | # Uncomment if necessary however generally it will be regenerated when needed
190 | #!**/[Pp]ackages/repositories.config
191 | # NuGet v3's project.json files produces more ignorable files
192 | *.nuget.props
193 | *.nuget.targets
194 |
195 | # Microsoft Azure Build Output
196 | csx/
197 | *.build.csdef
198 |
199 | # Microsoft Azure Emulator
200 | ecf/
201 | rcf/
202 |
203 | # Windows Store app package directories and files
204 | AppPackages/
205 | BundleArtifacts/
206 | Package.StoreAssociation.xml
207 | _pkginfo.txt
208 | *.appx
209 |
210 | # Visual Studio cache files
211 | # files ending in .cache can be ignored
212 | *.[Cc]ache
213 | # but keep track of directories ending in .cache
214 | !?*.[Cc]ache/
215 |
216 | # Others
217 | ClientBin/
218 | ~$*
219 | *~
220 | *.dbmdl
221 | *.dbproj.schemaview
222 | *.jfm
223 | *.pfx
224 | *.publishsettings
225 | orleans.codegen.cs
226 |
227 | # Including strong name files can present a security risk
228 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
229 | #*.snk
230 |
231 | # Since there are multiple workflows, uncomment next line to ignore bower_components
232 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
233 | #bower_components/
234 | # ASP.NET Core default setup: bower directory is configured as wwwroot/lib/ and bower restore is true
235 | **/wwwroot/lib/
236 |
237 | # RIA/Silverlight projects
238 | Generated_Code/
239 |
240 | # Backup & report files from converting an old project file
241 | # to a newer Visual Studio version. Backup files are not needed,
242 | # because we have git ;-)
243 | _UpgradeReport_Files/
244 | Backup*/
245 | UpgradeLog*.XML
246 | UpgradeLog*.htm
247 | ServiceFabricBackup/
248 | *.rptproj.bak
249 |
250 | # SQL Server files
251 | *.mdf
252 | *.ldf
253 | *.ndf
254 |
255 | # Business Intelligence projects
256 | *.rdl.data
257 | *.bim.layout
258 | *.bim_*.settings
259 | *.rptproj.rsuser
260 | *- Backup*.rdl
261 |
262 | # Microsoft Fakes
263 | FakesAssemblies/
264 |
265 | # GhostDoc plugin setting file
266 | *.GhostDoc.xml
267 |
268 | # Node.js Tools for Visual Studio
269 | .ntvs_analysis.dat
270 | node_modules/
271 |
272 | # Visual Studio 6 build log
273 | *.plg
274 |
275 | # Visual Studio 6 workspace options file
276 | *.opt
277 |
278 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
279 | *.vbw
280 |
281 | # Visual Studio LightSwitch build output
282 | **/*.HTMLClient/GeneratedArtifacts
283 | **/*.DesktopClient/GeneratedArtifacts
284 | **/*.DesktopClient/ModelManifest.xml
285 | **/*.Server/GeneratedArtifacts
286 | **/*.Server/ModelManifest.xml
287 | _Pvt_Extensions
288 |
289 | # Paket dependency manager
290 | .paket/paket.exe
291 | paket-files/
292 |
293 | # FAKE - F# Make
294 | .fake/
295 |
296 | # JetBrains Rider
297 | .idea/
298 | *.sln.iml
299 |
300 | # CodeRush personal settings
301 | .cr/personal
302 |
303 | # Python Tools for Visual Studio (PTVS)
304 | __pycache__/
305 | *.pyc
306 |
307 | # Cake - Uncomment if you are using it
308 | # tools/**
309 | # !tools/packages.config
310 |
311 | # Tabs Studio
312 | *.tss
313 |
314 | # Telerik's JustMock configuration file
315 | *.jmconfig
316 |
317 | # BizTalk build output
318 | *.btp.cs
319 | *.btm.cs
320 | *.odx.cs
321 | *.xsd.cs
322 |
323 | # OpenCover UI analysis results
324 | OpenCover/
325 |
326 | # Azure Stream Analytics local run output
327 | ASALocalRun/
328 |
329 | # MSBuild Binary and Structured Log
330 | *.binlog
331 |
332 | # NVidia Nsight GPU debugger configuration file
333 | *.nvuser
334 |
335 | # MFractors (Xamarin productivity tool) working folder
336 | .mfractor/
337 |
338 | # Local History for Visual Studio
339 | .localhistory/
340 |
341 | # BeatPulse healthcheck temp database
342 | healthchecksdb
--------------------------------------------------------------------------------
/KsDumper.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.28307.329
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "KsDumperDriver", "KsDumperDriver\KsDumperDriver.vcxproj", "{8EADAB93-F111-43AF-9E10-2376AE515491}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KsDumperClient", "KsDumperClient\KsDumperClient.csproj", "{7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|x64 = Debug|x64
13 | Release|x64 = Release|x64
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {8EADAB93-F111-43AF-9E10-2376AE515491}.Debug|x64.ActiveCfg = Release|x64
17 | {8EADAB93-F111-43AF-9E10-2376AE515491}.Debug|x64.Build.0 = Release|x64
18 | {8EADAB93-F111-43AF-9E10-2376AE515491}.Release|x64.ActiveCfg = Release|x64
19 | {8EADAB93-F111-43AF-9E10-2376AE515491}.Release|x64.Build.0 = Release|x64
20 | {7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}.Debug|x64.ActiveCfg = Debug|x64
21 | {7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}.Debug|x64.Build.0 = Debug|x64
22 | {7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}.Release|x64.ActiveCfg = Release|x64
23 | {7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}.Release|x64.Build.0 = Release|x64
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {B97C5D1A-00B8-411D-9716-A3805DA64FD6}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/KsDumperClient/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/KsDumperClient/Driver/DriverInterface.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.InteropServices;
4 | using KsDumperClient.Utility;
5 |
6 | using static KsDumperClient.Driver.Operations;
7 |
8 | namespace KsDumperClient.Driver
9 | {
10 | public class DriverInterface
11 | {
12 | private readonly IntPtr driverHandle;
13 |
14 | public DriverInterface(string registryPath)
15 | {
16 | driverHandle = WinApi.CreateFileA(registryPath, FileAccess.ReadWrite,
17 | FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
18 | }
19 |
20 | public bool HasValidHandle()
21 | {
22 | return driverHandle != WinApi.INVALID_HANDLE_VALUE;
23 | }
24 |
25 | public bool GetProcessSummaryList(out ProcessSummary[] result)
26 | {
27 | result = new ProcessSummary[0];
28 |
29 | if (driverHandle != WinApi.INVALID_HANDLE_VALUE)
30 | {
31 | int requiredBufferSize = GetProcessListRequiredBufferSize();
32 |
33 | if (requiredBufferSize > 0)
34 | {
35 | IntPtr bufferPointer = MarshalUtility.AllocZeroFilled(requiredBufferSize);
36 | KERNEL_PROCESS_LIST_OPERATION operation = new KERNEL_PROCESS_LIST_OPERATION
37 | {
38 | bufferAddress = (ulong)bufferPointer.ToInt64(),
39 | bufferSize = requiredBufferSize
40 | };
41 | IntPtr operationPointer = MarshalUtility.CopyStructToMemory(operation);
42 | int operationSize = Marshal.SizeOf();
43 |
44 | if (WinApi.DeviceIoControl(driverHandle, IO_GET_PROCESS_LIST, operationPointer, operationSize, operationPointer, operationSize, IntPtr.Zero, IntPtr.Zero))
45 | {
46 | operation = MarshalUtility.GetStructFromMemory(operationPointer);
47 |
48 | if (operation.processCount > 0)
49 | {
50 | byte[] managedBuffer = new byte[requiredBufferSize];
51 | Marshal.Copy(bufferPointer, managedBuffer, 0, requiredBufferSize);
52 | Marshal.FreeHGlobal(bufferPointer);
53 |
54 | result = new ProcessSummary[operation.processCount];
55 |
56 | using (BinaryReader reader = new BinaryReader(new MemoryStream(managedBuffer)))
57 | {
58 | for (int i = 0; i < result.Length; i++)
59 | {
60 | result[i] = ProcessSummary.FromStream(reader);
61 | }
62 | }
63 | return true;
64 | }
65 | }
66 | }
67 | }
68 | return false;
69 | }
70 |
71 | private int GetProcessListRequiredBufferSize()
72 | {
73 | IntPtr operationPointer = MarshalUtility.AllocEmptyStruct();
74 | int operationSize = Marshal.SizeOf();
75 |
76 | if (WinApi.DeviceIoControl(driverHandle, IO_GET_PROCESS_LIST, operationPointer, operationSize, operationPointer, operationSize, IntPtr.Zero, IntPtr.Zero))
77 | {
78 | KERNEL_PROCESS_LIST_OPERATION operation = MarshalUtility.GetStructFromMemory(operationPointer);
79 |
80 | if (operation.processCount == 0 && operation.bufferSize > 0)
81 | {
82 | return operation.bufferSize;
83 | }
84 | }
85 | return 0;
86 | }
87 |
88 | public bool CopyVirtualMemory(int targetProcessId, IntPtr targetAddress, IntPtr bufferAddress, int bufferSize)
89 | {
90 | if (driverHandle != WinApi.INVALID_HANDLE_VALUE)
91 | {
92 | KERNEL_COPY_MEMORY_OPERATION operation = new KERNEL_COPY_MEMORY_OPERATION
93 | {
94 | targetProcessId = targetProcessId,
95 | targetAddress = (ulong)targetAddress.ToInt64(),
96 | bufferAddress = (ulong)bufferAddress.ToInt64(),
97 | bufferSize = bufferSize
98 | };
99 |
100 | IntPtr operationPointer = MarshalUtility.CopyStructToMemory(operation);
101 |
102 | bool result = WinApi.DeviceIoControl(driverHandle, IO_COPY_MEMORY, operationPointer, Marshal.SizeOf(), IntPtr.Zero, 0, IntPtr.Zero, IntPtr.Zero);
103 | Marshal.FreeHGlobal(operationPointer);
104 |
105 | return result;
106 | }
107 | return false;
108 | }
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/KsDumperClient/Driver/Operations.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 |
3 | using static KsDumperClient.Utility.WinApi;
4 |
5 | namespace KsDumperClient.Driver
6 | {
7 | public static class Operations
8 | {
9 | public static readonly uint IO_GET_PROCESS_LIST = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1724, METHOD_BUFFERED, FILE_ANY_ACCESS);
10 |
11 | public static readonly uint IO_COPY_MEMORY = CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1725, METHOD_BUFFERED, FILE_ANY_ACCESS);
12 |
13 | [StructLayout(LayoutKind.Sequential)]
14 | public struct KERNEL_PROCESS_LIST_OPERATION
15 | {
16 | public ulong bufferAddress;
17 | public int bufferSize;
18 | public int processCount;
19 | }
20 |
21 | [StructLayout(LayoutKind.Sequential)]
22 | public struct KERNEL_COPY_MEMORY_OPERATION
23 | {
24 | public int targetProcessId;
25 | public ulong targetAddress;
26 | public ulong bufferAddress;
27 | public int bufferSize;
28 | }
29 |
30 | private static uint CTL_CODE(int deviceType, int function, int method, int access)
31 | {
32 | return (uint)(((deviceType) << 16) | ((access) << 14) | ((function) << 2) | (method));
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/KsDumperClient/Dumper.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace KsDumperClient
2 | {
3 | partial class Dumper
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.components = new System.ComponentModel.Container();
32 | this.toolStrip1 = new System.Windows.Forms.ToolStrip();
33 | this.refreshMenuBtn = new System.Windows.Forms.ToolStripButton();
34 | this.hideSystemProcessMenuBtn = new System.Windows.Forms.ToolStripButton();
35 | this.groupBox1 = new System.Windows.Forms.GroupBox();
36 | this.logsTextBox = new System.Windows.Forms.RichTextBox();
37 | this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
38 | this.dumpMainModuleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
39 | this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
40 | this.openInExplorerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
41 | this.processList = new KsDumperClient.Utility.ProcessListView();
42 | this.PIDHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
43 | this.NameHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
44 | this.PathHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
45 | this.BaseAddressHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
46 | this.EntryPointHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
47 | this.ImageSizeHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
48 | this.ImageTypeHeader = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
49 | this.toolStrip1.SuspendLayout();
50 | this.groupBox1.SuspendLayout();
51 | this.contextMenuStrip1.SuspendLayout();
52 | this.SuspendLayout();
53 | //
54 | // toolStrip1
55 | //
56 | this.toolStrip1.AllowMerge = false;
57 | this.toolStrip1.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
58 | this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
59 | this.refreshMenuBtn,
60 | this.hideSystemProcessMenuBtn});
61 | this.toolStrip1.Location = new System.Drawing.Point(0, 0);
62 | this.toolStrip1.Margin = new System.Windows.Forms.Padding(2);
63 | this.toolStrip1.Name = "toolStrip1";
64 | this.toolStrip1.Padding = new System.Windows.Forms.Padding(2, 3, 2, 2);
65 | this.toolStrip1.ShowItemToolTips = false;
66 | this.toolStrip1.Size = new System.Drawing.Size(1004, 27);
67 | this.toolStrip1.TabIndex = 4;
68 | this.toolStrip1.Text = "toolStrip1";
69 | //
70 | // refreshMenuBtn
71 | //
72 | this.refreshMenuBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
73 | this.refreshMenuBtn.ImageTransparentColor = System.Drawing.Color.Magenta;
74 | this.refreshMenuBtn.Name = "refreshMenuBtn";
75 | this.refreshMenuBtn.Size = new System.Drawing.Size(50, 19);
76 | this.refreshMenuBtn.Text = "Refresh";
77 | this.refreshMenuBtn.Click += new System.EventHandler(this.refreshMenuBtn_Click);
78 | //
79 | // hideSystemProcessMenuBtn
80 | //
81 | this.hideSystemProcessMenuBtn.Alignment = System.Windows.Forms.ToolStripItemAlignment.Right;
82 | this.hideSystemProcessMenuBtn.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
83 | this.hideSystemProcessMenuBtn.ImageTransparentColor = System.Drawing.Color.Magenta;
84 | this.hideSystemProcessMenuBtn.Name = "hideSystemProcessMenuBtn";
85 | this.hideSystemProcessMenuBtn.Size = new System.Drawing.Size(135, 19);
86 | this.hideSystemProcessMenuBtn.Text = "Show System Processes";
87 | this.hideSystemProcessMenuBtn.Click += new System.EventHandler(this.hideSystemProcessMenuBtn_Click);
88 | //
89 | // groupBox1
90 | //
91 | this.groupBox1.Controls.Add(this.logsTextBox);
92 | this.groupBox1.Location = new System.Drawing.Point(5, 525);
93 | this.groupBox1.Name = "groupBox1";
94 | this.groupBox1.Size = new System.Drawing.Size(992, 222);
95 | this.groupBox1.TabIndex = 5;
96 | this.groupBox1.TabStop = false;
97 | this.groupBox1.Text = "Logs";
98 | //
99 | // logsTextBox
100 | //
101 | this.logsTextBox.BackColor = System.Drawing.SystemColors.Control;
102 | this.logsTextBox.BorderStyle = System.Windows.Forms.BorderStyle.None;
103 | this.logsTextBox.Location = new System.Drawing.Point(12, 19);
104 | this.logsTextBox.Name = "logsTextBox";
105 | this.logsTextBox.ReadOnly = true;
106 | this.logsTextBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
107 | this.logsTextBox.Size = new System.Drawing.Size(968, 197);
108 | this.logsTextBox.TabIndex = 0;
109 | this.logsTextBox.Text = "";
110 | this.logsTextBox.TextChanged += new System.EventHandler(this.logsTextBox_TextChanged);
111 | //
112 | // contextMenuStrip1
113 | //
114 | this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
115 | this.dumpMainModuleToolStripMenuItem,
116 | this.toolStripSeparator1,
117 | this.openInExplorerToolStripMenuItem});
118 | this.contextMenuStrip1.Name = "contextMenuStrip1";
119 | this.contextMenuStrip1.Size = new System.Drawing.Size(182, 76);
120 | this.contextMenuStrip1.Opening += new System.ComponentModel.CancelEventHandler(this.contextMenuStrip1_Opening);
121 | //
122 | // dumpMainModuleToolStripMenuItem
123 | //
124 | this.dumpMainModuleToolStripMenuItem.Name = "dumpMainModuleToolStripMenuItem";
125 | this.dumpMainModuleToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
126 | this.dumpMainModuleToolStripMenuItem.Text = "Dump Main Module";
127 | this.dumpMainModuleToolStripMenuItem.Click += new System.EventHandler(this.dumpMainModuleToolStripMenuItem_Click);
128 | //
129 | // toolStripSeparator1
130 | //
131 | this.toolStripSeparator1.Name = "toolStripSeparator1";
132 | this.toolStripSeparator1.Size = new System.Drawing.Size(178, 6);
133 | //
134 | // openInExplorerToolStripMenuItem
135 | //
136 | this.openInExplorerToolStripMenuItem.Name = "openInExplorerToolStripMenuItem";
137 | this.openInExplorerToolStripMenuItem.Size = new System.Drawing.Size(181, 22);
138 | this.openInExplorerToolStripMenuItem.Text = "Open In Explorer";
139 | this.openInExplorerToolStripMenuItem.Click += new System.EventHandler(this.openInExplorerToolStripMenuItem_Click);
140 | //
141 | // processList
142 | //
143 | this.processList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
144 | this.PIDHeader,
145 | this.NameHeader,
146 | this.PathHeader,
147 | this.BaseAddressHeader,
148 | this.EntryPointHeader,
149 | this.ImageSizeHeader,
150 | this.ImageTypeHeader});
151 | this.processList.ContextMenuStrip = this.contextMenuStrip1;
152 | this.processList.FullRowSelect = true;
153 | this.processList.Location = new System.Drawing.Point(5, 28);
154 | this.processList.MultiSelect = false;
155 | this.processList.Name = "processList";
156 | this.processList.Size = new System.Drawing.Size(992, 491);
157 | this.processList.TabIndex = 2;
158 | this.processList.UseCompatibleStateImageBehavior = false;
159 | this.processList.View = System.Windows.Forms.View.Details;
160 | //
161 | // PIDHeader
162 | //
163 | this.PIDHeader.Text = "PID";
164 | this.PIDHeader.Width = 76;
165 | //
166 | // NameHeader
167 | //
168 | this.NameHeader.Text = "Name";
169 | this.NameHeader.Width = 143;
170 | //
171 | // PathHeader
172 | //
173 | this.PathHeader.Text = "Path";
174 | this.PathHeader.Width = 375;
175 | //
176 | // BaseAddressHeader
177 | //
178 | this.BaseAddressHeader.Text = "Base Address";
179 | this.BaseAddressHeader.Width = 106;
180 | //
181 | // EntryPointHeader
182 | //
183 | this.EntryPointHeader.Text = "Entry Point";
184 | this.EntryPointHeader.Width = 106;
185 | //
186 | // ImageSizeHeader
187 | //
188 | this.ImageSizeHeader.Text = "Image Size";
189 | this.ImageSizeHeader.Width = 88;
190 | //
191 | // ImageTypeHeader
192 | //
193 | this.ImageTypeHeader.Text = "Image Type";
194 | this.ImageTypeHeader.Width = 72;
195 | //
196 | // Dumper
197 | //
198 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
199 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
200 | this.ClientSize = new System.Drawing.Size(1004, 756);
201 | this.Controls.Add(this.groupBox1);
202 | this.Controls.Add(this.toolStrip1);
203 | this.Controls.Add(this.processList);
204 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
205 | this.MaximizeBox = false;
206 | this.Name = "Dumper";
207 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
208 | this.Text = "KsDumper";
209 | this.Load += new System.EventHandler(this.Dumper_Load);
210 | this.toolStrip1.ResumeLayout(false);
211 | this.toolStrip1.PerformLayout();
212 | this.groupBox1.ResumeLayout(false);
213 | this.contextMenuStrip1.ResumeLayout(false);
214 | this.ResumeLayout(false);
215 | this.PerformLayout();
216 |
217 | }
218 |
219 | #endregion
220 | private KsDumperClient.Utility.ProcessListView processList;
221 | private System.Windows.Forms.ColumnHeader PIDHeader;
222 | private System.Windows.Forms.ColumnHeader NameHeader;
223 | private System.Windows.Forms.ColumnHeader PathHeader;
224 | private System.Windows.Forms.ColumnHeader BaseAddressHeader;
225 | private System.Windows.Forms.ColumnHeader EntryPointHeader;
226 | private System.Windows.Forms.ColumnHeader ImageSizeHeader;
227 | private System.Windows.Forms.ColumnHeader ImageTypeHeader;
228 | private System.Windows.Forms.ToolStrip toolStrip1;
229 | private System.Windows.Forms.ToolStripButton refreshMenuBtn;
230 | private System.Windows.Forms.ToolStripButton hideSystemProcessMenuBtn;
231 | private System.Windows.Forms.GroupBox groupBox1;
232 | private System.Windows.Forms.RichTextBox logsTextBox;
233 | private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
234 | private System.Windows.Forms.ToolStripMenuItem dumpMainModuleToolStripMenuItem;
235 | private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
236 | private System.Windows.Forms.ToolStripMenuItem openInExplorerToolStripMenuItem;
237 | }
238 | }
239 |
240 |
--------------------------------------------------------------------------------
/KsDumperClient/Dumper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Threading.Tasks;
6 | using System.Windows.Forms;
7 | using KsDumperClient.Driver;
8 | using KsDumperClient.PE;
9 | using KsDumperClient.Utility;
10 |
11 | namespace KsDumperClient
12 | {
13 | public partial class Dumper : Form
14 | {
15 | private readonly DriverInterface driver;
16 | private readonly ProcessDumper dumper;
17 |
18 | public Dumper()
19 | {
20 | InitializeComponent();
21 |
22 | driver = new DriverInterface("\\\\.\\KsDumper");
23 | dumper = new ProcessDumper(driver);
24 | LoadProcessList();
25 | }
26 |
27 | private void Dumper_Load(object sender, EventArgs e)
28 | {
29 | Logger.OnLog += Logger_OnLog;
30 | Logger.Log("KsDumper v1.1 - By EquiFox");
31 | }
32 |
33 | private void LoadProcessList()
34 | {
35 | if (driver.HasValidHandle())
36 | {
37 | if (driver.GetProcessSummaryList(out ProcessSummary[] result))
38 | {
39 | processList.LoadProcesses(result);
40 | }
41 | else
42 | {
43 | MessageBox.Show("Unable to retrieve process list !", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
44 | }
45 | }
46 | }
47 |
48 | private void dumpMainModuleToolStripMenuItem_Click(object sender, EventArgs e)
49 | {
50 | if (driver.HasValidHandle())
51 | {
52 | ProcessSummary targetProcess = processList.SelectedItems[0].Tag as ProcessSummary;
53 |
54 | Task.Run(() =>
55 | {
56 |
57 | if (dumper.DumpProcess(targetProcess, out PEFile peFile))
58 | {
59 | Invoke(new Action(() =>
60 | {
61 | using (SaveFileDialog sfd = new SaveFileDialog())
62 | {
63 | sfd.FileName = targetProcess.ProcessName.Replace(".exe", "_dump.exe");
64 | sfd.Filter = "Executable File (.exe)|*.exe";
65 |
66 | if (sfd.ShowDialog() == DialogResult.OK)
67 | {
68 | peFile.SaveToDisk(sfd.FileName);
69 | Logger.Log("Saved at '{0}' !", sfd.FileName);
70 | }
71 | }
72 | }));
73 | }
74 | else
75 | {
76 | Invoke(new Action(() =>
77 | {
78 | MessageBox.Show("Unable to dump target process !", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
79 | }));
80 | }
81 | });
82 | }
83 | else
84 | {
85 | MessageBox.Show("Unable to communicate with driver ! Make sure it is loaded.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
86 | }
87 | }
88 |
89 | private void Logger_OnLog(string message)
90 | {
91 | logsTextBox.Invoke(new Action(() => logsTextBox.AppendText(message)));
92 | }
93 |
94 | private void refreshMenuBtn_Click(object sender, EventArgs e)
95 | {
96 | LoadProcessList();
97 | }
98 |
99 | private void hideSystemProcessMenuBtn_Click(object sender, EventArgs e)
100 | {
101 | if (!processList.SystemProcessesHidden)
102 | {
103 | processList.HideSystemProcesses();
104 | hideSystemProcessMenuBtn.Text = "Show System Processes";
105 | }
106 | else
107 | {
108 | processList.ShowSystemProcesses();
109 | hideSystemProcessMenuBtn.Text = "Hide System Processes";
110 | }
111 | }
112 |
113 | private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
114 | {
115 | e.Cancel = processList.SelectedItems.Count == 0;
116 | }
117 |
118 | private void logsTextBox_TextChanged(object sender, EventArgs e)
119 | {
120 | logsTextBox.SelectionStart = logsTextBox.Text.Length;
121 | logsTextBox.ScrollToCaret();
122 | }
123 |
124 | private void openInExplorerToolStripMenuItem_Click(object sender, EventArgs e)
125 | {
126 | ProcessSummary targetProcess = processList.SelectedItems[0].Tag as ProcessSummary;
127 | Process.Start("explorer.exe", Path.GetDirectoryName(targetProcess.MainModuleFileName));
128 | }
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/KsDumperClient/Dumper.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 132, 17
122 |
123 |
124 | 237, 17
125 |
126 |
--------------------------------------------------------------------------------
/KsDumperClient/KsDumperClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7881B99D-0B5A-44E7-AF34-80A0ECFFD5DB}
8 | WinExe
9 | KsDumperClient
10 | KsDumperClient
11 | v4.6.1
12 | 512
13 | true
14 | true
15 |
16 |
17 | true
18 | bin\x64\Debug\
19 | TRACE;DEBUG;WIN64
20 | full
21 | x64
22 | prompt
23 | MinimumRecommendedRules.ruleset
24 | true
25 |
26 |
27 | bin\x64\Release\
28 | TRACE;WIN64
29 | true
30 | pdbonly
31 | x64
32 | prompt
33 | MinimumRecommendedRules.ruleset
34 | true
35 |
36 |
37 | app.manifest
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | Form
57 |
58 |
59 | Dumper.cs
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 | Component
78 |
79 |
80 | Dumper.cs
81 |
82 |
83 | ResXFileCodeGenerator
84 | Resources.Designer.cs
85 | Designer
86 |
87 |
88 | True
89 | Resources.resx
90 | True
91 |
92 |
93 |
94 | SettingsSingleFileGenerator
95 | Settings.Designer.cs
96 |
97 |
98 | True
99 | Settings.settings
100 | True
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/32/PE32File.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Runtime.InteropServices;
3 |
4 | using static KsDumperClient.PE.NativePEStructs;
5 |
6 | namespace KsDumperClient.PE
7 | {
8 | public class PE32File : PEFile
9 | {
10 | public DOSHeader DOSHeader { get; private set; }
11 |
12 | public byte[] DOS_Stub { get; private set; }
13 |
14 | public PE32Header PEHeader { get; private set; }
15 |
16 | public PE32File(IMAGE_DOS_HEADER dosHeader, IMAGE_NT_HEADERS32 peHeader, byte[] dosStub)
17 | {
18 | Type = PEType.PE32;
19 | DOSHeader = DOSHeader.FromNativeStruct(dosHeader);
20 | PEHeader = PE32Header.FromNativeStruct(peHeader);
21 | Sections = new PESection[peHeader.FileHeader.NumberOfSections];
22 | DOS_Stub = dosStub;
23 | }
24 |
25 | public override void SaveToDisk(string fileName)
26 | {
27 | try
28 | {
29 | using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create, FileAccess.Write)))
30 | {
31 | DOSHeader.AppendToStream(writer);
32 | writer.Write(DOS_Stub);
33 | PEHeader.AppendToStream(writer);
34 | AppendSections(writer);
35 | }
36 | }
37 | catch { }
38 | }
39 |
40 | public override int GetFirstSectionHeaderOffset()
41 | {
42 | return Marshal.OffsetOf("OptionalHeader").ToInt32() +
43 | PEHeader.FileHeader.SizeOfOptionalHeader;
44 | }
45 |
46 | public override void AlignSectionHeaders()
47 | {
48 | int newFileSize = DOSHeader.e_lfanew + 0x4 +
49 | Marshal.SizeOf() +
50 | PEHeader.FileHeader.SizeOfOptionalHeader +
51 | (PEHeader.FileHeader.NumberOfSections * Marshal.SizeOf());
52 |
53 | OrderSectionsBy(s => s.Header.PointerToRawData);
54 |
55 | for (int i = 0; i < Sections.Length; i++)
56 | {
57 | Sections[i].Header.VirtualAddress = AlignValue(Sections[i].Header.VirtualAddress, PEHeader.OptionalHeader.SectionAlignment);
58 | Sections[i].Header.VirtualSize = AlignValue(Sections[i].Header.VirtualSize, PEHeader.OptionalHeader.SectionAlignment);
59 | Sections[i].Header.PointerToRawData = AlignValue((uint)newFileSize, PEHeader.OptionalHeader.FileAlignment);
60 | Sections[i].Header.SizeOfRawData = AlignValue((uint)Sections[i].DataSize, PEHeader.OptionalHeader.FileAlignment);
61 |
62 | newFileSize = (int)(Sections[i].Header.PointerToRawData + Sections[i].Header.SizeOfRawData);
63 | }
64 |
65 | OrderSectionsBy(s => s.Header.VirtualAddress);
66 | }
67 |
68 | public override void FixPEHeader()
69 | {
70 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
71 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
72 |
73 | for (uint i = PEHeader.OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
74 | {
75 | PEHeader.OptionalHeader.DataDirectory[i].VirtualAddress = 0;
76 | PEHeader.OptionalHeader.DataDirectory[i].Size = 0;
77 | }
78 |
79 | PEHeader.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
80 | PEHeader.FileHeader.SizeOfOptionalHeader = (ushort)Marshal.SizeOf();
81 | FixSizeOfImage();
82 |
83 | int size = DOSHeader.e_lfanew + 0x4 + Marshal.SizeOf();
84 | PEHeader.OptionalHeader.SizeOfHeaders = AlignValue((uint)(size + PEHeader.FileHeader.SizeOfOptionalHeader + (PEHeader.FileHeader.NumberOfSections * Marshal.SizeOf())), PEHeader.OptionalHeader.FileAlignment);
85 |
86 | RemoveIatDirectory();
87 | }
88 |
89 | private uint AlignValue(uint value, uint alignment)
90 | {
91 | return ((value + alignment - 1) / alignment) * alignment;
92 | }
93 |
94 | private void FixSizeOfImage()
95 | {
96 | uint lastSize = 0;
97 |
98 | for (int i = 0; i < PEHeader.FileHeader.NumberOfSections; i++)
99 | {
100 | if (Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize > lastSize)
101 | {
102 | lastSize = Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize;
103 | }
104 | }
105 | PEHeader.OptionalHeader.SizeOfImage = lastSize;
106 | }
107 |
108 | private void RemoveIatDirectory()
109 | {
110 | uint iatDataAddress = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
111 |
112 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
113 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
114 |
115 | if (iatDataAddress != 0)
116 | {
117 | for (int i = 0; i < PEHeader.FileHeader.NumberOfSections; i++)
118 | {
119 | if (Sections[i].Header.VirtualAddress <= iatDataAddress &&
120 | Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize > iatDataAddress)
121 | {
122 | Sections[i].Header.Characteristics |= DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite;
123 | }
124 | }
125 | }
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/32/PE32Header.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Linq;
3 |
4 | using static KsDumperClient.PE.NativePEStructs;
5 |
6 | namespace KsDumperClient.PE
7 | {
8 | public class PE32Header
9 | {
10 | public string Signature { get; private set; }
11 |
12 | public PE32FileHeader FileHeader { get; private set; }
13 |
14 | public PE32OptionalHeader OptionalHeader { get; private set; }
15 |
16 |
17 | public void AppendToStream(BinaryWriter writer)
18 | {
19 | writer.Write(Signature.ToCharArray());
20 | FileHeader.AppendToStream(writer);
21 | OptionalHeader.AppendToStream(writer);
22 | }
23 |
24 | public static PE32Header FromNativeStruct(IMAGE_NT_HEADERS32 nativeStruct)
25 | {
26 | return new PE32Header
27 | {
28 | Signature = new string(nativeStruct.Signature),
29 | FileHeader = PE32FileHeader.FromNativeStruct(nativeStruct.FileHeader),
30 | OptionalHeader = PE32OptionalHeader.FromNativeStruct(nativeStruct.OptionalHeader)
31 | };
32 | }
33 |
34 |
35 | public class PE32FileHeader
36 | {
37 | public ushort Machine { get; set; }
38 | public ushort NumberOfSections { get; set; }
39 | public uint TimeDateStamp { get; set; }
40 | public uint PointerToSymbolTable { get; set; }
41 | public uint NumberOfSymbols { get; set; }
42 | public ushort SizeOfOptionalHeader { get; set; }
43 | public ushort Characteristics { get; set; }
44 |
45 | public void AppendToStream(BinaryWriter writer)
46 | {
47 | writer.Write(Machine);
48 | writer.Write(NumberOfSections);
49 | writer.Write(TimeDateStamp);
50 | writer.Write(PointerToSymbolTable);
51 | writer.Write(NumberOfSymbols);
52 | writer.Write(SizeOfOptionalHeader);
53 | writer.Write(Characteristics);
54 | }
55 |
56 | public static PE32FileHeader FromNativeStruct(IMAGE_FILE_HEADER nativeStruct)
57 | {
58 | return new PE32FileHeader
59 | {
60 | Machine = nativeStruct.Machine,
61 | NumberOfSections = nativeStruct.NumberOfSections,
62 | TimeDateStamp = nativeStruct.TimeDateStamp,
63 | PointerToSymbolTable = nativeStruct.PointerToSymbolTable,
64 | NumberOfSymbols = nativeStruct.NumberOfSymbols,
65 | SizeOfOptionalHeader = nativeStruct.SizeOfOptionalHeader,
66 | Characteristics = nativeStruct.Characteristics
67 | };
68 | }
69 | }
70 |
71 | public class PE32OptionalHeader
72 | {
73 | public ushort Magic { get; set; }
74 | public byte MajorLinkerVersion { get; set; }
75 | public byte MinorLinkerVersion { get; set; }
76 | public uint SizeOfCode { get; set; }
77 | public uint SizeOfInitializedData { get; set; }
78 | public uint SizeOfUninitializedData { get; set; }
79 | public uint AddressOfEntryPoint { get; set; }
80 | public uint BaseOfCode { get; set; }
81 | public uint BaseOfData { get; set; }
82 | public uint ImageBase { get; set; }
83 | public uint SectionAlignment { get; set; }
84 | public uint FileAlignment { get; set; }
85 | public ushort MajorOperatingSystemVersion { get; set; }
86 | public ushort MinorOperatingSystemVersion { get; set; }
87 | public ushort MajorImageVersion { get; set; }
88 | public ushort MinorImageVersion { get; set; }
89 | public ushort MajorSubsystemVersion { get; set; }
90 | public ushort MinorSubsystemVersion { get; set; }
91 | public uint Win32VersionValue { get; set; }
92 | public uint SizeOfImage { get; set; }
93 | public uint SizeOfHeaders { get; set; }
94 | public uint CheckSum { get; set; }
95 | public ushort Subsystem { get; set; }
96 | public ushort DllCharacteristics { get; set; }
97 | public uint SizeOfStackReserve { get; set; }
98 | public uint SizeOfStackCommit { get; set; }
99 | public uint SizeOfHeapReserve { get; set; }
100 | public uint SizeOfHeapCommit { get; set; }
101 | public uint LoaderFlags { get; set; }
102 | public uint NumberOfRvaAndSizes { get; set; }
103 | public PE32DataDirectory[] DataDirectory { get; private set; }
104 |
105 |
106 | public void AppendToStream(BinaryWriter writer)
107 | {
108 | writer.Write(Magic);
109 | writer.Write(MajorLinkerVersion);
110 | writer.Write(MinorLinkerVersion);
111 | writer.Write(SizeOfCode);
112 | writer.Write(SizeOfInitializedData);
113 | writer.Write(SizeOfUninitializedData);
114 | writer.Write(AddressOfEntryPoint);
115 | writer.Write(BaseOfCode);
116 | writer.Write(BaseOfData);
117 | writer.Write(ImageBase);
118 | writer.Write(SectionAlignment);
119 | writer.Write(FileAlignment);
120 | writer.Write(MajorOperatingSystemVersion);
121 | writer.Write(MinorOperatingSystemVersion);
122 | writer.Write(MajorImageVersion);
123 | writer.Write(MinorImageVersion);
124 | writer.Write(MajorSubsystemVersion);
125 | writer.Write(MinorSubsystemVersion);
126 | writer.Write(Win32VersionValue);
127 | writer.Write(SizeOfImage);
128 | writer.Write(SizeOfHeaders);
129 | writer.Write(CheckSum);
130 | writer.Write(Subsystem);
131 | writer.Write(DllCharacteristics);
132 | writer.Write(SizeOfStackReserve);
133 | writer.Write(SizeOfStackCommit);
134 | writer.Write(SizeOfHeapReserve);
135 | writer.Write(SizeOfHeapCommit);
136 | writer.Write(LoaderFlags);
137 | writer.Write(NumberOfRvaAndSizes);
138 |
139 | foreach (PE32DataDirectory dataDirectory in DataDirectory)
140 | {
141 | dataDirectory.AppendToStream(writer);
142 | }
143 | }
144 |
145 | public static PE32OptionalHeader FromNativeStruct(IMAGE_OPTIONAL_HEADER32 nativeStruct)
146 | {
147 | PE32DataDirectory[] directories = nativeStruct.DataDirectory.Select(d => PE32DataDirectory.FromNativeStruct(d)).ToArray();
148 |
149 | return new PE32OptionalHeader
150 | {
151 | Magic = nativeStruct.Magic,
152 | MajorLinkerVersion = nativeStruct.MajorLinkerVersion,
153 | MinorLinkerVersion = nativeStruct.MinorLinkerVersion,
154 | SizeOfCode = nativeStruct.SizeOfCode,
155 | SizeOfInitializedData = nativeStruct.SizeOfInitializedData,
156 | SizeOfUninitializedData = nativeStruct.SizeOfUninitializedData,
157 | AddressOfEntryPoint = nativeStruct.AddressOfEntryPoint,
158 | BaseOfCode = nativeStruct.BaseOfCode,
159 | BaseOfData = nativeStruct.BaseOfData,
160 | ImageBase = nativeStruct.ImageBase,
161 | SectionAlignment = nativeStruct.SectionAlignment,
162 | FileAlignment = nativeStruct.FileAlignment,
163 | MajorOperatingSystemVersion = nativeStruct.MajorOperatingSystemVersion,
164 | MinorOperatingSystemVersion = nativeStruct.MinorOperatingSystemVersion,
165 | MajorImageVersion = nativeStruct.MajorImageVersion,
166 | MinorImageVersion = nativeStruct.MinorImageVersion,
167 | MajorSubsystemVersion = nativeStruct.MajorSubsystemVersion,
168 | MinorSubsystemVersion = nativeStruct.MinorSubsystemVersion,
169 | Win32VersionValue = nativeStruct.Win32VersionValue,
170 | SizeOfImage = nativeStruct.SizeOfImage,
171 | SizeOfHeaders = nativeStruct.SizeOfHeaders,
172 | CheckSum = nativeStruct.CheckSum,
173 | Subsystem = nativeStruct.Subsystem,
174 | DllCharacteristics = nativeStruct.DllCharacteristics,
175 | SizeOfStackReserve = nativeStruct.SizeOfStackReserve,
176 | SizeOfStackCommit = nativeStruct.SizeOfStackCommit,
177 | SizeOfHeapReserve = nativeStruct.SizeOfHeapReserve,
178 | SizeOfHeapCommit = nativeStruct.SizeOfHeapCommit,
179 | LoaderFlags = nativeStruct.LoaderFlags,
180 | NumberOfRvaAndSizes = nativeStruct.NumberOfRvaAndSizes,
181 | DataDirectory = directories
182 | };
183 | }
184 |
185 | public class PE32DataDirectory
186 | {
187 | public uint VirtualAddress { get; set; }
188 | public uint Size { get; set; }
189 |
190 |
191 | public void AppendToStream(BinaryWriter writer)
192 | {
193 | writer.Write(VirtualAddress);
194 | writer.Write(Size);
195 | }
196 |
197 | public static PE32DataDirectory FromNativeStruct(IMAGE_DATA_DIRECTORY nativeStruct)
198 | {
199 | return new PE32DataDirectory
200 | {
201 | VirtualAddress = nativeStruct.VirtualAddress,
202 | Size = nativeStruct.Size
203 | };
204 | }
205 | }
206 | }
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/64/PE64File.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Runtime.InteropServices;
3 |
4 | using static KsDumperClient.PE.NativePEStructs;
5 |
6 | namespace KsDumperClient.PE
7 | {
8 | public class PE64File : PEFile
9 | {
10 | public DOSHeader DOSHeader { get; private set; }
11 |
12 | public byte[] DOS_Stub { get; private set; }
13 |
14 | public PE64Header PEHeader { get; private set; }
15 |
16 | public PE64File(IMAGE_DOS_HEADER dosHeader, IMAGE_NT_HEADERS64 peHeader, byte[] dosStub)
17 | {
18 | Type = PEType.PE64;
19 | DOSHeader = DOSHeader.FromNativeStruct(dosHeader);
20 | PEHeader = PE64Header.FromNativeStruct(peHeader);
21 | Sections = new PESection[peHeader.FileHeader.NumberOfSections];
22 | DOS_Stub = dosStub;
23 | }
24 |
25 | public override void SaveToDisk(string fileName)
26 | {
27 | try
28 | {
29 | using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create, FileAccess.Write)))
30 | {
31 | DOSHeader.AppendToStream(writer);
32 | writer.Write(DOS_Stub);
33 | PEHeader.AppendToStream(writer);
34 | AppendSections(writer);
35 | }
36 | }
37 | catch { }
38 | }
39 |
40 | public override int GetFirstSectionHeaderOffset()
41 | {
42 | return Marshal.OffsetOf("OptionalHeader").ToInt32() +
43 | PEHeader.FileHeader.SizeOfOptionalHeader;
44 | }
45 |
46 | public override void AlignSectionHeaders()
47 | {
48 | int newFileSize = DOSHeader.e_lfanew + 0x4 +
49 | Marshal.SizeOf() +
50 | PEHeader.FileHeader.SizeOfOptionalHeader +
51 | (PEHeader.FileHeader.NumberOfSections * Marshal.SizeOf());
52 |
53 | OrderSectionsBy(s => s.Header.PointerToRawData);
54 |
55 | for (int i = 0; i < Sections.Length; i++)
56 | {
57 | Sections[i].Header.VirtualAddress = AlignValue(Sections[i].Header.VirtualAddress, PEHeader.OptionalHeader.SectionAlignment);
58 | Sections[i].Header.VirtualSize = AlignValue(Sections[i].Header.VirtualSize, PEHeader.OptionalHeader.SectionAlignment);
59 | Sections[i].Header.PointerToRawData = AlignValue((uint)newFileSize, PEHeader.OptionalHeader.FileAlignment);
60 | Sections[i].Header.SizeOfRawData = AlignValue((uint)Sections[i].DataSize, PEHeader.OptionalHeader.FileAlignment);
61 |
62 | newFileSize = (int)(Sections[i].Header.PointerToRawData + Sections[i].Header.SizeOfRawData);
63 | }
64 |
65 | OrderSectionsBy(s => s.Header.VirtualAddress);
66 | }
67 |
68 | public override void FixPEHeader()
69 | {
70 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
71 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
72 |
73 | for (uint i = PEHeader.OptionalHeader.NumberOfRvaAndSizes; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++)
74 | {
75 | PEHeader.OptionalHeader.DataDirectory[i].VirtualAddress = 0;
76 | PEHeader.OptionalHeader.DataDirectory[i].Size = 0;
77 | }
78 |
79 | PEHeader.OptionalHeader.NumberOfRvaAndSizes = IMAGE_NUMBEROF_DIRECTORY_ENTRIES;
80 | PEHeader.FileHeader.SizeOfOptionalHeader = (ushort)Marshal.SizeOf();
81 | FixSizeOfImage();
82 |
83 | int size = DOSHeader.e_lfanew + 0x4 + Marshal.SizeOf();
84 | PEHeader.OptionalHeader.SizeOfHeaders = AlignValue((uint)(size + PEHeader.FileHeader.SizeOfOptionalHeader + (PEHeader.FileHeader.NumberOfSections * Marshal.SizeOf())), PEHeader.OptionalHeader.FileAlignment);
85 |
86 | RemoveIatDirectory();
87 | }
88 |
89 | private uint AlignValue(uint value, uint alignment)
90 | {
91 | return ((value + alignment - 1) / alignment) * alignment;
92 | }
93 |
94 | private void FixSizeOfImage()
95 | {
96 | uint lastSize = 0;
97 |
98 | for (int i = 0; i < PEHeader.FileHeader.NumberOfSections; i++)
99 | {
100 | if (Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize > lastSize)
101 | {
102 | lastSize = Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize;
103 | }
104 | }
105 | PEHeader.OptionalHeader.SizeOfImage = lastSize;
106 | }
107 |
108 | private void RemoveIatDirectory()
109 | {
110 | uint iatDataAddress = PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress;
111 |
112 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = 0;
113 | PEHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = 0;
114 |
115 | if (iatDataAddress != 0)
116 | {
117 | for (int i = 0; i < PEHeader.FileHeader.NumberOfSections; i++)
118 | {
119 | if (Sections[i].Header.VirtualAddress <= iatDataAddress &&
120 | Sections[i].Header.VirtualAddress + Sections[i].Header.VirtualSize > iatDataAddress)
121 | {
122 | Sections[i].Header.Characteristics |= DataSectionFlags.MemoryRead | DataSectionFlags.MemoryWrite;
123 | }
124 | }
125 | }
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/64/PE64Header.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Linq;
3 |
4 | using static KsDumperClient.PE.NativePEStructs;
5 |
6 | namespace KsDumperClient.PE
7 | {
8 | public class PE64Header
9 | {
10 | public string Signature { get; private set; }
11 |
12 | public PE64FileHeader FileHeader { get; private set; }
13 |
14 | public PE64OptionalHeader OptionalHeader { get; private set; }
15 |
16 |
17 | public void AppendToStream(BinaryWriter writer)
18 | {
19 | writer.Write(Signature.ToCharArray());
20 | FileHeader.AppendToStream(writer);
21 | OptionalHeader.AppendToStream(writer);
22 | }
23 |
24 | public static PE64Header FromNativeStruct(IMAGE_NT_HEADERS64 nativeStruct)
25 | {
26 | return new PE64Header
27 | {
28 | Signature = new string(nativeStruct.Signature),
29 | FileHeader = PE64FileHeader.FromNativeStruct(nativeStruct.FileHeader),
30 | OptionalHeader = PE64OptionalHeader.FromNativeStruct(nativeStruct.OptionalHeader)
31 | };
32 | }
33 |
34 |
35 | public class PE64FileHeader
36 | {
37 | public ushort Machine { get; set; }
38 | public ushort NumberOfSections { get; set; }
39 | public uint TimeDateStamp { get; set; }
40 | public uint PointerToSymbolTable { get; set; }
41 | public uint NumberOfSymbols { get; set; }
42 | public ushort SizeOfOptionalHeader { get; set; }
43 | public ushort Characteristics { get; set; }
44 |
45 | public void AppendToStream(BinaryWriter writer)
46 | {
47 | writer.Write(Machine);
48 | writer.Write(NumberOfSections);
49 | writer.Write(TimeDateStamp);
50 | writer.Write(PointerToSymbolTable);
51 | writer.Write(NumberOfSymbols);
52 | writer.Write(SizeOfOptionalHeader);
53 | writer.Write(Characteristics);
54 | }
55 |
56 | public static PE64FileHeader FromNativeStruct(IMAGE_FILE_HEADER nativeStruct)
57 | {
58 | return new PE64FileHeader
59 | {
60 | Machine = nativeStruct.Machine,
61 | NumberOfSections = nativeStruct.NumberOfSections,
62 | TimeDateStamp = nativeStruct.TimeDateStamp,
63 | PointerToSymbolTable = nativeStruct.PointerToSymbolTable,
64 | NumberOfSymbols = nativeStruct.NumberOfSymbols,
65 | SizeOfOptionalHeader = nativeStruct.SizeOfOptionalHeader,
66 | Characteristics = nativeStruct.Characteristics
67 | };
68 | }
69 | }
70 |
71 | public class PE64OptionalHeader
72 | {
73 | public ushort Magic { get; set; }
74 | public byte MajorLinkerVersion { get; set; }
75 | public byte MinorLinkerVersion { get; set; }
76 | public uint SizeOfCode { get; set; }
77 | public uint SizeOfInitializedData { get; set; }
78 | public uint SizeOfUninitializedData { get; set; }
79 | public uint AddressOfEntryPoint { get; set; }
80 | public uint BaseOfCode { get; set; }
81 | #if WIN32
82 | public uint BaseOfData { get; set; }
83 | public uint ImageBase { get; set; }
84 | #else
85 | public ulong ImageBase { get; set; }
86 | #endif
87 | public uint SectionAlignment { get; set; }
88 | public uint FileAlignment { get; set; }
89 | public ushort MajorOperatingSystemVersion { get; set; }
90 | public ushort MinorOperatingSystemVersion { get; set; }
91 | public ushort MajorImageVersion { get; set; }
92 | public ushort MinorImageVersion { get; set; }
93 | public ushort MajorSubsystemVersion { get; set; }
94 | public ushort MinorSubsystemVersion { get; set; }
95 | public uint Win32VersionValue { get; set; }
96 | public uint SizeOfImage { get; set; }
97 | public uint SizeOfHeaders { get; set; }
98 | public uint CheckSum { get; set; }
99 | public ushort Subsystem { get; set; }
100 | public ushort DllCharacteristics { get; set; }
101 | #if WIN32
102 | public uint SizeOfStackReserve { get; set; }
103 | public uint SizeOfStackCommit { get; set; }
104 | public uint SizeOfHeapReserve { get; set; }
105 | public uint SizeOfHeapCommit { get; set; }
106 | #else
107 | public ulong SizeOfStackReserve { get; set; }
108 | public ulong SizeOfStackCommit { get; set; }
109 | public ulong SizeOfHeapReserve { get; set; }
110 | public ulong SizeOfHeapCommit { get; set; }
111 | #endif
112 | public uint LoaderFlags { get; set; }
113 | public uint NumberOfRvaAndSizes { get; set; }
114 | public PE64DataDirectory[] DataDirectory { get; private set; }
115 |
116 |
117 | public void AppendToStream(BinaryWriter writer)
118 | {
119 | writer.Write(Magic);
120 | writer.Write(MajorLinkerVersion);
121 | writer.Write(MinorLinkerVersion);
122 | writer.Write(SizeOfCode);
123 | writer.Write(SizeOfInitializedData);
124 | writer.Write(SizeOfUninitializedData);
125 | writer.Write(AddressOfEntryPoint);
126 | writer.Write(BaseOfCode);
127 | #if WIN32
128 | writer.Write(BaseOfData);
129 | #endif
130 | writer.Write(ImageBase);
131 | writer.Write(SectionAlignment);
132 | writer.Write(FileAlignment);
133 | writer.Write(MajorOperatingSystemVersion);
134 | writer.Write(MinorOperatingSystemVersion);
135 | writer.Write(MajorImageVersion);
136 | writer.Write(MinorImageVersion);
137 | writer.Write(MajorSubsystemVersion);
138 | writer.Write(MinorSubsystemVersion);
139 | writer.Write(Win32VersionValue);
140 | writer.Write(SizeOfImage);
141 | writer.Write(SizeOfHeaders);
142 | writer.Write(CheckSum);
143 | writer.Write(Subsystem);
144 | writer.Write(DllCharacteristics);
145 | writer.Write(SizeOfStackReserve);
146 | writer.Write(SizeOfStackCommit);
147 | writer.Write(SizeOfHeapReserve);
148 | writer.Write(SizeOfHeapCommit);
149 | writer.Write(LoaderFlags);
150 | writer.Write(NumberOfRvaAndSizes);
151 |
152 | foreach (PE64DataDirectory dataDirectory in DataDirectory)
153 | {
154 | dataDirectory.AppendToStream(writer);
155 | }
156 | }
157 |
158 | public static PE64OptionalHeader FromNativeStruct(IMAGE_OPTIONAL_HEADER64 nativeStruct)
159 | {
160 | PE64DataDirectory[] directories = nativeStruct.DataDirectory.Select(d => PE64DataDirectory.FromNativeStruct(d)).ToArray();
161 |
162 | return new PE64OptionalHeader
163 | {
164 | Magic = nativeStruct.Magic,
165 | MajorLinkerVersion = nativeStruct.MajorLinkerVersion,
166 | MinorLinkerVersion = nativeStruct.MinorLinkerVersion,
167 | SizeOfCode = nativeStruct.SizeOfCode,
168 | SizeOfInitializedData = nativeStruct.SizeOfInitializedData,
169 | SizeOfUninitializedData = nativeStruct.SizeOfUninitializedData,
170 | AddressOfEntryPoint = nativeStruct.AddressOfEntryPoint,
171 | BaseOfCode = nativeStruct.BaseOfCode,
172 | #if WIN32
173 | BaseOfData = nativeStruct.BaseOfData,
174 | #endif
175 | ImageBase = nativeStruct.ImageBase,
176 | SectionAlignment = nativeStruct.SectionAlignment,
177 | FileAlignment = nativeStruct.FileAlignment,
178 | MajorOperatingSystemVersion = nativeStruct.MajorOperatingSystemVersion,
179 | MinorOperatingSystemVersion = nativeStruct.MinorOperatingSystemVersion,
180 | MajorImageVersion = nativeStruct.MajorImageVersion,
181 | MinorImageVersion = nativeStruct.MinorImageVersion,
182 | MajorSubsystemVersion = nativeStruct.MajorSubsystemVersion,
183 | MinorSubsystemVersion = nativeStruct.MinorSubsystemVersion,
184 | Win32VersionValue = nativeStruct.Win32VersionValue,
185 | SizeOfImage = nativeStruct.SizeOfImage,
186 | SizeOfHeaders = nativeStruct.SizeOfHeaders,
187 | CheckSum = nativeStruct.CheckSum,
188 | Subsystem = nativeStruct.Subsystem,
189 | DllCharacteristics = nativeStruct.DllCharacteristics,
190 | SizeOfStackReserve = nativeStruct.SizeOfStackReserve,
191 | SizeOfStackCommit = nativeStruct.SizeOfStackCommit,
192 | SizeOfHeapReserve = nativeStruct.SizeOfHeapReserve,
193 | SizeOfHeapCommit = nativeStruct.SizeOfHeapCommit,
194 | LoaderFlags = nativeStruct.LoaderFlags,
195 | NumberOfRvaAndSizes = nativeStruct.NumberOfRvaAndSizes,
196 | DataDirectory = directories
197 | };
198 | }
199 |
200 | public class PE64DataDirectory
201 | {
202 | public uint VirtualAddress { get; set; }
203 | public uint Size { get; set; }
204 |
205 |
206 | public void AppendToStream(BinaryWriter writer)
207 | {
208 | writer.Write(VirtualAddress);
209 | writer.Write(Size);
210 | }
211 |
212 | public static PE64DataDirectory FromNativeStruct(IMAGE_DATA_DIRECTORY nativeStruct)
213 | {
214 | return new PE64DataDirectory
215 | {
216 | VirtualAddress = nativeStruct.VirtualAddress,
217 | Size = nativeStruct.Size
218 | };
219 | }
220 | }
221 | }
222 | }
223 | }
224 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/DOSHeader.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | using static KsDumperClient.PE.NativePEStructs;
4 |
5 | namespace KsDumperClient.PE
6 | {
7 | public class DOSHeader
8 | {
9 | public string e_magic { get; set; }
10 | public ushort e_cblp { get; set; }
11 | public ushort e_cp { get; set; }
12 | public ushort e_crlc { get; set; }
13 | public ushort e_cparhdr { get; set; }
14 | public ushort e_minalloc { get; set; }
15 | public ushort e_maxalloc { get; set; }
16 | public ushort e_ss { get; set; }
17 | public ushort e_sp { get; set; }
18 | public ushort e_csum { get; set; }
19 | public ushort e_ip { get; set; }
20 | public ushort e_cs { get; set; }
21 | public ushort e_lfarlc { get; set; }
22 | public ushort e_ovno { get; set; }
23 | public ushort[] e_res1 { get; set; }
24 | public ushort e_oemid { get; set; }
25 | public ushort e_oeminfo { get; set; }
26 | public ushort[] e_res2 { get; set; }
27 | public int e_lfanew { get; set; }
28 |
29 | public void AppendToStream(BinaryWriter writer)
30 | {
31 | writer.Write(e_magic.ToCharArray());
32 | writer.Write(e_cblp);
33 | writer.Write(e_cp);
34 | writer.Write(e_crlc);
35 | writer.Write(e_cparhdr);
36 | writer.Write(e_minalloc);
37 | writer.Write(e_maxalloc);
38 | writer.Write(e_ss);
39 | writer.Write(e_sp);
40 | writer.Write(e_csum);
41 | writer.Write(e_ip);
42 | writer.Write(e_cs);
43 | writer.Write(e_lfarlc);
44 | writer.Write(e_ovno);
45 |
46 | for (int i = 0; i < e_res1.Length; i++)
47 | {
48 | writer.Write(e_res1[i]);
49 | }
50 | writer.Write(e_oemid);
51 | writer.Write(e_oeminfo);
52 |
53 | for (int i = 0; i < e_res2.Length; i++)
54 | {
55 | writer.Write(e_res2[i]);
56 | }
57 | writer.Write(e_lfanew);
58 | }
59 |
60 | public static DOSHeader FromNativeStruct(IMAGE_DOS_HEADER nativeStruct)
61 | {
62 | return new DOSHeader
63 | {
64 | e_magic = new string(nativeStruct.e_magic),
65 | e_cblp = nativeStruct.e_cblp,
66 | e_cp = nativeStruct.e_cp,
67 | e_crlc = nativeStruct.e_crlc,
68 | e_cparhdr = nativeStruct.e_cparhdr,
69 | e_minalloc = nativeStruct.e_minalloc,
70 | e_maxalloc = nativeStruct.e_maxalloc,
71 | e_ss = nativeStruct.e_ss,
72 | e_sp = nativeStruct.e_sp,
73 | e_csum = nativeStruct.e_csum,
74 | e_ip = nativeStruct.e_ip,
75 | e_cs = nativeStruct.e_cs,
76 | e_lfarlc = nativeStruct.e_lfarlc,
77 | e_ovno = nativeStruct.e_ovno,
78 | e_res1 = nativeStruct.e_res1,
79 | e_oemid = nativeStruct.e_oemid,
80 | e_oeminfo = nativeStruct.e_oeminfo,
81 | e_res2 = nativeStruct.e_res2,
82 | e_lfanew = nativeStruct.e_lfanew
83 | };
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/NativePEStructs.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace KsDumperClient.PE
5 | {
6 | public static class NativePEStructs
7 | {
8 | public const uint IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
9 | public const uint IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
10 |
11 | public const uint IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
12 |
13 | public const uint IMAGE_DIRECTORY_ENTRY_EXPORT = 0;
14 | public const uint IMAGE_DIRECTORY_ENTRY_IMPORT = 1;
15 | public const uint IMAGE_DIRECTORY_ENTRY_RESOURCE = 2;
16 | public const uint IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3;
17 | public const uint IMAGE_DIRECTORY_ENTRY_SECURITY = 4;
18 | public const uint IMAGE_DIRECTORY_ENTRY_BASERELOC = 5;
19 | public const uint IMAGE_DIRECTORY_ENTRY_DEBUG = 6;
20 | public const uint IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7;
21 | public const uint IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8;
22 | public const uint IMAGE_DIRECTORY_ENTRY_TLS = 9;
23 | public const uint IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10;
24 | public const uint IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11;
25 | public const uint IMAGE_DIRECTORY_ENTRY_IAT = 12;
26 | public const uint IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13;
27 | public const uint IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14;
28 |
29 | [StructLayout(LayoutKind.Sequential)]
30 | public struct IMAGE_DOS_HEADER
31 | {
32 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
33 | public char[] e_magic;
34 | public ushort e_cblp;
35 | public ushort e_cp;
36 | public ushort e_crlc;
37 | public ushort e_cparhdr;
38 | public ushort e_minalloc;
39 | public ushort e_maxalloc;
40 | public ushort e_ss;
41 | public ushort e_sp;
42 | public ushort e_csum;
43 | public ushort e_ip;
44 | public ushort e_cs;
45 | public ushort e_lfarlc;
46 | public ushort e_ovno;
47 |
48 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
49 | public ushort[] e_res1;
50 | public ushort e_oemid;
51 | public ushort e_oeminfo;
52 |
53 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
54 | public ushort[] e_res2;
55 | public int e_lfanew;
56 |
57 | private string _e_magic
58 | {
59 | get { return new string(e_magic); }
60 | }
61 |
62 | public bool IsValid
63 | {
64 | get { return _e_magic == "MZ"; }
65 | }
66 | }
67 |
68 | [StructLayout(LayoutKind.Sequential)]
69 | public struct IMAGE_NT_HEADERS32
70 | {
71 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
72 | public char[] Signature;
73 |
74 | public IMAGE_FILE_HEADER FileHeader;
75 |
76 | public IMAGE_OPTIONAL_HEADER32 OptionalHeader;
77 |
78 | private string _Signature
79 | {
80 | get { return new string(Signature); }
81 | }
82 |
83 | public bool IsValid
84 | {
85 | get { return _Signature == "PE\0\0" && OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC; }
86 | }
87 | }
88 |
89 | [StructLayout(LayoutKind.Sequential)]
90 | public struct IMAGE_NT_HEADERS64
91 | {
92 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
93 | public char[] Signature;
94 |
95 | public IMAGE_FILE_HEADER FileHeader;
96 |
97 | public IMAGE_OPTIONAL_HEADER64 OptionalHeader;
98 |
99 | private string _Signature
100 | {
101 | get { return new string(Signature); }
102 | }
103 |
104 | public bool IsValid
105 | {
106 | get { return _Signature == "PE\0\0" && OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC; }
107 | }
108 | }
109 |
110 | [StructLayout(LayoutKind.Sequential)]
111 | public struct IMAGE_FILE_HEADER
112 | {
113 | internal ushort Machine;
114 | internal ushort NumberOfSections;
115 | internal uint TimeDateStamp;
116 | internal uint PointerToSymbolTable;
117 | internal uint NumberOfSymbols;
118 | internal ushort SizeOfOptionalHeader;
119 | internal ushort Characteristics;
120 | }
121 |
122 | [StructLayout(LayoutKind.Sequential)]
123 | public struct IMAGE_OPTIONAL_HEADER32
124 | {
125 | internal ushort Magic;
126 | internal byte MajorLinkerVersion;
127 | internal byte MinorLinkerVersion;
128 | internal uint SizeOfCode;
129 | internal uint SizeOfInitializedData;
130 | internal uint SizeOfUninitializedData;
131 | internal uint AddressOfEntryPoint;
132 | internal uint BaseOfCode;
133 | internal uint BaseOfData;
134 | internal uint ImageBase;
135 | internal uint SectionAlignment;
136 | internal uint FileAlignment;
137 | internal ushort MajorOperatingSystemVersion;
138 | internal ushort MinorOperatingSystemVersion;
139 | internal ushort MajorImageVersion;
140 | internal ushort MinorImageVersion;
141 | internal ushort MajorSubsystemVersion;
142 | internal ushort MinorSubsystemVersion;
143 | internal uint Win32VersionValue;
144 | internal uint SizeOfImage;
145 | internal uint SizeOfHeaders;
146 | internal uint CheckSum;
147 | internal ushort Subsystem;
148 | internal ushort DllCharacteristics;
149 | internal uint SizeOfStackReserve;
150 | internal uint SizeOfStackCommit;
151 | internal uint SizeOfHeapReserve;
152 | internal uint SizeOfHeapCommit;
153 | internal uint LoaderFlags;
154 | internal uint NumberOfRvaAndSizes;
155 |
156 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
157 | internal IMAGE_DATA_DIRECTORY[] DataDirectory;
158 | }
159 |
160 | [StructLayout(LayoutKind.Sequential)]
161 | public struct IMAGE_OPTIONAL_HEADER64
162 | {
163 | internal ushort Magic;
164 | internal byte MajorLinkerVersion;
165 | internal byte MinorLinkerVersion;
166 | internal uint SizeOfCode;
167 | internal uint SizeOfInitializedData;
168 | internal uint SizeOfUninitializedData;
169 | internal uint AddressOfEntryPoint;
170 | internal uint BaseOfCode;
171 | internal ulong ImageBase;
172 | internal uint SectionAlignment;
173 | internal uint FileAlignment;
174 | internal ushort MajorOperatingSystemVersion;
175 | internal ushort MinorOperatingSystemVersion;
176 | internal ushort MajorImageVersion;
177 | internal ushort MinorImageVersion;
178 | internal ushort MajorSubsystemVersion;
179 | internal ushort MinorSubsystemVersion;
180 | internal uint Win32VersionValue;
181 | internal uint SizeOfImage;
182 | internal uint SizeOfHeaders;
183 | internal uint CheckSum;
184 | internal ushort Subsystem;
185 | internal ushort DllCharacteristics;
186 | internal ulong SizeOfStackReserve;
187 | internal ulong SizeOfStackCommit;
188 | internal ulong SizeOfHeapReserve;
189 | internal ulong SizeOfHeapCommit;
190 | internal uint LoaderFlags;
191 | internal uint NumberOfRvaAndSizes;
192 |
193 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
194 | internal IMAGE_DATA_DIRECTORY[] DataDirectory;
195 | }
196 |
197 | [StructLayout(LayoutKind.Sequential)]
198 | public struct IMAGE_DATA_DIRECTORY
199 | {
200 | internal uint VirtualAddress;
201 | internal uint Size;
202 | }
203 |
204 | [StructLayout(LayoutKind.Sequential)]
205 | public struct IMAGE_SECTION_HEADER
206 | {
207 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
208 | public char[] Name;
209 |
210 | public uint VirtualSize;
211 |
212 | public uint VirtualAddress;
213 |
214 | public uint SizeOfRawData;
215 |
216 | public uint PointerToRawData;
217 |
218 | public uint PointerToRelocations;
219 |
220 | public uint PointerToLinenumbers;
221 |
222 | public ushort NumberOfRelocations;
223 |
224 | public ushort NumberOfLinenumbers;
225 |
226 | public DataSectionFlags Characteristics;
227 |
228 | public string SectionName
229 | {
230 | get { return new string(Name); }
231 | }
232 | }
233 |
234 | [Flags]
235 | public enum DataSectionFlags : uint
236 | {
237 | TypeReg = 0x00000000,
238 | TypeDsect = 0x00000001,
239 | TypeNoLoad = 0x00000002,
240 | TypeGroup = 0x00000004,
241 | TypeNoPadded = 0x00000008,
242 | TypeCopy = 0x00000010,
243 | ContentCode = 0x00000020,
244 | ContentInitializedData = 0x00000040,
245 | ContentUninitializedData = 0x00000080,
246 | LinkOther = 0x00000100,
247 | LinkInfo = 0x00000200,
248 | TypeOver = 0x00000400,
249 | LinkRemove = 0x00000800,
250 | LinkComDat = 0x00001000,
251 | NoDeferSpecExceptions = 0x00004000,
252 | RelativeGP = 0x00008000,
253 | MemPurgeable = 0x00020000,
254 | Memory16Bit = 0x00020000,
255 | MemoryLocked = 0x00040000,
256 | MemoryPreload = 0x00080000,
257 | Align1Bytes = 0x00100000,
258 | Align2Bytes = 0x00200000,
259 | Align4Bytes = 0x00300000,
260 | Align8Bytes = 0x00400000,
261 | Align16Bytes = 0x00500000,
262 | Align32Bytes = 0x00600000,
263 | Align64Bytes = 0x00700000,
264 | Align128Bytes = 0x00800000,
265 | Align256Bytes = 0x00900000,
266 | Align512Bytes = 0x00A00000,
267 | Align1024Bytes = 0x00B00000,
268 | Align2048Bytes = 0x00C00000,
269 | Align4096Bytes = 0x00D00000,
270 | Align8192Bytes = 0x00E00000,
271 | LinkExtendedRelocationOverflow = 0x01000000,
272 | MemoryDiscardable = 0x02000000,
273 | MemoryNotCached = 0x04000000,
274 | MemoryNotPaged = 0x08000000,
275 | MemoryShared = 0x10000000,
276 | MemoryExecute = 0x20000000,
277 | MemoryRead = 0x40000000,
278 | MemoryWrite = 0x80000000
279 | }
280 | }
281 | }
282 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/PEFile.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Linq;
4 |
5 | namespace KsDumperClient.PE
6 | {
7 | public abstract class PEFile
8 | {
9 | public PEType Type { get; protected set; }
10 |
11 | public PESection[] Sections { get; protected set; }
12 |
13 |
14 | public abstract int GetFirstSectionHeaderOffset();
15 |
16 | public abstract void AlignSectionHeaders();
17 |
18 | public abstract void FixPEHeader();
19 |
20 | public abstract void SaveToDisk(string fileName);
21 |
22 | protected void AppendSections(BinaryWriter writer)
23 | {
24 | foreach (var sectionHeader in Sections.Select(s => s.Header))
25 | {
26 | sectionHeader.AppendToStream(writer);
27 | }
28 |
29 | foreach (var section in Sections)
30 | {
31 | if (section.Header.PointerToRawData > 0)
32 | {
33 | if (section.Header.PointerToRawData > writer.BaseStream.Position)
34 | {
35 | long prePaddingSize = section.Header.PointerToRawData - writer.BaseStream.Position;
36 | writer.Write(new byte[prePaddingSize]);
37 | }
38 |
39 | if (section.DataSize > 0)
40 | {
41 | writer.Write(section.Content);
42 |
43 | if (section.DataSize < section.Header.SizeOfRawData)
44 | {
45 | long postPaddingSize = section.Header.SizeOfRawData - section.DataSize;
46 | writer.Write(new byte[postPaddingSize]);
47 | }
48 | }
49 | }
50 | }
51 | }
52 |
53 | protected void OrderSectionsBy(Func orderFunction)
54 | {
55 | Sections = Sections.OrderBy(orderFunction).ToArray();
56 | }
57 |
58 | public enum PEType
59 | {
60 | PE32,
61 | PE64
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/KsDumperClient/PE/PESection.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 |
3 | using static KsDumperClient.PE.NativePEStructs;
4 |
5 | namespace KsDumperClient.PE
6 | {
7 | public class PESection
8 | {
9 | public PESectionHeader Header { get; set; }
10 |
11 | public byte[] Content { get; set; }
12 |
13 | public int InitialSize { get; set; }
14 |
15 | public int DataSize { get; set; }
16 |
17 | public class PESectionHeader
18 | {
19 | public string Name { get; set; }
20 |
21 | public uint VirtualSize { get; set; }
22 |
23 | public uint VirtualAddress { get; set; }
24 |
25 | public uint SizeOfRawData { get; set; }
26 |
27 | public uint PointerToRawData { get; set; }
28 |
29 | public uint PointerToRelocations { get; set; }
30 |
31 | public uint PointerToLinenumbers { get; set; }
32 |
33 | public ushort NumberOfRelocations { get; set; }
34 |
35 | public ushort NumberOfLinenumbers { get; set; }
36 |
37 | public DataSectionFlags Characteristics { get; set; }
38 |
39 |
40 | public void AppendToStream(BinaryWriter writer)
41 | {
42 | writer.Write(Name.ToCharArray());
43 | writer.Write(VirtualSize);
44 | writer.Write(VirtualAddress);
45 | writer.Write(SizeOfRawData);
46 | writer.Write(PointerToRawData);
47 | writer.Write(PointerToRelocations);
48 | writer.Write(PointerToLinenumbers);
49 | writer.Write(NumberOfRelocations);
50 | writer.Write(NumberOfLinenumbers);
51 | writer.Write((uint)Characteristics);
52 | }
53 |
54 | public static PESectionHeader FromNativeStruct(IMAGE_SECTION_HEADER nativeStruct)
55 | {
56 | return new PESectionHeader
57 | {
58 | Name = nativeStruct.SectionName,
59 | VirtualSize = nativeStruct.VirtualSize,
60 | VirtualAddress = nativeStruct.VirtualAddress,
61 | SizeOfRawData = nativeStruct.SizeOfRawData,
62 | PointerToRawData = nativeStruct.PointerToRawData,
63 | PointerToRelocations = nativeStruct.PointerToRelocations,
64 | PointerToLinenumbers = nativeStruct.PointerToLinenumbers,
65 | NumberOfRelocations = nativeStruct.NumberOfRelocations,
66 | NumberOfLinenumbers = nativeStruct.NumberOfLinenumbers,
67 | Characteristics = nativeStruct.Characteristics
68 | };
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/KsDumperClient/ProcessDumper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using KsDumperClient.Driver;
4 | using KsDumperClient.PE;
5 | using KsDumperClient.Utility;
6 |
7 | using static KsDumperClient.PE.NativePEStructs;
8 |
9 | namespace KsDumperClient
10 | {
11 | public class ProcessDumper
12 | {
13 | private DriverInterface kernelDriver;
14 |
15 | public ProcessDumper(DriverInterface kernelDriver)
16 | {
17 | this.kernelDriver = kernelDriver;
18 | }
19 |
20 | public bool DumpProcess(ProcessSummary processSummary, out PEFile outputFile)
21 | {
22 | IntPtr basePointer = (IntPtr)processSummary.MainModuleBase;
23 | IMAGE_DOS_HEADER dosHeader = ReadProcessStruct(processSummary.ProcessId, basePointer);
24 | outputFile = default(PEFile);
25 |
26 | Logger.SkipLine();
27 | Logger.Log("Targeting Process: {0} ({1})", processSummary.ProcessName, processSummary.ProcessId);
28 |
29 | if (dosHeader.IsValid)
30 | {
31 | IntPtr peHeaderPointer = basePointer + dosHeader.e_lfanew;
32 | Logger.Log("PE Header Found: 0x{0:x8}", peHeaderPointer.ToInt64());
33 |
34 | IntPtr dosStubPointer = basePointer + Marshal.SizeOf();
35 | byte[] dosStub = ReadProcessBytes(processSummary.ProcessId, dosStubPointer, dosHeader.e_lfanew - Marshal.SizeOf());
36 |
37 | PEFile peFile;
38 |
39 | if (!processSummary.IsWOW64)
40 | {
41 | peFile = Dump64BitPE(processSummary.ProcessId, dosHeader, dosStub, peHeaderPointer);
42 | }
43 | else
44 | {
45 | peFile = Dump32BitPE(processSummary.ProcessId, dosHeader, dosStub, peHeaderPointer);
46 | }
47 |
48 | if (peFile != default(PEFile))
49 | {
50 | IntPtr sectionHeaderPointer = peHeaderPointer + peFile.GetFirstSectionHeaderOffset();
51 |
52 | Logger.Log("Header is valid ({0}) !", peFile.Type);
53 | Logger.Log("Parsing {0} Sections...", peFile.Sections.Length);
54 |
55 | for (int i = 0; i < peFile.Sections.Length; i++)
56 | {
57 | IMAGE_SECTION_HEADER sectionHeader = ReadProcessStruct(processSummary.ProcessId, sectionHeaderPointer);
58 | peFile.Sections[i] = new PESection
59 | {
60 | Header = PESection.PESectionHeader.FromNativeStruct(sectionHeader),
61 | InitialSize = (int)sectionHeader.VirtualSize
62 | };
63 |
64 | ReadSectionContent(processSummary.ProcessId, new IntPtr(basePointer.ToInt64() + sectionHeader.VirtualAddress), peFile.Sections[i]);
65 | sectionHeaderPointer += Marshal.SizeOf();
66 | }
67 |
68 | Logger.Log("Aligning Sections...");
69 | peFile.AlignSectionHeaders();
70 |
71 | Logger.Log("Fixing PE Header...");
72 | peFile.FixPEHeader();
73 |
74 | Logger.Log("Dump Completed !");
75 | outputFile = peFile;
76 | return true;
77 | }
78 | else
79 | {
80 | Logger.Log("Bad PE Header !");
81 | }
82 | }
83 | return false;
84 | }
85 |
86 | private PEFile Dump64BitPE(int processId, IMAGE_DOS_HEADER dosHeader, byte[] dosStub, IntPtr peHeaderPointer)
87 | {
88 | IMAGE_NT_HEADERS64 peHeader = ReadProcessStruct(processId, peHeaderPointer);
89 |
90 | if (peHeader.IsValid)
91 | {
92 | return new PE64File(dosHeader, peHeader, dosStub);
93 | }
94 | return default(PEFile);
95 | }
96 |
97 | private PEFile Dump32BitPE(int processId, IMAGE_DOS_HEADER dosHeader, byte[] dosStub, IntPtr peHeaderPointer)
98 | {
99 | IMAGE_NT_HEADERS32 peHeader = ReadProcessStruct(processId, peHeaderPointer);
100 |
101 | if (peHeader.IsValid)
102 | {
103 | return new PE32File(dosHeader, peHeader, dosStub);
104 | }
105 | return default(PEFile);
106 | }
107 |
108 | private T ReadProcessStruct(int processId, IntPtr address) where T : struct
109 | {
110 | IntPtr buffer = MarshalUtility.AllocEmptyStruct();
111 |
112 | if (kernelDriver.CopyVirtualMemory(processId, address, buffer, Marshal.SizeOf()))
113 | {
114 | return MarshalUtility.GetStructFromMemory(buffer);
115 | }
116 | return default(T);
117 | }
118 |
119 | private bool ReadSectionContent(int processId, IntPtr sectionPointer, PESection section)
120 | {
121 | const int maxReadSize = 100;
122 | int readSize = section.InitialSize;
123 |
124 | if (sectionPointer == IntPtr.Zero || readSize == 0)
125 | {
126 | return true;
127 | }
128 |
129 | if (readSize <= maxReadSize)
130 | {
131 | section.DataSize = readSize;
132 | section.Content = ReadProcessBytes(processId, sectionPointer, readSize);
133 |
134 | return true;
135 | }
136 | else
137 | {
138 | CalculateRealSectionSize(processId, sectionPointer, section);
139 |
140 | if (section.DataSize != 0)
141 | {
142 | section.Content = ReadProcessBytes(processId, sectionPointer, section.DataSize);
143 | return true;
144 | }
145 | }
146 | return false;
147 | }
148 |
149 | private byte[] ReadProcessBytes(int processId, IntPtr address, int size)
150 | {
151 | IntPtr unmanagedBytePointer = MarshalUtility.AllocZeroFilled(size);
152 | kernelDriver.CopyVirtualMemory(processId, address, unmanagedBytePointer, size);
153 |
154 | byte[] buffer = new byte[size];
155 | Marshal.Copy(unmanagedBytePointer, buffer, 0, size);
156 | Marshal.FreeHGlobal(unmanagedBytePointer);
157 |
158 | return buffer;
159 | }
160 |
161 | private void CalculateRealSectionSize(int processId, IntPtr sectionPointer, PESection section)
162 | {
163 | const int maxReadSize = 100;
164 | int readSize = section.InitialSize;
165 | int currentReadSize = readSize % maxReadSize;
166 |
167 | if (currentReadSize == 0)
168 | {
169 | currentReadSize = maxReadSize;
170 | }
171 | IntPtr currentOffset = sectionPointer + readSize - currentReadSize;
172 |
173 | while (currentOffset.ToInt64() >= sectionPointer.ToInt64())
174 | {
175 | byte[] buffer = ReadProcessBytes(processId, currentOffset, currentReadSize);
176 | int codeByteCount = GetInstructionByteCount(buffer);
177 |
178 | if (codeByteCount != 0)
179 | {
180 | currentOffset += codeByteCount;
181 |
182 | if (sectionPointer.ToInt64() < currentOffset.ToInt64())
183 | {
184 | section.DataSize = (int)(currentOffset.ToInt64() - sectionPointer.ToInt64());
185 | section.DataSize += 4;
186 |
187 | if (section.InitialSize < section.DataSize)
188 | {
189 | section.DataSize = section.InitialSize;
190 | }
191 | }
192 | break;
193 | }
194 |
195 | currentReadSize = maxReadSize;
196 | currentOffset -= currentReadSize;
197 | }
198 | }
199 |
200 | private int GetInstructionByteCount(byte[] dataBlock)
201 | {
202 | for (int i = (dataBlock.Length - 1); i >= 0; i--)
203 | {
204 | if (dataBlock[i] != 0)
205 | {
206 | return i + 1;
207 | }
208 | }
209 | return 0;
210 | }
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/KsDumperClient/ProcessSummary.cs:
--------------------------------------------------------------------------------
1 | using KsDumperClient.Utility;
2 | using System;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 |
8 | namespace KsDumperClient
9 | {
10 | public class ProcessSummary
11 | {
12 | public int ProcessId { get; private set; }
13 | public string ProcessName { get; private set; }
14 | public ulong MainModuleBase { get; private set; }
15 | public string MainModuleFileName { get; private set; }
16 | public uint MainModuleImageSize { get; private set; }
17 | public ulong MainModuleEntryPoint { get; private set; }
18 | public bool IsWOW64 { get; private set; }
19 |
20 | private ProcessSummary(int processId, ulong mainModuleBase, string mainModuleFileName, uint mainModuleImageSize, ulong mainModuleEntryPoint, bool isWOW64)
21 | {
22 | ProcessId = processId;
23 | MainModuleBase = mainModuleBase;
24 | MainModuleFileName = FixFileName(mainModuleFileName);
25 | MainModuleImageSize = mainModuleImageSize;
26 | MainModuleEntryPoint = mainModuleEntryPoint;
27 | ProcessName = Path.GetFileName(MainModuleFileName);
28 | IsWOW64 = isWOW64;
29 | }
30 |
31 | private string FixFileName(string fileName)
32 | {
33 | if (fileName.StartsWith(@"\"))
34 | {
35 | return fileName;
36 | }
37 |
38 | StringBuilder sb = new StringBuilder(256);
39 | int length = WinApi.GetLongPathName(fileName, sb, sb.Capacity);
40 |
41 | if (length > sb.Capacity)
42 | {
43 | sb.Capacity = length;
44 | length = WinApi.GetLongPathName(fileName, sb, sb.Capacity);
45 | }
46 | return sb.ToString();
47 | }
48 |
49 | public static ProcessSummary FromStream(BinaryReader reader)
50 | {
51 | return new ProcessSummary
52 | (
53 | reader.ReadInt32(),
54 | reader.ReadUInt64(),
55 | Encoding.Unicode.GetString(reader.ReadBytes(512)).Split('\0')[0],
56 | reader.ReadUInt32(),
57 | reader.ReadUInt64(),
58 | reader.ReadBoolean()
59 | );
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/KsDumperClient/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace KsDumperClient
5 | {
6 | static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | static void Main()
13 | {
14 | Application.EnableVisualStyles();
15 | Application.SetCompatibleTextRenderingDefault(false);
16 | Application.Run(new Dumper());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/KsDumperClient/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("KsDumper")]
9 | [assembly: AssemblyDescription("Dump processes from kernel space !")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("KsDumper")]
13 | [assembly: AssemblyCopyright("")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("7881b99d-0b5a-44e7-af34-80a0ecffd5db")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/KsDumperClient/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace KsDumperClient.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("KsDumperClient.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/KsDumperClient/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/KsDumperClient/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace KsDumperClient.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/KsDumperClient/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/KsDumperClient/Utility/Logger.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace KsDumperClient.Utility
4 | {
5 | public static class Logger
6 | {
7 | public static event Action OnLog;
8 |
9 | public static void SkipLine()
10 | {
11 | if (OnLog != null)
12 | {
13 | OnLog("\n");
14 | }
15 | else
16 | {
17 | Console.WriteLine();
18 | }
19 | }
20 |
21 | public static void Log(string message, params object[] args)
22 | {
23 | message = string.Format("[{0}] {1}\n", DateTime.Now.ToLongTimeString(), string.Format(message, args));
24 |
25 | if (OnLog != null)
26 | {
27 | OnLog(message);
28 | }
29 | else
30 | {
31 | Console.WriteLine(message);
32 | }
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/KsDumperClient/Utility/MarshalUtility.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace KsDumperClient.Utility
5 | {
6 | public static class MarshalUtility
7 | {
8 | public static IntPtr CopyStructToMemory(T obj) where T : struct
9 | {
10 | IntPtr unmanagedAddress = AllocEmptyStruct();
11 | Marshal.StructureToPtr(obj, unmanagedAddress, true);
12 |
13 | return unmanagedAddress;
14 | }
15 |
16 | public static IntPtr AllocEmptyStruct() where T : struct
17 | {
18 | int structSize = Marshal.SizeOf();
19 | IntPtr structPointer = AllocZeroFilled(Marshal.SizeOf());
20 |
21 | return structPointer;
22 | }
23 |
24 | public static IntPtr AllocZeroFilled(int size)
25 | {
26 | IntPtr allocatedPointer = Marshal.AllocHGlobal(size);
27 | ZeroMemory(allocatedPointer, size);
28 |
29 | return allocatedPointer;
30 | }
31 |
32 | public static void ZeroMemory(IntPtr pointer, int size)
33 | {
34 | for (int i = 0; i < size; i++)
35 | {
36 | Marshal.WriteByte(pointer + i, 0x0);
37 | }
38 | }
39 |
40 | public static T GetStructFromMemory(IntPtr unmanagedAddress, bool freeMemory = true) where T : struct
41 | {
42 | T structObj = Marshal.PtrToStructure(unmanagedAddress);
43 |
44 | if (freeMemory)
45 | {
46 | Marshal.FreeHGlobal(unmanagedAddress);
47 | }
48 | return structObj;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/KsDumperClient/Utility/ProcessListView.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.IO;
4 | using System.Runtime.InteropServices;
5 | using System.Windows.Forms;
6 |
7 | namespace KsDumperClient.Utility
8 | {
9 | public class ProcessListView : ListView
10 | {
11 | public bool SystemProcessesHidden { get; private set; } = true;
12 |
13 | private int sortColumnIndex = 1;
14 | private ProcessSummary[] processCache;
15 |
16 | public ProcessListView()
17 | {
18 | DoubleBuffered = true;
19 | Sorting = SortOrder.Ascending;
20 | }
21 |
22 | public void LoadProcesses(ProcessSummary[] processSummaries)
23 | {
24 | processCache = processSummaries;
25 | ReloadItems();
26 | }
27 |
28 | public void ShowSystemProcesses()
29 | {
30 | SystemProcessesHidden = false;
31 | ReloadItems();
32 | }
33 |
34 | public void HideSystemProcesses()
35 | {
36 | SystemProcessesHidden = true;
37 | ReloadItems();
38 | }
39 |
40 | private void ReloadItems()
41 | {
42 | Items.Clear();
43 |
44 | string systemRootFolder = Environment.GetFolderPath(Environment.SpecialFolder.Windows).ToLower();
45 |
46 | foreach (ProcessSummary processSummary in processCache)
47 | {
48 | if (SystemProcessesHidden &&
49 | (processSummary.MainModuleFileName.ToLower().StartsWith(systemRootFolder) ||
50 | processSummary.MainModuleFileName.StartsWith(@"\")))
51 | {
52 | continue;
53 | }
54 |
55 | ListViewItem lvi = new ListViewItem(processSummary.ProcessId.ToString());
56 | lvi.SubItems.Add(Path.GetFileName(processSummary.MainModuleFileName));
57 | lvi.SubItems.Add(processSummary.MainModuleFileName);
58 | lvi.SubItems.Add(string.Format("0x{0:x8}", processSummary.MainModuleBase));
59 | lvi.SubItems.Add(string.Format("0x{0:x8}", processSummary.MainModuleEntryPoint));
60 | lvi.SubItems.Add(string.Format("0x{0:x4}", processSummary.MainModuleImageSize));
61 | lvi.SubItems.Add(processSummary.IsWOW64 ? "x86" : "x64");
62 | lvi.Tag = processSummary;
63 |
64 | Items.Add(lvi);
65 | }
66 |
67 | ListViewItemSorter = new ProcessListViewItemComparer(sortColumnIndex, Sorting);
68 | Sort();
69 | }
70 |
71 | protected override void OnColumnClick(ColumnClickEventArgs e)
72 | {
73 | if (e.Column != sortColumnIndex)
74 | {
75 | sortColumnIndex = e.Column;
76 | Sorting = SortOrder.Ascending;
77 | }
78 | else
79 | {
80 | if (Sorting == SortOrder.Ascending)
81 | {
82 | Sorting = SortOrder.Descending;
83 | }
84 | else
85 | {
86 | Sorting = SortOrder.Ascending;
87 | }
88 | }
89 |
90 | ListViewItemSorter = new ProcessListViewItemComparer(e.Column, Sorting);
91 | Sort();
92 | }
93 |
94 | private class ProcessListViewItemComparer : IComparer
95 | {
96 | private readonly int columnIndex;
97 | private readonly SortOrder sortOrder;
98 |
99 | public ProcessListViewItemComparer(int columnIndex, SortOrder sortOrder)
100 | {
101 | this.columnIndex = columnIndex;
102 | this.sortOrder = sortOrder;
103 | }
104 |
105 | public int Compare(object x, object y)
106 | {
107 | if ((x is ListViewItem) && (y is ListViewItem))
108 | {
109 | ProcessSummary p1 = ((ListViewItem)x).Tag as ProcessSummary;
110 | ProcessSummary p2 = ((ListViewItem)y).Tag as ProcessSummary;
111 |
112 | if (!(p1 == null || p2 == null))
113 | {
114 | int result = 0;
115 |
116 | switch (columnIndex)
117 | {
118 | case 0:
119 | result = p1.ProcessId.CompareTo(p2.ProcessId);
120 | break;
121 | case 1:
122 | result = p1.ProcessName.CompareTo(p2.ProcessName);
123 | break;
124 | case 2:
125 | result = p1.MainModuleFileName.CompareTo(p2.MainModuleFileName);
126 | break;
127 | case 3:
128 | result = p1.MainModuleBase.CompareTo(p2.MainModuleBase);
129 | break;
130 | case 4:
131 | result = p1.MainModuleEntryPoint.CompareTo(p2.MainModuleEntryPoint);
132 | break;
133 | case 5:
134 | result = p1.MainModuleImageSize.CompareTo(p2.MainModuleImageSize);
135 | break;
136 | case 6:
137 | result = p1.IsWOW64.CompareTo(p2.IsWOW64);
138 | break;
139 | }
140 |
141 | if (sortOrder == SortOrder.Descending)
142 | {
143 | result = -result;
144 | }
145 | return result;
146 | }
147 | }
148 | return 0;
149 | }
150 | }
151 |
152 | protected override void WndProc(ref Message m)
153 | {
154 | if (m.Msg == 0x1)
155 | {
156 | SetWindowTheme(Handle, "Explorer", null);
157 | }
158 | base.WndProc(ref m);
159 | }
160 |
161 | [DllImport("uxtheme.dll", CharSet = CharSet.Unicode)]
162 | private extern static int SetWindowTheme(IntPtr hWnd, string pszSubAppName, string pszSubIdList);
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/KsDumperClient/Utility/WinApi.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace KsDumperClient.Utility
7 | {
8 | public static class WinApi
9 | {
10 | public static readonly int FILE_DEVICE_UNKNOWN = 0x22;
11 | public static readonly int METHOD_BUFFERED = 0x0;
12 | public static readonly int FILE_ANY_ACCESS = 0x0;
13 |
14 | public static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
15 |
16 | [DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true)]
17 | public static extern IntPtr CreateFileA(
18 | [MarshalAs(UnmanagedType.LPStr)] string filename,
19 | [MarshalAs(UnmanagedType.U4)] FileAccess access,
20 | [MarshalAs(UnmanagedType.U4)] FileShare share,
21 | IntPtr securityAttributes,
22 | [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
23 | [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes,
24 | IntPtr templateFile);
25 |
26 | [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
27 | public static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
28 | IntPtr lpInBuffer, int nInBufferSize,
29 | IntPtr lpOutBuffer, int nOutBufferSize,
30 | IntPtr lpBytesReturned, IntPtr lpOverlapped);
31 |
32 | [DllImport("kernel32.dll")]
33 | public static extern int GetLongPathName(string path, StringBuilder pszPath, int cchPath);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/KsDumperClient/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/KsDumperDriver/Driver.c:
--------------------------------------------------------------------------------
1 | #include "NTUndocumented.h"
2 | #include "ProcessLister.h"
3 | #include "UserModeBridge.h"
4 | #include
5 |
6 | DRIVER_INITIALIZE DriverEntry;
7 | #pragma alloc_text(INIT, DriverEntry)
8 |
9 | UNICODE_STRING deviceName, symLink;
10 |
11 | NTSTATUS CopyVirtualMemory(PEPROCESS targetProcess, PVOID sourceAddress, PVOID targetAddress, SIZE_T size)
12 | {
13 | PSIZE_T readBytes;
14 | return MmCopyVirtualMemory(targetProcess, sourceAddress, PsGetCurrentProcess(), targetAddress, size, UserMode, &readBytes);
15 | }
16 |
17 | NTSTATUS IoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
18 | {
19 | NTSTATUS status;
20 | ULONG bytesIO = 0;
21 | PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
22 | ULONG controlCode = stack->Parameters.DeviceIoControl.IoControlCode;
23 |
24 | if (controlCode == IO_COPY_MEMORY)
25 | {
26 | if (stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KERNEL_COPY_MEMORY_OPERATION))
27 | {
28 | PKERNEL_COPY_MEMORY_OPERATION request = (PKERNEL_COPY_MEMORY_OPERATION)Irp->AssociatedIrp.SystemBuffer;
29 | PEPROCESS targetProcess;
30 |
31 | if (NT_SUCCESS(PsLookupProcessByProcessId(request->targetProcessId, &targetProcess)))
32 | {
33 | CopyVirtualMemory(targetProcess, request->targetAddress, request->bufferAddress, request->bufferSize);
34 | ObDereferenceObject(targetProcess);
35 | }
36 |
37 | status = STATUS_SUCCESS;
38 | bytesIO = sizeof(KERNEL_COPY_MEMORY_OPERATION);
39 | }
40 | else
41 | {
42 | status = STATUS_INFO_LENGTH_MISMATCH;
43 | bytesIO = 0;
44 | }
45 | }
46 | else if (controlCode == IO_GET_PROCESS_LIST)
47 | {
48 | if (stack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KERNEL_PROCESS_LIST_OPERATION) &&
49 | stack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KERNEL_PROCESS_LIST_OPERATION))
50 | {
51 | PKERNEL_PROCESS_LIST_OPERATION request = (PKERNEL_PROCESS_LIST_OPERATION)Irp->AssociatedIrp.SystemBuffer;
52 |
53 | GetProcessList(request->bufferAddress, request->bufferSize, &request->bufferSize, &request->processCount);
54 |
55 | status = STATUS_SUCCESS;
56 | bytesIO = sizeof(KERNEL_PROCESS_LIST_OPERATION);
57 | }
58 | else
59 | {
60 | status = STATUS_INFO_LENGTH_MISMATCH;
61 | bytesIO = 0;
62 | }
63 | }
64 | else
65 | {
66 | status = STATUS_INVALID_PARAMETER;
67 | bytesIO = 0;
68 | }
69 |
70 | Irp->IoStatus.Status = status;
71 | Irp->IoStatus.Information = bytesIO;
72 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
73 |
74 | return status;
75 | }
76 |
77 | NTSTATUS UnsupportedDispatch(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
78 | {
79 | UNREFERENCED_PARAMETER(DeviceObject);
80 |
81 | Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
82 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
83 | return Irp->IoStatus.Status;
84 | }
85 |
86 | NTSTATUS CreateDispatch(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
87 | {
88 | UNREFERENCED_PARAMETER(DeviceObject);
89 |
90 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
91 | return Irp->IoStatus.Status;
92 | }
93 |
94 | NTSTATUS CloseDispatch(_In_ PDEVICE_OBJECT DeviceObject, _Inout_ PIRP Irp)
95 | {
96 | UNREFERENCED_PARAMETER(DeviceObject);
97 |
98 | IoCompleteRequest(Irp, IO_NO_INCREMENT);
99 | return Irp->IoStatus.Status;
100 | }
101 |
102 | NTSTATUS Unload(IN PDRIVER_OBJECT DriverObject)
103 | {
104 | IoDeleteSymbolicLink(&symLink);
105 | IoDeleteDevice(DriverObject->DeviceObject);
106 | }
107 |
108 | NTSTATUS DriverInitialize(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
109 | {
110 | NTSTATUS status;
111 | PDEVICE_OBJECT deviceObject;
112 |
113 | UNREFERENCED_PARAMETER(RegistryPath);
114 |
115 | RtlInitUnicodeString(&deviceName, L"\\Device\\KsDumper");
116 | RtlInitUnicodeString(&symLink, L"\\DosDevices\\KsDumper");
117 |
118 | status = IoCreateDevice(DriverObject, 0, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
119 |
120 | if (!NT_SUCCESS(status))
121 | {
122 | return status;
123 | }
124 | status = IoCreateSymbolicLink(&symLink, &deviceName);
125 |
126 | if (!NT_SUCCESS(status))
127 | {
128 | IoDeleteDevice(deviceObject);
129 | return status;
130 | }
131 | deviceObject->Flags |= DO_BUFFERED_IO;
132 |
133 | for (ULONG t = 0; t <= IRP_MJ_MAXIMUM_FUNCTION; t++)
134 | DriverObject->MajorFunction[t] = &UnsupportedDispatch;
135 |
136 | DriverObject->MajorFunction[IRP_MJ_CREATE] = &CreateDispatch;
137 | DriverObject->MajorFunction[IRP_MJ_CLOSE] = &CloseDispatch;
138 | DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = &IoControl;
139 | DriverObject->DriverUnload = &Unload;
140 | deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
141 |
142 | return status;
143 | }
144 |
145 | NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
146 | {
147 | UNREFERENCED_PARAMETER(DriverObject);
148 | UNREFERENCED_PARAMETER(RegistryPath);
149 |
150 | return IoCreateDriver(NULL, &DriverInitialize);
151 | }
152 |
--------------------------------------------------------------------------------
/KsDumperDriver/KsDumperDriver.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | {8EADAB93-F111-43AF-9E10-2376AE515491}
15 | {1bc93793-694f-48fe-9372-81e2b05556fd}
16 | v4.5
17 | 12.0
18 | Debug
19 | Win32
20 | TestDriver
21 | KsDumperDriver
22 |
23 |
24 |
25 | Windows10
26 | true
27 | WindowsKernelModeDriver10.0
28 | Driver
29 | KMDF
30 | Universal
31 |
32 |
33 | Windows10
34 | false
35 | WindowsKernelModeDriver10.0
36 | Driver
37 | KMDF
38 | Universal
39 | false
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | DbgengKernelDebugger
51 |
52 |
53 | DbgengKernelDebugger
54 |
55 |
56 |
57 |
58 | false
59 | true
60 | Speed
61 | false
62 | true
63 | All
64 | true
65 | CompileAsC
66 | false
67 | false
68 |
69 |
70 | false
71 | true
72 | DriverEntry
73 | true
74 | true
75 | false
76 |
77 |
78 |
79 |
80 | false
81 | true
82 | Speed
83 | false
84 | true
85 | All
86 | true
87 | CompileAsC
88 | false
89 | false
90 |
91 |
92 | false
93 | true
94 | DriverEntry
95 | true
96 | true
97 | false
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/KsDumperDriver/KsDumperDriver.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hpp;hxx;hm;inl;inc;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 |
29 |
30 | Header Files
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 |
--------------------------------------------------------------------------------
/KsDumperDriver/NTUndocumented.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | typedef struct _KAPC_STATE {
5 | LIST_ENTRY ApcListHead[MaximumMode];
6 | struct _KPROCESS *Process;
7 | BOOLEAN KernelApcInProgress;
8 | BOOLEAN KernelApcPending;
9 | BOOLEAN UserApcPending;
10 | } KAPC_STATE, *PKAPC_STATE, *PRKAPC_STATE;
11 |
12 | typedef enum _SYSTEM_INFORMATION_CLASS
13 | {
14 | SystemProcessInformation = 5
15 | } SYSTEM_INFORMATION_CLASS;
16 |
17 | typedef enum _MEMORY_INFORMATION_CLASS
18 | {
19 | MemoryBasicInformation,
20 | MemoryWorkingSetInformation,
21 | MemoryMappedFilenameInformation,
22 | MemoryRegionInformation,
23 | MemoryWorkingSetExInformation
24 |
25 | } MEMORY_INFORMATION_CLASS;
26 |
27 |
28 | typedef struct _MEMORY_BASIC_INFORMATION {
29 | PVOID BaseAddress;
30 | PVOID AllocationBase;
31 | INT32 AllocationProtect;
32 | SIZE_T RegionSize;
33 | INT32 State;
34 | INT32 Protect;
35 | INT32 Type;
36 | } MEMORY_BASIC_INFORMATION, *PMEMORY_BASIC_INFORMATION;
37 |
38 | NTKERNELAPI NTSTATUS IoCreateDriver(IN PUNICODE_STRING DriverName, OPTIONAL IN PDRIVER_INITIALIZE InitializationFunction);
39 |
40 | NTKERNELAPI VOID KeStackAttachProcess(__inout struct _KPROCESS * PROCESS, __out PRKAPC_STATE ApcState);
41 | NTKERNELAPI VOID KeUnstackDetachProcess(__in PRKAPC_STATE ApcState);
42 |
43 | NTKERNELAPI NTSTATUS NTAPI MmCopyVirtualMemory(IN PEPROCESS FromProcess, IN PVOID FromAddress, IN PEPROCESS ToProcess, OUT PVOID ToAddress, IN SIZE_T BufferSize, IN KPROCESSOR_MODE PreviousMode, OUT PSIZE_T NumberOfBytesCopied);
44 |
45 | NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInformationClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL);
46 | NTSYSAPI NTSTATUS NTAPI ZwQueryVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength OPTIONAL);
47 |
48 | NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(IN HANDLE ProcessId, OUT PEPROCESS *Process);
49 | NTKERNELAPI PVOID PsGetProcessSectionBaseAddress(__in PEPROCESS Process);
50 | NTKERNELAPI PPEB NTAPI PsGetProcessPeb(IN PEPROCESS Process);
--------------------------------------------------------------------------------
/KsDumperDriver/ProcessLister.c:
--------------------------------------------------------------------------------
1 | #include "NTUndocumented.h"
2 | #include "ProcessLister.h"
3 | #include "Utility.h"
4 |
5 | static PSYSTEM_PROCESS_INFORMATION GetRawProcessList()
6 | {
7 | ULONG bufferSize = 0;
8 | PVOID bufferPtr = NULL;
9 |
10 | if (ZwQuerySystemInformation(SystemProcessInformation, 0, bufferSize, &bufferSize) == STATUS_INFO_LENGTH_MISMATCH)
11 | {
12 | bufferPtr = ExAllocatePool(NonPagedPool, bufferSize);
13 |
14 | if (bufferPtr != NULL)
15 | {
16 | ZwQuerySystemInformation(SystemProcessInformation, bufferPtr, bufferSize, &bufferSize);
17 | }
18 | }
19 | return (PSYSTEM_PROCESS_INFORMATION)bufferPtr;
20 | }
21 |
22 | static ULONG CalculateProcessListOutputSize(PSYSTEM_PROCESS_INFORMATION rawProcessList)
23 | {
24 | int size = 0;
25 |
26 | while (rawProcessList->NextEntryOffset)
27 | {
28 | size += sizeof(PROCESS_SUMMARY);
29 | rawProcessList = (PSYSTEM_PROCESS_INFORMATION)(((CHAR*)rawProcessList) + rawProcessList->NextEntryOffset);
30 | }
31 | return size;
32 | }
33 |
34 | static PLDR_DATA_TABLE_ENTRY GetMainModuleDataTableEntry(PPEB64 peb)
35 | {
36 | if (SanitizeUserPointer(peb, sizeof(PEB64)))
37 | {
38 | if (peb->Ldr)
39 | {
40 | if (SanitizeUserPointer(peb->Ldr, sizeof(PEB_LDR_DATA)))
41 | {
42 | if (!peb->Ldr->Initialized)
43 | {
44 | int initLoadCount = 0;
45 |
46 | while (!peb->Ldr->Initialized && initLoadCount++ < 4)
47 | {
48 | DriverSleep(250);
49 | }
50 | }
51 |
52 | if (peb->Ldr->Initialized)
53 | {
54 | return CONTAINING_RECORD(peb->Ldr->InLoadOrderModuleList.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
55 | }
56 | }
57 | }
58 | }
59 | return NULL;
60 | }
61 |
62 | NTSTATUS GetProcessList(PVOID listedProcessBuffer, INT32 bufferSize, PINT32 requiredBufferSize, PINT32 processCount)
63 | {
64 | PPROCESS_SUMMARY processSummary = (PPROCESS_SUMMARY)listedProcessBuffer;
65 | PSYSTEM_PROCESS_INFORMATION rawProcessList = GetRawProcessList();
66 | PVOID listHeadPointer = rawProcessList;
67 | *processCount = 0;
68 |
69 | if (rawProcessList)
70 | {
71 | int expectedBufferSize = CalculateProcessListOutputSize(rawProcessList);
72 |
73 | if (!listedProcessBuffer || bufferSize < expectedBufferSize)
74 | {
75 | *requiredBufferSize = expectedBufferSize;
76 | return STATUS_INFO_LENGTH_MISMATCH;
77 | }
78 |
79 | while (rawProcessList->NextEntryOffset)
80 | {
81 | PEPROCESS targetProcess;
82 | PKAPC_STATE state = NULL;
83 |
84 | if (NT_SUCCESS(PsLookupProcessByProcessId(rawProcessList->UniqueProcessId, &targetProcess)))
85 | {
86 | PVOID mainModuleBase = NULL;
87 | PVOID mainModuleEntryPoint = NULL;
88 | UINT32 mainModuleImageSize = 0;
89 | PWCHAR mainModuleFileName = NULL;
90 | BOOLEAN isWow64 = 0;
91 |
92 | __try
93 | {
94 | KeStackAttachProcess(targetProcess, &state);
95 |
96 | __try
97 | {
98 | mainModuleBase = PsGetProcessSectionBaseAddress(targetProcess);
99 |
100 | if (mainModuleBase)
101 | {
102 | PPEB64 peb = (PPEB64)PsGetProcessPeb(targetProcess);
103 |
104 | if (peb)
105 | {
106 | PLDR_DATA_TABLE_ENTRY mainModuleEntry = GetMainModuleDataTableEntry(peb);
107 | mainModuleEntry = SanitizeUserPointer(mainModuleEntry, sizeof(LDR_DATA_TABLE_ENTRY));
108 |
109 | if (mainModuleEntry)
110 | {
111 | mainModuleEntryPoint = mainModuleEntry->EntryPoint;
112 | mainModuleImageSize = mainModuleEntry->SizeOfImage;
113 | isWow64 = IS_WOW64_PE(mainModuleBase);
114 |
115 | mainModuleFileName = ExAllocatePool(NonPagedPool, 256 * sizeof(WCHAR));
116 | RtlZeroMemory(mainModuleFileName, 256 * sizeof(WCHAR));
117 | RtlCopyMemory(mainModuleFileName, mainModuleEntry->FullDllName.Buffer, 256 * sizeof(WCHAR));
118 | }
119 | }
120 | }
121 | }
122 | __except (GetExceptionCode())
123 | {
124 | DbgPrintEx(0, 0, "Peb Interaction Failed.\n");
125 | }
126 | }
127 | __finally
128 | {
129 | KeUnstackDetachProcess(&state);
130 | }
131 |
132 | if (mainModuleFileName)
133 | {
134 | RtlCopyMemory(processSummary->MainModuleFileName, mainModuleFileName, 256 * sizeof(WCHAR));
135 | ExFreePool(mainModuleFileName);
136 |
137 | processSummary->ProcessId = rawProcessList->UniqueProcessId;
138 | processSummary->MainModuleBase = mainModuleBase;
139 | processSummary->MainModuleEntryPoint = mainModuleEntryPoint;
140 | processSummary->MainModuleImageSize = mainModuleImageSize;
141 | processSummary->WOW64 = isWow64;
142 |
143 | processSummary++;
144 | (*processCount)++;
145 | }
146 |
147 | ObDereferenceObject(targetProcess);
148 | }
149 |
150 | rawProcessList = (PSYSTEM_PROCESS_INFORMATION)(((CHAR*)rawProcessList) + rawProcessList->NextEntryOffset);
151 | }
152 |
153 | ExFreePool(listHeadPointer);
154 | return STATUS_SUCCESS;
155 | }
156 | }
--------------------------------------------------------------------------------
/KsDumperDriver/ProcessLister.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #pragma pack(push, 1)
5 | typedef struct _PROCESS_SUMMARY
6 | {
7 | INT32 ProcessId;
8 | PVOID MainModuleBase;
9 | WCHAR MainModuleFileName[256];
10 | UINT32 MainModuleImageSize;
11 | PVOID MainModuleEntryPoint;
12 | BOOLEAN WOW64;
13 | } PROCESS_SUMMARY, *PPROCESS_SUMMARY;
14 | #pragma pack(pop)
15 |
16 | typedef struct _SYSTEM_PROCESS_INFORMATION
17 | {
18 | ULONG NextEntryOffset;
19 | ULONG NumberOfThreads;
20 | LARGE_INTEGER SpareLi1;
21 | LARGE_INTEGER SpareLi2;
22 | LARGE_INTEGER SpareLi3;
23 | LARGE_INTEGER CreateTime;
24 | LARGE_INTEGER UserTime;
25 | LARGE_INTEGER KernelTime;
26 | UNICODE_STRING ImageName;
27 | KPRIORITY BasePriority;
28 | HANDLE UniqueProcessId;
29 | HANDLE InheritedFromUniqueProcessId;
30 | ULONG HandleCount;
31 | ULONG SessionId;
32 | ULONG_PTR PageDirectoryBase;
33 | SIZE_T PeakVirtualSize;
34 | SIZE_T VirtualSize;
35 | ULONG PageFaultCount;
36 | SIZE_T PeakWorkingSetSize;
37 | SIZE_T WorkingSetSize;
38 | SIZE_T QuotaPeakPagedPoolUsage;
39 | SIZE_T QuotaPagedPoolUsage;
40 | SIZE_T QuotaPeakNonPagedPoolUsage;
41 | SIZE_T QuotaNonPagedPoolUsage;
42 | SIZE_T PagefileUsage;
43 | SIZE_T PeakPagefileUsage;
44 | SIZE_T PrivatePageCount;
45 | LARGE_INTEGER ReadOperationCount;
46 | LARGE_INTEGER WriteOperationCount;
47 | LARGE_INTEGER OtherOperationCount;
48 | LARGE_INTEGER ReadTransferCount;
49 | LARGE_INTEGER WriteTransferCount;
50 | LARGE_INTEGER OtherTransferCount;
51 | } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
52 |
53 | typedef struct _LDR_DATA_TABLE_ENTRY
54 | {
55 | LIST_ENTRY InLoadOrderLinks;
56 | LIST_ENTRY InMemoryOrderLinks;
57 | CHAR Reserved0[0x10];
58 | PVOID DllBase;
59 | PVOID EntryPoint;
60 | ULONG SizeOfImage;
61 | UNICODE_STRING FullDllName;
62 | UNICODE_STRING BaseDllName;
63 | } LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
64 |
65 | typedef struct _PEB_LDR_DATA
66 | {
67 | ULONG Length;
68 | BOOLEAN Initialized;
69 | PVOID SsHandler;
70 | LIST_ENTRY InLoadOrderModuleList;
71 | LIST_ENTRY InMemoryOrderModuleList;
72 | LIST_ENTRY InInitializationOrderModuleList;
73 | PVOID EntryInProgress;
74 | } PEB_LDR_DATA, *PPEB_LDR_DATA;
75 |
76 | typedef struct _PEB64 {
77 | CHAR Reserved[0x10];
78 | PVOID ImageBaseAddress;
79 | PPEB_LDR_DATA Ldr;
80 | } PEB64, *PPEB64;
81 |
82 | typedef struct _IMAGE_DOS_HEADER {
83 | USHORT e_magic;
84 | USHORT e_cblp;
85 | USHORT e_cp;
86 | USHORT e_crlc;
87 | USHORT e_cparhdr;
88 | USHORT e_minalloc;
89 | USHORT e_maxalloc;
90 | USHORT e_ss;
91 | USHORT e_sp;
92 | USHORT e_csum;
93 | USHORT e_ip;
94 | USHORT e_cs;
95 | USHORT e_lfarlc;
96 | USHORT e_ovno;
97 | USHORT e_res[4];
98 | USHORT e_oemid;
99 | USHORT e_oeminfo;
100 | USHORT e_res2[10];
101 | LONG e_lfanew;
102 | } IMAGE_DOS_HEADER, *PIMAGE_DOS_HEADER;
103 |
104 | typedef struct _PE_HEADER {
105 | CHAR Signature[4];
106 | USHORT Machine;
107 | USHORT NumberOfSections;
108 | UINT32 TimeDateStamp;
109 | UINT32 PointerToSymbolTable;
110 | UINT32 NumberOfSymbols;
111 | USHORT SizeOfOptionalHeader;
112 | USHORT Characteristics;
113 | USHORT Magic;
114 | } PE_HEADER, *PPE_HEADER;
115 |
116 | #define PE_HEADER_MAGIC_OFFSET 0x18
117 | #define IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b
118 |
119 | #define IS_WOW64_PE( baseAddress ) (*((USHORT*)((CHAR *)baseAddress + \
120 | ((PIMAGE_DOS_HEADER)baseAddress)->e_lfanew + PE_HEADER_MAGIC_OFFSET)) \
121 | == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
122 |
123 | NTSTATUS GetProcessList(PVOID listedProcessBuffer, INT32 bufferSize, PINT32 requiredBufferSize, PINT32 processCount);
--------------------------------------------------------------------------------
/KsDumperDriver/UserModeBridge.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | #define IO_GET_PROCESS_LIST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1724, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
5 |
6 | #define IO_COPY_MEMORY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x1725, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
7 |
8 | typedef struct _KERNEL_PROCESS_LIST_OPERATION
9 | {
10 | PVOID bufferAddress;
11 | INT32 bufferSize;
12 | INT32 processCount;
13 | } KERNEL_PROCESS_LIST_OPERATION, *PKERNEL_PROCESS_LIST_OPERATION;
14 |
15 | typedef struct _KERNEL_COPY_MEMORY_OPERATION
16 | {
17 | INT32 targetProcessId;
18 | PVOID targetAddress;
19 | PVOID bufferAddress;
20 | INT32 bufferSize;
21 | } KERNEL_COPY_MEMORY_OPERATION, *PKERNEL_COPY_MEMORY_OPERATION;
--------------------------------------------------------------------------------
/KsDumperDriver/Utility.c:
--------------------------------------------------------------------------------
1 | #include "NTUndocumented.h"
2 | #include "Utility.h"
3 |
4 | NTSTATUS DriverSleep(int ms)
5 | {
6 | LARGE_INTEGER li;
7 | li.QuadPart = -10000;
8 |
9 | for (int i = 0; i < ms; i++)
10 | {
11 | KeDelayExecutionThread(KernelMode, FALSE, &li);
12 | return STATUS_SUCCESS;
13 | }
14 | return STATUS_UNSUCCESSFUL;
15 | }
16 |
17 | PVOID SanitizeUserPointer(PVOID pointer, SIZE_T size)
18 | {
19 | MEMORY_BASIC_INFORMATION memInfo;
20 |
21 | if (NT_SUCCESS(ZwQueryVirtualMemory(ZwCurrentProcess(), pointer, MemoryBasicInformation, &memInfo, sizeof(MEMORY_BASIC_INFORMATION), NULL)))
22 | {
23 | if (!(((uintptr_t)memInfo.BaseAddress + memInfo.RegionSize) < (((uintptr_t)pointer + size))))
24 | {
25 | if (memInfo.State & MEM_COMMIT || !(memInfo.Protect & (PAGE_GUARD | PAGE_NOACCESS)))
26 | {
27 | if (memInfo.Protect & PAGE_EXECUTE_READWRITE || memInfo.Protect & PAGE_EXECUTE_WRITECOPY || memInfo.Protect & PAGE_READWRITE || memInfo.Protect & PAGE_WRITECOPY)
28 | {
29 | return pointer;
30 | }
31 | }
32 | }
33 | }
34 | return NULL;
35 | }
36 |
--------------------------------------------------------------------------------
/KsDumperDriver/Utility.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 |
4 | NTSTATUS DriverSleep(int ms);
5 |
6 | PVOID SanitizeUserPointer(PVOID pointer, SIZE_T size);
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Nicolas Tremblay
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 🔴 This repo is outdated due to the Capcom driver being patched 🔴
2 | Thanks to **mastercodeon314** there's now a port working on Windows 11. Enjoy !
3 | https://github.com/mastercodeon314/KsDumper-11
4 |
5 | # KsDumper
6 | 
7 |
8 | I always had an interest in reverse engineering. A few days ago I wanted to look at some game internals for fun, but it was packed & protected by EAC (EasyAntiCheat).
9 | This means its handle were stripped and I was unable to dump the process from Ring3. I decided to try to make a custom driver that would allow me to copy the process memory without using OpenProcess.
10 | I knew nothing about Windows kernel, PE file structure, so I spent a lot of time reading articles and forums to make this project.
11 |
12 | ## Features
13 | - Dump any process main module using a kernel driver (both x86 and x64)
14 | - Rebuild PE32/PE64 header and sections
15 | - Works on protected system processes & processes with stripped handles (anti-cheats)
16 |
17 | **Note**: Import table isn't rebuilt.
18 |
19 | ## Usage
20 | Before using KsDumperClient, the KsDumper driver needs to be loaded.
21 |
22 | It is unsigned so you need to load it however you want. I'm using drvmap for Win10.
23 | Everything is provided in this release if you want to use it aswell.
24 |
25 | - Run `Driver/LoadCapcom.bat` as Admin. Don't press any key or close the window yet !
26 | - Run `Driver/LoadUnsignedDriver.bat` as Admin.
27 | - Press enter in the `LoadCapcom` cmd to unload the driver.
28 | - Run `KsDumperClient.exe`.
29 | - Profit !
30 |
31 | **Note**: The driver stays loaded until you reboot, so if you close KsDumperClient.exe, you can just reopen it !
32 | **Note2**: Even though it can dump both x86 & x64 processes, this has to run on x64 Windows.
33 |
34 | ## Disclaimer
35 | This project was a way for me to learn about Windows kernel, PE file structure and kernel-user space interactions. It has been made available for informational and educational purposes only.
36 |
37 | Considering the nature of this project, it is highly recommended to run it in a `Virtual Environment`. I am not responsible for any crash or damage that could happen to your system.
38 |
39 | **Important**: This tool makes no attempt at hiding itself. If you target protected games, the anti-cheat might flag this as a cheat and ban you after a while. Use a `Virtual Environment` !
40 |
41 | ## References
42 | - https://github.com/not-wlan/drvmap
43 | - https://github.com/Zer0Mem0ry/KernelBhop
44 | - https://github.com/NtQuery/Scylla/
45 | - http://terminus.rewolf.pl/terminus/
46 | - https://www.unknowncheats.me/
47 |
48 | ## Compile Yourself
49 | - Requires Visual Studio 2017
50 | - Requires Windows Driver Kit (WDK)
51 | - Requires .NET 4.6.1
52 |
--------------------------------------------------------------------------------