forked from iovisor/bcc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tool to sniff data contents before encrypted with OpenSSL
Add tool as talked in iovisor-dev 'BCC: bpf_probe_read read function arguments'
- Loading branch information
Showing
4 changed files
with
263 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
.TH sslsniff 8 "2016-08-16" "USER COMMANDS" | ||
.SH NAME | ||
sslsniff \- Print data passed to OpenSSL. Uses Linux eBPF/bcc. | ||
.SH SYNOPSIS | ||
.B sslsniff | ||
.SH DESCRIPTION | ||
sslsniff prints data sent to SSL_write and SSL_read OpenSSL functions, allowing | ||
us to read plain text content before encryption (when writing) and after | ||
decryption (when reading). | ||
|
||
This works reading the second parameter of both functions (*buf). | ||
|
||
Since this uses BPF, only the root user can use this tool. | ||
.SH REQUIREMENTS | ||
CONFIG_BPF and bcc. | ||
.SH EXAMPLES | ||
.TP | ||
Print all calls to SSL_write and SSL_read system-wide: | ||
# | ||
.B sslsniff | ||
.SH FIELDS | ||
.TP | ||
FUNC | ||
Which function is being called (SSL_write or SSL_read) | ||
.TP | ||
TIME | ||
Time of the command, in seconds. | ||
.TP | ||
COMM | ||
Entered command. | ||
.TP | ||
PID | ||
Process ID calling OpenSSL. | ||
.TP | ||
LEN | ||
Bytes written or read by OpenSSL functions. | ||
.SH SOURCE | ||
This is from bcc. | ||
.IP | ||
https://github.com/iovisor/bcc | ||
.PP | ||
Also look in the bcc distribution for a companion _examples.txt file containing | ||
example usage, output, and commentary for this tool. | ||
.SH OS | ||
Linux | ||
.SH STABILITY | ||
Unstable - in development. | ||
.SH AUTHORS | ||
Adrian Lopez and Mark Drayton | ||
.SH SEE ALSO | ||
trace(8) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
#!/usr/bin/python | ||
# | ||
# sslsniff Captures data on SSL_READ or SSL_WRITE functions of OpenSSL | ||
# For Linux, uses BCC, eBPF. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License") | ||
# | ||
# 12-Aug-2016 Adrian Lopez Created this. | ||
# 13-Aug-2016 Mark Drayton Fix SSL_Read | ||
|
||
from __future__ import print_function | ||
import ctypes as ct | ||
from bcc import BPF | ||
|
||
prog = """ | ||
#include <linux/ptrace.h> | ||
#include <linux/sched.h> /* For TASK_COMM_LEN */ | ||
struct probe_SSL_data_t { | ||
u64 timestamp_ns; | ||
u32 pid; | ||
char comm[TASK_COMM_LEN]; | ||
char v0[472]; | ||
u32 len; | ||
}; | ||
BPF_PERF_OUTPUT(perf_SSL_write); | ||
int probe_SSL_write(struct pt_regs *ctx, void *ssl, void *buf, int num) { | ||
struct probe_SSL_data_t __data = {0}; | ||
__data.timestamp_ns = bpf_ktime_get_ns(); | ||
__data.pid = bpf_get_current_pid_tgid(); | ||
__data.len = num; | ||
bpf_get_current_comm(&__data.comm, sizeof(__data.comm)); | ||
if ( buf != 0) { | ||
bpf_probe_read(&__data.v0, sizeof(__data.v0), buf); | ||
} | ||
perf_SSL_write.perf_submit(ctx, &__data, sizeof(__data)); | ||
return 0; | ||
} | ||
BPF_PERF_OUTPUT(perf_SSL_read); | ||
BPF_HASH(bufs, u32, u64); | ||
int probe_SSL_read_enter(struct pt_regs *ctx, void *ssl, void *buf, int num) { | ||
u32 pid = bpf_get_current_pid_tgid(); | ||
bufs.update(&pid, (u64*)&buf); | ||
return 0; | ||
} | ||
int probe_SSL_read_exit(struct pt_regs *ctx, void *ssl, void *buf, int num) { | ||
u32 pid = bpf_get_current_pid_tgid(); | ||
u64 *bufp = bufs.lookup(&pid); | ||
if (bufp == 0) { | ||
return 0; | ||
} | ||
struct probe_SSL_data_t __data = {0}; | ||
__data.timestamp_ns = bpf_ktime_get_ns(); | ||
__data.pid = pid; | ||
__data.len = PT_REGS_RC(ctx); | ||
bpf_get_current_comm(&__data.comm, sizeof(__data.comm)); | ||
if (bufp != 0) { | ||
bpf_probe_read(&__data.v0, sizeof(__data.v0), (char *)*bufp); | ||
} | ||
bufs.delete(&pid); | ||
perf_SSL_read.perf_submit(ctx, &__data, sizeof(__data)); | ||
return 0; | ||
} | ||
""" | ||
|
||
b = BPF(text=prog) | ||
|
||
# Join to ssl_write | ||
b.attach_uprobe(name="ssl", sym="SSL_write", fn_name="probe_SSL_write") | ||
|
||
# Join to ssl_read | ||
# It looks like SSL_read's arguments aren't available in a return probe so you | ||
# need to stash the buffer address in a map on the function entry and read it | ||
# on its exit (Mark Drayton) | ||
b.attach_uprobe(name="ssl", sym="SSL_read", fn_name="probe_SSL_read_enter") | ||
b.attach_uretprobe(name="ssl", sym="SSL_read", fn_name="probe_SSL_read_exit") | ||
|
||
# define output data structure in Python | ||
TASK_COMM_LEN = 16 # linux/sched.h | ||
MAX_BUF_SIZE = 472 # Limited by the BPF stack | ||
|
||
|
||
# Max size of the whole struct: 512 bytes | ||
class Data(ct.Structure): | ||
_fields_ = [ | ||
("timestamp_ns", ct.c_ulonglong), | ||
("pid", ct.c_uint), | ||
("comm", ct.c_char * TASK_COMM_LEN), | ||
("v0", ct.c_char * MAX_BUF_SIZE), | ||
("len", ct.c_uint) | ||
] | ||
|
||
|
||
# header | ||
print("%-12s %-18s %-16s %-6s %-6s" % ("FUNC", "TIME(s)", "COMM", "PID", | ||
"LEN")) | ||
|
||
# process event | ||
start = 0 | ||
|
||
|
||
def print_event_write(cpu, data, size): | ||
print_event(cpu, data, size, "SSL_WRITE") | ||
|
||
|
||
def print_event_read(cpu, data, size): | ||
print_event(cpu, data, size, "SSL_READ") | ||
|
||
|
||
def print_event(cpu, data, size, rw): | ||
global start | ||
event = ct.cast(data, ct.POINTER(Data)).contents | ||
if start == 0: | ||
start = event.timestamp_ns | ||
time_s = (float(event.timestamp_ns - start)) / 1000000000 | ||
|
||
s_mark = "-" * 5 + " DATA " + "-" * 5 | ||
|
||
e_mark = "-" * 5 + " END DATA " + "-" * 5 | ||
|
||
truncated_bytes = event.len - MAX_BUF_SIZE | ||
if truncated_bytes > 0 : | ||
e_mark = "-" * 5 + " END DATA (TRUNCATED, " + str(truncated_bytes) + \ | ||
" bytes lost) " + "-" * 5 | ||
|
||
print("%-12s %-18.9f %-16s %-6d %-6d\n%s\n%s\n%s\n" % (rw, time_s, | ||
event.comm, | ||
event.pid, | ||
event.len, | ||
s_mark, event.v0, | ||
e_mark)) | ||
|
||
b["perf_SSL_write"].open_perf_buffer(print_event_write) | ||
b["perf_SSL_read"].open_perf_buffer(print_event_read) | ||
while 1: | ||
b.kprobe_poll() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
Demonstrations of sslsniff.py | ||
|
||
|
||
This tool traces the OpenSSL functions SSL_READ and SSL_WRITE. | ||
Data passed to this functions is printed as plain text. | ||
Useful, for example, to sniff HTTP before encrypted with SSL. | ||
|
||
|
||
Output of tool executing in other shell "curl https://example.com" | ||
|
||
% sudo python sslsniff.py | ||
FUNC TIME(s) COMM PID LEN | ||
SSL_WRITE 0.000000000 curl 12915 75 | ||
----- DATA ----- | ||
GET / HTTP/1.1 | ||
Host: example.com | ||
User-Agent: curl/7.50.1 | ||
Accept: */* | ||
|
||
|
||
----- END DATA ----- | ||
|
||
SSL_READ 0.127144585 curl 12915 333 | ||
----- DATA ----- | ||
HTTP/1.1 200 OK | ||
Cache-Control: max-age=604800 | ||
Content-Type: text/html | ||
Date: Tue, 16 Aug 2016 15:42:12 GMT | ||
Etag: "359670651+gzip+ident" | ||
Expires: Tue, 23 Aug 2016 15:42:12 GMT | ||
Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT | ||
Server: ECS (iad/18CB) | ||
Vary: Accept-Encoding | ||
X-Cache: HIT | ||
x-ec-custom-error: 1 | ||
Content-Length: 1270 | ||
|
||
|
||
----- END DATA ----- | ||
|
||
SSL_READ 0.129967972 curl 12915 1270 | ||
----- DATA ----- | ||
<!doctype html> | ||
<html> | ||
<head> | ||
<title>Example Domain</title> | ||
|
||
<meta charset="utf-8" /> | ||
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<style type="text/css"> | ||
body { | ||
background-color: #f0f0f2; | ||
margin: 0; | ||
padding: 0; | ||
font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; | ||
|
||
} | ||
div { | ||
w | ||
----- END DATA (TRUNCATED, 798 bytes lost) ----- |