You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+24-24Lines changed: 24 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -46,17 +46,29 @@ _(the above image was borrowed from **Eli Bendersky's** post named [Stack frame
46
46
This precise logic is provided by `walkCallStack` and `spoofCallStack` functions in `main.cpp`.
47
47
48
48
49
-
## Actually this is not (yet) a true stack spoofing
49
+
## Demo
50
50
51
-
As it's been pointed out to me, the technique here is not _yet_ truly holding up to its name for being a _stack spoofer_. Since we're merely overwriting return addresses on the thread's stack, we're not spoofing the remaining areas of the stack itself. Moreover we leave a sequence of `::CreateFileW` addresses which looks very odd and let the thread be unable to unwind its stack. That's because `CreateFile` was meant to solely act as an example, we're making the stack non-unwindable but still obscuring references to our shellcode memory pages.
51
+
This is how a call stack may look like when it is **NOT** spoofed:
52
52
53
-
However I'm aware of these shortcomings, at the moment I've left it as is since I cared mostly about evading automated scanners that could iterate over processes, enumerate their threads, walk those threads stacks and pick up on any return address pointing back to a non-image memory (such as `SEC_PRIVATE` - the one allocated dynamically by `VirtuaAlloc` and friends). A focused malware analyst would immediately spot the oddity and consider the thread rather unusual, hunting down our implant. More than sure about it. Yet, I don't believe that nowadays automated scanners such as AV/EDR have sorts of heuristics implemented that would _actually walk each thread's stack_ to verify whether its un-windable `¯\_(ツ)_/¯` .
53
+

54
54
55
-
Surely this project (and commercial implementation found in C2 frameworks) gives AV & EDR vendors arguments to consider implementing appropriate heuristics covering such a novel evasion technique.
55
+
This in turn, when thread stack spoofing is enabled:
56
56
57
-
The research on the subject is not yet finished and hopefully will result in a better quality _Stack Spoofing_ in upcoming days. Nonetheless, I'm releasing what I got so far in hope of sparkling inspirations and interest community into further researching this area.
57
+

58
58
59
-
Next areas improving the outcome are to research how we can _exchange_ or copy stacks (utilising [`GetCurrentThreadStackLimits`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadstacklimits)/`NtQueryInformationThread`) from a legitimate thread running `kernel32!Sleep(INFINITE)` or possibly by manipulating our Beacon's thread `TEB/TIB` structures and fields such as `TebBaseAddress` providing shadowed TEB. Another idea would be to play with `RBP/EBP` and `RSP/ESP` pointers on a paused Beacon's thread to change stacks in a similar manner to ROP chains.
59
+
Above we can see a sequence of `kernel32!CreateFileW` being implanted as return addresses. That's merely an example proving that we can manipulate return addresses.
60
+
To better enhance quality of this call stack, one could prepare a list of addresses and then use them while picking subsequent frames for overwriting.
61
+
62
+
For example, a following chain of addresses could be used:
63
+
64
+
```
65
+
KernelBase.dll!WaitForSingleObjectEx+0x8e
66
+
KernelBase.dll!WaitForSingleObject+0x52
67
+
kernel32!BaseThreadInitThunk+0x14
68
+
ntdll!RtlUserThreadStart+0x21
69
+
```
70
+
71
+
When thinking about AVs, EDRs and other automated scanners - we don't need to care about how much legitimate our thread's call stack look, since these scanners only care whether a frame points back to a `SEC_IMAGE` memory pages, meaning it was a legitimate DLL/EXE call (and whether these DLLs are trusted/signed themselves). Thus, we don't need to bother that much about these chain of `CreateFileW` frames.
60
72
61
73
62
74
## How do I use it?
@@ -72,29 +84,17 @@ While developing your advanced shellcode loader, you might also want to implemen
72
84
-**Unhook everything you might have hooked** (such as AMSI, ETW, WLDP) before sleeping and then re-hook afterwards.
73
85
74
86
75
-
## Demo
76
-
77
-
This is how a call stack may look like when it is **NOT** spoofed:
78
-
79
-

80
-
81
-
This in turn, when thread stack spoofing is enabled:
87
+
## Actually this is not (yet) a true stack spoofing
82
88
83
-

89
+
As it's been pointed out to me, the technique here is not _yet_ truly holding up to its name for being a _stack spoofer_. Since we're merely overwriting return addresses on the thread's stack, we're not spoofing the remaining areas of the stack itself. Moreover we leave a sequence of `::CreateFileW` addresses which looks very odd and let the thread be unable to unwind its stack. That's because `CreateFile` was meant to solely act as an example, we're making the stack non-unwindable but still obscuring references to our shellcode memory pages.
84
90
85
-
Above we can see a sequence of `kernel32!CreateFileW` being implanted as return addresses. That's merely an example proving that we can manipulate return addresses.
86
-
To better enhance quality of this call stack, one could prepare a list of addresses and then use them while picking subsequent frames for overwriting.
91
+
However I'm aware of these shortcomings, at the moment I've left it as is since I cared mostly about evading automated scanners that could iterate over processes, enumerate their threads, walk those threads stacks and pick up on any return address pointing back to a non-image memory (such as `SEC_PRIVATE` - the one allocated dynamically by `VirtuaAlloc` and friends). A focused malware analyst would immediately spot the oddity and consider the thread rather unusual, hunting down our implant. More than sure about it. Yet, I don't believe that nowadays automated scanners such as AV/EDR have sorts of heuristics implemented that would _actually walk each thread's stack_ to verify whether its un-windable `¯\_(ツ)_/¯` .
87
92
88
-
For example, a following chain of addresses could be used:
93
+
Surely this project (and commercial implementation found in C2 frameworks) gives AV & EDR vendors arguments to consider implementing appropriate heuristics covering such a novel evasion technique.
89
94
90
-
```
91
-
KernelBase.dll!WaitForSingleObjectEx+0x8e
92
-
KernelBase.dll!WaitForSingleObject+0x52
93
-
kernel32!BaseThreadInitThunk+0x14
94
-
ntdll!RtlUserThreadStart+0x21
95
-
```
95
+
The research on the subject is not yet finished and hopefully will result in a better quality _Stack Spoofing_ in upcoming days. Nonetheless, I'm releasing what I got so far in hope of sparkling inspirations and interest community into further researching this area.
96
96
97
-
When thinking about AVs, EDRs and other automated scanners - we don't need to care about how much legitimate our thread's call stack look, since these scanners only care whether a frame points back to a `SEC_IMAGE` memory pages, meaning it was a legitimate DLL/EXE call (and whether these DLLs are trusted/signed themselves). Thus, we don't need to bother that much about these chain of `CreateFileW` frames.
97
+
Next areas improving the outcome are to research how we can _exchange_ or copy stacks (utilising [`GetCurrentThreadStackLimits`](https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentthreadstacklimits)/`NtQueryInformationThread`) from a legitimate thread running `kernel32!Sleep(INFINITE)` or possibly by manipulating our Beacon's thread `TEB/TIB` structures and fields such as `TebBaseAddress` providing shadowed TEB. Another idea would be to play with `RBP/EBP` and `RSP/ESP` pointers on a paused Beacon's thread to change stacks in a similar manner to ROP chains.
0 commit comments