├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── client
├── client.vcxproj
├── client.vcxproj.filters
├── common.hpp
├── main.cpp
├── memory.cpp
├── memory.hpp
├── sock.cpp
├── sock.hpp
├── utils.cpp
├── utils.hpp
└── xorstr.hpp
├── driver
├── berkeley.c
├── berkeley.h
├── common.h
├── driver.inf
├── driver.vcxproj
├── driver.vcxproj.filters
├── imports.h
├── intdefs.h
├── ksocket.c
├── ksocket.h
├── main.c
├── server.c
├── server.h
├── utils.c
└── utils.h
└── kersock.sln
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.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 |
235 | # RIA/Silverlight projects
236 | Generated_Code/
237 |
238 | # Backup & report files from converting an old project file
239 | # to a newer Visual Studio version. Backup files are not needed,
240 | # because we have git ;-)
241 | _UpgradeReport_Files/
242 | Backup*/
243 | UpgradeLog*.XML
244 | UpgradeLog*.htm
245 | ServiceFabricBackup/
246 | *.rptproj.bak
247 |
248 | # SQL Server files
249 | *.mdf
250 | *.ldf
251 | *.ndf
252 |
253 | # Business Intelligence projects
254 | *.rdl.data
255 | *.bim.layout
256 | *.bim_*.settings
257 | *.rptproj.rsuser
258 | *- Backup*.rdl
259 |
260 | # Microsoft Fakes
261 | FakesAssemblies/
262 |
263 | # GhostDoc plugin setting file
264 | *.GhostDoc.xml
265 |
266 | # Node.js Tools for Visual Studio
267 | .ntvs_analysis.dat
268 | node_modules/
269 |
270 | # Visual Studio 6 build log
271 | *.plg
272 |
273 | # Visual Studio 6 workspace options file
274 | *.opt
275 |
276 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
277 | *.vbw
278 |
279 | # Visual Studio LightSwitch build output
280 | **/*.HTMLClient/GeneratedArtifacts
281 | **/*.DesktopClient/GeneratedArtifacts
282 | **/*.DesktopClient/ModelManifest.xml
283 | **/*.Server/GeneratedArtifacts
284 | **/*.Server/ModelManifest.xml
285 | _Pvt_Extensions
286 |
287 | # Paket dependency manager
288 | .paket/paket.exe
289 | paket-files/
290 |
291 | # FAKE - F# Make
292 | .fake/
293 |
294 | # JetBrains Rider
295 | .idea/
296 | *.sln.iml
297 |
298 | # CodeRush personal settings
299 | .cr/personal
300 |
301 | # Python Tools for Visual Studio (PTVS)
302 | __pycache__/
303 | *.pyc
304 |
305 | # Cake - Uncomment if you are using it
306 | # tools/**
307 | # !tools/packages.config
308 |
309 | # Tabs Studio
310 | *.tss
311 |
312 | # Telerik's JustMock configuration file
313 | *.jmconfig
314 |
315 | # BizTalk build output
316 | *.btp.cs
317 | *.btm.cs
318 | *.odx.cs
319 | *.xsd.cs
320 |
321 | # OpenCover UI analysis results
322 | OpenCover/
323 |
324 | # Azure Stream Analytics local run output
325 | ASALocalRun/
326 |
327 | # MSBuild Binary and Structured Log
328 | *.binlog
329 |
330 | # NVidia Nsight GPU debugger configuration file
331 | *.nvuser
332 |
333 | # MFractors (Xamarin productivity tool) working folder
334 | .mfractor/
335 |
336 | # Local History for Visual Studio
337 | .localhistory/
338 |
339 | # BeatPulse healthcheck temp database
340 | healthchecksdb
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Deputation
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 | # kernel_sockets_memory
2 | Kernel-based memory hacking framework communicating with a kernel driver via sockets, it allows for memory reading, writing, allocation, freeing, protection changing without a valid user-mode handle.
3 | Kernel-mode sockets kindly provided by wbenny's KSOCKET framework. Credits to him. https://github.com/wbenny/ksocket
4 |
5 | Some simple features like service unloading and complete disconnection (and cleanup) have been omitted from the project to prevent abuse by pay-to-cheat services that would abuse it for monetary gain. I'll leave these as an exercise to the reader.
6 |
7 | # Notes
8 | The driver was written entirely in C, while the client was written in C++. The part of the project meant to be used by people who have no idea how it works behind the scenes (the ``memory::virtual_controller_t`` class) is well documented. xorstr class from JustasMasiluis. Credits to him. https://github.com/JustasMasiulis/xorstr
9 |
10 | # Loading the driver
11 | The driver can be loaded regularly and also via DSE-bypass techniques like manual mapping, as it doesn't use any ``__try{} __except() {}`` blocks nor tries doing anything patchguard-unfriendly. Once loaded, the driver spawns a new thread for every client that would like to connect.
12 |
13 | # Client
14 | The client connects and sends packets with the regular wsa socket api present in windows. The idea to use unions for the socket structures was taken from r6s-external-nuklear-socket by alxbrn. Credits to him. https://github.com/alxbrn/r6s-external-nuklear-socket
15 |
16 | # Tests
17 | A small subset of "tests" showing simply how to use the provided ``memory::virtual_controller_t`` class is present in the main() function of the client.
18 |
19 | # Getting started
20 | - Download VS2019 with the relevant C++ packages and the W10 SDK.
21 | - Download the Windows WDK and install its relevant extension.
22 | - Clone the project.
23 | - Build.
24 |
25 | # How to use
26 | - Create the driver's service by executing "``sc create ksocketsmem type= kernel binPath= "C:\Path\To\Your\File.sys"``" in an elevated command prompt.
27 | - Start the driver's service by executing "``sc start ksocketsmem``" in an elevated command prompt.
28 | - Open the client.
29 |
--------------------------------------------------------------------------------
/client/client.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | 16.0
15 | Win32Proj
16 | {81699472-e045-4df8-99a1-72936ee445ee}
17 | client
18 | 10.0
19 |
20 |
21 |
22 | Application
23 | true
24 | v142
25 | Unicode
26 |
27 |
28 | Application
29 | false
30 | v142
31 | true
32 | Unicode
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | true
48 |
49 |
50 | false
51 |
52 |
53 |
54 | Level3
55 | true
56 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
57 | true
58 | MultiThreadedDebug
59 | stdcpp17
60 |
61 |
62 | Console
63 | true
64 |
65 |
66 |
67 |
68 | Level3
69 | true
70 | true
71 | true
72 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
73 | true
74 | MultiThreaded
75 | stdcpp17
76 |
77 |
78 | Console
79 | true
80 | true
81 | true
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/client/client.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;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 | Source Files
29 |
30 |
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 | Header Files
40 |
41 |
42 | Header Files
43 |
44 |
45 | Header Files
46 |
47 |
48 |
--------------------------------------------------------------------------------
/client/common.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 |
13 | #include
14 |
15 | #include
16 | #include
17 | #include
18 |
19 | #pragma comment(lib, "Ws2_32")
20 |
21 | #define log(...) std::printf(__VA_ARGS__)
22 |
23 | #include "xorstr.hpp"
24 | #include "sock.hpp"
25 | #include "utils.hpp"
26 | #include "memory.hpp"
--------------------------------------------------------------------------------
/client/main.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | int main(void)
4 | {
5 | auto ksock = std::make_shared(55123);
6 | log("KSOCK connected on port %d\n", ksock->port);
7 | auto process = std::make_shared(ksock, utils::get_process_id("client.exe"), L"client.exe");
8 |
9 | log("Testing ksock connection using the virtual controller.\n");
10 |
11 | auto secret = 0x1337u;
12 |
13 | log("Base address (main module): %p\n", process->get_base());
14 | log("Size (main module): %p\n", process->get_size());
15 | log("Base address (ntdll.dll): %p\n", process->get_base(L"ntdll.dll"));
16 | log("Size (ntdll.dll): %p\n", process->get_size(L"ntdll.dll"));
17 | log("Read (reading secret): %p\n", process->read(reinterpret_cast(&secret)));
18 | log("Write (changing secret): %p\n", process->write(reinterpret_cast(&secret), 0xCAFEBABE));
19 | log("Read 2 (reading secret): %p\n", process->read(reinterpret_cast(&secret)));
20 |
21 | auto region = process->allocate(PAGE_EXECUTE_READWRITE, MEM_COMMIT | MEM_RESERVE, 0x1000);
22 | log("Allocation: %p\n", region);
23 |
24 | // The two values should be the same, since the old protection was PAGE_EXECUTE_READWRITE
25 | log("Protection: %p - %p\n", process->protect(region, PAGE_READWRITE, 0x1000), PAGE_EXECUTE_READWRITE);
26 |
27 | process->free(region, 0x1000);
28 | ksock->disconnect();
29 |
30 | // So you can read results even if you double clicked.
31 | std::cin.get();
32 |
33 | return 0;
34 | }
--------------------------------------------------------------------------------
/client/memory.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | memory::virtual_controller_t::virtual_controller_t(std::shared_ptr& server, uint32_t pid, const wchar_t* name)
4 | {
5 | this->server = server;
6 | this->pid = pid;
7 | this->name = std::wstring(name);
8 | }
9 |
10 | memory::virtual_controller_t::~virtual_controller_t()
11 | {
12 | }
13 |
14 | uint64_t memory::virtual_controller_t::get_base()
15 | {
16 | return server->get_base(this->pid, this->name.data());
17 | }
18 |
19 | uint64_t memory::virtual_controller_t::get_base(const wchar_t* module_name)
20 | {
21 | return server->get_base(this->pid, module_name);
22 | }
23 |
24 | uint64_t memory::virtual_controller_t::get_size()
25 | {
26 | return server->get_size(this->pid, this->name.data());
27 | }
28 |
29 | uint64_t memory::virtual_controller_t::get_size(const wchar_t* module_name)
30 | {
31 | return server->get_size(this->pid, module_name);
32 | }
33 |
34 | uint64_t memory::virtual_controller_t::allocate(uint32_t protection, uint32_t allocation_type, size_t size)
35 | {
36 | return this->server->zw_allocate_virtual_memory(this->pid, protection, allocation_type, size);
37 | }
38 |
39 | void memory::virtual_controller_t::free(uint64_t target_address, size_t size)
40 | {
41 | this->server->zw_free_vritual_memory(this->pid, target_address, size);
42 | }
43 |
44 | uint64_t memory::virtual_controller_t::protect(uint64_t target_address, uint32_t protection, size_t size)
45 | {
46 | return this->server->zw_protect_virtual_memory(this->pid, target_address, protection, size);
47 | }
48 |
--------------------------------------------------------------------------------
/client/memory.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace memory
4 | {
5 | class virtual_controller_t
6 | {
7 | protected:
8 | std::shared_ptr server;
9 |
10 | public:
11 | uint32_t pid;
12 | std::wstring name;
13 |
14 | ///
15 | /// Instantiate the virtual memory controller.
16 | ///
17 | /// A ksock_t shared instance.
18 | /// The process id you want the virtual controller to bind to.
19 | /// Process executable's name.
20 | virtual_controller_t(std::shared_ptr& server, uint32_t pid, const wchar_t* name);
21 |
22 | ///
23 | /// Destructor. Unimplemented as of now.
24 | ///
25 | ~virtual_controller_t();
26 |
27 | ///
28 | /// Get the process' main module base.
29 | ///
30 | /// The main module's base.
31 | uint64_t get_base();
32 |
33 | ///
34 | /// Get a process module's base address.
35 | ///
36 | /// The name of the module of which you want to retrieve the base address.
37 | /// The base address of the specified module.
38 | uint64_t get_base(const wchar_t* module_name);
39 |
40 | ///
41 | /// Get the process' main module's size.
42 | ///
43 | /// The main module's size.
44 | uint64_t get_size();
45 |
46 | ///
47 | /// Get a process module's size.
48 | ///
49 | /// The name of the module of which you want to retrieve the size.
50 | /// The size of the module.
51 | uint64_t get_size(const wchar_t* module_name);
52 |
53 | ///
54 | /// Write to the process' virtual memory.
55 | ///
56 | /// The data type of the data you want to write.
57 | /// The address you want the data to be written to.
58 | /// The data you want to write.
59 | /// The amount of bytes written.
60 | template
61 | inline size_t write(uint64_t address, t value)
62 | {
63 | auto buffer = value;
64 |
65 | return this->server->mm_copy_virtual_memory(GetCurrentProcessId(),
66 | reinterpret_cast(&buffer), this->pid, address, sizeof(t));
67 | }
68 |
69 | ///
70 | /// Reads virtual memory from the process.
71 | ///
72 | /// The data type located at the address.
73 | /// The address that you want to read.
74 | /// The data read.
75 | template
76 | inline t read(uint64_t address)
77 | {
78 | t buffer;
79 |
80 | this->server->mm_copy_virtual_memory(this->pid, address, GetCurrentProcessId(),
81 | reinterpret_cast(&buffer), sizeof(t));
82 |
83 | return buffer;
84 | }
85 |
86 | ///
87 | /// Issue a kernel memory allocation. Pages will have the specified allocation type and protection.
88 | ///
89 | /// The pages' protection.
90 | /// The allocation's type.
91 | /// The allocation's size.
92 | /// The base address of the allocated memory zone.
93 | uint64_t allocate(uint32_t protection, uint32_t allocation_type, size_t size);
94 |
95 | ///
96 | /// Frees memory with the MEM_RELEASE free type.
97 | ///
98 | /// The base adddress of the allocation to free.
99 | /// The size of the memory allocation to free.
100 | void free(uint64_t target_address, size_t size);
101 |
102 | ///
103 | /// Changes a memory zone's protection.
104 | ///
105 | /// The address of which the protection will be changed. (Affects an entire
106 | /// page), standard PAGE_SIZE is 0x1000.
107 | /// The new protection.
108 | /// The amount of bytes to be affected, starting from the specified target address.
109 | /// The old protection.
110 | uint64_t protect(uint64_t target_address, uint32_t protection, size_t size);
111 | };
112 | }
113 |
114 |
--------------------------------------------------------------------------------
/client/sock.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | connection::ksock_t::ksock_t(uint16_t port)
4 | {
5 | WSAStartup(MAKEWORD(2, 2), &this->wsa_data);
6 |
7 | this->connection = this->connect(port);
8 | this->port = port;
9 | }
10 |
11 | connection::ksock_t::~ksock_t()
12 | {
13 | WSACleanup();
14 | }
15 |
16 | SOCKET connection::ksock_t::connect(uint16_t port)
17 | {
18 | SOCKADDR_IN address = {};
19 |
20 | address.sin_family = AF_INET;
21 | address.sin_addr.s_addr = htonl(server_ip);
22 | address.sin_port = htons(port);
23 |
24 | const auto sockfd = socket(AF_INET, SOCK_STREAM, 0);
25 |
26 | if (sockfd != INVALID_SOCKET)
27 | {
28 | if (::connect(sockfd, reinterpret_cast(&address), sizeof(address)) == SOCKET_ERROR)
29 | {
30 | closesocket(sockfd);
31 | return INVALID_SOCKET;
32 | }
33 | else
34 | {
35 | return sockfd;
36 | }
37 | }
38 | else
39 | {
40 | return sockfd;
41 | }
42 | }
43 |
44 | void connection::ksock_t::disconnect()
45 | {
46 | closesocket(connection);
47 | }
48 |
49 | bool connection::ksock_t::send_data(data_packet_t& packet, uint64_t& result)
50 | {
51 | data_packet_t response = {};
52 |
53 | if (send(this->connection, reinterpret_cast(&packet), sizeof(packet), 0) == SOCKET_ERROR)
54 | {
55 | return false;
56 | }
57 |
58 | const auto recv_result = recv(this->connection, reinterpret_cast(&response), sizeof(packet), 0);
59 |
60 | if (recv_result < sizeof(packet_header_t) || response.header.magic_header != magic_header_value
61 | || response.header.type != e_packet_type::completed)
62 | {
63 | return false;
64 | }
65 |
66 | result = response.data.response.data;
67 |
68 | return true;
69 | }
70 |
71 | uint64_t connection::ksock_t::ping(int32_t value)
72 | {
73 | data_packet_t ping = {};
74 |
75 | ping.header.magic_header = magic_header_value;
76 | ping.header.type = e_packet_type::ping;
77 | ping.data.ping.ping_magic = value;
78 |
79 | auto result = 0ull;
80 |
81 | if (this->send_data(ping, result))
82 | {
83 | return result;
84 | }
85 |
86 | return 0;
87 | }
88 |
89 | uint64_t connection::ksock_t::get_base(uint32_t target_pid, const wchar_t* module_name)
90 | {
91 | std::wstring buffer = module_name;
92 |
93 | data_packet_t get_base = {};
94 |
95 | get_base.header.magic_header = magic_header_value;
96 | get_base.header.type = e_packet_type::packet_get_base;
97 | get_base.data.get_base.target_pid = target_pid;
98 |
99 | memset(&get_base.data.get_base.module_name[0], 0, 64 * sizeof(wchar_t));
100 | memcpy(&get_base.data.get_base.module_name[0], const_cast(buffer.data()),
101 | (std::wcslen(buffer.data()) + 1) * sizeof(wchar_t));
102 |
103 | auto result = 0ull;
104 |
105 | if (this->send_data(get_base, result))
106 | {
107 | return result;
108 | }
109 |
110 | return 0;
111 | }
112 |
113 | uint64_t connection::ksock_t::get_size(uint32_t target_pid, const wchar_t* module_name)
114 | {
115 | std::wstring buffer = module_name;
116 |
117 | data_packet_t get_size = {};
118 |
119 | get_size.header.magic_header = magic_header_value;
120 | get_size.header.type = e_packet_type::packet_get_size;
121 | get_size.data.get_size.target_pid = target_pid;
122 |
123 | memset(&get_size.data.get_size.module_name[0], 0, 64 * sizeof(wchar_t));
124 | memcpy(&get_size.data.get_size.module_name[0], const_cast(buffer.data()),
125 | (std::wcslen(buffer.data()) + 1) * sizeof(wchar_t));
126 |
127 | auto result = 0ull;
128 |
129 | if (this->send_data(get_size, result))
130 | {
131 | return result;
132 | }
133 |
134 | return 0;
135 | }
136 |
137 | uint64_t connection::ksock_t::mm_copy_virtual_memory(uint32_t source_pid, uintptr_t source_address,
138 | uint32_t target_pid, uintptr_t target_address, size_t size)
139 | {
140 | data_packet_t copy_memory = {};
141 |
142 | copy_memory.header.magic_header = magic_header_value;
143 | copy_memory.header.type = e_packet_type::packet_copy_memory;
144 | copy_memory.data.copy_memory.source_pid = source_pid;
145 | copy_memory.data.copy_memory.source_address = source_address;
146 | copy_memory.data.copy_memory.target_pid = target_pid;
147 | copy_memory.data.copy_memory.target_address = target_address;
148 | copy_memory.data.copy_memory.size = size;
149 |
150 | auto result = 0ull;
151 |
152 | if (this->send_data(copy_memory, result))
153 | {
154 | return result;
155 | }
156 |
157 | return 0;
158 | }
159 |
160 | uint64_t connection::ksock_t::zw_allocate_virtual_memory(uint32_t target_pid, uint32_t protection,
161 | uint32_t allocation_type, size_t size)
162 | {
163 | data_packet_t allocate_memory = {};
164 |
165 | allocate_memory.header.magic_header = magic_header_value;
166 | allocate_memory.header.type = e_packet_type::packet_allocate;
167 | allocate_memory.data.allocate_memory.target_pid = target_pid;
168 | allocate_memory.data.allocate_memory.protection = protection;
169 | allocate_memory.data.allocate_memory.allocation_type = allocation_type;
170 | allocate_memory.data.allocate_memory.size = size;
171 |
172 | auto result = 0ull;
173 |
174 | if (this->send_data(allocate_memory, result))
175 | {
176 | return result;
177 | }
178 |
179 | return 0;
180 | }
181 |
182 | uint64_t connection::ksock_t::zw_free_vritual_memory(uint32_t target_pid, uint64_t target_address, size_t size)
183 | {
184 | data_packet_t free_memory = {};
185 |
186 | free_memory.header.magic_header = magic_header_value;
187 | free_memory.header.type = e_packet_type::packet_free;
188 | free_memory.data.free_memory.target_pid = target_pid;
189 | free_memory.data.free_memory.target_address = target_address;
190 | free_memory.data.free_memory.size = size;
191 |
192 | auto result = 0ull;
193 |
194 | if (this->send_data(free_memory, result))
195 | {
196 | return result;
197 | }
198 |
199 | return 0;
200 | }
201 |
202 | uint64_t connection::ksock_t::zw_protect_virtual_memory(uint32_t target_pid, uint64_t target_address, uint32_t protection, size_t size)
203 | {
204 | data_packet_t protect_memory = {};
205 |
206 | protect_memory.header.magic_header = magic_header_value;
207 | protect_memory.header.type = e_packet_type::packet_protect;
208 | protect_memory.data.protect_memory.target_pid = target_pid;
209 | protect_memory.data.protect_memory.target_address = target_address;
210 | protect_memory.data.protect_memory.new_protection = protection;
211 | protect_memory.data.protect_memory.size = size;
212 |
213 | auto result = 0ull;
214 |
215 | if (this->send_data(protect_memory, result))
216 | {
217 | return result;
218 | }
219 |
220 | return 0;
221 | }
222 |
--------------------------------------------------------------------------------
/client/sock.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace connection
4 | {
5 | constexpr auto magic_header_value = 0x59da412859da4128;
6 | constexpr auto server_ip = 0x7F000001; // localhost
7 |
8 | enum class e_packet_type : uint32_t
9 | {
10 | packet_get_base,
11 | packet_get_size,
12 | packet_copy_memory,
13 | packet_allocate,
14 | packet_free,
15 | packet_protect,
16 | completed,
17 | ping
18 | };
19 |
20 | struct packet_header_t
21 | {
22 | uint64_t magic_header;
23 | e_packet_type type;
24 | };
25 |
26 | struct packet_response_t
27 | {
28 | uint64_t data;
29 | };
30 |
31 | struct packet_ping_t
32 | {
33 | int32_t ping_magic;
34 | };
35 |
36 | struct packet_copy_memory_t
37 | {
38 | uint32_t source_pid;
39 | uint64_t source_address;
40 | uint32_t target_pid;
41 | uint64_t target_address;
42 | size_t size;
43 | };
44 |
45 | struct packet_allocate_memory_t
46 | {
47 | uint32_t target_pid;
48 | uint32_t protection;
49 | uint32_t allocation_type;
50 | size_t size;
51 | };
52 |
53 | struct packet_free_memory_t
54 | {
55 | uint32_t target_pid;
56 | uint64_t target_address;
57 | size_t size;
58 | };
59 |
60 | struct packet_get_base_t
61 | {
62 | uint32_t target_pid;
63 | wchar_t module_name[64];
64 | };
65 |
66 | struct packet_get_size_t
67 | {
68 | uint32_t target_pid;
69 | wchar_t module_name[64];
70 | };
71 |
72 | struct packet_protect_memory_t
73 | {
74 | uint32_t target_pid;
75 | uint64_t target_address;
76 | uint32_t new_protection;
77 | size_t size;
78 | };
79 |
80 | struct data_packet_t
81 | {
82 | packet_header_t header;
83 |
84 | union
85 | {
86 | packet_response_t response;
87 | packet_ping_t ping;
88 | packet_copy_memory_t copy_memory;
89 | packet_allocate_memory_t allocate_memory;
90 | packet_free_memory_t free_memory;
91 | packet_protect_memory_t protect_memory;
92 | packet_get_base_t get_base;
93 | packet_get_size_t get_size;
94 | } data;
95 | };
96 |
97 | class ksock_t
98 | {
99 | protected:
100 | WSADATA wsa_data;
101 | SOCKET connection;
102 |
103 | public:
104 | uint16_t port;
105 |
106 | ksock_t(uint16_t port);
107 | ~ksock_t();
108 |
109 | SOCKET connect(uint16_t port);
110 | void disconnect();
111 |
112 | bool send_data(data_packet_t& packet, uint64_t& result);
113 |
114 | uint64_t ping(int32_t value);
115 |
116 | uint64_t get_base(uint32_t target_pid, const wchar_t* module_name);
117 | uint64_t get_size(uint32_t target_pid, const wchar_t* module_name);
118 |
119 | uint64_t mm_copy_virtual_memory(uint32_t source_pid, uintptr_t source_address, uint32_t target_pid,
120 | uintptr_t target_address, size_t size);
121 |
122 | uint64_t zw_allocate_virtual_memory(uint32_t target_pid, uint32_t protection, uint32_t allocation_type, size_t size);
123 | uint64_t zw_free_vritual_memory(uint32_t target_pid, uint64_t target_address, size_t size);
124 | uint64_t zw_protect_virtual_memory(uint32_t target_pid, uint64_t target_address, uint32_t protection, size_t size);
125 | };
126 | }
--------------------------------------------------------------------------------
/client/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "common.hpp"
2 |
3 | uint32_t utils::get_process_id(const char* exe_name)
4 | {
5 | auto snapshot_handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
6 |
7 | if (snapshot_handle == INVALID_HANDLE_VALUE)
8 | {
9 | return 0;
10 | }
11 |
12 | PROCESSENTRY32 pe = { 0 };
13 | pe.dwSize = sizeof(PROCESSENTRY32);
14 |
15 | for (auto success = Process32First(snapshot_handle, &pe); success == true; success = Process32Next(snapshot_handle, &pe))
16 | {
17 | auto wide_name = std::wstring(pe.szExeFile);
18 | auto ascii_name = std::string(wide_name.begin(), wide_name.end());
19 |
20 | if (!ascii_name.compare(exe_name))
21 | {
22 | CloseHandle(snapshot_handle);
23 | return pe.th32ProcessID;
24 | }
25 | }
26 |
27 | CloseHandle(snapshot_handle);
28 | return NULL;
29 | }
30 |
--------------------------------------------------------------------------------
/client/utils.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace utils
4 | {
5 | uint32_t get_process_id(const char* exe_name);
6 | }
--------------------------------------------------------------------------------
/client/xorstr.hpp:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | /*
4 | * Copyright 2017 - 2020 Justas Masiulis
5 | *
6 | * Licensed under the Apache License, Version 2.0 (the "License");
7 | * you may not use this file except in compliance with the License.
8 | * You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 |
19 | #ifndef JM_XORSTR_HPP
20 | #define JM_XORSTR_HPP
21 |
22 | #define xorstr(str) ::jm::xor_string([]() { return str; }, std::integral_constant{}, std::make_index_sequence<::jm::detail::_buffer_size()>{})
23 | #define xorstr_(str) xorstr(str).crypt_get()
24 |
25 | #ifdef _MSC_VER
26 | #define XORSTR_FORCEINLINE __forceinline
27 | #else
28 | #define XORSTR_FORCEINLINE __attribute__((always_inline)) inline
29 | #endif
30 |
31 | #if defined(__clang__) || defined(__GNUC__)
32 | #define JM_XORSTR_LOAD_FROM_REG(x) ::jm::detail::load_from_reg(x)
33 | #else
34 | #define JM_XORSTR_LOAD_FROM_REG(x) (x)
35 | #endif
36 |
37 | namespace jm
38 | {
39 |
40 | namespace detail
41 | {
42 |
43 | template
44 | XORSTR_FORCEINLINE constexpr std::size_t _buffer_size()
45 | {
46 | return ((Size / 16) + (Size % 16 != 0)) * 2;
47 | }
48 |
49 | template
50 | XORSTR_FORCEINLINE constexpr std::uint32_t key4() noexcept
51 | {
52 | std::uint32_t value = Seed;
53 | for (char c : __TIME__)
54 | value = static_cast((value ^ c) * 16777619ull);
55 | return value;
56 | }
57 |
58 | template
59 | XORSTR_FORCEINLINE constexpr std::uint64_t key8()
60 | {
61 | constexpr auto first_part = key4<2166136261 + S>();
62 | constexpr auto second_part = key4();
63 | return (static_cast(first_part) << 32) | second_part;
64 | }
65 |
66 | // loads up to 8 characters of string into uint64 and xors it with the key
67 | template
68 | XORSTR_FORCEINLINE constexpr std::uint64_t
69 | load_xored_str8(std::uint64_t key, std::size_t idx, const CharT* str) noexcept
70 | {
71 | using cast_type = typename std::make_unsigned::type;
72 | constexpr auto value_size = sizeof(CharT);
73 | constexpr auto idx_offset = 8 / value_size;
74 |
75 | std::uint64_t value = key;
76 | for (std::size_t i = 0; i < idx_offset && i + idx * idx_offset < N; ++i)
77 | value ^=
78 | (std::uint64_t{ static_cast(str[i + idx * idx_offset]) }
79 | << ((i % idx_offset) * 8 * value_size));
80 |
81 | return value;
82 | }
83 |
84 | // forces compiler to use registers instead of stuffing constants in rdata
85 | XORSTR_FORCEINLINE std::uint64_t load_from_reg(std::uint64_t value) noexcept
86 | {
87 | #if defined(__clang__) || defined(__GNUC__)
88 | asm("" : "=r"(value) : "0"(value) : );
89 | #endif
90 | return value;
91 | }
92 |
93 | template
94 | struct uint64_v
95 | {
96 | constexpr static std::uint64_t value = V;
97 | };
98 |
99 | } // namespace detail
100 |
101 | template
102 | class xor_string;
103 |
104 | template
105 | class xor_string, std::index_sequence>
106 | {
107 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
108 | constexpr static inline std::uint64_t alignment = ((Size > 16) ? 32 : 16);
109 | #else
110 | constexpr static inline std::uint64_t alignment = 16;
111 | #endif
112 |
113 | alignas(alignment) std::uint64_t _storage[sizeof...(Keys)];
114 |
115 | public:
116 | using value_type = CharT;
117 | using size_type = std::size_t;
118 | using pointer = CharT*;
119 | using const_pointer = const CharT*;
120 |
121 | template
122 | XORSTR_FORCEINLINE xor_string(L l, std::integral_constant, std::index_sequence) noexcept
123 | : _storage{ JM_XORSTR_LOAD_FROM_REG(detail::uint64_v(Keys, Indices, l())>::value)... }
124 | {}
125 |
126 | XORSTR_FORCEINLINE constexpr size_type size() const noexcept
127 | {
128 | return Size - 1;
129 | }
130 |
131 | XORSTR_FORCEINLINE void crypt() noexcept
132 | {
133 | #if defined(__clang__)
134 | alignas(alignment)
135 | std::uint64_t arr[]{ JM_XORSTR_LOAD_FROM_REG(Keys)... };
136 | std::uint64_t* keys =
137 | (std::uint64_t*)JM_XORSTR_LOAD_FROM_REG((std::uint64_t)arr);
138 | #else
139 | alignas(alignment) std::uint64_t keys[]{ JM_XORSTR_LOAD_FROM_REG(Keys)... };
140 | #endif
141 |
142 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
143 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
144 | reinterpret_cast<__m256i*>(_storage) + Indices,
145 | _mm256_xor_si256(
146 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
147 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
148 |
149 | if constexpr (sizeof(_storage) % 32 != 0)
150 | _mm_store_si128(
151 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
152 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
153 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
154 | #else
155 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
156 | reinterpret_cast<__m128i*>(_storage) + Indices,
157 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
158 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
159 | #endif
160 | }
161 |
162 | XORSTR_FORCEINLINE const_pointer get() const noexcept
163 | {
164 | return reinterpret_cast(_storage);
165 | }
166 |
167 | XORSTR_FORCEINLINE pointer get() noexcept
168 | {
169 | return reinterpret_cast(_storage);
170 | }
171 |
172 | XORSTR_FORCEINLINE pointer crypt_get() noexcept
173 | {
174 | // crypt() function inlined by hand, because MSVC linker chokes when you have a lot of strings
175 | // on 32 bit builds, so don't blame me for shit code :pepekms:
176 | #if defined(__clang__)
177 | alignas(alignment)
178 | std::uint64_t arr[]{ JM_XORSTR_LOAD_FROM_REG(Keys)... };
179 | std::uint64_t* keys =
180 | (std::uint64_t*)JM_XORSTR_LOAD_FROM_REG((std::uint64_t)arr);
181 | #else
182 | alignas(alignment) std::uint64_t keys[]{ JM_XORSTR_LOAD_FROM_REG(Keys)... };
183 | #endif
184 |
185 | #ifndef JM_XORSTR_DISABLE_AVX_INTRINSICS
186 | ((Indices >= sizeof(_storage) / 32 ? static_cast(0) : _mm256_store_si256(
187 | reinterpret_cast<__m256i*>(_storage) + Indices,
188 | _mm256_xor_si256(
189 | _mm256_load_si256(reinterpret_cast(_storage) + Indices),
190 | _mm256_load_si256(reinterpret_cast(keys) + Indices)))), ...);
191 |
192 | if constexpr (sizeof(_storage) % 32 != 0)
193 | _mm_store_si128(
194 | reinterpret_cast<__m128i*>(_storage + sizeof...(Keys) - 2),
195 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage + sizeof...(Keys) - 2)),
196 | _mm_load_si128(reinterpret_cast(keys + sizeof...(Keys) - 2))));
197 | #else
198 | ((Indices >= sizeof(_storage) / 16 ? static_cast(0) : _mm_store_si128(
199 | reinterpret_cast<__m128i*>(_storage) + Indices,
200 | _mm_xor_si128(_mm_load_si128(reinterpret_cast(_storage) + Indices),
201 | _mm_load_si128(reinterpret_cast(keys) + Indices)))), ...);
202 | #endif
203 | return (pointer)(_storage);
204 | }
205 | };
206 |
207 | template
208 | xor_string(L l, std::integral_constant, std::index_sequence)->xor_string<
209 | std::remove_const_t>,
210 | Size,
211 | std::integer_sequence()...>,
212 | std::index_sequence>;
213 |
214 | } // namespace jm
215 |
216 | #endif // include guard
217 |
--------------------------------------------------------------------------------
/driver/berkeley.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | //////////////////////////////////////////////////////////////////////////
4 | // Definitions.
5 | //////////////////////////////////////////////////////////////////////////
6 |
7 | #define MEMORY_TAG ' bsK'
8 | #define SOCKETFD_MAX 128
9 | #define TO_SOCKETFD(index) ((index % SOCKETFD_MAX) + 1)
10 | #define FROM_SOCKETFD(sockfd) ((sockfd) - 1)
11 |
12 | //////////////////////////////////////////////////////////////////////////
13 | // Function prototypes.
14 | //////////////////////////////////////////////////////////////////////////
15 |
16 | NTSTATUS
17 | NTAPI
18 | KspUtilAddrInfoToAddrInfoEx(
19 | _In_ PADDRINFOA AddrInfo,
20 | _Out_ PADDRINFOEXW * AddrInfoEx
21 | );
22 |
23 | NTSTATUS
24 | NTAPI
25 | KspUtilAddrInfoExToAddrInfo(
26 | _In_ PADDRINFOEXW AddrInfoEx,
27 | _Out_ PADDRINFOA* AddrInfo
28 | );
29 |
30 | VOID
31 | NTAPI
32 | KspUtilFreeAddrInfo(
33 | _In_ PADDRINFOA AddrInfo
34 | );
35 |
36 | VOID
37 | NTAPI
38 | KspUtilFreeAddrInfoEx(
39 | _In_ PADDRINFOEXW AddrInfo
40 | );
41 |
42 | //////////////////////////////////////////////////////////////////////////
43 | // Variables.
44 | //////////////////////////////////////////////////////////////////////////
45 |
46 | //
47 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
48 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
49 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
50 | //
51 | // This is complete bollocks and ideally it should be replaced with
52 | // something like RTL_AVL_TABLE.
53 | //
54 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
55 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
56 | // !!!!!!!!!!!!!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
57 | //
58 |
59 | PKSOCKET KsArray[SOCKETFD_MAX] = { 0 };
60 | ULONG KsIndex = 0;
61 |
62 | //////////////////////////////////////////////////////////////////////////
63 | // Private functions.
64 | //////////////////////////////////////////////////////////////////////////
65 |
66 | NTSTATUS
67 | NTAPI
68 | KspUtilAddrInfoToAddrInfoEx(
69 | _In_ PADDRINFOA AddrInfo,
70 | _Out_ PADDRINFOEXW* AddrInfoEx
71 | )
72 | {
73 | NTSTATUS Status;
74 |
75 | //
76 | // Convert NULL input into NULL output.
77 | //
78 |
79 | if (AddrInfo == NULL)
80 | {
81 | *AddrInfoEx = NULL;
82 | return STATUS_SUCCESS;
83 | }
84 |
85 | //
86 | // Allocate memory for the output structure.
87 | //
88 |
89 | PADDRINFOEXW Result = ExAllocatePoolWithTag(PagedPool, sizeof(ADDRINFOEXW), MEMORY_TAG);
90 |
91 | if (Result == NULL)
92 | {
93 | Status = STATUS_INSUFFICIENT_RESOURCES;
94 | goto Error1;
95 | }
96 |
97 | //
98 | // Copy numeric values.
99 | //
100 |
101 | RtlZeroMemory(Result, sizeof(ADDRINFOEXW));
102 | Result->ai_flags = AddrInfo->ai_flags;
103 | Result->ai_family = AddrInfo->ai_family;
104 | Result->ai_socktype = AddrInfo->ai_socktype;
105 | Result->ai_protocol = AddrInfo->ai_protocol;
106 | Result->ai_addrlen = AddrInfo->ai_addrlen;
107 |
108 | //
109 | // Copy canonical name.
110 | //
111 |
112 | ANSI_STRING CanonicalNameAnsi;
113 | UNICODE_STRING CanonicalNameUnicode;
114 |
115 | if (AddrInfo->ai_canonname)
116 | {
117 | RtlInitAnsiString(&CanonicalNameAnsi, AddrInfo->ai_canonname);
118 |
119 | Status = RtlAnsiStringToUnicodeString(&CanonicalNameUnicode, &CanonicalNameAnsi, TRUE);
120 |
121 | if (!NT_SUCCESS(Status))
122 | {
123 | goto Error2;
124 | }
125 |
126 | Result->ai_canonname = CanonicalNameUnicode.Buffer;
127 | }
128 |
129 | //
130 | // Copy address.
131 | //
132 |
133 | Result->ai_addr = AddrInfo->ai_addr;
134 |
135 | //
136 | // Copy the next structure (recursively).
137 | //
138 |
139 | PADDRINFOEXW NextAddrInfo;
140 | Status = KspUtilAddrInfoToAddrInfoEx(AddrInfo->ai_next, &NextAddrInfo);
141 |
142 | if (!NT_SUCCESS(Status))
143 | {
144 | goto Error3;
145 | }
146 |
147 | Result->ai_next = NextAddrInfo;
148 |
149 | //
150 | // All done!
151 | //
152 |
153 | *AddrInfoEx = Result;
154 |
155 | return Status;
156 |
157 | Error3:
158 | RtlFreeAnsiString(&CanonicalNameAnsi);
159 |
160 | Error2:
161 | ExFreePoolWithTag(Result, MEMORY_TAG);
162 |
163 | Error1:
164 | return Status;
165 | }
166 |
167 | NTSTATUS
168 | NTAPI
169 | KspUtilAddrInfoExToAddrInfo(
170 | _In_ PADDRINFOEXW AddrInfoEx,
171 | _Out_ PADDRINFOA* AddrInfo
172 | )
173 | {
174 | NTSTATUS Status;
175 |
176 | //
177 | // Convert NULL input into NULL output.
178 | //
179 |
180 | if (AddrInfoEx == NULL)
181 | {
182 | *AddrInfo = NULL;
183 | return STATUS_SUCCESS;
184 | }
185 |
186 | //
187 | // Allocate memory for the output structure.
188 | //
189 |
190 | PADDRINFOA Result = ExAllocatePoolWithTag(PagedPool, sizeof(ADDRINFOA), MEMORY_TAG);
191 |
192 | if (Result == NULL)
193 | {
194 | Status = STATUS_INSUFFICIENT_RESOURCES;
195 | goto Error1;
196 | }
197 |
198 | //
199 | // Copy numeric values.
200 | //
201 |
202 | RtlZeroMemory(Result, sizeof(ADDRINFOA));
203 | Result->ai_flags = AddrInfoEx->ai_flags;
204 | Result->ai_family = AddrInfoEx->ai_family;
205 | Result->ai_socktype = AddrInfoEx->ai_socktype;
206 | Result->ai_protocol = AddrInfoEx->ai_protocol;
207 | Result->ai_addrlen = AddrInfoEx->ai_addrlen;
208 |
209 | //
210 | // Copy canonical name.
211 | //
212 |
213 | UNICODE_STRING CanonicalNameUnicode;
214 | ANSI_STRING CanonicalNameAnsi;
215 |
216 | if (AddrInfoEx->ai_canonname)
217 | {
218 | RtlInitUnicodeString(&CanonicalNameUnicode, AddrInfoEx->ai_canonname);
219 | Status = RtlUnicodeStringToAnsiString(&CanonicalNameAnsi, &CanonicalNameUnicode, TRUE);
220 |
221 | if (!NT_SUCCESS(Status))
222 | {
223 | goto Error2;
224 | }
225 |
226 | Result->ai_canonname = CanonicalNameAnsi.Buffer;
227 | }
228 |
229 | //
230 | // Copy address.
231 | //
232 |
233 | Result->ai_addr = AddrInfoEx->ai_addr;
234 |
235 | //
236 | // Copy the next structure (recursively).
237 | //
238 |
239 | PADDRINFOA NextAddrInfo;
240 | Status = KspUtilAddrInfoExToAddrInfo(AddrInfoEx->ai_next, &NextAddrInfo);
241 |
242 | if (!NT_SUCCESS(Status))
243 | {
244 | goto Error3;
245 | }
246 |
247 | Result->ai_next = NextAddrInfo;
248 |
249 | //
250 | // All done!
251 | //
252 |
253 | *AddrInfo = Result;
254 |
255 | return Status;
256 |
257 | Error3:
258 | RtlFreeAnsiString(&CanonicalNameAnsi);
259 |
260 | Error2:
261 | ExFreePoolWithTag(Result, MEMORY_TAG);
262 |
263 | Error1:
264 | return Status;
265 | }
266 |
267 | VOID
268 | NTAPI
269 | KspUtilFreeAddrInfo(
270 | _In_ PADDRINFOA AddrInfo
271 | )
272 | {
273 | //
274 | // Free all structures recursively.
275 | //
276 |
277 | if (AddrInfo->ai_next)
278 | {
279 | KspUtilFreeAddrInfo(AddrInfo->ai_next);
280 | }
281 |
282 | //
283 | // Free the canonical name buffer.
284 | //
285 |
286 | if (AddrInfo->ai_canonname)
287 | {
288 | ANSI_STRING CanonicalName;
289 | RtlInitAnsiString(&CanonicalName, AddrInfo->ai_canonname);
290 | RtlFreeAnsiString(&CanonicalName);
291 | }
292 |
293 | //
294 | // Finally, free the structure itself.
295 | //
296 |
297 | ExFreePoolWithTag(AddrInfo, MEMORY_TAG);
298 | }
299 |
300 | VOID
301 | NTAPI
302 | KspUtilFreeAddrInfoEx(
303 | _In_ PADDRINFOEXW AddrInfo
304 | )
305 | {
306 | //
307 | // Free all structures recursively.
308 | //
309 |
310 | if (AddrInfo->ai_next)
311 | {
312 | KspUtilFreeAddrInfoEx(AddrInfo->ai_next);
313 | }
314 |
315 | //
316 | // Free the canonical name buffer.
317 | //
318 |
319 | if (AddrInfo->ai_canonname)
320 | {
321 | UNICODE_STRING CanonicalName;
322 | RtlInitUnicodeString(&CanonicalName, AddrInfo->ai_canonname);
323 | RtlFreeUnicodeString(&CanonicalName);
324 | }
325 |
326 | //
327 | // Finally, free the structure itself.
328 | //
329 |
330 | ExFreePoolWithTag(AddrInfo, MEMORY_TAG);
331 | }
332 |
333 | //////////////////////////////////////////////////////////////////////////
334 | // Public functions.
335 | //////////////////////////////////////////////////////////////////////////
336 |
337 | uint32_t htonl(uint32_t hostlong)
338 | {
339 | return RtlUlongByteSwap(hostlong);
340 | }
341 |
342 | uint16_t htons(uint16_t hostshort)
343 | {
344 | return RtlUshortByteSwap(hostshort);
345 | }
346 |
347 | uint32_t ntohl(uint32_t netlong)
348 | {
349 | return RtlUlongByteSwap(netlong);
350 | }
351 |
352 | uint16_t ntohs(uint16_t netshort)
353 | {
354 | return RtlUshortByteSwap(netshort);
355 | }
356 |
357 | int getaddrinfo(const char* node, const char* service, const struct addrinfo* hints, struct addrinfo** res)
358 | {
359 | NTSTATUS Status;
360 |
361 | //
362 | // Convert node name to the UNICODE_STRING (if present).
363 | //
364 |
365 | ANSI_STRING NodeNameAnsi;
366 | UNICODE_STRING NodeNameUnicode;
367 | PUNICODE_STRING NodeName = NULL;
368 |
369 | if (node)
370 | {
371 | RtlInitAnsiString(&NodeNameAnsi, node);
372 | Status = RtlAnsiStringToUnicodeString(&NodeNameUnicode, &NodeNameAnsi, TRUE);
373 |
374 | if (!NT_SUCCESS(Status))
375 | {
376 | goto Error1;
377 | }
378 |
379 | NodeName = &NodeNameUnicode;
380 | }
381 |
382 | //
383 | // Convert service name to the UNICODE_STRING (if present).
384 | //
385 |
386 | ANSI_STRING ServiceNameAnsi;
387 | UNICODE_STRING ServiceNameUnicode;
388 | PUNICODE_STRING ServiceName = NULL;
389 |
390 | if (service)
391 | {
392 | RtlInitAnsiString(&ServiceNameAnsi, service);
393 | Status = RtlAnsiStringToUnicodeString(&ServiceNameUnicode, &ServiceNameAnsi, TRUE);
394 |
395 | if (!NT_SUCCESS(Status))
396 | {
397 | goto Error2;
398 | }
399 |
400 | ServiceName = &ServiceNameUnicode;
401 | }
402 |
403 | //
404 | // Convert "struct addrinfo" to the "ADDRINFOEXW".
405 | //
406 |
407 | PADDRINFOEXW Hints;
408 | Status = KspUtilAddrInfoToAddrInfoEx((PADDRINFOA)hints, &Hints);
409 |
410 | if (!NT_SUCCESS(Status))
411 | {
412 | goto Error3;
413 | }
414 |
415 | //
416 | // All data is prepared, call the underlying API.
417 | //
418 |
419 | PADDRINFOEXW Result;
420 | Status = KsGetAddrInfo(NodeName, ServiceName, Hints, &Result);
421 |
422 | //
423 | // Free the memory of the converted "Hints".
424 | //
425 |
426 | KspUtilFreeAddrInfoEx(Hints);
427 |
428 | if (!NT_SUCCESS(Status))
429 | {
430 | goto Error3;
431 | }
432 |
433 | //
434 | // Convert the result "ADDRINFOEXW" to the "struct addrinfo".
435 | //
436 |
437 | Status = KspUtilAddrInfoExToAddrInfo(Result, res);
438 |
439 | //
440 | // Free the original result.
441 | //
442 |
443 | KsFreeAddrInfo(Result);
444 |
445 | if (!NT_SUCCESS(Status))
446 | {
447 | goto Error3;
448 | }
449 |
450 | return STATUS_SUCCESS;
451 |
452 | Error3:
453 | RtlFreeUnicodeString(&ServiceNameUnicode);
454 |
455 | Error2:
456 | RtlFreeUnicodeString(&NodeNameUnicode);
457 |
458 | Error1:
459 | return Status;
460 | }
461 |
462 | void freeaddrinfo(struct addrinfo* res)
463 | {
464 | //
465 | // Call our implementation.
466 | //
467 |
468 | KspUtilFreeAddrInfo(res);
469 | }
470 |
471 | int socket_connection(int domain, int type, int protocol)
472 | {
473 | NTSTATUS Status;
474 | PKSOCKET Socket;
475 |
476 | Status = KsCreateConnectionSocket(
477 | &Socket,
478 | (ADDRESS_FAMILY)domain,
479 | (USHORT)type,
480 | (ULONG)protocol
481 | );
482 |
483 | if (NT_SUCCESS(Status))
484 | {
485 | int sockfd = TO_SOCKETFD(KsIndex++);
486 |
487 | KsArray[FROM_SOCKETFD(sockfd)] = Socket;
488 |
489 | return sockfd;
490 | }
491 |
492 | return -1;
493 | }
494 |
495 | int socket_listen(int domain, int type, int protocol)
496 | {
497 | NTSTATUS Status;
498 | PKSOCKET Socket;
499 |
500 | //
501 | // WskSocket() returns STATUS_PROTOCOL_UNREACHABLE (0xC000023E)
502 | // when Protocol == 0, so coerce this value to IPPROTO_TCP here.
503 | //
504 |
505 | Status = KsCreateListenSocket(
506 | &Socket,
507 | (ADDRESS_FAMILY)domain,
508 | (USHORT)type,
509 | protocol ? (ULONG)protocol : IPPROTO_TCP
510 | );
511 |
512 | if (NT_SUCCESS(Status))
513 | {
514 | int sockfd = TO_SOCKETFD(KsIndex++);
515 |
516 | KsArray[FROM_SOCKETFD(sockfd)] = Socket;
517 |
518 | return sockfd;
519 | }
520 |
521 | return -1;
522 | }
523 |
524 | int socket_datagram(int domain, int type, int protocol)
525 | {
526 | NTSTATUS Status;
527 | PKSOCKET Socket;
528 |
529 | Status = KsCreateDatagramSocket(
530 | &Socket,
531 | (ADDRESS_FAMILY)domain,
532 | (USHORT)type,
533 | (ULONG)protocol
534 | );
535 |
536 | if (NT_SUCCESS(Status))
537 | {
538 | int sockfd = TO_SOCKETFD(KsIndex++);
539 |
540 | KsArray[FROM_SOCKETFD(sockfd)] = Socket;
541 |
542 | return sockfd;
543 | }
544 |
545 | return -1;
546 | }
547 |
548 | int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen)
549 | {
550 | UNREFERENCED_PARAMETER(addrlen);
551 |
552 | NTSTATUS Status;
553 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
554 |
555 | Status = KsConnect(Socket, (PSOCKADDR)addr);
556 |
557 | return NT_SUCCESS(Status)
558 | ? 0
559 | : -1;
560 | }
561 |
562 | int listen(int sockfd, int backlog)
563 | {
564 | UNREFERENCED_PARAMETER(sockfd);
565 | UNREFERENCED_PARAMETER(backlog);
566 | return 0;
567 | }
568 |
569 | int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen)
570 | {
571 | UNREFERENCED_PARAMETER(addrlen);
572 |
573 | NTSTATUS Status;
574 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
575 |
576 | Status = KsBind(Socket, (PSOCKADDR)addr);
577 |
578 | return NT_SUCCESS(Status)
579 | ? 0
580 | : -1;
581 | }
582 |
583 | int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)
584 | {
585 | NTSTATUS Status;
586 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
587 |
588 | PKSOCKET NewSocket;
589 | Status = KsAccept(Socket, &NewSocket, NULL, (PSOCKADDR)addr);
590 | *addrlen = sizeof(SOCKADDR);
591 |
592 | if (NT_SUCCESS(Status))
593 | {
594 | int newsockfd = TO_SOCKETFD(KsIndex++);
595 |
596 | KsArray[FROM_SOCKETFD(newsockfd)] = NewSocket;
597 |
598 | return newsockfd;
599 | }
600 |
601 | return -1;
602 | }
603 |
604 | int send(int sockfd, const void* buf, size_t len, int flags)
605 | {
606 | NTSTATUS Status;
607 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
608 |
609 | ULONG Length = (ULONG)len;
610 | Status = KsSend(Socket, (PVOID)buf, &Length, (ULONG)flags);
611 |
612 | return NT_SUCCESS(Status)
613 | ? (int)Length
614 | : -1;
615 | }
616 |
617 | int sendto(int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen)
618 | {
619 | UNREFERENCED_PARAMETER(addrlen);
620 |
621 | NTSTATUS Status;
622 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
623 |
624 | ULONG Length = (ULONG)len;
625 | Status = KsSendTo(Socket, (PVOID)buf, &Length, (ULONG)flags, (PSOCKADDR)dest_addr);
626 | Status = KsSendTo(Socket, (PVOID)buf, &Length, (ULONG)flags, (PSOCKADDR)dest_addr);
627 |
628 | return NT_SUCCESS(Status)
629 | ? (int)Length
630 | : -1;
631 | }
632 |
633 | int recv(int sockfd, void* buf, size_t len, int flags)
634 | {
635 | NTSTATUS Status;
636 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
637 |
638 | ULONG Length = (ULONG)len;
639 | Status = KsRecv(Socket, (PVOID)buf, &Length, (ULONG)flags);
640 |
641 | return NT_SUCCESS(Status)
642 | ? (int)Length
643 | : -1;
644 | }
645 |
646 | int recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen)
647 | {
648 | UNREFERENCED_PARAMETER(addrlen);
649 |
650 | NTSTATUS Status;
651 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
652 |
653 | ULONG Length = (ULONG)len;
654 | Status = KsSendTo(Socket, (PVOID)buf, &Length, (ULONG)flags, (PSOCKADDR)src_addr);
655 | *addrlen = sizeof(SOCKADDR);
656 |
657 | return NT_SUCCESS(Status)
658 | ? (int)Length
659 | : -1;
660 | }
661 |
662 | int closesocket(int sockfd)
663 | {
664 | NTSTATUS Status;
665 | PKSOCKET Socket = KsArray[FROM_SOCKETFD(sockfd)];
666 |
667 | Status = KsCloseSocket(Socket);
668 |
669 | KsArray[FROM_SOCKETFD(sockfd)] = NULL;
670 |
671 | return NT_SUCCESS(Status)
672 | ? 0
673 | : -1;
674 | }
--------------------------------------------------------------------------------
/driver/berkeley.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 |
7 | typedef int socklen_t;
8 | typedef intptr_t ssize_t;
9 |
10 | uint32_t htonl(uint32_t hostlong);
11 | uint16_t htons(uint16_t hostshort);
12 | uint32_t ntohl(uint32_t netlong);
13 | uint16_t ntohs(uint16_t netshort);
14 |
15 | int getaddrinfo(const char* node, const char* service, const struct addrinfo* hints, struct addrinfo** res);
16 | void freeaddrinfo(struct addrinfo* res);
17 |
18 | int socket_connection(int domain, int type, int protocol);
19 | int socket_listen(int domain, int type, int protocol);
20 | int socket_datagram(int domain, int type, int protocol);
21 | int connect(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
22 | int listen(int sockfd, int backlog);
23 | int bind(int sockfd, const struct sockaddr* addr, socklen_t addrlen);
24 | int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
25 | int send(int sockfd, const void* buf, size_t len, int flags);
26 | int sendto(int sockfd, const void* buf, size_t len, int flags, const struct sockaddr* dest_addr, socklen_t addrlen);
27 | int recv(int sockfd, void* buf, size_t len, int flags);
28 | int recvfrom(int sockfd, void* buf, size_t len, int flags, struct sockaddr* src_addr, socklen_t* addrlen);
29 | int closesocket(int sockfd);
30 |
31 | #define socket socket_connection
32 |
33 | #ifdef __cplusplus
34 | }
35 | #endif
--------------------------------------------------------------------------------
/driver/common.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #define log(...) DbgPrintEx(0, 0, __VA_ARGS__);
8 |
9 | #include "intdefs.h"
10 | #include "imports.h"
11 | #include "utils.h"
12 | #include "berkeley.h"
13 | #include "ksocket.h"
14 | #include "server.h"
--------------------------------------------------------------------------------
/driver/driver.inf:
--------------------------------------------------------------------------------
1 | ;
2 | ; driver.inf
3 | ;
4 |
5 | [Version]
6 | Signature="$WINDOWS NT$"
7 | Class=Sample ; TODO: edit Class
8 | ClassGuid={78A1C341-4539-11d3-B88D-00C04FAD5171} ; TODO: edit ClassGuid
9 | Provider=%ManufacturerName%
10 | CatalogFile=driver.cat
11 | DriverVer= ; TODO: set DriverVer in stampinf property pages
12 | PnpLockDown=1
13 |
14 | [DestinationDirs]
15 | DefaultDestDir = 12
16 | driver_Device_CoInstaller_CopyFiles = 11
17 |
18 | ; ================= Class section =====================
19 |
20 | [ClassInstall32]
21 | Addreg=SampleClassReg
22 |
23 | [SampleClassReg]
24 | HKR,,,0,%ClassName%
25 | HKR,,Icon,,-5
26 |
27 | [SourceDisksNames]
28 | 1 = %DiskName%,,,""
29 |
30 | [SourceDisksFiles]
31 | driver.sys = 1,,
32 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll=1 ; make sure the number matches with SourceDisksNames
33 |
34 | ;*****************************************
35 | ; Install Section
36 | ;*****************************************
37 |
38 | [Manufacturer]
39 | %ManufacturerName%=Standard,NT$ARCH$
40 |
41 | [Standard.NT$ARCH$]
42 | %driver.DeviceDesc%=driver_Device, Root\driver ; TODO: edit hw-id
43 |
44 | [driver_Device.NT]
45 | CopyFiles=Drivers_Dir
46 |
47 | [Drivers_Dir]
48 | driver.sys
49 |
50 | ;-------------- Service installation
51 | [driver_Device.NT.Services]
52 | AddService = driver,%SPSVCINST_ASSOCSERVICE%, driver_Service_Inst
53 |
54 | ; -------------- driver driver install sections
55 | [driver_Service_Inst]
56 | DisplayName = %driver.SVCDESC%
57 | ServiceType = 1 ; SERVICE_KERNEL_DRIVER
58 | StartType = 3 ; SERVICE_DEMAND_START
59 | ErrorControl = 1 ; SERVICE_ERROR_NORMAL
60 | ServiceBinary = %12%\driver.sys
61 |
62 | ;
63 | ;--- driver_Device Coinstaller installation ------
64 | ;
65 |
66 | [driver_Device.NT.CoInstallers]
67 | AddReg=driver_Device_CoInstaller_AddReg
68 | CopyFiles=driver_Device_CoInstaller_CopyFiles
69 |
70 | [driver_Device_CoInstaller_AddReg]
71 | HKR,,CoInstallers32,0x00010000, "WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll,WdfCoInstaller"
72 |
73 | [driver_Device_CoInstaller_CopyFiles]
74 | WdfCoInstaller$KMDFCOINSTALLERVERSION$.dll
75 |
76 | [driver_Device.NT.Wdf]
77 | KmdfService = driver, driver_wdfsect
78 | [driver_wdfsect]
79 | KmdfLibraryVersion = $KMDFVERSION$
80 |
81 | [Strings]
82 | SPSVCINST_ASSOCSERVICE= 0x00000002
83 | ManufacturerName="" ;TODO: Replace with your manufacturer name
84 | ClassName="Samples" ; TODO: edit ClassName
85 | DiskName = "driver Installation Disk"
86 | driver.DeviceDesc = "driver Device"
87 | driver.SVCDESC = "driver Service"
88 |
--------------------------------------------------------------------------------
/driver/driver.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | x64
7 |
8 |
9 | Release
10 | x64
11 |
12 |
13 |
14 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}
15 | {1bc93793-694f-48fe-9372-81e2b05556fd}
16 | v4.5
17 | 12.0
18 | Debug
19 | Win32
20 | driver
21 |
22 |
23 |
24 | Windows10
25 | true
26 | WindowsKernelModeDriver10.0
27 | Driver
28 | KMDF
29 | Universal
30 |
31 |
32 | Windows10
33 | false
34 | WindowsKernelModeDriver10.0
35 | Driver
36 | KMDF
37 | Universal
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | DbgengKernelDebugger
49 |
50 |
51 | DbgengKernelDebugger
52 |
53 |
54 |
55 | false
56 |
57 |
58 | Netio.lib;%(AdditionalDependencies)
59 |
60 |
61 |
62 |
63 | false
64 |
65 |
66 | Netio.lib;%(AdditionalDependencies)
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 |
--------------------------------------------------------------------------------
/driver/driver.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 | {8E41214B-6785-4CFE-B992-037D68949A14}
18 | inf;inv;inx;mof;mc;
19 |
20 |
21 | {c0533627-79fb-48cb-84cf-812855aa3f3b}
22 |
23 |
24 |
25 |
26 | Driver Files
27 |
28 |
29 |
30 |
31 | Source Files
32 |
33 |
34 | Header Files\ksocket
35 |
36 |
37 | Header Files\ksocket
38 |
39 |
40 | Source Files
41 |
42 |
43 | Source Files
44 |
45 |
46 |
47 |
48 | Header Files
49 |
50 |
51 | Header Files
52 |
53 |
54 | Header Files
55 |
56 |
57 | Header Files\ksocket
58 |
59 |
60 | Header Files\ksocket
61 |
62 |
63 | Header Files
64 |
65 |
66 | Header Files
67 |
68 |
69 |
--------------------------------------------------------------------------------
/driver/imports.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef enum _SYSTEM_INFORMATION_CLASS
4 | {
5 | SystemBasicInformation = 0x0,
6 | SystemProcessorInformation = 0x1,
7 | SystemPerformanceInformation = 0x2,
8 | SystemTimeOfDayInformation = 0x3,
9 | SystemPathInformation = 0x4,
10 | SystemProcessInformation = 0x5,
11 | SystemCallCountInformation = 0x6,
12 | SystemDeviceInformation = 0x7,
13 | SystemProcessorPerformanceInformation = 0x8,
14 | SystemFlagsInformation = 0x9,
15 | SystemCallTimeInformation = 0xa,
16 | SystemModuleInformation = 0xb,
17 | SystemLocksInformation = 0xc,
18 | SystemStackTraceInformation = 0xd,
19 | SystemPagedPoolInformation = 0xe,
20 | SystemNonPagedPoolInformation = 0xf,
21 | SystemHandleInformation = 0x10,
22 | SystemObjectInformation = 0x11,
23 | SystemPageFileInformation = 0x12,
24 | SystemVdmInstemulInformation = 0x13,
25 | SystemVdmBopInformation = 0x14,
26 | SystemFileCacheInformation = 0x15,
27 | SystemPoolTagInformation = 0x16,
28 | SystemInterruptInformation = 0x17,
29 | SystemDpcBehaviorInformation = 0x18,
30 | SystemFullMemoryInformation = 0x19,
31 | SystemLoadGdiDriverInformation = 0x1a,
32 | SystemUnloadGdiDriverInformation = 0x1b,
33 | SystemTimeAdjustmentInformation = 0x1c,
34 | SystemSummaryMemoryInformation = 0x1d,
35 | SystemMirrorMemoryInformation = 0x1e,
36 | SystemPerformanceTraceInformation = 0x1f,
37 | SystemObsolete0 = 0x20,
38 | SystemExceptionInformation = 0x21,
39 | SystemCrashDumpStateInformation = 0x22,
40 | SystemKernelDebuggerInformation = 0x23,
41 | SystemContextSwitchInformation = 0x24,
42 | SystemRegistryQuotaInformation = 0x25,
43 | SystemExtendServiceTableInformation = 0x26,
44 | SystemPrioritySeperation = 0x27,
45 | SystemVerifierAddDriverInformation = 0x28,
46 | SystemVerifierRemoveDriverInformation = 0x29,
47 | SystemProcessorIdleInformation = 0x2a,
48 | SystemLegacyDriverInformation = 0x2b,
49 | SystemCurrentTimeZoneInformation = 0x2c,
50 | SystemLookasideInformation = 0x2d,
51 | SystemTimeSlipNotification = 0x2e,
52 | SystemSessionCreate = 0x2f,
53 | SystemSessionDetach = 0x30,
54 | SystemSessionInformation = 0x31,
55 | SystemRangeStartInformation = 0x32,
56 | SystemVerifierInformation = 0x33,
57 | SystemVerifierThunkExtend = 0x34,
58 | SystemSessionProcessInformation = 0x35,
59 | SystemLoadGdiDriverInSystemSpace = 0x36,
60 | SystemNumaProcessorMap = 0x37,
61 | SystemPrefetcherInformation = 0x38,
62 | SystemExtendedProcessInformation = 0x39,
63 | SystemRecommendedSharedDataAlignment = 0x3a,
64 | SystemComPlusPackage = 0x3b,
65 | SystemNumaAvailableMemory = 0x3c,
66 | SystemProcessorPowerInformation = 0x3d,
67 | SystemEmulationBasicInformation = 0x3e,
68 | SystemEmulationProcessorInformation = 0x3f,
69 | SystemExtendedHandleInformation = 0x40,
70 | SystemLostDelayedWriteInformation = 0x41,
71 | SystemBigPoolInformation = 0x42,
72 | SystemSessionPoolTagInformation = 0x43,
73 | SystemSessionMappedViewInformation = 0x44,
74 | SystemHotpatchInformation = 0x45,
75 | SystemObjectSecurityMode = 0x46,
76 | SystemWatchdogTimerHandler = 0x47,
77 | SystemWatchdogTimerInformation = 0x48,
78 | SystemLogicalProcessorInformation = 0x49,
79 | SystemWow64SharedInformationObsolete = 0x4a,
80 | SystemRegisterFirmwareTableInformationHandler = 0x4b,
81 | SystemFirmwareTableInformation = 0x4c,
82 | SystemModuleInformationEx = 0x4d,
83 | SystemVerifierTriageInformation = 0x4e,
84 | SystemSuperfetchInformation = 0x4f,
85 | SystemMemoryListInformation = 0x50,
86 | SystemFileCacheInformationEx = 0x51,
87 | SystemThreadPriorityClientIdInformation = 0x52,
88 | SystemProcessorIdleCycleTimeInformation = 0x53,
89 | SystemVerifierCancellationInformation = 0x54,
90 | SystemProcessorPowerInformationEx = 0x55,
91 | SystemRefTraceInformation = 0x56,
92 | SystemSpecialPoolInformation = 0x57,
93 | SystemProcessIdInformation = 0x58,
94 | SystemErrorPortInformation = 0x59,
95 | SystemBootEnvironmentInformation = 0x5a,
96 | SystemHypervisorInformation = 0x5b,
97 | SystemVerifierInformationEx = 0x5c,
98 | SystemTimeZoneInformation = 0x5d,
99 | SystemImageFileExecutionOptionsInformation = 0x5e,
100 | SystemCoverageInformation = 0x5f,
101 | SystemPrefetchPatchInformation = 0x60,
102 | SystemVerifierFaultsInformation = 0x61,
103 | SystemSystemPartitionInformation = 0x62,
104 | SystemSystemDiskInformation = 0x63,
105 | SystemProcessorPerformanceDistribution = 0x64,
106 | SystemNumaProximityNodeInformation = 0x65,
107 | SystemDynamicTimeZoneInformation = 0x66,
108 | SystemCodeIntegrityInformation = 0x67,
109 | SystemProcessorMicrocodeUpdateInformation = 0x68,
110 | SystemProcessorBrandString = 0x69,
111 | SystemVirtualAddressInformation = 0x6a,
112 | SystemLogicalProcessorAndGroupInformation = 0x6b,
113 | SystemProcessorCycleTimeInformation = 0x6c,
114 | SystemStoreInformation = 0x6d,
115 | SystemRegistryAppendString = 0x6e,
116 | SystemAitSamplingValue = 0x6f,
117 | SystemVhdBootInformation = 0x70,
118 | SystemCpuQuotaInformation = 0x71,
119 | SystemNativeBasicInformation = 0x72,
120 | SystemErrorPortTimeouts = 0x73,
121 | SystemLowPriorityIoInformation = 0x74,
122 | SystemBootEntropyInformation = 0x75,
123 | SystemVerifierCountersInformation = 0x76,
124 | SystemPagedPoolInformationEx = 0x77,
125 | SystemSystemPtesInformationEx = 0x78,
126 | SystemNodeDistanceInformation = 0x79,
127 | SystemAcpiAuditInformation = 0x7a,
128 | SystemBasicPerformanceInformation = 0x7b,
129 | SystemQueryPerformanceCounterInformation = 0x7c,
130 | SystemSessionBigPoolInformation = 0x7d,
131 | SystemBootGraphicsInformation = 0x7e,
132 | SystemScrubPhysicalMemoryInformation = 0x7f,
133 | SystemBadPageInformation = 0x80,
134 | SystemProcessorProfileControlArea = 0x81,
135 | SystemCombinePhysicalMemoryInformation = 0x82,
136 | SystemEntropyInterruptTimingInformation = 0x83,
137 | SystemConsoleInformation = 0x84,
138 | SystemPlatformBinaryInformation = 0x85,
139 | SystemThrottleNotificationInformation = 0x86,
140 | SystemHypervisorProcessorCountInformation = 0x87,
141 | SystemDeviceDataInformation = 0x88,
142 | SystemDeviceDataEnumerationInformation = 0x89,
143 | SystemMemoryTopologyInformation = 0x8a,
144 | SystemMemoryChannelInformation = 0x8b,
145 | SystemBootLogoInformation = 0x8c,
146 | SystemProcessorPerformanceInformationEx = 0x8d,
147 | SystemSpare0 = 0x8e,
148 | SystemSecureBootPolicyInformation = 0x8f,
149 | SystemPageFileInformationEx = 0x90,
150 | SystemSecureBootInformation = 0x91,
151 | SystemEntropyInterruptTimingRawInformation = 0x92,
152 | SystemPortableWorkspaceEfiLauncherInformation = 0x93,
153 | SystemFullProcessInformation = 0x94,
154 | SystemKernelDebuggerInformationEx = 0x95,
155 | SystemBootMetadataInformation = 0x96,
156 | SystemSoftRebootInformation = 0x97,
157 | SystemElamCertificateInformation = 0x98,
158 | SystemOfflineDumpConfigInformation = 0x99,
159 | SystemProcessorFeaturesInformation = 0x9a,
160 | SystemRegistryReconciliationInformation = 0x9b,
161 | MaxSystemInfoClass = 0x9c,
162 | } SYSTEM_INFORMATION_CLASS;
163 |
164 | typedef struct _SYSTEM_MODULE // Information Class 11
165 | {
166 | ULONG_PTR Reserved[2];
167 | PVOID Base;
168 | ULONG Size;
169 | ULONG Flags;
170 | USHORT Index;
171 | USHORT Unknown;
172 | USHORT LoadCount;
173 | USHORT ModuleNameOffset;
174 | CHAR ImageName[256];
175 | } SYSTEM_MODULE, * PSYSTEM_MODULE;
176 |
177 | NTKERNELAPI NTSTATUS MmCopyVirtualMemory(
178 | IN PEPROCESS SourceProcess,
179 | IN PVOID SourceAddress,
180 | IN PEPROCESS TargetProcess,
181 | IN PVOID TargetAddress,
182 | IN SIZE_T BufferSize,
183 | IN KPROCESSOR_MODE PreviousMode,
184 | OUT PSIZE_T ReturnSize
185 | );
186 |
187 | NTKERNELAPI PVOID PsGetProcessSectionBaseAddress(
188 | IN PEPROCESS Process
189 | );
190 |
191 | NTKERNELAPI NTSTATUS ZwQuerySystemInformation(
192 | SYSTEM_INFORMATION_CLASS SystemInformationClass,
193 | PVOID SystemInformation,
194 | ULONG SystemInformationLength,
195 | PULONG ReturnLength
196 | );
197 |
198 | NTSYSCALLAPI NTSTATUS NTAPI ZwProtectVirtualMemory(HANDLE ProcessHandle, PVOID* BaseAddress, PSIZE_T RegionSize, ULONG NewAccessProtection, PULONG OldAccessProtection);
199 |
200 | NTSYSAPI ULONG RtlRandomEx(
201 | PULONG Seed
202 | );
203 |
204 | NTKERNELAPI PPEB NTAPI PsGetProcessPeb(PEPROCESS Process);
205 |
206 | typedef struct _PEB_LDR_DATA
207 | {
208 | ULONG Length;
209 | UCHAR Initialized;
210 | PVOID SsHandle;
211 | LIST_ENTRY InLoadOrderModuleList;
212 | LIST_ENTRY InMemoryOrderModuleList;
213 | LIST_ENTRY InInitializationOrderModuleList;
214 | } PEB_LDR_DATA, * PPEB_LDR_DATA;
215 |
216 | typedef struct _LDR_DATA_TABLE_ENTRY
217 | {
218 | LIST_ENTRY InLoadOrderLinks;
219 | LIST_ENTRY InMemoryOrderLinks;
220 | LIST_ENTRY InInitializationOrderLinks;
221 | PVOID DllBase;
222 | PVOID EntryPoint;
223 | ULONG SizeOfImage;
224 | UNICODE_STRING FullDllName;
225 | UNICODE_STRING BaseDllName;
226 | ULONG Flags;
227 | USHORT LoadCount;
228 | USHORT TlsIndex;
229 | LIST_ENTRY HashLinks;
230 | ULONG TimeDateStamp;
231 | } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY;
232 |
233 | typedef struct _PEB
234 | {
235 | UCHAR InheritedAddressSpace;
236 | UCHAR ReadImageFileExecOptions;
237 | UCHAR BeingDebugged;
238 | UCHAR BitField;
239 | PVOID Mutant;
240 | PVOID ImageBaseAddress;
241 | PPEB_LDR_DATA Ldr;
242 | PVOID ProcessParameters;
243 | PVOID SubSystemData;
244 | PVOID ProcessHeap;
245 | PVOID FastPebLock;
246 | PVOID AtlThunkSListPtr;
247 | PVOID IFEOKey;
248 | PVOID CrossProcessFlags;
249 | PVOID KernelCallbackTable;
250 | ULONG SystemReserved;
251 | ULONG AtlThunkSListPtr32;
252 | PVOID ApiSetMap;
253 | } PEB, * PPEB;
--------------------------------------------------------------------------------
/driver/intdefs.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | typedef int SOCKET;
4 |
5 | #define INVALID_SOCKET (SOCKET)(-1)
6 | #define SOCKET_ERROR -1
7 |
8 | typedef __int8 int8_t;
9 | typedef __int16 int16_t;
10 | typedef __int32 int32_t;
11 | typedef __int64 int64_t;
12 |
13 | typedef unsigned __int8 uint8_t;
14 | typedef unsigned __int16 uint16_t;
15 | typedef unsigned __int32 uint32_t;
16 | typedef unsigned __int64 uint64_t;
17 |
18 | typedef uint8_t bool;
--------------------------------------------------------------------------------
/driver/ksocket.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | //////////////////////////////////////////////////////////////////////////
4 | // Definitions.
5 | //////////////////////////////////////////////////////////////////////////
6 |
7 | #define MEMORY_TAG ' sK'
8 |
9 | //////////////////////////////////////////////////////////////////////////
10 | // Structures.
11 | //////////////////////////////////////////////////////////////////////////
12 |
13 | typedef struct _KSOCKET_ASYNC_CONTEXT
14 | {
15 | KEVENT CompletionEvent;
16 | PIRP Irp;
17 | } KSOCKET_ASYNC_CONTEXT, * PKSOCKET_ASYNC_CONTEXT;
18 |
19 | typedef struct _KSOCKET
20 | {
21 | PWSK_SOCKET WskSocket;
22 |
23 | union
24 | {
25 | PVOID WskDispatch;
26 |
27 | PWSK_PROVIDER_CONNECTION_DISPATCH WskConnectionDispatch;
28 | PWSK_PROVIDER_LISTEN_DISPATCH WskListenDispatch;
29 | PWSK_PROVIDER_DATAGRAM_DISPATCH WskDatagramDispatch;
30 | #if (NTDDI_VERSION >= NTDDI_WIN10_RS2)
31 | PWSK_PROVIDER_STREAM_DISPATCH WskStreamDispatch;
32 | #endif
33 | };
34 |
35 | KSOCKET_ASYNC_CONTEXT AsyncContext;
36 | } KSOCKET, * PKSOCKET;
37 |
38 | //////////////////////////////////////////////////////////////////////////
39 | // Variables.
40 | //////////////////////////////////////////////////////////////////////////
41 |
42 | WSK_REGISTRATION WskRegistration;
43 | WSK_PROVIDER_NPI WskProvider;
44 | WSK_CLIENT_DISPATCH WskDispatch = { MAKE_WSK_VERSION(1,0), 0, NULL };
45 |
46 | //////////////////////////////////////////////////////////////////////////
47 | // Function prototypes.
48 | //////////////////////////////////////////////////////////////////////////
49 |
50 | NTSTATUS
51 | NTAPI
52 | KspAsyncContextAllocate(
53 | _Out_ PKSOCKET_ASYNC_CONTEXT AsyncContext
54 | );
55 |
56 | VOID
57 | NTAPI
58 | KspAsyncContextFree(
59 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext
60 | );
61 |
62 | VOID
63 | NTAPI
64 | KspAsyncContextReset(
65 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext
66 | );
67 |
68 | NTSTATUS
69 | NTAPI
70 | KspAsyncContextCompletionRoutine(
71 | _In_ PDEVICE_OBJECT DeviceObject,
72 | _In_ PIRP Irp,
73 | _In_ PKEVENT CompletionEvent
74 | );
75 |
76 | NTSTATUS
77 | NTAPI
78 | KspAsyncContextWaitForCompletion(
79 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext,
80 | _Inout_ PNTSTATUS Status
81 | );
82 |
83 | //////////////////////////////////////////////////////////////////////////
84 | // Private functions.
85 | //////////////////////////////////////////////////////////////////////////
86 |
87 | NTSTATUS
88 | NTAPI
89 | KspAsyncContextAllocate(
90 | _Out_ PKSOCKET_ASYNC_CONTEXT AsyncContext
91 | )
92 | {
93 | //
94 | // Initialize the completion event.
95 | //
96 |
97 | KeInitializeEvent(
98 | &AsyncContext->CompletionEvent,
99 | SynchronizationEvent,
100 | FALSE
101 | );
102 |
103 | //
104 | // Initialize the IRP.
105 | //
106 |
107 | AsyncContext->Irp = IoAllocateIrp(1, FALSE);
108 |
109 | if (AsyncContext->Irp == NULL)
110 | {
111 | return STATUS_INSUFFICIENT_RESOURCES;
112 | }
113 |
114 | //
115 | // KspAsyncContextCompletionRoutine will set
116 | // the CompletionEvent.
117 | //
118 |
119 | IoSetCompletionRoutine(
120 | AsyncContext->Irp,
121 | &KspAsyncContextCompletionRoutine,
122 | &AsyncContext->CompletionEvent,
123 | TRUE,
124 | TRUE,
125 | TRUE
126 | );
127 |
128 | return STATUS_SUCCESS;
129 | }
130 |
131 | VOID
132 | NTAPI
133 | KspAsyncContextFree(
134 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext
135 | )
136 | {
137 | //
138 | // Free the IRP.
139 | //
140 |
141 | IoFreeIrp(AsyncContext->Irp);
142 | }
143 |
144 | VOID
145 | NTAPI
146 | KspAsyncContextReset(
147 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext
148 | )
149 | {
150 | //
151 | // If the WSK application allocated the IRP, or is reusing an IRP
152 | // that it previously allocated, then it must set an IoCompletion
153 | // routine for the IRP before calling a WSK function. In this
154 | // situation, the WSK application must specify TRUE for the
155 | // InvokeOnSuccess, InvokeOnError, and InvokeOnCancel parameters that
156 | // are passed to the IoSetCompletionRoutine function to ensure that
157 | // the IoCompletion routine is always called. Furthermore, the IoCompletion
158 | // routine that is set for the IRP must always return
159 | // STATUS_MORE_PROCESSING_REQUIRED to terminate the completion processing
160 | // of the IRP. If the WSK application is done using the IRP after the
161 | // IoCompletion routine has been called, then it should call the IoFreeIrp
162 | // function to free the IRP before returning from the IoCompletion routine.
163 | // If the WSK application does not free the IRP then it can reuse the IRP
164 | // for a call to another WSK function.
165 | //
166 | // (ref: https://docs.microsoft.com/en-us/windows-hardware/drivers/network/using-irps-with-winsock-kernel-functions)
167 | //
168 |
169 | //
170 | // Reset the completion event.
171 | //
172 |
173 | KeResetEvent(&AsyncContext->CompletionEvent);
174 |
175 | //
176 | // Reuse the IRP.
177 | //
178 |
179 | IoReuseIrp(AsyncContext->Irp, STATUS_UNSUCCESSFUL);
180 |
181 | IoSetCompletionRoutine(
182 | AsyncContext->Irp,
183 | &KspAsyncContextCompletionRoutine,
184 | &AsyncContext->CompletionEvent,
185 | TRUE,
186 | TRUE,
187 | TRUE
188 | );
189 | }
190 |
191 | NTSTATUS
192 | NTAPI
193 | KspAsyncContextCompletionRoutine(
194 | _In_ PDEVICE_OBJECT DeviceObject,
195 | _In_ PIRP Irp,
196 | _In_ PKEVENT CompletionEvent
197 | )
198 | {
199 | UNREFERENCED_PARAMETER(DeviceObject);
200 | UNREFERENCED_PARAMETER(Irp);
201 |
202 | KeSetEvent(CompletionEvent, IO_NO_INCREMENT, FALSE);
203 | return STATUS_MORE_PROCESSING_REQUIRED;
204 | }
205 |
206 | NTSTATUS
207 | NTAPI
208 | KspAsyncContextWaitForCompletion(
209 | _In_ PKSOCKET_ASYNC_CONTEXT AsyncContext,
210 | _Inout_ PNTSTATUS Status
211 | )
212 | {
213 | if (*Status == STATUS_PENDING)
214 | {
215 | KeWaitForSingleObject(
216 | &AsyncContext->CompletionEvent,
217 | Executive,
218 | KernelMode,
219 | FALSE,
220 | NULL
221 | );
222 |
223 | *Status = AsyncContext->Irp->IoStatus.Status;
224 | }
225 |
226 | return *Status;
227 | }
228 |
229 | //////////////////////////////////////////////////////////////////////////
230 | // Public functions.
231 | //////////////////////////////////////////////////////////////////////////
232 |
233 | NTSTATUS
234 | NTAPI
235 | KsInitialize(
236 | VOID
237 | )
238 | {
239 | NTSTATUS Status;
240 |
241 | //
242 | // Register as a WSK client.
243 | //
244 |
245 | WSK_CLIENT_NPI WskClient;
246 | WskClient.ClientContext = NULL;
247 | WskClient.Dispatch = &WskDispatch;
248 |
249 | Status = WskRegister(&WskClient, &WskRegistration);
250 |
251 | if (!NT_SUCCESS(Status))
252 | {
253 | return Status;
254 | }
255 |
256 | //
257 | // Capture the provider NPI.
258 | //
259 |
260 | return WskCaptureProviderNPI(
261 | &WskRegistration,
262 | WSK_INFINITE_WAIT,
263 | &WskProvider
264 | );
265 | }
266 |
267 | VOID
268 | NTAPI
269 | KsDestroy(
270 | VOID
271 | )
272 | {
273 | //
274 | // Release the provider NPI instance.
275 | //
276 |
277 | WskReleaseProviderNPI(&WskRegistration);
278 |
279 | //
280 | // Deregister as a WSK client.
281 | //
282 |
283 | WskDeregister(&WskRegistration);
284 | }
285 |
286 | NTSTATUS
287 | NTAPI
288 | KsGetAddrInfo(
289 | _In_ PUNICODE_STRING NodeName,
290 | _In_ PUNICODE_STRING ServiceName,
291 | _In_ PADDRINFOEXW Hints,
292 | _Out_ PADDRINFOEXW* Result
293 | )
294 | {
295 | NTSTATUS Status;
296 |
297 | //
298 | // Allocate async context.
299 | //
300 |
301 | KSOCKET_ASYNC_CONTEXT AsyncContext;
302 | Status = KspAsyncContextAllocate(&AsyncContext);
303 |
304 | if (!NT_SUCCESS(Status))
305 | {
306 | return Status;
307 | }
308 |
309 | //
310 | // Call the WSK API.
311 | //
312 |
313 | Status = WskProvider.Dispatch->WskGetAddressInfo(
314 | WskProvider.Client, // Client
315 | NodeName, // NodeName
316 | ServiceName, // ServiceName
317 | 0, // NameSpace
318 | NULL, // Provider
319 | Hints, // Hints
320 | Result, // Result
321 | NULL, // OwningProcess
322 | NULL, // OwningThread
323 | AsyncContext.Irp // Irp
324 | );
325 |
326 | KspAsyncContextWaitForCompletion(&AsyncContext, &Status);
327 |
328 | //
329 | // Free the async context.
330 | //
331 |
332 | KspAsyncContextFree(&AsyncContext);
333 |
334 | return Status;
335 | }
336 |
337 | VOID
338 | NTAPI
339 | KsFreeAddrInfo(
340 | _In_ PADDRINFOEXW AddrInfo
341 | )
342 | {
343 | WskProvider.Dispatch->WskFreeAddressInfo(
344 | WskProvider.Client, // Client
345 | AddrInfo // AddrInfo
346 | );
347 | }
348 |
349 | NTSTATUS
350 | NTAPI
351 | KsCreateSocket(
352 | _Out_ PKSOCKET* Socket,
353 | _In_ ADDRESS_FAMILY AddressFamily,
354 | _In_ USHORT SocketType,
355 | _In_ ULONG Protocol,
356 | _In_ ULONG Flags
357 | )
358 | {
359 | NTSTATUS Status;
360 |
361 | //
362 | // Allocate memory for the socket structure.
363 | //
364 |
365 | PKSOCKET NewSocket = ExAllocatePoolWithTag(PagedPool, sizeof(KSOCKET), MEMORY_TAG);
366 |
367 | if (!NewSocket)
368 | {
369 | return STATUS_INSUFFICIENT_RESOURCES;
370 | }
371 |
372 | //
373 | // Allocate async context for the socket.
374 | //
375 |
376 | Status = KspAsyncContextAllocate(&NewSocket->AsyncContext);
377 |
378 | if (!NT_SUCCESS(Status))
379 | {
380 | return Status;
381 | }
382 |
383 | //
384 | // Create the WSK socket.
385 | //
386 |
387 | Status = WskProvider.Dispatch->WskSocket(
388 | WskProvider.Client, // Client
389 | AddressFamily, // AddressFamily
390 | SocketType, // SocketType
391 | Protocol, // Protocol
392 | Flags, // Flags
393 | NULL, // SocketContext
394 | NULL, // Dispatch
395 | NULL, // OwningProcess
396 | NULL, // OwningThread
397 | NULL, // SecurityDescriptor
398 | NewSocket->AsyncContext.Irp // Irp
399 | );
400 |
401 | KspAsyncContextWaitForCompletion(&NewSocket->AsyncContext, &Status);
402 |
403 | //
404 | // Save the socket instance and the socket dispatch table.
405 | //
406 |
407 | if (NT_SUCCESS(Status))
408 | {
409 | NewSocket->WskSocket = (PWSK_SOCKET)NewSocket->AsyncContext.Irp->IoStatus.Information;
410 | NewSocket->WskDispatch = (PVOID)NewSocket->WskSocket->Dispatch;
411 |
412 | *Socket = NewSocket;
413 | }
414 |
415 | return Status;
416 | }
417 |
418 | NTSTATUS
419 | NTAPI
420 | KsCreateConnectionSocket(
421 | _Out_ PKSOCKET* Socket,
422 | _In_ ADDRESS_FAMILY AddressFamily,
423 | _In_ USHORT SocketType,
424 | _In_ ULONG Protocol
425 | )
426 | {
427 | return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, WSK_FLAG_CONNECTION_SOCKET);
428 | }
429 |
430 | NTSTATUS
431 | NTAPI
432 | KsCreateListenSocket(
433 | _Out_ PKSOCKET* Socket,
434 | _In_ ADDRESS_FAMILY AddressFamily,
435 | _In_ USHORT SocketType,
436 | _In_ ULONG Protocol
437 | )
438 | {
439 | return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, WSK_FLAG_LISTEN_SOCKET);
440 | }
441 |
442 | NTSTATUS
443 | NTAPI
444 | KsCreateDatagramSocket(
445 | _Out_ PKSOCKET* Socket,
446 | _In_ ADDRESS_FAMILY AddressFamily,
447 | _In_ USHORT SocketType,
448 | _In_ ULONG Protocol
449 | )
450 | {
451 | return KsCreateSocket(Socket, AddressFamily, SocketType, Protocol, WSK_FLAG_DATAGRAM_SOCKET);
452 | }
453 |
454 | NTSTATUS
455 | NTAPI
456 | KsCloseSocket(
457 | _In_ PKSOCKET Socket
458 | )
459 | {
460 | NTSTATUS Status;
461 |
462 | //
463 | // Reset the async context.
464 | //
465 |
466 | KspAsyncContextReset(&Socket->AsyncContext);
467 |
468 | //
469 | // Close the WSK socket.
470 | //
471 |
472 | Status = Socket->WskConnectionDispatch->WskCloseSocket(
473 | Socket->WskSocket,
474 | Socket->AsyncContext.Irp
475 | );
476 |
477 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
478 |
479 | //
480 | // Free the async context.
481 | //
482 |
483 | KspAsyncContextFree(&Socket->AsyncContext);
484 |
485 | //
486 | // Free memory for the socket structure.
487 | //
488 |
489 | ExFreePoolWithTag(Socket, MEMORY_TAG);
490 |
491 | return Status;
492 | }
493 |
494 | NTSTATUS
495 | NTAPI
496 | KsBind(
497 | _In_ PKSOCKET Socket,
498 | _In_ PSOCKADDR LocalAddress
499 | )
500 | {
501 | NTSTATUS Status;
502 |
503 | //
504 | // Reset the async context.
505 | //
506 |
507 | KspAsyncContextReset(&Socket->AsyncContext);
508 |
509 | //
510 | // Bind the socket.
511 | //
512 |
513 | Status = Socket->WskListenDispatch->WskBind(
514 | Socket->WskSocket, // Socket
515 | LocalAddress, // LocalAddress
516 | 0, // Flags (reserved)
517 | Socket->AsyncContext.Irp // Irp
518 | );
519 |
520 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
521 |
522 | return Status;
523 | }
524 |
525 | NTSTATUS
526 | NTAPI
527 | KsAccept(
528 | _In_ PKSOCKET Socket,
529 | _Out_ PKSOCKET* NewSocket,
530 | _Out_opt_ PSOCKADDR LocalAddress,
531 | _Out_opt_ PSOCKADDR RemoteAddress
532 | )
533 | {
534 | NTSTATUS Status;
535 |
536 | //
537 | // Reset the async context.
538 | //
539 |
540 | KspAsyncContextReset(&Socket->AsyncContext);
541 |
542 | //
543 | // Accept the connection.
544 | //
545 |
546 | Status = Socket->WskListenDispatch->WskAccept(
547 | Socket->WskSocket, // ListenSocket
548 | 0, // Flags
549 | NULL, // AcceptSocketContext
550 | NULL, // AcceptSocketDispatch
551 | LocalAddress, // LocalAddress
552 | RemoteAddress, // RemoteAddress
553 | Socket->AsyncContext.Irp // Irp
554 | );
555 |
556 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
557 |
558 | //
559 | // Save the socket instance and the socket dispatch table.
560 | //
561 |
562 | if (NT_SUCCESS(Status))
563 | {
564 | PKSOCKET KNewSocket = ExAllocatePoolWithTag(PagedPool, sizeof(KSOCKET), MEMORY_TAG);
565 |
566 | if (!KNewSocket)
567 | {
568 | return STATUS_INSUFFICIENT_RESOURCES;
569 | }
570 |
571 | KNewSocket->WskSocket = (PWSK_SOCKET)Socket->AsyncContext.Irp->IoStatus.Information;
572 | KNewSocket->WskDispatch = (PVOID)KNewSocket->WskSocket->Dispatch;
573 | KspAsyncContextAllocate(&KNewSocket->AsyncContext);
574 |
575 | *NewSocket = KNewSocket;
576 | }
577 |
578 | return Status;
579 | }
580 |
581 | NTSTATUS
582 | NTAPI
583 | KsConnect(
584 | _In_ PKSOCKET Socket,
585 | _In_ PSOCKADDR RemoteAddress
586 | )
587 | {
588 | NTSTATUS Status;
589 |
590 | //
591 | // Reset the async context.
592 | //
593 |
594 | KspAsyncContextReset(&Socket->AsyncContext);
595 |
596 | //
597 | // Bind the socket to the local address.
598 | //
599 |
600 | SOCKADDR_IN LocalAddress;
601 | LocalAddress.sin_family = AF_INET;
602 | LocalAddress.sin_addr.s_addr = INADDR_ANY;
603 | LocalAddress.sin_port = 0;
604 |
605 | Status = Socket->WskConnectionDispatch->WskBind(
606 | Socket->WskSocket, // Socket
607 | (PSOCKADDR)& LocalAddress, // LocalAddress
608 | 0, // Flags (reserved)
609 | Socket->AsyncContext.Irp // Irp
610 | );
611 |
612 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
613 |
614 | if (!NT_SUCCESS(Status))
615 | {
616 | return Status;
617 | }
618 |
619 | //
620 | // Reset the async context (again).
621 | //
622 |
623 | KspAsyncContextReset(&Socket->AsyncContext);
624 |
625 | //
626 | // Connect to the remote host.
627 | //
628 | // N.B.: Instead of calling WskSocket(), WskBind() and WskConnect(),
629 | // it is possible to just call WskSocketConnect().
630 | //
631 |
632 | Status = Socket->WskConnectionDispatch->WskConnect(
633 | Socket->WskSocket, // Socket
634 | RemoteAddress, // RemoteAddress
635 | 0, // Flags (reserved)
636 | Socket->AsyncContext.Irp // Irp
637 | );
638 |
639 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
640 |
641 | return Status;
642 | }
643 |
644 | NTSTATUS
645 | NTAPI
646 | KsSendRecv(
647 | _In_ PKSOCKET Socket,
648 | _In_ PVOID Buffer,
649 | _Inout_ PULONG Length,
650 | _In_ ULONG Flags,
651 | _In_ BOOLEAN Send
652 | )
653 | {
654 | NTSTATUS Status;
655 |
656 | //
657 | // Wrap the buffer into the "WSK buffer".
658 | //
659 |
660 | WSK_BUF WskBuffer;
661 | WskBuffer.Offset = 0;
662 | WskBuffer.Length = *Length;
663 | WskBuffer.Mdl = IoAllocateMdl(Buffer, (ULONG)WskBuffer.Length, FALSE, FALSE, NULL);
664 |
665 | __try
666 | {
667 | MmProbeAndLockPages(WskBuffer.Mdl, KernelMode, IoWriteAccess);
668 | }
669 | __except (EXCEPTION_EXECUTE_HANDLER)
670 | {
671 | Status = STATUS_ACCESS_VIOLATION;
672 | goto Error;
673 | }
674 |
675 | //
676 | // Reset the async context.
677 | //
678 |
679 | KspAsyncContextReset(&Socket->AsyncContext);
680 |
681 | //
682 | // Send / receive the data.
683 | //
684 |
685 | if (Send)
686 | {
687 | Status = Socket->WskConnectionDispatch->WskSend(
688 | Socket->WskSocket, // Socket
689 | &WskBuffer, // Buffer
690 | Flags, // Flags
691 | Socket->AsyncContext.Irp // Irp
692 | );
693 | }
694 | else
695 | {
696 | Status = Socket->WskConnectionDispatch->WskReceive(
697 | Socket->WskSocket, // Socket
698 | &WskBuffer, // Buffer
699 | Flags, // Flags
700 | Socket->AsyncContext.Irp // Irp
701 | );
702 | }
703 |
704 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
705 |
706 | //
707 | // Set the number of bytes sent / received.
708 | //
709 |
710 | if (NT_SUCCESS(Status))
711 | {
712 | *Length = (ULONG)Socket->AsyncContext.Irp->IoStatus.Information;
713 | }
714 |
715 | //
716 | // Free the MDL.
717 | //
718 |
719 | MmUnlockPages(WskBuffer.Mdl);
720 |
721 | Error:
722 | IoFreeMdl(WskBuffer.Mdl);
723 | return Status;
724 | }
725 |
726 | NTSTATUS
727 | NTAPI
728 | KsSendRecvUdp(
729 | _In_ PKSOCKET Socket,
730 | _In_ PVOID Buffer,
731 | _Inout_ PULONG Length,
732 | _In_ ULONG Flags,
733 | _In_ PSOCKADDR RemoteAddress,
734 | _In_ BOOLEAN Send
735 | )
736 | {
737 | NTSTATUS Status;
738 |
739 | //
740 | // Wrap the buffer into the "WSK buffer".
741 | //
742 |
743 | WSK_BUF WskBuffer;
744 | WskBuffer.Offset = 0;
745 | WskBuffer.Length = *Length;
746 | WskBuffer.Mdl = IoAllocateMdl(Buffer, (ULONG)WskBuffer.Length, FALSE, FALSE, NULL);
747 |
748 | __try
749 | {
750 | MmProbeAndLockPages(WskBuffer.Mdl, KernelMode, IoWriteAccess);
751 | }
752 | __except (EXCEPTION_EXECUTE_HANDLER)
753 | {
754 | Status = STATUS_ACCESS_VIOLATION;
755 | goto Error;
756 | }
757 |
758 | //
759 | // Reset the async context.
760 | //
761 |
762 | KspAsyncContextReset(&Socket->AsyncContext);
763 |
764 | //
765 | // Send / receive the data.
766 | //
767 |
768 | if (Send)
769 | {
770 | Status = Socket->WskDatagramDispatch->WskSendTo(
771 | Socket->WskSocket, // Socket
772 | &WskBuffer, // Buffer
773 | Flags, // Flags (reserved)
774 | RemoteAddress, // RemoteAddress
775 | 0, // ControlInfoLength
776 | NULL, // ControlInfo
777 | Socket->AsyncContext.Irp // Irp
778 | );
779 | }
780 | else
781 | {
782 | //
783 | // Use #pragma prefast (suppress: ...), because SAL annotation is wrong
784 | // for this function.
785 | //
786 | // From MSDN:
787 | // ControlLength
788 | // ControlInfo
789 | //
790 | // ... This pointer is optional and can be NULL. If the ControlInfoLength
791 | // parameter is NULL, the ControlInfo parameter should be NULL.
792 | //
793 |
794 | #pragma prefast ( \
795 | suppress:__WARNING_INVALID_PARAM_VALUE_1, \
796 | "If the ControlInfoLength parameter is NULL, the ControlInfo parameter should be NULL." \
797 | )
798 |
799 | Status = Socket->WskDatagramDispatch->WskReceiveFrom(
800 | Socket->WskSocket, // Socket
801 | &WskBuffer, // Buffer
802 | Flags, // Flags (reserved)
803 | RemoteAddress, // RemoteAddress
804 | NULL, // ControlInfoLength
805 | NULL, // ControlInfo
806 | NULL, // ControlFlags
807 | Socket->AsyncContext.Irp // Irp
808 | );
809 | }
810 |
811 | KspAsyncContextWaitForCompletion(&Socket->AsyncContext, &Status);
812 |
813 | //
814 | // Set the number of bytes sent / received.
815 | //
816 |
817 | if (NT_SUCCESS(Status))
818 | {
819 | *Length = (ULONG)Socket->AsyncContext.Irp->IoStatus.Information;
820 | }
821 |
822 | //
823 | // Free the MDL.
824 | //
825 |
826 | MmUnlockPages(WskBuffer.Mdl);
827 |
828 | Error:
829 | IoFreeMdl(WskBuffer.Mdl);
830 | return Status;
831 | }
832 |
833 | NTSTATUS
834 | NTAPI
835 | KsSend(
836 | _In_ PKSOCKET Socket,
837 | _In_ PVOID Buffer,
838 | _Inout_ PULONG Length,
839 | _In_ ULONG Flags
840 | )
841 | {
842 | return KsSendRecv(Socket, Buffer, Length, Flags, TRUE);
843 | }
844 |
845 | NTSTATUS
846 | NTAPI
847 | KsRecv(
848 | _In_ PKSOCKET Socket,
849 | _In_ PVOID Buffer,
850 | _Inout_ PULONG Length,
851 | _In_ ULONG Flags
852 | )
853 | {
854 | return KsSendRecv(Socket, Buffer, Length, Flags, FALSE);
855 | }
856 |
857 | NTSTATUS
858 | NTAPI
859 | KsSendTo(
860 | _In_ PKSOCKET Socket,
861 | _In_ PVOID Buffer,
862 | _Inout_ PULONG Length,
863 | _In_ ULONG Flags,
864 | _In_ PSOCKADDR RemoteAddress
865 | )
866 | {
867 | return KsSendRecvUdp(Socket, Buffer, Length, Flags, RemoteAddress, TRUE);
868 | }
869 |
870 | NTSTATUS
871 | NTAPI
872 | KsRecvFrom(
873 | _In_ PKSOCKET Socket,
874 | _In_ PVOID Buffer,
875 | _Inout_ PULONG Length,
876 | _In_ ULONG Flags,
877 | _In_ PSOCKADDR RemoteAddress
878 | )
879 | {
880 | return KsSendRecvUdp(Socket, Buffer, Length, Flags, RemoteAddress, FALSE);
881 | }
--------------------------------------------------------------------------------
/driver/ksocket.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 |
7 | typedef struct _KSOCKET KSOCKET, * PKSOCKET;
8 |
9 | NTSTATUS
10 | NTAPI
11 | KsInitialize(
12 | VOID
13 | );
14 |
15 | VOID
16 | NTAPI
17 | KsDestroy(
18 | VOID
19 | );
20 |
21 | NTSTATUS
22 | NTAPI
23 | KsGetAddrInfo(
24 | _In_ PUNICODE_STRING NodeName,
25 | _In_ PUNICODE_STRING ServiceName,
26 | _In_ PADDRINFOEXW Hints,
27 | _Out_ PADDRINFOEXW* Result
28 | );
29 |
30 | VOID
31 | NTAPI
32 | KsFreeAddrInfo(
33 | _In_ PADDRINFOEXW AddrInfo
34 | );
35 |
36 | NTSTATUS
37 | NTAPI
38 | KsCreateSocket(
39 | _Out_ PKSOCKET* Socket,
40 | _In_ ADDRESS_FAMILY AddressFamily,
41 | _In_ USHORT SocketType,
42 | _In_ ULONG Protocol,
43 | _In_ ULONG Flags
44 | );
45 |
46 | NTSTATUS
47 | NTAPI
48 | KsCreateConnectionSocket(
49 | _Out_ PKSOCKET* Socket,
50 | _In_ ADDRESS_FAMILY AddressFamily,
51 | _In_ USHORT SocketType,
52 | _In_ ULONG Protocol
53 | );
54 |
55 | NTSTATUS
56 | NTAPI
57 | KsCreateListenSocket(
58 | _Out_ PKSOCKET* Socket,
59 | _In_ ADDRESS_FAMILY AddressFamily,
60 | _In_ USHORT SocketType,
61 | _In_ ULONG Protocol
62 | );
63 |
64 | NTSTATUS
65 | NTAPI
66 | KsCreateDatagramSocket(
67 | _Out_ PKSOCKET* Socket,
68 | _In_ ADDRESS_FAMILY AddressFamily,
69 | _In_ USHORT SocketType,
70 | _In_ ULONG Protocol
71 | );
72 |
73 | NTSTATUS
74 | NTAPI
75 | KsCloseSocket(
76 | _In_ PKSOCKET Socket
77 | );
78 |
79 | NTSTATUS
80 | NTAPI
81 | KsBind(
82 | _In_ PKSOCKET Socket,
83 | _In_ PSOCKADDR LocalAddress
84 | );
85 |
86 | NTSTATUS
87 | NTAPI
88 | KsAccept(
89 | _In_ PKSOCKET Socket,
90 | _Out_ PKSOCKET* NewSocket,
91 | _Out_opt_ PSOCKADDR LocalAddress,
92 | _Out_opt_ PSOCKADDR RemoteAddress
93 | );
94 |
95 | NTSTATUS
96 | NTAPI
97 | KsConnect(
98 | _In_ PKSOCKET Socket,
99 | _In_ PSOCKADDR RemoteAddress
100 | );
101 |
102 | NTSTATUS
103 | NTAPI
104 | KsSendRecv(
105 | _In_ PKSOCKET Socket,
106 | _In_ PVOID Buffer,
107 | _Inout_ PULONG Length,
108 | _In_ ULONG Flags,
109 | _In_ BOOLEAN Send
110 | );
111 |
112 | NTSTATUS
113 | NTAPI
114 | KsSendRecvUdp(
115 | _In_ PKSOCKET Socket,
116 | _In_ PVOID Buffer,
117 | _Inout_ PULONG Length,
118 | _In_ ULONG Flags,
119 | _In_ PSOCKADDR RemoteAddress,
120 | _In_ BOOLEAN Send
121 | );
122 |
123 | NTSTATUS
124 | NTAPI
125 | KsSend(
126 | _In_ PKSOCKET Socket,
127 | _In_ PVOID Buffer,
128 | _Inout_ PULONG Length,
129 | _In_ ULONG Flags
130 | );
131 |
132 | NTSTATUS
133 | NTAPI
134 | KsRecv(
135 | _In_ PKSOCKET Socket,
136 | _In_ PVOID Buffer,
137 | _Inout_ PULONG Length,
138 | _In_ ULONG Flags
139 | );
140 |
141 | NTSTATUS
142 | NTAPI
143 | KsSendTo(
144 | _In_ PKSOCKET Socket,
145 | _In_ PVOID Buffer,
146 | _Inout_ PULONG Length,
147 | _In_ ULONG Flags,
148 | _In_ PSOCKADDR RemoteAddress
149 | );
150 |
151 | NTSTATUS
152 | NTAPI
153 | KsRecvFrom(
154 | _In_ PKSOCKET Socket,
155 | _In_ PVOID Buffer,
156 | _Inout_ PULONG Length,
157 | _In_ ULONG Flags,
158 | _In_ PSOCKADDR RemoteAddress
159 | );
160 |
161 | #ifdef __cplusplus
162 | }
163 | #endif
--------------------------------------------------------------------------------
/driver/main.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | void start(void* context)
4 | {
5 | log("Thread started.\n");
6 |
7 | initialize_server(55123ui16);
8 |
9 | return;
10 | }
11 |
12 | NTSTATUS DriverEntry(PDRIVER_OBJECT driver_object, PUNICODE_STRING registry_path)
13 | {
14 | HANDLE thread_handle;
15 | auto result = PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, 0, 0, 0, start, 0);
16 |
17 | return result;
18 | }
--------------------------------------------------------------------------------
/driver/server.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | SOCKET create_server_socket(uint16_t port)
4 | {
5 | SOCKADDR_IN address;
6 |
7 | address.sin_family = AF_INET;
8 | address.sin_addr.s_addr = htonl(server_ip);
9 | address.sin_port = htons(port);
10 |
11 | SOCKET sockfd = socket_listen(AF_INET, SOCK_STREAM, 0);
12 | if (sockfd == INVALID_SOCKET)
13 | {
14 | log("Failed to create a valid server socket.\n");
15 |
16 | return INVALID_SOCKET;
17 | }
18 |
19 | if (bind(sockfd, (SOCKADDR*)&address, sizeof(address)) == SOCKET_ERROR)
20 | {
21 | log("Failed to bind the server socket.\n");
22 |
23 | closesocket(sockfd);
24 | return INVALID_SOCKET;
25 | }
26 |
27 | if (listen(sockfd, 10) == SOCKET_ERROR)
28 | {
29 | log("Failed to start listening in on the server socket.\n");
30 |
31 | closesocket(sockfd);
32 | return INVALID_SOCKET;
33 | }
34 |
35 | return sockfd;
36 | }
37 |
38 | void initialize_server(uint16_t port)
39 | {
40 | NTSTATUS status = KsInitialize();
41 |
42 | if (!NT_SUCCESS(status))
43 | {
44 | log("Failed to initialize KSOCKET.\n");
45 |
46 | return;
47 | }
48 |
49 | SOCKET server_socket = create_server_socket(port);
50 |
51 | if (server_socket == INVALID_SOCKET)
52 | {
53 | log("Failed to initialize the server socket.\n");
54 |
55 | KsDestroy();
56 | return;
57 | }
58 |
59 | log("Listening on port %d\n", port);
60 |
61 | while (TRUE)
62 | {
63 | struct sockaddr socket_addr;
64 | socklen_t socket_length;
65 |
66 | SOCKET client_connection = accept(server_socket, &socket_addr, &socket_length);
67 |
68 | if (client_connection == INVALID_SOCKET)
69 | {
70 | log("Failed to accept client connection.\n", port);
71 | }
72 | else
73 | {
74 | HANDLE thread_handle;
75 | PsCreateSystemThread(&thread_handle, THREAD_ALL_ACCESS, 0, 0, 0, server_thread, &client_connection);
76 | }
77 | }
78 |
79 | log("The main thread has terminated...\n");
80 |
81 | closesocket(server_socket);
82 | }
83 |
84 | uint64_t handle_ping(data_packet_t packet)
85 | {
86 | log("Received ping packet! %d\n", packet.data.ping.ping_magic);
87 |
88 | return packet.data.ping.ping_magic + 1;
89 | }
90 |
91 | uint64_t handle_copy_memory(data_packet_t packet)
92 | {
93 | SIZE_T return_size = 0ull;
94 | PEPROCESS source, target;
95 |
96 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.copy_memory.source_pid, &source)) &&
97 | NT_SUCCESS(PsLookupProcessByProcessId(packet.data.copy_memory.target_pid, &target)))
98 | {
99 | bool source_valid = FALSE;
100 | bool target_valid = FALSE;
101 |
102 | KAPC_STATE kapc;
103 | KeStackAttachProcess(source, &kapc);
104 | {
105 | source_valid = MmIsAddressValid(packet.data.copy_memory.source_address);
106 | }
107 | KeUnstackDetachProcess(&kapc);
108 |
109 | KeStackAttachProcess(target, &kapc);
110 | {
111 | target_valid = MmIsAddressValid(packet.data.copy_memory.target_address);
112 | }
113 | KeUnstackDetachProcess(&kapc);
114 |
115 | if (target_valid && source_valid)
116 | {
117 | MmCopyVirtualMemory(source, (PVOID)packet.data.copy_memory.source_address, target,
118 | (PVOID)packet.data.copy_memory.target_address, packet.data.copy_memory.size, KernelMode, &return_size);
119 | }
120 |
121 | ObDereferenceObject(source);
122 | ObDereferenceObject(target);
123 | }
124 |
125 | return return_size;
126 | }
127 |
128 | uint64_t handle_allocate(data_packet_t packet)
129 | {
130 | PVOID base_address = 0;
131 | PEPROCESS target;
132 |
133 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.allocate_memory.target_pid, &target)))
134 | {
135 | KAPC_STATE kapc;
136 | KeStackAttachProcess(target, &kapc);
137 | {
138 | ZwAllocateVirtualMemory(ZwCurrentProcess(), &base_address, 0, &packet.data.allocate_memory.size,
139 | packet.data.allocate_memory.allocation_type, packet.data.allocate_memory.protection);
140 | }
141 | KeUnstackDetachProcess(&kapc);
142 |
143 | ObDereferenceObject(target);
144 | }
145 |
146 | return base_address;
147 | }
148 |
149 | uint64_t handle_free(data_packet_t packet)
150 | {
151 | NTSTATUS result;
152 | PEPROCESS target;
153 |
154 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.free_memory.target_pid, &target)))
155 | {
156 | KAPC_STATE kapc;
157 | KeStackAttachProcess(target, &kapc);
158 | {
159 | result = ZwFreeVirtualMemory(ZwCurrentProcess(), &packet.data.free_memory.target_address,
160 | &packet.data.free_memory.region_size, MEM_RELEASE);
161 | }
162 | KeUnstackDetachProcess(&kapc);
163 |
164 | ObDereferenceObject(target);
165 | }
166 |
167 | return result;
168 | }
169 |
170 | uint64_t handle_protect(data_packet_t packet)
171 | {
172 | uint64_t result = 0ull;
173 | PEPROCESS target;
174 |
175 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.protect_memory.target_pid, &target)))
176 | {
177 | KAPC_STATE kapc;
178 | KeStackAttachProcess(target, &kapc);
179 | {
180 | ZwProtectVirtualMemory(ZwCurrentProcess(), &packet.data.protect_memory.target_address,
181 | &packet.data.protect_memory.size, packet.data.protect_memory.new_protection, &result);
182 | }
183 | KeUnstackDetachProcess(&kapc);
184 |
185 | ObDereferenceObject(target);
186 | }
187 |
188 | return result;
189 | }
190 |
191 | uint64_t handle_get_base(data_packet_t packet)
192 | {
193 | uint64_t result = 0ull;
194 | PEPROCESS target;
195 |
196 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.get_base.target_pid, &target)))
197 | {
198 | KAPC_STATE kapc;
199 | KeStackAttachProcess(target, &kapc);
200 | {
201 | PLDR_DATA_TABLE_ENTRY entry = get_module_by_name_x64(target, packet.data.get_base.module_name);
202 |
203 | if (entry)
204 | {
205 | result = entry->DllBase;
206 | }
207 | }
208 | KeUnstackDetachProcess(&kapc);
209 |
210 | ObDereferenceObject(target);
211 | }
212 |
213 | return result;
214 | }
215 |
216 | uint64_t handle_get_size(data_packet_t packet)
217 | {
218 | uint64_t result = 0ull;
219 | PEPROCESS target;
220 |
221 | if (NT_SUCCESS(PsLookupProcessByProcessId(packet.data.get_size.target_pid, &target)))
222 | {
223 | KAPC_STATE kapc;
224 | KeStackAttachProcess(target, &kapc);
225 | {
226 | PLDR_DATA_TABLE_ENTRY entry = get_module_by_name_x64(target, packet.data.get_size.module_name);
227 |
228 | if (entry)
229 | {
230 | result = entry->SizeOfImage;
231 | }
232 | }
233 | KeUnstackDetachProcess(&kapc);
234 |
235 | ObDereferenceObject(target);
236 | }
237 |
238 | return result;
239 | }
240 |
241 | uint64_t handle_packet(data_packet_t packet)
242 | {
243 | uint64_t result = 0ull;
244 |
245 | switch (packet.header.type)
246 | {
247 | case ping:
248 | result = handle_ping(packet);
249 | break;
250 |
251 | case packet_copy_memory:
252 | result = handle_copy_memory(packet);
253 | break;
254 |
255 | case packet_allocate:
256 | result = handle_allocate(packet);
257 | break;
258 |
259 | case packet_free:
260 | result = handle_free(packet);
261 | break;
262 |
263 | case packet_protect:
264 | result = handle_protect(packet);
265 | break;
266 |
267 | case packet_get_base:
268 | result = handle_get_base(packet);
269 | break;
270 |
271 | case packet_get_size:
272 | result = handle_get_size(packet);
273 | break;
274 |
275 | default:
276 | log("Received unknown packet.\n");
277 | break;
278 | }
279 |
280 | return result;
281 | }
282 |
283 | bool answer_client(SOCKET sockfd, uint64_t result)
284 | {
285 | data_packet_t packet;
286 | packet.header.magic_header = magic_header_value;
287 | packet.header.type = completed;
288 | packet.data.response.data = result;
289 |
290 | return send(sockfd, &packet, sizeof(packet), 0) != SOCKET_ERROR;
291 | }
292 |
293 | void server_thread(SOCKET* sockfd)
294 | {
295 | log("Connection received, server thread spawned.\n");
296 |
297 |
298 | SOCKET connection = *sockfd;
299 |
300 | data_packet_t packet;
301 |
302 | while (TRUE)
303 | {
304 | int result = recv(connection, (void*)&packet, sizeof(packet), 0);
305 |
306 | if (result > 0 && result >= sizeof(packet.header) && packet.header.magic_header == magic_header_value)
307 | {
308 | uint64_t packet_result = handle_packet(packet);
309 |
310 | if (!answer_client(connection, packet_result))
311 | {
312 | break;
313 | }
314 | }
315 | }
316 |
317 | log("A server thread has terminated...\n");
318 | }
319 |
--------------------------------------------------------------------------------
/driver/server.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define magic_header_value 0x59da412859da4128
4 | #define server_ip 0x7F000001 // localhost
5 |
6 | enum e_packet_type
7 | {
8 | packet_get_base,
9 | packet_get_size,
10 | packet_copy_memory,
11 | packet_allocate,
12 | packet_free,
13 | packet_protect,
14 | completed,
15 | ping
16 | };
17 |
18 | typedef struct _packet_header_t
19 | {
20 | uint64_t magic_header;
21 | int type;
22 | } packet_header_t, *lpacket_header_t;
23 |
24 | typedef struct _packet_response_t
25 | {
26 | uint64_t data;
27 | } packet_response_t, *lpacket_response_t;
28 |
29 | typedef struct _packet_ping_t
30 | {
31 | int32_t ping_magic;
32 | } packet_ping_t, *lpacket_ping_t;
33 |
34 | typedef struct _packet_copy_memory_t
35 | {
36 | uint32_t source_pid;
37 | uint64_t source_address;
38 | uint32_t target_pid;
39 | uint64_t target_address;
40 | size_t size;
41 | } packet_copy_memory_t, *lpacket_copy_memory_t;
42 |
43 | typedef struct _packet_allocate_memory_t
44 | {
45 | uint32_t target_pid;
46 | uint32_t protection;
47 | uint32_t allocation_type;
48 | size_t size;
49 | } packet_allocate_memory_t, *lpacket_allocate_memory_t;
50 |
51 | typedef struct _packet_free_memory_t
52 | {
53 | uint32_t target_pid;
54 | uint64_t target_address;
55 | size_t region_size;
56 | } packet_free_memory_t, *lpacket_free_memory_t;
57 |
58 | typedef struct _packet_protect_memory_t
59 | {
60 | uint32_t target_pid;
61 | uint64_t target_address;
62 | uint32_t new_protection;
63 | size_t size;
64 | } packet_protect_memory_t, *lpacket_protect_memory_t;
65 |
66 | typedef struct _packet_get_base_t
67 | {
68 | uint32_t target_pid;
69 | wchar_t module_name[64];
70 | } packet_get_base_t, *lpacket_get_base_t;
71 |
72 | typedef struct _packet_get_size_t
73 | {
74 | uint32_t target_pid;
75 | wchar_t module_name[64];
76 | } packet_get_size_t, *lpacket_get_size_t;
77 |
78 | typedef struct _data_packet_t
79 | {
80 | packet_header_t header;
81 | union
82 | {
83 | packet_response_t response;
84 | packet_ping_t ping;
85 | packet_copy_memory_t copy_memory;
86 | packet_allocate_memory_t allocate_memory;
87 | packet_free_memory_t free_memory;
88 | packet_protect_memory_t protect_memory;
89 | packet_get_base_t get_base;
90 | packet_get_size_t get_size;
91 | } data;
92 | } data_packet_t, *lpdata_packet_t;
93 |
94 | // server initialization
95 | SOCKET create_server_socket(uint16_t port);
96 | void initialize_server(uint16_t port);
97 |
98 | // specific handlers
99 | uint64_t handle_ping(data_packet_t packet);
100 | uint64_t handle_copy_memory(data_packet_t packet);
101 | uint64_t handle_allocate(data_packet_t packet);
102 | uint64_t handle_free(data_packet_t packet);
103 | uint64_t handle_protect(data_packet_t packet);
104 | uint64_t handle_get_base(data_packet_t packet);
105 | uint64_t handle_get_size(data_packet_t packet);
106 |
107 | // master handler(s)
108 | uint64_t handle_packet(data_packet_t packet);
109 | bool answer_client(SOCKET sockfd, uint64_t result);
110 | void server_thread(SOCKET* sockfd);
--------------------------------------------------------------------------------
/driver/utils.c:
--------------------------------------------------------------------------------
1 | #include "common.h"
2 |
3 | PLDR_DATA_TABLE_ENTRY get_module_by_name_x64(PEPROCESS process, wchar_t* module_name)
4 | {
5 | UNICODE_STRING module_name_unicode = { 0 };
6 | RtlInitUnicodeString(&module_name_unicode, module_name);
7 |
8 | PLIST_ENTRY list = &(PsGetProcessPeb(process)->Ldr->InLoadOrderModuleList);
9 |
10 | for (PLIST_ENTRY entry = list->Flink; entry != list; )
11 | {
12 | PLDR_DATA_TABLE_ENTRY module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
13 |
14 | if (RtlCompareUnicodeString(&module->BaseDllName, &module_name_unicode, TRUE) == 0)
15 | {
16 | return module;
17 | }
18 |
19 | entry = module->InLoadOrderLinks.Flink;
20 | }
21 |
22 | return NULL;
23 | }
--------------------------------------------------------------------------------
/driver/utils.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | PLDR_DATA_TABLE_ENTRY get_module_by_name_x64(PEPROCESS process, wchar_t* module_name);
--------------------------------------------------------------------------------
/kersock.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.31005.135
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "client", "client\client.vcxproj", "{81699472-E045-4DF8-99A1-72936EE445EE}"
7 | EndProject
8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "driver", "driver\driver.vcxproj", "{6AA61830-4BA3-4097-B4FF-EA62F47D98D6}"
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 | {81699472-E045-4DF8-99A1-72936EE445EE}.Debug|x64.ActiveCfg = Debug|x64
17 | {81699472-E045-4DF8-99A1-72936EE445EE}.Debug|x64.Build.0 = Debug|x64
18 | {81699472-E045-4DF8-99A1-72936EE445EE}.Release|x64.ActiveCfg = Release|x64
19 | {81699472-E045-4DF8-99A1-72936EE445EE}.Release|x64.Build.0 = Release|x64
20 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Debug|x64.ActiveCfg = Debug|x64
21 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Debug|x64.Build.0 = Debug|x64
22 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Debug|x64.Deploy.0 = Debug|x64
23 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Release|x64.ActiveCfg = Release|x64
24 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Release|x64.Build.0 = Release|x64
25 | {6AA61830-4BA3-4097-B4FF-EA62F47D98D6}.Release|x64.Deploy.0 = Release|x64
26 | EndGlobalSection
27 | GlobalSection(SolutionProperties) = preSolution
28 | HideSolutionNode = FALSE
29 | EndGlobalSection
30 | GlobalSection(ExtensibilityGlobals) = postSolution
31 | SolutionGuid = {5440F2C6-E2BF-4D38-9500-0EC8FE4A4105}
32 | EndGlobalSection
33 | EndGlobal
34 |
--------------------------------------------------------------------------------