Update README

This commit is contained in:
DB
2026-03-08 15:14:19 +05:30
parent 2de212bc9b
commit 45c76ad2f5
2 changed files with 73 additions and 16 deletions
+65 -1
View File
@@ -1 +1,65 @@
# StackTracer
# StackTracer
[!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/whokilleddb)
The goal of this project is find valid stack frames which you can replicate in your payloads. In C2s like BRC4, you can specify a stack frame which looks legit - and this can help in increasing the evasiveness of your shellcode. Using this tool you can examine legit processes for their stack frames and copy them over.
## Building
Building this tool is as easy as rust makes it:
```
$ cargo build --release
```
Note that you might need to install the `x86_64-pc-windows-gnu` toolchain
## Usage:
To view a detailed usage guide, you can pass the `--help` flag:
```
Z:\> stackfinder.exe --help
_____ _ _ _______
/ ____| | | |__ __|
| (___ | |_ __ _ ___| | _| |_ __ __ _ ___ ___ _ __
\___ \| __/ _` |/ __| |/ / | '__/ _` |/ __/ _ \ '__|
____) | || (_| | (__| <| | | | (_| | (_| __/ |
|_____/ \__\__,_|\___|_|\_\_|_| \__,_|\___\___|_|
DB @whokilleddb
A rust program to print the stack trace of a given thread
Usage: stackfinder.exe [OPTIONS] --pid <pid>
Options:
--pid <pid> Process ID
--tid <tid> Thread ID (defaults to 0) [default: 0]
--hide-banner Hide the banner
-h, --help Print help
-V, --version Print version
```
The only required option is the `--pid` flag. To enumerate a process without targetting a particular thread, you go like:
```
Z:\> stackfinder.exe --pid 1234
```
To enumerate a specific thread, you can specify the ThreadID using the `--tid` flag:
```
Z:\>.\stackfinder.exe --pid 3688 --tid 7336
_____ _ _ _______
/ ____| | | |__ __|
| (___ | |_ __ _ ___| | _| |_ __ __ _ ___ ___ _ __
\___ \| __/ _` |/ __| |/ / | '__/ _` |/ __/ _ \ '__|
____) | || (_| | (__| <| | | | (_| | (_| __/ |
|_____/ \__\__,_|\___|_|\_\_|_| \__,_|\___\___|_|
DB @whokilleddb
PID | TID | STACK FRAME
3688 | 7336 | win32u.dll!NtUserWaitMessage+0x14,USER32.DLL!IsDialogMessageA+0x3ba,USER32.DLL!Ordinal2635+0x267,USER32.DLL!SoftModalMessageBox+0x5b6,USER32.DLL!MessageBoxIndirectA+0x562,USER32.DLL!MessageBoxTimeoutW+0x18f,USER32.DLL!MessageBoxTimeoutA+0x100,USER32.DLL!MessageBoxA+0x45,0x25c70680050,KERNEL32.DLL+0x0
```
_Hope this helps!_
+8 -15
View File
@@ -5,9 +5,8 @@ use std::path::Path;
use winapi::shared::minwindef::{DWORD, FALSE};
// use winapi::shared::ntdef::NULL;
use winapi::um::dbghelp::{
AddrModeFlat, IMAGEHLP_MODULEW64, STACKFRAME64, SYMBOL_INFOW, SYMOPT_DEFERRED_LOADS,
SYMOPT_UNDNAME, StackWalk64, SymFromAddrW, SymFunctionTableAccess64, SymGetModuleBase64,
SymGetModuleInfoW64,
AddrModeFlat, IMAGEHLP_MODULEW64, STACKFRAME64, SYMBOL_INFOW, StackWalk64, SymFromAddrW,
SymFunctionTableAccess64, SymGetModuleBase64, SymGetModuleInfoW64,
};
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::handleapi::CloseHandle;
@@ -18,9 +17,6 @@ use winapi::um::winnt::{
};
const MAX_SYM_NAME_LEN: usize = 512;
// ---------------------------------------------------------------------------
// Resolve a single PC address to "module.dll!Symbol+0xNN" / "module.dll+0xNN"
// ---------------------------------------------------------------------------
fn resolve_address(h_process: HANDLE, addr: u64) -> String {
unsafe {
@@ -41,9 +37,6 @@ fn resolve_address(h_process: HANDLE, addr: u64) -> String {
String::new()
};
// ── 2. Try to resolve to a symbol via SymFromAddrW ──
// SYMBOL_INFOW has a trailing `Name[1]` flexible-array member;
// we over-allocate to hold up to MAX_SYM_NAME_LEN wide characters.
let buf_size = mem::size_of::<SYMBOL_INFOW>() + MAX_SYM_NAME_LEN * mem::size_of::<u16>();
let mut buf = vec![0u8; buf_size];
let sym = buf.as_mut_ptr() as *mut SYMBOL_INFOW;
@@ -52,6 +45,7 @@ fn resolve_address(h_process: HANDLE, addr: u64) -> String {
let mut sym_displacement: u64 = 0;
// https://learn.microsoft.com/en-us/windows/win32/debug/retrieving-symbol-information-by-address
if SymFromAddrW(h_process, addr, &mut sym_displacement, sym) != 0 {
// We have a symbol name (wide)
let name_slice =
@@ -113,7 +107,7 @@ pub fn trace_thread_stack(pid: u32, h_process: HANDLE, tid: u32) {
frame.AddrStack.Mode = AddrModeFlat;
let mut entries: Vec<String> = Vec::new();
// ── Walk the stack ──
loop {
let ok = StackWalk64(
IMAGE_FILE_MACHINE_AMD64 as DWORD,
@@ -133,16 +127,15 @@ pub fn trace_thread_stack(pid: u32, h_process: HANDLE, tid: u32) {
entries.push(resolve_address(h_process, frame.AddrPC.Offset));
}
// ── Output ──
println!("PID\t| TID\t| STACK FRAME");
if entries.is_empty() {
println!("{} | {} | ", pid, tid);
println!("{}\t| {}\t| ", pid, tid);
} else {
println!("{} | {} | {}", pid, tid, entries.join(","));
println!("{}\t| {}\t| {}", pid, tid, entries.join(","));
}
break;
}
// Initialize DbgHelp symbol handler
// let opts = SymGetOptions();
if !h_thread.is_null() {
CloseHandle(h_thread);