seccomp-tools 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +105 -17
- data/ext/ptrace/ptrace.c +56 -4
- data/lib/seccomp-tools/asm/asm.rb +8 -6
- data/lib/seccomp-tools/asm/compiler.rb +130 -224
- data/lib/seccomp-tools/asm/sasm.tab.rb +780 -0
- data/lib/seccomp-tools/asm/sasm.y +175 -0
- data/lib/seccomp-tools/asm/scalar.rb +129 -0
- data/lib/seccomp-tools/asm/scanner.rb +163 -0
- data/lib/seccomp-tools/asm/statement.rb +32 -0
- data/lib/seccomp-tools/asm/token.rb +29 -0
- data/lib/seccomp-tools/bpf.rb +31 -7
- data/lib/seccomp-tools/cli/asm.rb +3 -3
- data/lib/seccomp-tools/cli/base.rb +4 -4
- data/lib/seccomp-tools/cli/disasm.rb +27 -3
- data/lib/seccomp-tools/cli/dump.rb +4 -2
- data/lib/seccomp-tools/cli/emu.rb +1 -4
- data/lib/seccomp-tools/const.rb +37 -3
- data/lib/seccomp-tools/consts/sys_nr/aarch64.rb +284 -0
- data/lib/seccomp-tools/consts/sys_nr/amd64.rb +5 -1
- data/lib/seccomp-tools/consts/sys_nr/i386.rb +14 -14
- data/lib/seccomp-tools/consts/sys_nr/s390x.rb +365 -0
- data/lib/seccomp-tools/disasm/context.rb +2 -2
- data/lib/seccomp-tools/disasm/disasm.rb +16 -9
- data/lib/seccomp-tools/dumper.rb +12 -3
- data/lib/seccomp-tools/emulator.rb +5 -9
- data/lib/seccomp-tools/error.rb +31 -0
- data/lib/seccomp-tools/instruction/alu.rb +1 -1
- data/lib/seccomp-tools/instruction/base.rb +1 -1
- data/lib/seccomp-tools/instruction/jmp.rb +28 -10
- data/lib/seccomp-tools/instruction/ld.rb +5 -3
- data/lib/seccomp-tools/syscall.rb +23 -13
- data/lib/seccomp-tools/templates/asm.s390x.asm +26 -0
- data/lib/seccomp-tools/util.rb +3 -1
- data/lib/seccomp-tools/version.rb +1 -1
- metadata +38 -9
- data/lib/seccomp-tools/asm/tokenizer.rb +0 -169
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 898cc2a23df6443f39054c4b9027a576fb929729f74fc804ae82ae3b11c6772e
|
|
4
|
+
data.tar.gz: 0e07d2d1914ac7185135425d0e34f0dcb1b6100e977176d8bd9ce23f95a3f287
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec604fca33e16dd6ca77e923e34629338245828abdf3c97e9974d205a2306aa9ae0f3bc074b90e056790a8de86ed6484ab17ce190524b30394f2fda2b5dd9432
|
|
7
|
+
data.tar.gz: 399e5e77fa99de23f3ad5013c442fc29a800a261d04150ab0bd467744a9302601ca7c60e5570e4e65f423cf4c93e4eb4428ae3f33b97d6a64c223af13b342e47
|
data/README.md
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
[](https://dependabot.com)
|
|
1
|
+
[](https://github.com/david942j/seccomp-tools/actions)
|
|
3
2
|
[](https://codeclimate.com/github/david942j/seccomp-tools)
|
|
4
3
|
[](https://codeclimate.com/github/david942j/seccomp-tools)
|
|
5
4
|
[](https://codeclimate.com/github/david942j/seccomp-tools/coverage)
|
|
6
5
|
[](https://inch-ci.org/github/david942j/seccomp-tools)
|
|
6
|
+
[](https://www.rubydoc.info/github/david942j/seccomp-tools/)
|
|
7
7
|
[](http://choosealicense.com/licenses/mit/)
|
|
8
8
|
|
|
9
9
|
# Seccomp Tools
|
|
10
10
|
Provide powerful tools for seccomp analysis.
|
|
11
11
|
|
|
12
|
-
This project
|
|
13
|
-
Some features might be CTF-specific, but
|
|
12
|
+
This project targets to (but is not limited to) analyze seccomp sandbox in CTF pwn challenges.
|
|
13
|
+
Some features might be CTF-specific, but also useful for analyzing seccomp of real cases.
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
|
-
* Dump - Automatically dumps seccomp
|
|
17
|
-
* Disasm - Converts
|
|
18
|
-
-
|
|
19
|
-
-
|
|
16
|
+
* Dump - Automatically dumps seccomp BPF from execution file(s).
|
|
17
|
+
* Disasm - Converts seccomp BPF to a human readable format.
|
|
18
|
+
- With simple decompilation.
|
|
19
|
+
- With syscall names and arguments whenever possible.
|
|
20
20
|
- Colorful!
|
|
21
|
-
* Asm -
|
|
21
|
+
* Asm - Makes writing seccomp rules similar to writing codes.
|
|
22
22
|
* Emu - Emulates seccomp rules.
|
|
23
|
-
* Supports multi-
|
|
23
|
+
* Supports multi-architecture.
|
|
24
24
|
|
|
25
25
|
## Installation
|
|
26
26
|
|
|
@@ -54,6 +54,7 @@ $ seccomp-tools --help
|
|
|
54
54
|
|
|
55
55
|
$ seccomp-tools dump --help
|
|
56
56
|
# dump - Automatically dump seccomp bpf from execution file(s).
|
|
57
|
+
# NOTE : This function is only available on Linux.
|
|
57
58
|
#
|
|
58
59
|
# Usage: seccomp-tools dump [exec] [options]
|
|
59
60
|
# -c, --sh-exec <command> Executes the given command (via sh).
|
|
@@ -75,8 +76,8 @@ $ seccomp-tools dump --help
|
|
|
75
76
|
|
|
76
77
|
### dump
|
|
77
78
|
|
|
78
|
-
Dumps the seccomp
|
|
79
|
-
This work is done by the `ptrace` syscall.
|
|
79
|
+
Dumps the seccomp BPF from an execution file.
|
|
80
|
+
This work is done by utilizing the `ptrace` syscall.
|
|
80
81
|
|
|
81
82
|
NOTICE: beware of the execution file will be executed.
|
|
82
83
|
```bash
|
|
@@ -123,7 +124,7 @@ $ seccomp-tools dump spec/binary/twctf-2016-diary -f raw | xxd
|
|
|
123
124
|
|
|
124
125
|
### disasm
|
|
125
126
|
|
|
126
|
-
Disassembles the seccomp from raw
|
|
127
|
+
Disassembles the seccomp from raw BPF.
|
|
127
128
|
```bash
|
|
128
129
|
$ xxd spec/data/twctf-2016-diary.bpf | head -n 3
|
|
129
130
|
# 00000000: 2000 0000 0000 0000 1500 0001 0200 0000 ...............
|
|
@@ -169,7 +170,7 @@ $ seccomp-tools asm
|
|
|
169
170
|
# -f, --format FORMAT Output format. FORMAT can only be one of <inspect|raw|c_array|c_source|assembly>.
|
|
170
171
|
# Default: inspect
|
|
171
172
|
# -a, --arch ARCH Specify architecture.
|
|
172
|
-
# Supported architectures are <amd64|i386>.
|
|
173
|
+
# Supported architectures are <aarch64|amd64|i386|s390x>.
|
|
173
174
|
# Default: amd64
|
|
174
175
|
|
|
175
176
|
# Input file for asm
|
|
@@ -258,6 +259,83 @@ $ seccomp-tools asm spec/data/libseccomp.asm -f raw | seccomp-tools disasm -
|
|
|
258
259
|
|
|
259
260
|
```
|
|
260
261
|
|
|
262
|
+
Since v1.6.0 [not released yet], `asm` has switched to using a yacc-based syntax parser, hence supports more flexible and intuitive syntax!
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
$ cat spec/data/example.asm
|
|
266
|
+
# # An example of supported assembly syntax
|
|
267
|
+
# if (A == X)
|
|
268
|
+
# goto next # 'next' is a reserved label, means the next statement ("A = args[0]" in this example)
|
|
269
|
+
# else
|
|
270
|
+
# goto err_label # custom defined label
|
|
271
|
+
# A = args[0]
|
|
272
|
+
# if (
|
|
273
|
+
# A # put a comment here is also valid
|
|
274
|
+
# == 0x123
|
|
275
|
+
# ) goto disallow
|
|
276
|
+
# if (! (A & 0x1337)) # support bang in if-conditions
|
|
277
|
+
# goto 0 # equivalent to 'goto next'
|
|
278
|
+
# else goto 2 # goto $ + 2, 'mem[0] = A' in this example
|
|
279
|
+
# A = sys_number
|
|
280
|
+
# A = instruction_pointer >> 32
|
|
281
|
+
# mem[0] = A
|
|
282
|
+
# A = data[4] # equivalent to 'A = arch'
|
|
283
|
+
# err_label: return ERRNO(1337)
|
|
284
|
+
# disallow:
|
|
285
|
+
# return KILL
|
|
286
|
+
|
|
287
|
+
$ seccomp-tools asm spec/data/example.asm -f raw | seccomp-tools disasm -
|
|
288
|
+
# line CODE JT JF K
|
|
289
|
+
# =================================
|
|
290
|
+
# 0000: 0x1d 0x00 0x07 0x00000000 if (A != X) goto 0008
|
|
291
|
+
# 0001: 0x20 0x00 0x00 0x00000010 A = args[0]
|
|
292
|
+
# 0002: 0x15 0x06 0x00 0x00000123 if (A == 0x123) goto 0009
|
|
293
|
+
# 0003: 0x45 0x02 0x00 0x00001337 if (A & 0x1337) goto 0006
|
|
294
|
+
# 0004: 0x20 0x00 0x00 0x00000000 A = sys_number
|
|
295
|
+
# 0005: 0x20 0x00 0x00 0x0000000c A = instruction_pointer >> 32
|
|
296
|
+
# 0006: 0x02 0x00 0x00 0x00000000 mem[0] = A
|
|
297
|
+
# 0007: 0x20 0x00 0x00 0x00000004 A = arch
|
|
298
|
+
# 0008: 0x06 0x00 0x00 0x00050539 return ERRNO(1337)
|
|
299
|
+
# 0009: 0x06 0x00 0x00 0x00000000 return KILL
|
|
300
|
+
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
The output of `seccomp-tools disasm <file> --asm-able` is a valid input of `asm`:
|
|
304
|
+
```bash
|
|
305
|
+
$ seccomp-tools disasm spec/data/x32.bpf --asm-able
|
|
306
|
+
# 0000: A = arch
|
|
307
|
+
# 0001: if (A != ARCH_X86_64) goto 0011
|
|
308
|
+
# 0002: A = sys_number
|
|
309
|
+
# 0003: if (A < 0x40000000) goto 0011
|
|
310
|
+
# 0004: if (A == x32_read) goto 0011
|
|
311
|
+
# 0005: if (A == x32_write) goto 0011
|
|
312
|
+
# 0006: if (A == x32_iopl) goto 0011
|
|
313
|
+
# 0007: if (A != x32_mmap) goto 0011
|
|
314
|
+
# 0008: A = args[0]
|
|
315
|
+
# 0009: if (A == 0x0) goto 0011
|
|
316
|
+
# 0010: return ERRNO(5)
|
|
317
|
+
# 0011: return ALLOW
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
# disasm then asm then disasm!
|
|
321
|
+
$ seccomp-tools disasm spec/data/x32.bpf --asm-able | seccomp-tools asm - -f raw | seccomp-tools disasm -
|
|
322
|
+
# line CODE JT JF K
|
|
323
|
+
# =================================
|
|
324
|
+
# 0000: 0x20 0x00 0x00 0x00000004 A = arch
|
|
325
|
+
# 0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011
|
|
326
|
+
# 0002: 0x20 0x00 0x00 0x00000000 A = sys_number
|
|
327
|
+
# 0003: 0x35 0x00 0x07 0x40000000 if (A < 0x40000000) goto 0011
|
|
328
|
+
# 0004: 0x15 0x06 0x00 0x40000000 if (A == x32_read) goto 0011
|
|
329
|
+
# 0005: 0x15 0x05 0x00 0x40000001 if (A == x32_write) goto 0011
|
|
330
|
+
# 0006: 0x15 0x04 0x00 0x400000ac if (A == x32_iopl) goto 0011
|
|
331
|
+
# 0007: 0x15 0x00 0x03 0x40000009 if (A != x32_mmap) goto 0011
|
|
332
|
+
# 0008: 0x20 0x00 0x00 0x00000010 A = addr # x32_mmap(addr, len, prot, flags, fd, pgoff)
|
|
333
|
+
# 0009: 0x15 0x01 0x00 0x00000000 if (A == 0x0) goto 0011
|
|
334
|
+
# 0010: 0x06 0x00 0x00 0x00050005 return ERRNO(5)
|
|
335
|
+
# 0011: 0x06 0x00 0x00 0x7fff0000 return ALLOW
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
|
|
261
339
|
### Emu
|
|
262
340
|
|
|
263
341
|
Emulates seccomp given `sys_nr`, `arg0`, `arg1`, etc.
|
|
@@ -267,7 +345,7 @@ $ seccomp-tools emu --help
|
|
|
267
345
|
#
|
|
268
346
|
# Usage: seccomp-tools emu [options] BPF_FILE [sys_nr [arg0 [arg1 ... arg5]]]
|
|
269
347
|
# -a, --arch ARCH Specify architecture.
|
|
270
|
-
# Supported architectures are <amd64|i386>.
|
|
348
|
+
# Supported architectures are <aarch64|amd64|i386|s390x>.
|
|
271
349
|
# Default: amd64
|
|
272
350
|
# -q, --[no-]quiet Run quietly, only show emulation result.
|
|
273
351
|
|
|
@@ -300,6 +378,16 @@ $ seccomp-tools emu spec/data/libseccomp.bpf write 0x3
|
|
|
300
378
|
|
|
301
379
|

|
|
302
380
|
|
|
381
|
+
## Supported Architectures
|
|
382
|
+
|
|
383
|
+
- [x] x86_64
|
|
384
|
+
- [x] x32
|
|
385
|
+
- [x] x86
|
|
386
|
+
- [x] arm64 (@saagarjha)
|
|
387
|
+
- [x] s390x (@iii-i)
|
|
388
|
+
|
|
389
|
+
Pull Requests of adding more architectures support are welcome!
|
|
390
|
+
|
|
303
391
|
## Development
|
|
304
392
|
|
|
305
393
|
I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environment.
|
|
@@ -319,6 +407,6 @@ I recommend to use [rbenv](https://github.com/rbenv/rbenv) for your Ruby environ
|
|
|
319
407
|
|
|
320
408
|
## I Need You
|
|
321
409
|
|
|
322
|
-
Any
|
|
323
|
-
Feel free to file
|
|
410
|
+
Any suggestions or feature requests are welcome!
|
|
411
|
+
Feel free to file issues or send pull requests.
|
|
324
412
|
And, if you like this work, I'll be happy to be [starred](https://github.com/david942j/seccomp-tools/stargazers) :grimacing:
|
data/ext/ptrace/ptrace.c
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
// ptrace is only available on Linux, therefore let this file be an empty
|
|
2
|
+
// object when installing on other platforms.
|
|
3
|
+
#if __linux__
|
|
4
|
+
|
|
5
|
+
#include <assert.h>
|
|
1
6
|
#include <errno.h>
|
|
7
|
+
#include <linux/elf.h>
|
|
2
8
|
#include <linux/filter.h>
|
|
9
|
+
#include <stdint.h>
|
|
3
10
|
#include <sys/ptrace.h>
|
|
4
11
|
#include <sys/signal.h>
|
|
12
|
+
#include <sys/uio.h>
|
|
5
13
|
#include <sys/wait.h>
|
|
6
14
|
|
|
7
15
|
#include "ruby.h"
|
|
@@ -19,10 +27,53 @@ ptrace_peekdata(VALUE _mod, VALUE pid, VALUE addr, VALUE _data) {
|
|
|
19
27
|
return LONG2NUM(val);
|
|
20
28
|
}
|
|
21
29
|
|
|
30
|
+
// aarch64 doesn't support PTRACE_PEEKUSER, but it does support
|
|
31
|
+
// PTRACE_GETREGSET which is fairly similar. Since i386 and x86_64 support it
|
|
32
|
+
// too, just use that unconditionally to present the same API for the registers
|
|
33
|
+
// we care about.
|
|
22
34
|
static VALUE
|
|
23
|
-
ptrace_peekuser(VALUE _mod, VALUE pid, VALUE off, VALUE _data) {
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
ptrace_peekuser(VALUE _mod, VALUE pid, VALUE off, VALUE _data, VALUE bits) {
|
|
36
|
+
size_t offset = NUM2LONG(off);
|
|
37
|
+
// Unless your registers fill an entire page, an offset greater than this is
|
|
38
|
+
// probably wrong.
|
|
39
|
+
if (offset >= 4096) {
|
|
40
|
+
return LONG2NUM(-1);
|
|
41
|
+
}
|
|
42
|
+
size_t width = NUM2LONG(bits);
|
|
43
|
+
if (width != 32 && width != 64) {
|
|
44
|
+
return LONG2NUM(-1);
|
|
45
|
+
}
|
|
46
|
+
width /= 8;
|
|
47
|
+
union {
|
|
48
|
+
uint32_t val32;
|
|
49
|
+
uint64_t val64;
|
|
50
|
+
} val;
|
|
51
|
+
// Dynamically allocate a buffer to store registers-well, at least enough
|
|
52
|
+
// registers to reach the offset we want. Normally we'd want to use
|
|
53
|
+
// user_pt_regs or similar, but it's difficult to find it available in the
|
|
54
|
+
// the same header across different versions of Linux or libcs, or even with
|
|
55
|
+
// the same *name*, so this is the compromise.
|
|
56
|
+
size_t size = offset + width;
|
|
57
|
+
char *regs = malloc(size);
|
|
58
|
+
if (!regs) {
|
|
59
|
+
return LONG2NUM(-1);
|
|
60
|
+
}
|
|
61
|
+
struct iovec vec = { regs, size };
|
|
62
|
+
if (ptrace(PTRACE_GETREGSET, NUM2LONG(pid), NT_PRSTATUS, &vec) != -1 && vec.iov_len >= size) {
|
|
63
|
+
memcpy(&val, regs + offset, width);
|
|
64
|
+
} else {
|
|
65
|
+
free(regs);
|
|
66
|
+
return LONG2NUM(-1);
|
|
67
|
+
}
|
|
68
|
+
free(regs);
|
|
69
|
+
if (width == sizeof(val.val32)) {
|
|
70
|
+
return LONG2NUM(val.val32);
|
|
71
|
+
} else if (width == sizeof(val.val64)) {
|
|
72
|
+
return LONG2NUM(val.val64);
|
|
73
|
+
} else {
|
|
74
|
+
assert(!"Unreachable");
|
|
75
|
+
return LONG2NUM(-1);
|
|
76
|
+
}
|
|
26
77
|
}
|
|
27
78
|
|
|
28
79
|
static VALUE
|
|
@@ -107,7 +158,7 @@ void Init_ptrace(void) {
|
|
|
107
158
|
/* get data */
|
|
108
159
|
rb_define_module_function(mPtrace, "peekdata", ptrace_peekdata, 3);
|
|
109
160
|
/* get registers */
|
|
110
|
-
rb_define_module_function(mPtrace, "peekuser", ptrace_peekuser,
|
|
161
|
+
rb_define_module_function(mPtrace, "peekuser", ptrace_peekuser, 4);
|
|
111
162
|
/* set ptrace options */
|
|
112
163
|
rb_define_module_function(mPtrace, "setoptions", ptrace_setoptions, 3);
|
|
113
164
|
/* wait for syscall */
|
|
@@ -124,3 +175,4 @@ void Init_ptrace(void) {
|
|
|
124
175
|
rb_define_module_function(mPtrace, "detach", ptrace_detach, 1);
|
|
125
176
|
}
|
|
126
177
|
|
|
178
|
+
#endif /* __linux__ */
|
|
@@ -10,16 +10,18 @@ module SeccompTools
|
|
|
10
10
|
|
|
11
11
|
# Assembler of seccomp bpf.
|
|
12
12
|
# @param [String] str
|
|
13
|
-
# @param [
|
|
13
|
+
# @param [String] filename
|
|
14
|
+
# Only used for error messages.
|
|
15
|
+
# @param [Symbol?] arch
|
|
14
16
|
# @return [String]
|
|
15
|
-
# Raw
|
|
17
|
+
# Raw BPF bytes.
|
|
16
18
|
# @example
|
|
17
19
|
# SeccompTools::Asm.asm(<<-EOS)
|
|
18
20
|
# # lines start with '#' are comments
|
|
19
21
|
# A = sys_number # here's a comment, too
|
|
20
22
|
# A >= 0x40000000 ? dead : next # 'next' is a keyword, denote the next instruction
|
|
21
23
|
# A == read ? ok : next # custom defined label 'dead' and 'ok'
|
|
22
|
-
# A == 1 ? ok : next # SYS_write = 1
|
|
24
|
+
# A == 1 ? ok : next # SYS_write = 1 on amd64
|
|
23
25
|
# return ERRNO(1)
|
|
24
26
|
# dead:
|
|
25
27
|
# return KILL
|
|
@@ -27,10 +29,10 @@ module SeccompTools
|
|
|
27
29
|
# return ALLOW
|
|
28
30
|
# EOS
|
|
29
31
|
# #=> <raw binary bytes>
|
|
30
|
-
def asm(str, arch: nil)
|
|
32
|
+
def asm(str, filename: '-', arch: nil)
|
|
33
|
+
filename = nil if filename == '-'
|
|
31
34
|
arch = Util.system_arch if arch.nil?
|
|
32
|
-
compiler = Compiler.new(arch)
|
|
33
|
-
str.lines.each { |l| compiler.process(l) }
|
|
35
|
+
compiler = Compiler.new(str, filename, arch)
|
|
34
36
|
compiler.compile!.map(&:asm).join
|
|
35
37
|
end
|
|
36
38
|
end
|