I analyzed a creature trying to spawn new processes for survival and thought of a new technique.
During my tests, I successfully detected “Grandchild Processes Spawned by Malware”.
Let me first talk about the problem :
“We have a creature named MalDaddy and he wants to raise a child (MalChild) to survive and divide his evil activities in order to attract less attention. There is even a grandchild (MalGrandchild) and even a great-grandchild…”
Technically, we can detect the parent process of a spawned process with the help of the “InheritedFromUniqueProcessId” value in the EPROCESS structure.
1: kd> dt nt!_EPROCESS
+0x260 Job : Ptr64 _EJOB
+0x268 SectionObject : Ptr64 Void
+0x270 SectionBaseAddress : Ptr64 Void
+0x278 Cookie : Uint4B
+0x27c UmsScheduledThreads : Uint4B
+0x280 WorkingSetWatch : Ptr64 _PAGEFAULT_HISTORY
+0x288 Win32WindowStation : Ptr64 Void
+0x290 InheritedFromUniqueProcessId : Ptr64 Void
We can detect the parent process of a newly-created process by checking this field (of course, there are easier ways).
The Windows Internals book says:
“Processes whose parents aren’t alive are left-justified (as is Explorer.exe in the preceding example) because
even if a grandparent process exists, there’s no way to find that relationship. Windows
maintains only the creator process ID, not a link back to the creator of the creator, and
Following the link backwards, it is possible to detect relationships between processes. This is what ProcessExplorer does.
What if a spawned process (MalChild) clears this field in kernel mode or spawns a new process (MalGrandchild)? What if the MalChild process terminates and only MalDaddy and MalGranchild continue to execute?
Here is what i suggest :
Fact 1: Each process has a Handle Table
Fact 2: Each handle holds a pointer to its Object.
Fact 3: Each inherited handle has the same index in the handle table as MalDaddy’s handles and would be inheritable.
Malware spawns processes with at least one handle flagged with “Inherit Handle”.
My answer to the problem is enumerating MalDaddy’s handle-table’s “Inherited Handles” and testing those indexes against running processes. This way we can easily detect processes with the same parent with accuracy. It is unlikely to see two different processes with the same objects indexed with the same offset in their handle tables.