├── .gitignore ├── LICENSE ├── defs.h ├── fnv.hpp ├── hwid.cpp ├── hwid.sln ├── hwid.vcxproj ├── hwid.vcxproj.filters └── serial_gen.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | [Xx]64/ 19 | [Xx]86/ 20 | [Bb]uild/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | artifacts/ 46 | 47 | *_i.c 48 | *_p.c 49 | *_i.h 50 | *.ilk 51 | *.meta 52 | *.obj 53 | *.pch 54 | *.pdb 55 | *.pgc 56 | *.pgd 57 | *.rsp 58 | *.sbr 59 | *.tlb 60 | *.tli 61 | *.tlh 62 | *.tmp 63 | *.tmp_proj 64 | *.log 65 | *.vspscc 66 | *.vssscc 67 | .builds 68 | *.pidb 69 | *.svclog 70 | *.scc 71 | 72 | # Chutzpah Test files 73 | _Chutzpah* 74 | 75 | # Visual C++ cache files 76 | ipch/ 77 | *.aps 78 | *.ncb 79 | *.opendb 80 | *.opensdf 81 | *.sdf 82 | *.cachefile 83 | *.VC.db 84 | 85 | # Visual Studio profiler 86 | *.psess 87 | *.vsp 88 | *.vspx 89 | *.sap 90 | 91 | # TFS 2012 Local Workspace 92 | $tf/ 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | *.DotSettings.user 101 | 102 | # JustCode is a .NET coding add-in 103 | .JustCode 104 | 105 | # TeamCity is a build add-in 106 | _TeamCity* 107 | 108 | # DotCover is a Code Coverage Tool 109 | *.dotCover 110 | 111 | # NCrunch 112 | _NCrunch_* 113 | .*crunch*.local.xml 114 | nCrunchTemp_* 115 | 116 | # MightyMoose 117 | *.mm.* 118 | AutoTest.Net/ 119 | 120 | # Web workbench (sass) 121 | .sass-cache/ 122 | 123 | # Installshield output folder 124 | [Ee]xpress/ 125 | 126 | # DocProject is a documentation generator add-in 127 | DocProject/buildhelp/ 128 | DocProject/Help/*.HxT 129 | DocProject/Help/*.HxC 130 | DocProject/Help/*.hhc 131 | DocProject/Help/*.hhk 132 | DocProject/Help/*.hhp 133 | DocProject/Help/Html2 134 | DocProject/Help/html 135 | 136 | # Click-Once directory 137 | publish/ 138 | 139 | # Publish Web Output 140 | *.[Pp]ublish.xml 141 | *.azurePubxml 142 | 143 | # TODO: Un-comment the next line if you do not want to checkin 144 | # your web deploy settings because they may include unencrypted 145 | # passwords 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # NuGet Packages 150 | *.nupkg 151 | # The packages folder can be ignored because of Package Restore 152 | **/packages/* 153 | # except build/, which is used as an MSBuild target. 154 | !**/packages/build/ 155 | # Uncomment if necessary however generally it will be regenerated when needed 156 | #!**/packages/repositories.config 157 | # NuGet v3's project.json files produces more ignoreable files 158 | *.nuget.props 159 | *.nuget.targets 160 | 161 | # Microsoft Azure Build Output 162 | csx/ 163 | *.build.csdef 164 | 165 | # Microsoft Azure Emulator 166 | ecf/ 167 | rcf/ 168 | 169 | # Windows Store app package directory 170 | AppPackages/ 171 | BundleArtifacts/ 172 | 173 | # Visual Studio cache files 174 | # files ending in .cache can be ignored 175 | *.[Cc]ache 176 | # but keep track of directories ending in .cache 177 | !*.[Cc]ache/ 178 | 179 | # Others 180 | ClientBin/ 181 | [Ss]tyle[Cc]op.* 182 | ~$* 183 | *~ 184 | *.dbmdl 185 | *.dbproj.schemaview 186 | *.pfx 187 | *.publishsettings 188 | node_modules/ 189 | orleans.codegen.cs 190 | 191 | # RIA/Silverlight projects 192 | Generated_Code/ 193 | 194 | # Backup & report files from converting an old project file 195 | # to a newer Visual Studio version. Backup files are not needed, 196 | # because we have git ;-) 197 | _UpgradeReport_Files/ 198 | Backup*/ 199 | UpgradeLog*.XML 200 | UpgradeLog*.htm 201 | 202 | # SQL Server files 203 | *.mdf 204 | *.ldf 205 | 206 | # Business Intelligence projects 207 | *.rdl.data 208 | *.bim.layout 209 | *.bim_*.settings 210 | 211 | # Microsoft Fakes 212 | FakesAssemblies/ 213 | 214 | # GhostDoc plugin setting file 215 | *.GhostDoc.xml 216 | 217 | # Node.js Tools for Visual Studio 218 | .ntvs_analysis.dat 219 | 220 | # Visual Studio 6 build log 221 | *.plg 222 | 223 | # Visual Studio 6 workspace options file 224 | *.opt 225 | 226 | # Visual Studio LightSwitch build output 227 | **/*.HTMLClient/GeneratedArtifacts 228 | **/*.DesktopClient/GeneratedArtifacts 229 | **/*.DesktopClient/ModelManifest.xml 230 | **/*.Server/GeneratedArtifacts 231 | **/*.Server/ModelManifest.xml 232 | _Pvt_Extensions 233 | 234 | # LightSwitch generated files 235 | GeneratedArtifacts/ 236 | ModelManifest.xml 237 | 238 | # Paket dependency manager 239 | .paket/paket.exe 240 | 241 | # FAKE - F# Make 242 | .fake/ 243 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) namazso 2018 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 | -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | EXTERN_C_START 5 | 6 | extern NTKERNELAPI 7 | NTSTATUS 8 | ObReferenceObjectByName( 9 | IN PUNICODE_STRING ObjectName, 10 | IN ULONG Attributes, 11 | IN PACCESS_STATE PassedAccessState, 12 | IN ACCESS_MASK DesiredAccess, 13 | IN POBJECT_TYPE ObjectType, 14 | IN KPROCESSOR_MODE AccessMode, 15 | IN OUT PVOID ParseContext, 16 | OUT PVOID * Object 17 | ); 18 | 19 | extern POBJECT_TYPE *IoDriverObjectType; 20 | 21 | #define SMART_RCV_DRIVE_DATA \ 22 | CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 23 | 24 | #define DFP_SEND_DRIVE_COMMAND \ 25 | CTL_CODE(IOCTL_DISK_BASE, 0x0021, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 26 | 27 | #define DFP_RECEIVE_DRIVE_DATA \ 28 | CTL_CODE(IOCTL_DISK_BASE, 0x0022, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) 29 | 30 | 31 | #define IDE_ATA_IDENTIFY 0xEC 32 | 33 | typedef struct _IDINFO 34 | { 35 | USHORT wGenConfig; 36 | USHORT wNumCyls; 37 | USHORT wReserved; 38 | USHORT wNumHeads; 39 | USHORT wBytesPerTrack; 40 | USHORT wBytesPerSector; 41 | USHORT wNumSectorsPerTrack; 42 | USHORT wVendorUnique[3]; 43 | CHAR sSerialNumber[20]; 44 | USHORT wBufferType; 45 | USHORT wBufferSize; 46 | USHORT wECCSize; 47 | CHAR sFirmwareRev[8]; 48 | CHAR sModelNumber[40]; 49 | USHORT wMoreVendorUnique; 50 | USHORT wDoubleWordIO; 51 | struct { 52 | USHORT Reserved : 8; 53 | USHORT DMA : 1; 54 | USHORT LBA : 1; 55 | USHORT DisIORDY : 1; 56 | USHORT IORDY : 1; 57 | USHORT SoftReset : 1; 58 | USHORT Overlap : 1; 59 | USHORT Queue : 1; 60 | USHORT InlDMA : 1; 61 | } wCapabilities; 62 | USHORT wReserved1; 63 | USHORT wPIOTiming; 64 | USHORT wDMATiming; 65 | struct { 66 | USHORT CHSNumber : 1; 67 | USHORT CycleNumber : 1; 68 | USHORT UnltraDMA : 1; 69 | USHORT Reserved : 13; 70 | } wFieldValidity; 71 | USHORT wNumCurCyls; 72 | USHORT wNumCurHeads; 73 | USHORT wNumCurSectorsPerTrack; 74 | USHORT wCurSectorsLow; 75 | USHORT wCurSectorsHigh; 76 | struct { 77 | USHORT CurNumber : 8; 78 | USHORT Multi : 1; 79 | USHORT Reserved : 7; 80 | } wMultSectorStuff; 81 | ULONG dwTotalSectors; 82 | USHORT wSingleWordDMA; 83 | struct { 84 | USHORT Mode0 : 1; 85 | USHORT Mode1 : 1; 86 | USHORT Mode2 : 1; 87 | USHORT Reserved1 : 5; 88 | USHORT Mode0Sel : 1; 89 | USHORT Mode1Sel : 1; 90 | USHORT Mode2Sel : 1; 91 | USHORT Reserved2 : 5; 92 | } wMultiWordDMA; 93 | struct { 94 | USHORT AdvPOIModes : 8; 95 | USHORT Reserved : 8; 96 | } wPIOCapacity; 97 | USHORT wMinMultiWordDMACycle; 98 | USHORT wRecMultiWordDMACycle; 99 | USHORT wMinPIONoFlowCycle; 100 | USHORT wMinPOIFlowCycle; 101 | USHORT wReserved69[11]; 102 | struct { 103 | USHORT Reserved1 : 1; 104 | USHORT ATA1 : 1; 105 | USHORT ATA2 : 1; 106 | USHORT ATA3 : 1; 107 | USHORT ATA4 : 1; 108 | USHORT ATA5 : 1; 109 | USHORT ATA6 : 1; 110 | USHORT ATA7 : 1; 111 | USHORT ATA8 : 1; 112 | USHORT ATA9 : 1; 113 | USHORT ATA10 : 1; 114 | USHORT ATA11 : 1; 115 | USHORT ATA12 : 1; 116 | USHORT ATA13 : 1; 117 | USHORT ATA14 : 1; 118 | USHORT Reserved2 : 1; 119 | } wMajorVersion; 120 | USHORT wMinorVersion; 121 | USHORT wReserved82[6]; 122 | struct { 123 | USHORT Mode0 : 1; 124 | USHORT Mode1 : 1; 125 | USHORT Mode2 : 1; 126 | USHORT Mode3 : 1; 127 | USHORT Mode4 : 1; 128 | USHORT Mode5 : 1; 129 | USHORT Mode6 : 1; 130 | USHORT Mode7 : 1; 131 | USHORT Mode0Sel : 1; 132 | USHORT Mode1Sel : 1; 133 | USHORT Mode2Sel : 1; 134 | USHORT Mode3Sel : 1; 135 | USHORT Mode4Sel : 1; 136 | USHORT Mode5Sel : 1; 137 | USHORT Mode6Sel : 1; 138 | USHORT Mode7Sel : 1; 139 | } wUltraDMA; 140 | USHORT wReserved89[167]; 141 | } IDINFO, *PIDINFO; 142 | 143 | EXTERN_C_END -------------------------------------------------------------------------------- /fnv.hpp: -------------------------------------------------------------------------------- 1 | /* This file is part of hdd_serial_spoofer by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #pragma once 26 | #include 27 | #include 28 | 29 | // Implements FNV-1a hash algorithm 30 | namespace detail 31 | { 32 | template 33 | struct SizeDependantData 34 | { 35 | using type = Type; 36 | 37 | constexpr static auto k_offset_basis = OffsetBasis; 38 | constexpr static auto k_prime = Prime; 39 | }; 40 | 41 | template 42 | struct SizeSelector : std::false_type {}; 43 | 44 | template <> 45 | struct SizeSelector<32> : SizeDependantData {}; 46 | 47 | template <> 48 | struct SizeSelector<64> : SizeDependantData {}; 49 | 50 | template 51 | class FnvHash 52 | { 53 | private: 54 | using data_t = SizeSelector; 55 | 56 | public: 57 | using hash = typename data_t::type; 58 | 59 | private: 60 | constexpr static auto k_offset_basis = data_t::k_offset_basis; 61 | constexpr static auto k_prime = data_t::k_prime; 62 | 63 | public: 64 | static __forceinline constexpr auto hash_init( 65 | ) -> hash 66 | { 67 | return k_offset_basis; 68 | } 69 | 70 | static __forceinline constexpr auto hash_byte( 71 | hash current, 72 | std::uint8_t byte 73 | ) -> hash 74 | { 75 | return (current ^ byte) * k_prime; 76 | } 77 | 78 | template 79 | static __forceinline constexpr auto hash_constexpr( 80 | const char (&str)[N], 81 | const std::size_t size = N - 1 /* do not hash the null */ 82 | ) -> hash 83 | { 84 | const auto prev_hash = size == 1 ? hash_init() : hash_constexpr(str, size - 1); 85 | const auto cur_hash = hash_byte(prev_hash, str[size - 1]); 86 | return cur_hash; 87 | } 88 | 89 | static auto __forceinline hash_runtime_data( 90 | const void* data, 91 | const std::size_t sz 92 | ) -> hash 93 | { 94 | const auto bytes = static_cast(data); 95 | const auto end = bytes + sz; 96 | auto result = hash_init(); 97 | for (auto it = bytes; it < end; ++it) 98 | result = hash_byte(result, *it); 99 | 100 | return result; 101 | } 102 | 103 | static auto __forceinline hash_runtime( 104 | const char* str 105 | ) -> hash 106 | { 107 | auto result = hash_init(); 108 | do 109 | result = hash_byte(result, *str++); 110 | while (*str != '\0'); 111 | 112 | return result; 113 | } 114 | }; 115 | } 116 | 117 | using fnv32 = ::detail::FnvHash<32>; 118 | using fnv64 = ::detail::FnvHash<64>; 119 | using fnv = ::detail::FnvHash; 120 | 121 | #define FNV(str) (std::integral_constant::value) 122 | #define FNV32(str) (std::integral_constant::value) 123 | #define FNV64(str) (std::integral_constant::value) 124 | -------------------------------------------------------------------------------- /hwid.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of hdd_serial_spoofer by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "defs.h" 30 | 31 | PDRIVER_DISPATCH g_original_device_control; 32 | 33 | void spoof_serial(char* serial, bool is_smart); 34 | unsigned long long g_startup_time; 35 | 36 | struct REQUEST_STRUCT 37 | { 38 | PIO_COMPLETION_ROUTINE OldRoutine; 39 | PVOID OldContext; 40 | ULONG OutputBufferLength; 41 | PVOID SystemBuffer; 42 | }; 43 | 44 | NTSTATUS completed_storage_query( 45 | PDEVICE_OBJECT device_object, 46 | PIRP irp, 47 | PVOID context 48 | ) 49 | { 50 | if(!context) 51 | { 52 | KdPrint(("%s %d : Context was nullptr\n", __FUNCTION__, __LINE__)); 53 | return STATUS_SUCCESS; 54 | } 55 | 56 | const auto request = (REQUEST_STRUCT*)context; 57 | const auto buffer_length = request->OutputBufferLength; 58 | const auto buffer = (PSTORAGE_DEVICE_DESCRIPTOR)request->SystemBuffer; 59 | const auto old_routine = request->OldRoutine; 60 | const auto old_context = request->OldContext; 61 | ExFreePool(context); 62 | 63 | do 64 | { 65 | 66 | if(buffer_length < FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties)) 67 | break; // They just want the size 68 | 69 | if(buffer->SerialNumberOffset == 0) 70 | { 71 | KdPrint(("%s %d : Device doesn't have unique ID\n", __FUNCTION__, __LINE__)); 72 | break; 73 | } 74 | 75 | if(buffer_length < FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties) + buffer->RawPropertiesLength 76 | || buffer->SerialNumberOffset < FIELD_OFFSET(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties) 77 | || buffer->SerialNumberOffset >= buffer_length 78 | ) 79 | { 80 | KdPrint(("%s %d : Malformed buffer (should never happen) size: %d\n", __FUNCTION__, __LINE__, buffer_length)); 81 | } 82 | else 83 | { 84 | const auto serial = (char*)buffer + buffer->SerialNumberOffset; 85 | KdPrint(("%s %d : Serial0: %s\n", __FUNCTION__, __LINE__, serial)); 86 | spoof_serial(serial, false); 87 | KdPrint(("%s %d : Serial1: %s\n", __FUNCTION__, __LINE__, serial)); 88 | } 89 | } while(false); 90 | 91 | // Call next completion routine (if any) 92 | if(irp->StackCount > 1ul && old_routine) 93 | return old_routine(device_object, irp, old_context); 94 | 95 | return STATUS_SUCCESS; 96 | } 97 | 98 | NTSTATUS completed_smart( 99 | PDEVICE_OBJECT device_object, 100 | PIRP irp, 101 | PVOID context 102 | ) 103 | { 104 | UNREFERENCED_PARAMETER(device_object); 105 | 106 | if(!context) 107 | { 108 | KdPrint(("%s %d : Context was nullptr\n", __FUNCTION__, __LINE__)); 109 | return STATUS_SUCCESS; 110 | } 111 | 112 | const auto request = (REQUEST_STRUCT*)context; 113 | const auto buffer_length = request->OutputBufferLength; 114 | const auto buffer = (SENDCMDOUTPARAMS*)request->SystemBuffer; 115 | //const auto old_routine = request->OldRoutine; 116 | //const auto old_context = request->OldContext; 117 | ExFreePool(context); 118 | 119 | if(buffer_length < FIELD_OFFSET(SENDCMDOUTPARAMS, bBuffer) 120 | || FIELD_OFFSET(SENDCMDOUTPARAMS, bBuffer) + buffer->cBufferSize > buffer_length 121 | || buffer->cBufferSize < sizeof(IDINFO) 122 | ) 123 | { 124 | KdPrint(("%s %d : Malformed buffer (should never happen) size: %d\n", __FUNCTION__, __LINE__, buffer_length)); 125 | } 126 | else 127 | { 128 | const auto info = (IDINFO*)buffer->bBuffer; 129 | const auto serial = info->sSerialNumber; 130 | KdPrint(("%s %d : Serial0: %s\n", __FUNCTION__, __LINE__, serial)); 131 | spoof_serial(serial, true); 132 | KdPrint(("%s %d : Serial1: %s\n", __FUNCTION__, __LINE__, serial)); 133 | } 134 | 135 | // I have no fucking idea why not calling the original doesnt cause problems but whatever 136 | 137 | //KdPrint(("%s: Returning STATUS_NOT_SUPPORTED\n", __FUNCTION__)); 138 | 139 | // We deny access by returning an ERROR code 140 | //irp->IoStatus.Status = STATUS_NOT_SUPPORTED; 141 | 142 | // Call next completion routine (if any) 143 | //if ((irp->StackCount > (ULONG)1) && (OldCompletionRoutine != NULL)) 144 | // return OldCompletionRoutine(device_object, irp, OldContext); 145 | 146 | return irp->IoStatus.Status; 147 | } 148 | 149 | void do_completion_hook(PIRP irp, PIO_STACK_LOCATION ioc, PIO_COMPLETION_ROUTINE routine) 150 | { 151 | // Register CompletionRotuine 152 | ioc->Control = 0; 153 | ioc->Control |= SL_INVOKE_ON_SUCCESS; 154 | 155 | // Save old completion routine 156 | // Yes we rewrite any routine to be on success only 157 | // and somehow it doesnt cause disaster 158 | const auto old_context = ioc->Context; 159 | ioc->Context = ExAllocatePool(NonPagedPool, sizeof(REQUEST_STRUCT)); 160 | const auto request = (REQUEST_STRUCT*)ioc->Context; 161 | request->OldRoutine = ioc->CompletionRoutine; 162 | request->OldContext = old_context; 163 | request->OutputBufferLength = ioc->Parameters.DeviceIoControl.OutputBufferLength; 164 | request->SystemBuffer = irp->AssociatedIrp.SystemBuffer; 165 | 166 | // Setup our function to be called upon completion of the IRP 167 | ioc->CompletionRoutine = routine; 168 | } 169 | 170 | NTSTATUS hooked_device_control(PDEVICE_OBJECT device_object, PIRP irp) 171 | { 172 | const auto ioc = IoGetCurrentIrpStackLocation(irp); 173 | 174 | switch(ioc->Parameters.DeviceIoControl.IoControlCode) 175 | { 176 | case IOCTL_STORAGE_QUERY_PROPERTY: 177 | { 178 | const auto query = (PSTORAGE_PROPERTY_QUERY)irp->AssociatedIrp.SystemBuffer; 179 | 180 | if(query->PropertyId == StorageDeviceProperty) 181 | do_completion_hook(irp, ioc, &completed_storage_query); 182 | } 183 | break; 184 | case SMART_RCV_DRIVE_DATA: 185 | do_completion_hook(irp, ioc, &completed_smart); 186 | break; 187 | default: 188 | break; 189 | } 190 | 191 | return g_original_device_control(device_object, irp); 192 | } 193 | 194 | void apply_hook() 195 | { 196 | UNICODE_STRING driver_name = RTL_CONSTANT_STRING(L"\\Driver\\Disk"); 197 | PDRIVER_OBJECT driver_object = nullptr; 198 | auto status = ObReferenceObjectByName( 199 | &driver_name, 200 | OBJ_CASE_INSENSITIVE, 201 | nullptr, 202 | 0, 203 | *IoDriverObjectType, 204 | KernelMode, 205 | nullptr, 206 | (PVOID*)&driver_object 207 | ); 208 | 209 | if(!driver_object || !NT_SUCCESS(status)) 210 | { 211 | KdPrint(("%s %d : ObReferenceObjectByName returned 0x%08X driver_object: 0x%016X\n", __FUNCTION__, __LINE__, status, driver_object)); 212 | return; 213 | } 214 | 215 | auto& device_control = driver_object->MajorFunction[IRP_MJ_DEVICE_CONTROL]; 216 | g_original_device_control = device_control; 217 | device_control = &hooked_device_control; 218 | 219 | ObDereferenceObject(driver_object); 220 | } 221 | 222 | /*extern "C" 223 | size_t EntryPoint(void* ntoskrn, void* image, void* alloc) 224 | { 225 | KeQuerySystemTime(&g_startup_time); 226 | apply_hook(); 227 | return 0; 228 | }*/ 229 | 230 | extern "C" 231 | NTSTATUS EntryPoint( 232 | _DRIVER_OBJECT *DriverObject, 233 | PUNICODE_STRING RegistryPath 234 | ) 235 | { 236 | UNREFERENCED_PARAMETER(DriverObject); 237 | UNREFERENCED_PARAMETER(RegistryPath); 238 | 239 | KeQuerySystemTime(&g_startup_time); 240 | apply_hook(); 241 | return STATUS_SUCCESS; 242 | } -------------------------------------------------------------------------------- /hwid.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2010 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hwid", "hwid.vcxproj", "{6D3117AB-3B25-44B9-9966-90608B632EA3}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Release|x64 = Release|x64 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Debug|x64.ActiveCfg = Debug|x64 15 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Debug|x64.Build.0 = Debug|x64 16 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Debug|x64.Deploy.0 = Debug|x64 17 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Release|x64.ActiveCfg = Release|x64 18 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Release|x64.Build.0 = Release|x64 19 | {6D3117AB-3B25-44B9-9966-90608B632EA3}.Release|x64.Deploy.0 = Release|x64 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(ExtensibilityGlobals) = postSolution 25 | SolutionGuid = {483508DE-B553-446E-BDAF-E8D889244E63} 26 | EndGlobalSection 27 | EndGlobal 28 | -------------------------------------------------------------------------------- /hwid.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Release 10 | x64 11 | 12 | 13 | 14 | {6D3117AB-3B25-44B9-9966-90608B632EA3} 15 | {1bc93793-694f-48fe-9372-81e2b05556fd} 16 | v4.5 17 | 12.0 18 | Debug 19 | Win32 20 | hwid 21 | 22 | 23 | 24 | Windows7 25 | true 26 | WindowsKernelModeDriver10.0 27 | Driver 28 | KMDF 29 | Desktop 30 | 31 | 32 | Windows7 33 | false 34 | WindowsKernelModeDriver10.0 35 | Driver 36 | KMDF 37 | Desktop 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | DbgengKernelDebugger 49 | false 50 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(IncludePath) 51 | 52 | 53 | DbgengKernelDebugger 54 | false 55 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(IncludePath) 56 | 57 | 58 | 59 | EntryPoint 60 | $(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib 61 | 62 | 63 | false 64 | false 65 | false 66 | 67 | 68 | 69 | 70 | EntryPoint 71 | $(DDK_LIB_PATH)ntoskrnl.lib;$(DDK_LIB_PATH)hal.lib;$(DDK_LIB_PATH)wmilib.lib 72 | 73 | 74 | false 75 | false 76 | false 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /hwid.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 | 22 | 23 | Header Files 24 | 25 | 26 | Header Files 27 | 28 | 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | -------------------------------------------------------------------------------- /serial_gen.cpp: -------------------------------------------------------------------------------- 1 | /* This file is part of hdd_serial_spoofer by namazso, licensed under the MIT license: 2 | * 3 | * MIT License 4 | * 5 | * Copyright (c) namazso 2018 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | */ 25 | #include 26 | #include "fnv.hpp" 27 | #include 28 | #include 29 | 30 | extern unsigned long long g_startup_time; 31 | 32 | static inline bool is_good_char(char c) 33 | { 34 | const auto u = uint8_t(c); 35 | return (u >= uint8_t('0') && u <= uint8_t('9')) 36 | || (u >= uint8_t('A') && u <= uint8_t('Z')) 37 | || (u >= uint8_t('a') && u <= uint8_t('z')); 38 | } 39 | static inline bool is_hex(char c) 40 | { 41 | const auto u = uint8_t(c); 42 | return (u >= uint8_t('0') && u <= uint8_t('9')) 43 | || (u >= uint8_t('A') && u <= uint8_t('F')) 44 | || (u >= uint8_t('a') && u <= uint8_t('f')); 45 | } 46 | static inline uint8_t unhex_char(char c) 47 | { 48 | const auto u = uint8_t(c); 49 | if (u >= uint8_t('0') && u <= uint8_t('9')) 50 | return u - uint8_t('0'); 51 | if (u >= uint8_t('A') && u <= uint8_t('F')) 52 | return u - uint8_t('A') + 0xA; 53 | if (u >= uint8_t('a') && u <= uint8_t('f')) 54 | return u - uint8_t('a') + 0xa; 55 | return 0xFF; 56 | } 57 | static inline uint8_t unhex_byte(char a, char b) { return (unhex_char(a) << 4) + unhex_char(b); } 58 | static inline char hex_char(uint8_t v) 59 | { 60 | if (v < 0xA) 61 | return char(uint8_t('0') + v); 62 | return char(uint8_t('A') + v - 0xA); 63 | } 64 | static inline std::pair hex_byte(uint8_t v) { return { hex_char(v >> 4), hex_char(v & 0xF) }; } 65 | 66 | static fnv::hash hash_subserial(const char* serial, size_t len) 67 | { 68 | auto h = fnv::hash_init(); 69 | for (auto i = 0u; i < len; ++i) 70 | if (is_good_char(serial[i])) 71 | h = fnv::hash_byte(h, serial[i]); 72 | return h; 73 | } 74 | 75 | void randomize_subserial(char* serial, size_t len) 76 | { 77 | const auto seed = hash_subserial(serial, len) ^ g_startup_time; 78 | auto engine = std::mt19937_64{ seed }; 79 | const auto distribution = std::uniform_int_distribution('A', 'Z'); 80 | 81 | KdPrint(("Randomizing subserial: seed: %016llX len: %d\n old: ", seed, len)); 82 | for (auto i = 0u; i < len; ++i) 83 | KdPrint(("%02hhX ", uint8_t(serial[i]))); 84 | KdPrint(("\n new: ")); 85 | 86 | for (auto i = 0u; i < len; ++i) 87 | if(is_good_char(serial[i])) 88 | serial[i] = char(distribution(engine)); 89 | 90 | for (auto i = 0u; i < len; ++i) 91 | KdPrint(("%02hhX ", uint8_t(serial[i]))); 92 | KdPrint(("\n")); 93 | } 94 | 95 | void spoof_serial(char* serial, bool is_smart) 96 | { 97 | // must be 20 or less 98 | size_t len; 99 | char buf[21]; 100 | bool is_serial_hex; 101 | if(is_smart) 102 | { 103 | is_serial_hex = false; 104 | len = 20; 105 | memcpy(buf, serial, 20); 106 | } 107 | else 108 | { 109 | is_serial_hex = true; 110 | for (len = 0; serial[len]; ++len) 111 | if (!is_hex(serial[len])) 112 | is_serial_hex = false; 113 | 114 | if(is_serial_hex) 115 | { 116 | len /= 2; 117 | len = std::min(len, 20); 118 | for (auto i = 0u; i < len; ++i) 119 | buf[i] = unhex_byte(serial[i * 2], serial[i * 2 + 1]); 120 | } 121 | else 122 | { 123 | memcpy(buf, serial, len); 124 | } 125 | } 126 | 127 | buf[len] = 0; 128 | char split[2][11]; 129 | memset(split, 0, sizeof(split)); 130 | 131 | for (auto i = 0u; i < len; ++i) 132 | split[i % 2][i / 2] = buf[i]; 133 | 134 | randomize_subserial(split[0], (len + 1) / 2); 135 | randomize_subserial(split[1], len / 2); 136 | 137 | for (auto i = 0u; i < len; ++i) 138 | buf[i] = split[i % 2][i / 2]; 139 | buf[len] = 0; 140 | 141 | if(is_smart) 142 | { 143 | memcpy(serial, buf, 20); 144 | } 145 | else 146 | { 147 | if (is_serial_hex) 148 | { 149 | for (auto i = 0u; i < len; ++i) 150 | std::tie(serial[i * 2], serial[i * 2 + 1]) = hex_byte(buf[i]); 151 | serial[len * 2] = 0; 152 | } 153 | else 154 | { 155 | memcpy(serial, buf, len + 1); 156 | } 157 | } 158 | } --------------------------------------------------------------------------------