seccomp-tools 1.4.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
[![Build Status](https://
|
2
|
-
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=david942j/seccomp-tools)](https://dependabot.com)
|
1
|
+
[![Build Status](https://github.com/david942j/seccomp-tools/workflows/build/badge.svg)](https://github.com/david942j/seccomp-tools/actions)
|
3
2
|
[![Code Climate](https://codeclimate.com/github/david942j/seccomp-tools/badges/gpa.svg)](https://codeclimate.com/github/david942j/seccomp-tools)
|
4
3
|
[![Issue Count](https://codeclimate.com/github/david942j/seccomp-tools/badges/issue_count.svg)](https://codeclimate.com/github/david942j/seccomp-tools)
|
5
4
|
[![Test Coverage](https://codeclimate.com/github/david942j/seccomp-tools/badges/coverage.svg)](https://codeclimate.com/github/david942j/seccomp-tools/coverage)
|
6
5
|
[![Inline docs](https://inch-ci.org/github/david942j/seccomp-tools.svg?branch=master)](https://inch-ci.org/github/david942j/seccomp-tools)
|
6
|
+
[![Yard Docs](http://img.shields.io/badge/yard-docs-blue.svg)](https://www.rubydoc.info/github/david942j/seccomp-tools/)
|
7
7
|
[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](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
|
![emu](https://github.com/david942j/seccomp-tools/blob/master/examples/emu-amigo.png?raw=true)
|
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
|