{"id":13574411,"url":"https://github.com/jxy-s/herpaderping","last_synced_at":"2025-05-16T10:08:09.079Z","repository":{"id":44385163,"uuid":"278176624","full_name":"jxy-s/herpaderping","owner":"jxy-s","description":"Process Herpaderping proof of concept, tool, and technical deep dive. Process Herpaderping bypasses security products by obscuring the intentions of a process.","archived":false,"fork":false,"pushed_at":"2023-07-05T17:04:57.000Z","size":23905,"stargazers_count":1128,"open_issues_count":1,"forks_count":220,"subscribers_count":33,"default_branch":"main","last_synced_at":"2025-04-09T04:08:04.171Z","etag":null,"topics":["antivirus","antivirus-evasion","exploit","exploit-development","exploit-framework","exploitation","exploits","process-doppelganging","process-herpaderping","process-hollowing","process-migration","security","security-vulnerability","vulnerability","windows","windows-10","windows-7","windows-defender"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jxy-s.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-07-08T19:26:16.000Z","updated_at":"2025-03-24T09:46:55.000Z","dependencies_parsed_at":"2022-07-14T14:47:10.382Z","dependency_job_id":"ce3b4a67-0ae0-422a-ac92-e12da8dd5439","html_url":"https://github.com/jxy-s/herpaderping","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxy-s%2Fherpaderping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxy-s%2Fherpaderping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxy-s%2Fherpaderping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jxy-s%2Fherpaderping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jxy-s","download_url":"https://codeload.github.com/jxy-s/herpaderping/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254509477,"owners_count":22082891,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["antivirus","antivirus-evasion","exploit","exploit-development","exploit-framework","exploitation","exploits","process-doppelganging","process-herpaderping","process-hollowing","process-migration","security","security-vulnerability","vulnerability","windows","windows-10","windows-7","windows-defender"],"created_at":"2024-08-01T15:00:51.352Z","updated_at":"2025-05-16T10:08:04.065Z","avatar_url":"https://github.com/jxy-s.png","language":"C++","funding_links":[],"categories":["C++"],"sub_categories":[],"readme":"# Process Herpaderping \r\n[\u003cimg align=\"left\" style=\"margin: 0px 15px 15px 0px;\" src=\"res/HerpaderpIcon.png\" width=\"150\"/\u003e][png.HerpaderpIcon]\r\nProcess Herpaderping is a method of obscuring the intentions of a process by \r\nmodifying the content on disk after the image has been mapped. This results \r\nin curious behavior by security products and the OS itself.\r\n\r\n![][png.mimioogle]\r\n\r\n![][gif.SurivDemo]\r\n\r\n## Summary\r\nGenerally, a security product takes action on process creation by registering a \r\ncallback in the Windows Kernel \r\n([PsSetCreateProcessNotifyRoutineEx][msdn.PsSetCreateProcessNotifyRoutineEx]). \r\nAt this point, a security product may inspect the file that was used to map \r\nthe executable and determine if this process should be allowed to execute. This \r\nkernel callback is invoked when the initial thread is inserted, not when the \r\nprocess object is created. \r\n\r\nBecause of this, an actor can create and map a process, modify the content of \r\nthe file, then create the initial thread. A product that does inspection at the \r\ncreation callback would see the modified content. Additionally, some products \r\nuse an on-write scanning approach which consists of monitoring for file writes. \r\nA familiar optimization here is recording the file has been written to and \r\ndefer the actual inspection until [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] \r\noccurs (e.g. the file handle is closed). Thus, an actor using a \r\n`write -\u003e map -\u003e modify -\u003e execute -\u003e close` workflow will subvert on-write scanning \r\nthat solely relies on inspection at [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP].\r\n\r\nTo abuse this convention, we first write a binary to a target file on disk. \r\nThen, we map an image of the target file and provide it to the OS to use for \r\nprocess creation. The OS kindly maps the original binary for us. Using \r\nthe existing file handle, and before creating the initial thread, we modify the \r\ntarget file content to obscure or fake the file backing the image. Some time later, \r\nwe create the initial thread to begin execution of the original binary. Finally, we \r\n will close the target file handle. Let's walk through this step-by-step:\r\n1. Write target binary to disk, keeping the handle open. This is what will \r\n   execute in memory.\r\n2. Map the file as an image section ([NtCreateSection][msdn.NtCreateSection], \r\n   [SEC_IMAGE][msdn.SEC_IMAGE]).\r\n3. Create the process object using the section handle (`NtCreateProcessEx`).\r\n4. Using the same target file handle, obscure the file on disk.\r\n5. Create the initial thread in the process (`NtCreateThreadEx`).\r\n    - At this point the process creation callback in the kernel will fire. The \r\n      contents on disk do not match what was mapped. Inspection of the file at \r\n      this point will result in incorrect attribution.\r\n6. Close the handle. [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] will occur here.\r\n    - Since we've hidden the contents of what is executing, inspection at this \r\n      point will result in incorrect attribution.\r\n\r\n![][svg.StateDiagram]\r\n\u003cdetails\u003e\r\n    \u003csummary\u003eplantuml\u003c/summary\u003e\r\n\u003cp\u003e\r\n\r\n```plantuml\r\n@startuml\r\nhide empty description\r\n\r\n[*] --\u003e CreateFile\r\nCreateFile --\u003e FileHandle\r\nFileHandle --\u003e Write\r\nFileHandle --\u003e NtCreateSection\r\nWrite -[hidden]-\u003e NtCreateSection\r\nNtCreateSection --\u003e SectionHandle\r\nSectionHandle --\u003e NtCreateProcessEx\r\nFileHandle --\u003e Modify\r\nNtCreateProcessEx -[hidden]-\u003e Modify\r\nNtCreateProcessEx --\u003e NtCreateThreadEx\r\nModify -[hidden]-\u003e NtCreateThreadEx\r\nNtCreateThreadEx --\u003e [*]\r\nFileHandle --\u003e CloseFile\r\nNtCreateThreadEx -[hidden]-\u003e CloseFile\r\nNtCreateThreadEx --\u003e PspCallProcessNotifyRoutines\r\nPspCallProcessNotifyRoutines -[hidden]-\u003e [*]\r\nCloseFile --\u003e IRP_MJ_CLEANUP\r\nIRP_MJ_CLEANUP -[hidden]-\u003e [*]\r\nPspCallProcessNotifyRoutines --\u003e Inspect\r\nPspCallProcessNotifyRoutines -[hidden]-\u003e CloseFile \r\nIRP_MJ_CLEANUP --\u003e Inspect\r\nInspect -[hidden]-\u003e [*]\r\n\r\nCreateFile : Create target file, keep handle open.\r\nWrite : Write source payload into target file.\r\nModify : Obscure the file on disk.\r\nNtCreateSection : Create section using file handle.\r\nNtCreateProcessEx : Image section for process is mapped and cached in file object.\r\nNtCreateThreadEx : The cached section is used.\r\nNtCreateThreadEx : Process notify routines fire in kernel.\r\nInspect : The contents on disk do not match what was executed. \r\nInspect : Inspection of the file at this point will result in incorrect attribution.\r\n@enduml\r\n```\r\n\r\n\u003c/p\u003e\r\n\u003c/details\u003e\r\n\r\n## Behavior\r\nYou'll see in the demo below, `CMD.exe` is used as the execution target. The \r\nfirst run overwrites the bytes on disk with a pattern. The second run overwrites \r\n`CMD.exe` with `ProcessHacker.exe`. The Herpaderping tool fixes up the binary to \r\nlook as close to `ProcessHacker.exe` as possible, even retaining the original \r\nsignature. Note the multiple executions of the same binary and how the process \r\nlooks to the user compared to what is in the file on disk.\r\n\r\n![][gif.ProcessHerpaderp]\r\n\r\n![][png.procmon]\r\n\r\n### Diving Deeper \u003ca name=\"tag-diving-deeper\"\u003e\u003c/a\u003e\r\nWe've observed the behavior and some of this may be surprising. Let's try to \r\nexplain this behavior.\r\n\r\n[Technical Deep Dive][md.DivingDeeper]\r\n\r\n## Background and Motivation\r\nWhen designing products for securing Windows platforms, many engineers in \r\nthis field (myself included) have fallen on preconceived notions with respect \r\nto how the OS will handle data. In this scenario, some might expect the file on \r\ndisk to remain \"locked\" when the process is created. You can't delete the file. \r\nYou can't write to it. But you can rename it. Seen here, under the right \r\nconditions, you can in fact write to it. Remain vigilant on your assumptions, \r\nalways question them, and do your research.\r\n\r\nThe motivation for this research came about when discovering how to do analysis \r\nwhen a file is written. With prior background researching process Hollowing and \r\nDoppelganging, I had theorized this might be possible. The goal is to provide \r\nbetter security. You cannot create a better lock without first understanding \r\nhow to break the old one.\r\n\r\n### Similar Techniques\r\nHerpaderping is similar to Hollowing and Doppelganging however there are some \r\nkey differences:\r\n\r\n#### Process Hollowing\r\nProcess Hollowing involves modifying the mapped section before execution \r\nbegins, which abstractly this looks like: `map -\u003e modify section -\u003e execute`. This workflow \r\nresults in the intended execution flow of the Hollowed process diverging into \r\nunintended code. Doppelganging might be considered a form of Hollowing. \r\nHowever, Hollowing, in my opinion, is closer to injection in that Hollowing \r\nusually involves an explicit write to the already mapped code. This differs \r\nfrom Herpaderping where there are no modified sections.\r\n\r\n#### Process Doppelganging\r\nProcess Doppelganging is closer to Herpaderping. Doppelganging abuses \r\ntransacted file operations and generally involves these steps: \r\n`transact -\u003e write -\u003e map -\u003e rollback -\u003e execute`. \r\nIn this workflow, the OS will create the image section and account for \r\ntransactions, so the cached image section ends up being what you wrote to the \r\ntransaction. The OS has patched this technique. Well, they patched the crash it caused. \r\nMaybe they consider this a \"legal\" use of a transaction. Thankfully, Windows \r\nDefender does catch the Doppelganging technique. Doppelganging differs from \r\nHerpaderping in that Herpaderping does not rely on transacted file operations. \r\nAnd Defender doesn't catch Herpaderping.\r\n\r\n#### Comparison\r\nFor reference, the generalized techniques: \r\n\r\n| Type          | Technique                                         |\r\n| :------------ | :------------------------------------------------ |\r\n| Hollowing     | `map -\u003e modify section -\u003e execute`                |\r\n| Doppelganging | `transact -\u003e write -\u003e map -\u003e rollback -\u003e execute` |\r\n| Herpaderping  | `write -\u003e map -\u003e modify -\u003e execute -\u003e close`      |\r\n\r\nWe can see the differences laid out here. While Herpaderping is arguably \r\nnoisier than Doppelganging, in that the malicious bits do hit the disk, we've \r\nseen that security products are still incapable of detecting Herpaderping. \r\n\r\n## Possible Solution\r\nThere is not a clear fix here. It seems reasonable that preventing an image \r\nsection from being mapped/cached when there is write access to the file \r\nshould close the hole. However, that may or may not be a practical solution.\r\n\r\nAnother option might be to flush the changes to the file through to the cached \r\nimage section if it hasn't yet been mapped into a process. However, since the \r\nmap into the new process occurs at `NtCreateProcess` that is probably not a \r\nviable solution.\r\n\r\nFrom a detection standpoint, there is not a great way to identify the actual \r\nbits that got mapped, inspection at [IRP_MJ_CLEANUP][msdn.IRP_MJ_CLEANUP] or \r\na callback registered at \r\n[PsSetCreateProcessNotifyRoutineEx][msdn.PsSetCreateProcessNotifyRoutineEx] \r\nresults in incorrect attribution since the bits on disk have been changed, you \r\nwould have to rebuild the file from the section that got created. It's worth \r\npointing out here there is a new callback in Windows 10 you may register for \r\n[PsSetCreateProcessNotifyRoutineEx2][msdn.PsSetCreateProcessNotifyRoutineEx2] \r\nhowever this suffers from the same problem as the previous callback, it's \r\ncalled out when the initial thread is executed, not when the process object is \r\ncreated. Microsoft did add \r\n[PsSetCreateThreadNotifyRoutineEx][msdn.PsSetCreateThreadNotifyRoutineEx] which \r\nis called out when the initial thread is inserted if registered with \r\n[PsCreateThreadNotifyNonSystem][msdn.PSCREATETHREADNOTIFYTYPE], opposed to when \r\nit is about to begin execution (as the old callback did). Extending \r\n[PSCREATEPROCESSNOTIFYTYPE][msdn.PSCREATEPROCESSNOTIFYTYPE] to be called out \r\nwhen the process object is created won't help either, we've seen in the \r\n[Diving Deeper](#tag-diving-deeper) section that the image section object is \r\ncached on the [NtCreateSection][msdn.NtCreateSection] call not \r\n`NtCreateProcess`.\r\n\r\nWe can't easily identify what got executed. We're left with trying to detect \r\nthe exploitive behavior by the actor, I'll leave discovery of the behavior \r\nindicators as an exercise for the reader.\r\n\r\n## Known Affected Platforms\r\nBelow is a list of products and Windows OSes that have been tested as of \r\n(8/31/2020). Tests were carried out with a known malicious binary.\r\n\r\n| Operating System                    | Version         | Vulnerable |\r\n| :---------------------------------- | :-------------- | :--------: |\r\n| Windows 7 Enterprise x86            | 6.1.7601        | Yes        |\r\n| Windows 10 Pro x64                  | 10.0.18363.900  | Yes        |\r\n| Windows 10 Pro Insider Preview x64  | 10.0.20170.1000 | Yes        |\r\n| Windows 10 Pro Insider Preview x64  | 10.0.20201.1000 | Yes        |\r\n\r\n| Security Product                    | Version       | Vulnerable |\r\n| :---------------------------------- | :------------ | :--------: |\r\n| Windows Defender AntiMalware Client | 4.18.2006.10  | Yes        |\r\n| Windows Defender Engine             | 1.1.17200.2   | Yes        |\r\n| Windows Defender Antivirus          | 1.319.1127.0  | Yes        |\r\n| Windows Defender Antispyware        | 1.319.1127.0  | Yes        |\r\n| Windows Defender AntiMalware Client | 4.18.2007.6   | Yes        |\r\n| Windows Defender Engine             | 1.1.17300.2   | Yes        |\r\n| Windows Defender Antivirus          | 1.319.1676.0  | Yes        |\r\n| Windows Defender Antispyware        | 1.319.1676.0  | Yes        |\r\n| Windows Defender AntiMalware Client | 4.18.2007.8   | Yes        |\r\n| Windows Defender Engine             | 1.1.17400.5   | Yes        |\r\n| Windows Defender Antivirus          | 1.323.267.0   | Yes        |\r\n| Windows Defender Antispyware        | 1.323.267.0   | Yes        |\r\n\r\n## Responsible Disclosure\r\nThis vulnerability was disclosed to the Microsoft Security Response Center \r\n(MSRC) on 7/17/2020 and a case was opened by MSRC on 7/22/2020. MSRC concluded \r\ntheir investigation on 8/25/2020 and determined the findings are valid but do \r\nnot meet their bar for immediate servicing. At this time their case is closed, \r\nwithout resolution, and is marked for future review, with no timeline.\r\n\r\nWe disagree on the severity of this bug; this was communicated to MSRC on \r\n8/27/2020. \r\n1. There are similar vulnerabilities in this class (Hollowing and \r\nDoppelganging). \r\n1. The vulnerability is shown to defeat security features inherent to the \r\nOS (Windows Defender).\r\n1. The vulnerability allows an actor to gain execution of arbitrary code.\r\n1. The user is not notified of the execution of unintended code.\r\n1. The process information presented to the user does not accurately reflect \r\nwhat is executing. \r\n1. Facilities to accurately identify the process are not intuitive or \r\nincorrect, even from the kernel. \r\n\r\n\r\n# Source \r\nThis repo contains a tool for exercising the Herpaderping method of process \r\nobfuscation. Usage is as follows:\r\n```\r\nProcess Herpaderping Tool - Copyright (c) Johnny Shaw\r\nProcessHerpaderping.exe SourceFile TargetFile [ReplacedWith] [Options...]\r\nUsage:\r\n  SourceFile               Source file to execute.\r\n  TargetFile               Target file to execute the source from.\r\n  ReplacedWith             File to replace the target with. Optional,\r\n                           default overwrites the binary with a pattern.\r\n  -h,--help                Prints tool usage.\r\n  -d,--do-not-wait         Does not wait for spawned process to exit,\r\n                           default waits.\r\n  -l,--logging-mask number Specifies the logging mask, defaults to full\r\n                           logging.\r\n                               0x1   Successes\r\n                               0x2   Informational\r\n                               0x4   Warnings\r\n                               0x8   Errors\r\n                               0x10  Contextual\r\n  -q,--quiet               Runs quietly, overrides logging mask, no title.\r\n  -r,--random-obfuscation  Uses random bytes rather than a pattern for\r\n                           file obfuscation.\r\n  -e,--exclusive           Target file is created with exclusive access and\r\n                           the handle is held open as long as possible.\r\n                           Without this option the handle has full share\r\n                           access and is closed as soon as possible.\r\n  -u,--do-not-flush-file   Does not flush file after overwrite.\r\n  -c,--close-file-early    Closes file before thread creation (before the\r\n                           process notify callback fires in the kernel).\r\n                           Not valid with \"--exclusive\" option.\r\n  -k,--kill                Terminates the spawned process regardless of\r\n                           success or failure, this is useful in some\r\n                           automation environments. Forces \"--do-not-wait\r\n                           option.\r\n```\r\n\r\n## Cloning and Building\r\nThe repo uses submodules, after cloning be sure to init and update the \r\nsubmodules. Projects files are targeted to Visual Studio 2019.\r\n```\r\ngit clone https://github.com/jxy-s/herpaderping.git\r\ncd .\\herpaderping\\\r\ngit submodule update --init --recursive\r\nMSBuild .\\herpaderping.sln\r\n```\r\n\r\n## Credits\r\nThe following are used without modification. Credits to their authors.\r\n- [Windows Implementation Libraries (WIL)][github.wil]  \r\nA header-only C++ library created to make life easier for developers on Windows \r\nthrough readable type-safe C++ interfaces for common Windows coding patterns.  \r\n- [Process Hacker Native API Headers][github.phnt]   \r\nCollection of Native API header files. Gathered from Microsoft header files and \r\nsymbol files, as well as a lot of reverse engineering and guessing.\r\n\r\n[//]: # (Hyperlink IDs)\r\n[github.wil]: https://github.com/microsoft/wil\r\n[github.phnt]: https://github.com/processhacker/phnt\r\n[msdn.PsSetCreateProcessNotifyRoutineEx]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex\r\n[msdn.PsSetCreateProcessNotifyRoutineEx2]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreateprocessnotifyroutineex2\r\n[msdn.PsSetCreateThreadNotifyRoutineEx]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-pssetcreatethreadnotifyroutineex\r\n[msdn.PSCREATETHREADNOTIFYTYPE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_pscreatethreadnotifytype\r\n[msdn.PSCREATEPROCESSNOTIFYTYPE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ne-ntddk-_pscreateprocessnotifytype\r\n[msdn.IRP_MJ_CLEANUP]: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-cleanup\r\n[msdn.NtCreateSection]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-zwcreatesection\r\n[msdn.SEC_IMAGE]: https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga\r\n[msdn.IRP_MJ_ACQUIRE_FOR_SECTION_SYNCHRONIZATION]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/flt-parameters-for-irp-mj-acquire-for-section-synchronization\r\n[msdn.IRP_MJ_WRITE]: https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/irp-mj-write \r\n[msdn.FILE_OBJECT]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_file_object\r\n[msdn.SECTION_OBJECT_POINTERS]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/ns-wdm-_section_object_pointers\r\n[msdn.PS_CREATE_NOTIFY_INFO]: https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/ns-ntddk-_ps_create_notify_info\r\n\r\n[//]: # (Relative Path IDs)\r\n[gif.ProcessHerpaderp]: res/ProcessHerpaderp.gif\r\n[gif.SurivDemo]: res/SurivDemo.gif\r\n[png.procmon]: res/procmon.png\r\n[png.mimioogle]: res/mimioogle.png\r\n[svg.StateDiagram]: res/StateDiagram.svg\r\n[png.HerpaderpIcon]: res/HerpaderpIcon.png\r\n[md.DivingDeeper]: res/DivingDeeper.md","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjxy-s%2Fherpaderping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjxy-s%2Fherpaderping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjxy-s%2Fherpaderping/lists"}