Hi, Mom!
1
Living Under the Land�On Linux
Stuart McMurray
BSides Belfast ~ 11 September 2025
$ whoami
/* TODO: Twitter QR code here */
3
$ whoami
/* TODO: Twitter QR code here */
4
Red Teamer
$ whoami
/* TODO: Twitter QR code here */
5
Attender of Meetings
Disclaimers
6
Up Next...
Very roughly, with some other bits in there as well
7
A Simple Shell
8
Initial access
9
Curlrevshell - Listening
10
Curlrevshell - The General Idea
11
Curlrevshell - The General Idea
12
Curlrevshell - The General Idea
13
https://not-h4x.lol/$ID/o
https://not-h4x.lol/$ID/i
Curlrevshell - The General Idea
14
Output
Commands
Curlrevshell - The General Idea
15
Shell Stdout/Stderr via Curl
Shell Stdin via Curl
Curlrevshell - The General Idea
16
Shell Stdout/Stderr via Curl
Shell Stdin via Curl
Syscalls
Callback
17
Callback
18
Callback
19
Callback
20
Callback
21
Callback
22
Callback
23
Callback
24
Situational Awareness
25
Situational Awareness - An admin?
26
Situational Awareness - EDR, such as it is
27
Situational Awareness - The other end of exploit.sh
28
Situational Awareness - Kinda goofy
29
Situational Awareness - Not root
30
Situational Awareness - No custom code (yet)
31
Situational Awareness - Probably not in a container
32
A Simple Shell - So...?
33
tl;dr - We type things, target does things
A Simple Shell - So...?
34
tl;dr - We type things, target does things
I'm a Teal Deer...
Things which aren't quite Hacking yet
35
Things which aren't quite Hacking yet
36
Philosophical Rambling
- Mrs. McMurray
Back to the shell
37
Back to the shell - "Us"
38
Back to the shell - A command
39
Back to the shell - A program
40
Back to the shell - Programs
41
The bulk of Linux theft: Reading files
42
The bulk of Linux theft: Reading files
43
The bulk of Linux theft: Reading files
44
The bulk of Linux theft: Reading files
45
Or read(2)ing files
46
Or read(2)ing files
47
Or read(2)ing files
48
Or read(2)ing files - Argv
49
Or read(2)ing files - "The command"
50
Or read(2)ing files
51
Or read(2)ing files - open(2)
52
Or read(2)ing files - read(2)
53
Or read(2)ing files - The important part
54
openat(2) - Prep
55
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | |
rdi | Directory FD | |
rsi | *Pathname | |
rdx | Flags | |
You are here
openat(2) - Prep
56
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | |
rsi | *Pathname | |
rdx | Flags | |
You are here
openat(2) - Prep
57
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | |
rdx | Flags | |
You are here
openat(2) - Prep
58
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | |
You are here
openat(2) - Prep
59
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | |
You are here
openat(2) - Prep
60
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | |
You are here
openat(2) - Prep
61
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | O_RDONLY (0) |
You are here
openat(2) - Kernel
62
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | O_RDONLY (0) |
Pid | FD | Inode | Device |
| | | |
You are here
openat(2) - Kernel
63
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 257 |
rdi | Directory FD | AT_FCWD (-100) |
rsi | *Pathname | 0xOverHere |
rdx | Flags | O_RDONLY (0) |
Pid | FD | Inode | Device |
477234 | 3 | 1408718 | 0,20 |
You are here
openat(2) - Kernel
64
/proc/476982/environ\x00
Memory
Registers | ||
rax | File Descriptor | 3 |
rdi | | |
rsi | | |
rdx | | |
Pid | FD | Inode | Device |
477234 | 3 | 1408718 | 0,20 |
You are here
openat(2) - Return
65
/proc/476982/environ\x00
Memory
Registers | ||
rax | File Descriptor | 3 |
rdi | | |
rsi | | |
rdx | | |
You are here
read(2) - Prep
66
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | |
rdi | FD | |
rsi | *Buffer | |
rdx | Size | |
You are here
read(2) - Prep
67
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | |
rsi | *Buffer | |
rdx | Size | |
You are here
read(2) - Prep
68
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 3 |
rsi | *Buffer | |
rdx | Size | |
You are here
read(2) - Prep
69
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 3 |
rsi | *Buffer | 0xOverThere |
rdx | Size | 131072 |
You are here
read(2) - Prep
70
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 3 |
rsi | *Buffer | 0xOverThere |
rdx | Size | 131072 |
You are here
read(2) - Prep
71
/proc/476982/environ\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 3 |
rsi | *Buffer | 0xOverThere |
rdx | Size | 131072 |
You are here
read(2) - Return
72
/proc/476982/environ\x00
PATH=/home/wurzel/bin:/home/wurzel/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games\x00VULNERABLE_SERVER_PASSWORD=b6974f35b717c68ee1455840c884c4ac\x00SHELL=/bin/bash\x00PWD=/home/wurzel\x00LOGNAME=wurzel\x00XDG_SESSION_TYPE=tty\x00MOTD_SHOWN=pam\x00HOME=/home/wurzel\x00LANG=C.UTF-8\x00XDG_SESSION_CLASS=user\x00USER=wurzel\x00SHLVL=0\x00XDG_SESSION_ID=565\x00XDG_RUNTIME_DIR=/run/user/1000\x00DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus\x00_=/home/wurzel/bin/vulnerableserver\x00
Memory
Registers | ||
rax | Number of bytes read | 454 |
rdi | | |
rsi | | |
rdx | | |
You are here
write(2) - Prep
73
/proc/476982/environ\x00
PATH=/home/wurzel/bin:/home/wurzel/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games\x00VULNERABLE_SERVER_PASSWORD=b6974f35b717c68ee1455840c884c4ac\x00SHELL=/bin/bash\x00PWD=/home/wurzel\x00LOGNAME=wurzel\x00XDG_SESSION_TYPE=tty\x00MOTD_SHOWN=pam\x00HOME=/home/wurzel\x00LANG=C.UTF-8\x00XDG_SESSION_CLASS=user\x00USER=wurzel\x00SHLVL=0\x00XDG_SESSION_ID=456\x00XDG_RUNTIME_DIR=/run/user/1000\x00DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus\x00_=/home/wurzel/bin/vulnerableserver\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 1 |
rsi | *Buffer | 0xOverThere |
rdx | Size | 454 |
You are here
write(2) - Stdout
74
/proc/476982/environ\x00
PATH=/home/wurzel/bin:/home/wurzel/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games\x00VULNERABLE_SERVER_PASSWORD=b6974f35b717c68ee1455840c884c4ac\x00SHELL=/bin/bash\x00PWD=/home/wurzel\x00LOGNAME=wurzel\x00XDG_SESSION_TYPE=tty\x00MOTD_SHOWN=pam\x00HOME=/home/wurzel\x00LANG=C.UTF-8\x00XDG_SESSION_CLASS=user\x00USER=wurzel\x00SHLVL=0\x00XDG_SESSION_ID=456\x00XDG_RUNTIME_DIR=/run/user/1000\x00DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus\x00_=/home/wurzel/bin/vulnerableserver\x00
Memory
Registers | ||
rax | Syscall number | 0 |
rdi | FD | 1 |
rsi | *Buffer | 0xOverThere |
rdx | Size | 454 |
You are here
write(2) - Return
75
/proc/476982/environ\x00
PATH=/home/wurzel/bin:/home/wurzel/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games\x00VULNERABLE_SERVER_PASSWORD=b6974f35b717c68ee1455840c884c4ac\x00SHELL=/bin/bash\x00PWD=/home/wurzel\x00LOGNAME=wurzel\x00XDG_SESSION_TYPE=tty\x00MOTD_SHOWN=pam\x00HOME=/home/wurzel\x00LANG=C.UTF-8\x00XDG_SESSION_CLASS=user\x00USER=wurzel\x00SHLVL=0\x00XDG_SESSION_ID=456\x00XDG_RUNTIME_DIR=/run/user/1000\x00DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus\x00_=/home/wurzel/bin/vulnerableserver\x00
Memory
Registers | ||
rax | Number of bytes written | 454 |
rdi | | |
rsi | | |
rdx | | |
write(2) - Return
76
/proc/476982/environ\x00
PATH=/home/wurzel/bin:/home/wurzel/bin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games\x00VULNERABLE_SERVER_PASSWORD=b6974f35b717c68ee1455840c884c4ac\x00SHELL=/bin/bash\x00PWD=/home/wurzel\x00LOGNAME=wurzel\x00XDG_SESSION_TYPE=tty\x00MOTD_SHOWN=pam\x00HOME=/home/wurzel\x00LANG=C.UTF-8\x00XDG_SESSION_CLASS=user\x00USER=wurzel\x00SHLVL=0\x00XDG_SESSION_ID=456\x00XDG_RUNTIME_DIR=/run/user/1000\x00DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus\x00_=/home/wurzel/bin/vulnerableserver\x00
Memory
Registers | ||
rax | Number of bytes written | 454 |
rdi | | |
rsi | | |
rdx | | |
What are the system calls?
77
It's programs/syscalls/turtles all the way down
78
It's programs/syscalls/turtles all the way down
79
It's programs/syscalls/turtles all the way down
80
It's programs/syscalls/turtles all the way down
81
It's programs/syscalls/turtles all the way down
82
It's programs/syscalls/turtles all the way down
83
It's programs/syscalls/turtles all the way down
84
It's programs/syscalls/turtles all the way down
85
It's programs/syscalls/turtles all the way down
86
It's programs/syscalls/turtles all the way down
87
It's programs/syscalls/turtles all the way down
88
It's programs/syscalls/turtles all the way down
89
It's programs/syscalls/turtles all the way down
90
It's programs/syscalls/turtles all the way down
91
It's programs/syscalls/turtles all the way down
92
It's programs/syscalls/turtles all the way down
93
Turtles are connected by pipes and file descriptors
94
Turtles are connected by pipes and file descriptors
95
Turtles are connected by pipes and file descriptors
96
Turtles are connected by pipes and file descriptors
97
Turtles are connected by pipes and file descriptors
98
Turtles are connected by pipes and file descriptors
99
Turtles are connected by pipes and file descriptors
100
Turtles are connected by pipes and file descriptors
101
Turtles are connected by pipes and file descriptors
102
Turtles are connected by pipes and file descriptors
103
Turtles are connected by pipes and file descriptors
104
Turtles are connected by pipes and file descriptors
105
Turtles are connected by pipes and file descriptors
106
Turtles are connected by pipes and file descriptors
107
Turtles are connected by pipes and file descriptors
108
Turtles are connected by pipes and file descriptors
109
Turtles are connected by pipes and file descriptors
110
Turtles are connected by pipes and file descriptors
111
Turtles are connected by pipes and file descriptors
112
Turtles are connected by pipes and file descriptors
113
Turtles are connected by pipes and file descriptors
114
Turtles are connected by pipes and file descriptors
115
Turtles are connected by pipes and file descriptors
116
Curlrevshell - Turtle Power!
117
Shell Stdout/Stderr via Curl
Syscalls
Cowabunga!!!
id
Aside: OpenBSD's ktrace(1)
118
Aside: OpenBSD's ktrace(1)
119
Aside: OpenBSD's ktrace(1)
120
Aside: OpenBSD's ktrace(1)
121
Aside: OpenBSD's ktrace(1)
122
Aside: OpenBSD's ktrace(1)
123
Aside: OpenBSD's ktrace(1)
124
perl -ne 's/.*proctitle=\"(.*)\"/\1/||
s/.*proctitle=(.*)/pack"H*",$1/e||s/.*//s;s/\0/ /g;' /var/log/audit/audit.log
125
Regex in a trenchcoat
126
That's the whole thing, no response actions
127
ed(1)
128
The Blue Team's favorite* syscall: execve(2)
129
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
130
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
131
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
132
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
133
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
134
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
135
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
136
* This statement not endorsed by...
The Blue Team's favorite* syscall: execve(2)
137
* ...well, anybody, really.
The Blue Team's favorite syscall: execve(2)
Screenshot: tail -n 20 /var/log/procrastinationedr.log
EDR is regex in a trenchcoat
Don't see the echos
which/type difference for echo
TODO: Delete this
138
That's quite enough not hacking for now
N is just N+1 with extra steps...
139
That's quite enough not hacking for now
N is just N+1 with extra steps...
140
tl;dr - We just want the right syscalls in the right order
H4x
141
Root -> SIGSTOP EDR
142
Root -> SIGSTOP EDR
143
Root -> SIGSTOP EDR
144
Root -> SIGSTOP EDR
145
Root -> SIGSTOP EDR
146
Root -> SIGSTOP EDR
147
Root -> SIGSTOP EDR
148
Root -> SIGSTOP EDR
149
Root -> SIGSTOP EDR
150
Root -> SIGSTOP EDR
151
Root -> SIGSTOP EDR
152
Visible data-grabbing - cat(1)/argv
153
Visible data-grabbing - cat(1)/argv
154
Visible data-grabbing - cat(1)/argv
155
Less-visible data-grabbing - cat(1), sneakier
156
Less-visible data-grabbing - cat(1), sneakier
157
Less-visible data-grabbing - cat(1), sneakier
158
Less-visible data-grabbing - cat(1)less file redirection
159
Less-visible data-grabbing - cat(1)less file redirection
160
Less-visible data-grabbing - cat(1)less file redirection
161
Less-visible data-grabbing - cat(1)less file redirection
162
Invisible data-grabbing - read(2) without execve(2)
163
Invisible data-grabbing - read(2) without execve(2)
164
Invisible data-grabbing - read(2) without execve(2)
165
Invisible data-grabbing - read(2) without execve(2)
166
Invisible data-grabbing - read(2) without execve(2)
167
Invisible data-grabbing - read(2) without execve(2)
168
Invisible data-grabbing - read(2) without execve(2)
169
Invisible data-grabbing - read(2) without execve(2)
170
Invisible data-grabbing - read(2) without execve(2)
171
Invisible data-grabbing - read(2) without execve(2)
172
Invisible data-grabbing - read(2) without execve(2)
173
Invisible data-grabbing - read(2) without execve(2)
174
Invisible data-grabbing - read(2) without execve(2)
175
Invisible data-processing - coreutils without execve(2)
176
Invisible data-processing - coreutils without execve(2)
177
Invisible data-processing - coreutils without execve(2)
178
Invisible data-processing - coreutils without execve(2)
179
Invisible data-processing - coreutils without execve(2)
180
Invisible data-processing - coreutils without execve(2)
181
Invisible data-processing - coreutils without execve(2)
182
Invisible data-processing - coreutils without execve(2)
183
curlrevshell -ctrl-i crs/ctrl-i
184
curlrevshell -ctrl-i crs/ctrl-i
185
Text streams are a universal interface, except NULs
186
Text streams are a universal interface, except NULs
187
Text streams are a universal interface, except NULs
188
Text streams are a universal interface, except NULs
189
Text streams are a universal interface, except NULs
190
Text streams are a universal interface, except NULs
191
Text streams are a universal interface, except NULs
192
Text streams are a universal interface, except NULs
193
Text streams are a universal interface, except NULs
194
Text streams are a universal interface, except NULs
195
Text streams are a universal interface, except NULs
196
Text streams are a universal interface, except NULs
197
Text streams are a universal interface, except NULs
198
Text streams are a universal interface, except NULs
199
Situational awareness with less ED(R?) awareness
200
Situational awareness with less ED(R?) awareness
201
Situational awareness with less ED(R?) awareness
202
Shell Gymnastics
A recap
203
Shell Gymnastics
A recap
204
tl;dr - We make syscalls, kernel does things
socket(2)/connect(2)/math/read(2)/write(2)
205
Math
Math
Shell Stdout/Stderr via TLS
Shell Stdin via TLS
Syscalls
We'll look at that curl thing later
206
We'll look at that curl thing later
207
We'll look at that curl thing later
208
Original curl
209
What the original curl did
210
What the original curl did but all pretty
211
What the original curl did but all pretty
212
What the original curl did but all pretty
213
What the original curl did but all pretty
214
What the original curl did but all pretty
215
What the original curl did but all pretty
216
Less-bad curl execve(2)
217
Less-bad curl execve(2)
218
Less-bad curl execve(2)
219
Less-bad curl execve(2)
220
Less-bad curl execve(2)
221
Less-bad curl execve(2)
222
Less-bad curl execve(2)
223
Less-bad curl execve(2)
224
Less-bad curl execve(2)
225
Less-bad curl execve(2)
226
Less-bad curl execve(2)
227
Less-bad curl execve(2)
228
Less-bad curl execve(2)
229
Less-bad curl execve(2)
230
Less-bad curl execve(2)
231
Less-bad curl execve(2)
232
Less-bad curl execve(2)
233
Less-bad curl execve(2)
234
Less-bad curl execve(2)
235
Less-bad curl execve(2)
236
Less-bad curl execve(2)
237
Less-bad curl execve(2)
238
Less-bad curl execve(2)
239
Less-bad curl execve(2)
240
Slightly more execve(2)
241
Slightly more execve(2)
242
Cat scan
243
Wow - Mrs. McMurray
244
Networking
Can you hear me now?
245
Networking
Can you hear me now?
246
tl;dr - Kernel moves packets about, we're happy
Curlrevshell - The General Idea (again)
247
https://not-h4x.lol/$ID/o
https://not-h4x.lol/$ID/i
Syscalls
Curlrevshell - The General Idea (again)
248
Syscalls
Curlrevshell - Now with fewer Curls (and more Gophers)
249
Syscalls
Curlrevshell - Now with fewer Curls (and more Gophers)
250
https://not-h4x.lol/$ID/io
Syscalls
No custom code yet
251
No custom code yet
252
No custom code yet
253
No custom code yet
254
No custom code yet
255
No custom code yet
256
No custom code yet
257
No custom code yet
258
No custom code yet
259
No custom code yet
260
No custom code yet
261
Go is "easy" to compile
262
Go is "easy" to compile
263
Go is "easy" to compile
264
Go is "easy" to compile
265
Go is "easy" to compile
266
Uploading is just write(2)
267
Uploading is just write(2)
268
Uploading is just write(2)
269
Uploading is just write(2)
270
Uploading is just write(2)
271
Uploading is just write(2)
272
Uploading is just write(2)
273
Uploading is just write(2)
274
Uploading is just write(2)
275
Curlrevshell, the reverse bit
276
Curlrevshell, the reverse bit
277
Curlrevshell, the reverse bit
278
Curlrevshell, the reverse bit
279
Curlrevshell, the reverse bit
280
Curlrevshell, the reverse bit
281
Stealth is the eye of the EDR-holder
282
Stealth is the eye of the EDR-holder
283
On Linux, everything is a file (descriptor)
284
Memory we have mapped (mmap(2)'d)
285
Files we shouldn't have mapped
286
Files we shouldn't have mapped
287
The plan
288
The plan
289
mmap(2)
The plan
290
Temporary Buffer
The plan
291
Copy
Temporary Buffer
The plan
292
Temporary Buffer
mremap(2)
The plan
293
mremap(2)
The plan
294
Gone
Sneaky Remap
295
Sneaky Remap
296
Sneaky Remap
297
Sneaky Remap
298
Sneaky Remap
299
Activating the cloak of invisibility
300
Activating the cloak of invisibility
301
Activating the cloak of invisibility
302
Activating the cloak of invisibility
303
Activating the cloak of invisibility
304
Activating the cloak of invisibility
305
Sneakily remapped
306
Sneakily remapped
307
Sneakily remapped
308
tl;dr
One last time...
309
tl;dr
One last time...
310
tl;dr - The important thing is the syscalls
Thanks :)
Questions?
311
Thanks :)
No time for questions :(
312