I've finally had the displeasure of witnessing thread pool injection first hand while investigating a sample today.

The sample is heavily obfuscated with CFF and strings are encrypted as well so it was already fairly challenging to reverse. I spent hours looking up and down trying to figure out why I'm not seeing any allocation calls, typical remote injection techniques, and how are processes being spawned without NtCreateUserProcess. All I saw was a file being written to with nothing interesting inside, and somehow 2 new processes have spawned with the parent being sihost.

Turns out it was using thread pool injection via sihost by hijacking a IoCompletion handle from it, mapping the payload into a new section, mapping the section to sihost alongside a fake thread pool struct, and then writing the temp file to trigger the IoCompletion and thereby triggering the callback which runs the "injected" call.

The thing is it's not my first time seeing thread pool injection, at least I had studied it briefly in proof of concept before with the PoolParty technique a few years back, but it did not occur to me until I looked far deeper.

This was such an annoying sample to look at, and it really shows I still don't know enough about these in practice.