What is it?
Three separate Rust programs demonstrating where shellcode can live inside a compiled binary — each placement choice has different memory characteristics, permissions at runtime, and detection profiles. A fourth variant shows loading shellcode from the binary’s resource section instead of embedding it in data sections.
How it works
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
| Placement 1: .data section (mutable static)
static mut DATA: [u8; 272] = [ 0xFC, 0x48, ... ];
Location: .data section of the PE on disk
Runtime: .data is loaded RW (read-write) by default
Must call VirtualProtect to make executable
Visibility: shellcode bytes appear in .data in IDA/PE tools
Address: &DATA → a writable memory address
Placement 2: .rdata section (immutable static)
static RDATA: [u8; 272] = [ 0xFC, 0x48, ... ];
Location: .rdata section (read-only data)
Runtime: .rdata is loaded RO (read-only) by default
Must call VirtualProtect to make writable+executable
Visibility: shellcode bytes appear in .rdata
Note: slightly less suspicious than .data (constant-looking data)
Placement 3: .text section (link_section attribute)
#[no_mangle]
#[link_section = ".text"]
static TEXT_SECTION: [u8; 272] = [ 0xFC, 0x48, ... ];
Location: .text section alongside actual compiled code
Runtime: .text is already RX (read-execute) — no VirtualProtect needed
Shellcode can execute directly from .text
Stealthier: executable memory with a file backing (the binary itself)
Not anonymous private allocation — looks like legitimate code
Caveat: .text content is compared against file on disk by memory scanners
Placement 4: .rsrc section (resource embedding)
FindResourceW(null_module,
MAKEINTRESOURCEW(1337),
RT_RCDATA)
→ hResourceInfo
LoadResource(null_module, hResourceInfo) → hLoadedResource
LockResource(hLoadedResource) → resource_ptr (raw pointer to .rsrc data)
SizeofResource(null_module, hResourceInfo) → resource_size
resource_ptr: shellcode lives in .rsrc section
Advantage: many static scanners skip resource sections
or only scan known resource types (icons, strings)
Custom RT_RCDATA with ID 1337 is obscure
Comparison:
Section │ Default perms │ VirtualProtect needed │ Detectability
.data │ RW │ Yes (add X) │ High (obvious shellcode bytes)
.rdata │ RO │ Yes (add W+X) │ High
.text │ RX │ No │ Medium (file-backed, looks like code)
.rsrc │ RO │ Yes (add W+X) │ Lower (often skipped by scanners)
|
The .text placement is the most operationally interesting — shellcode embedded alongside compiled code inherits the section’s execute permission without needing a VirtualProtect call. The memory region is backed by the binary itself (not anonymous private memory), which bypasses the common “executable anonymous region” detection heuristic. The downside is that disk-vs-memory comparison tools (PE-sieve) will flag the mismatch between what’s in .text on disk and what’s actually there at runtime.
demo.c
1
2
3
4
5
| #include <stdio.h>
int main() {
printf("[+] This is Metadata Modification Demo");
}
|
resource.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
| //
// Microsoft Visual C++ generated include file.
// Used by MetaData-Modification.rc
//
#define IDR_ACCELERATOR1 101
#define IDI_ICON1 102
#define IDI_ICON2 103
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40002
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
|