contrib: add extract-handshakes kprobe example
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
e6ce5fd386
commit
d4421aea89
6 changed files with 176 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -20,3 +20,4 @@ src/tests/qemu/distfiles/
|
|||
*.nam
|
||||
*.til
|
||||
*.pro.user
|
||||
.cache.mk
|
||||
|
|
3
contrib/extract-handshakes/.gitignore
vendored
Normal file
3
contrib/extract-handshakes/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
offset-finder.o
|
||||
offset-finder
|
||||
offsets.include
|
28
contrib/extract-handshakes/Makefile
Normal file
28
contrib/extract-handshakes/Makefile
Normal file
|
@ -0,0 +1,28 @@
|
|||
ifeq ($(KERNELRELEASE),)
|
||||
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
|
||||
PWD := $(shell pwd)
|
||||
CFLAGS ?= -O3 -march=native
|
||||
CFLAGS += -Wall -pedantic -std=gnu11
|
||||
|
||||
offsets.include: offset-finder
|
||||
./$^ > $@
|
||||
|
||||
offset-finder: offset-finder.c offset-finder.o
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $^
|
||||
|
||||
offset-finder.o: offset-finder.c
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) $@
|
||||
objcopy -j '.rodata*' $@ $@
|
||||
|
||||
clean:
|
||||
rm -f offset-finder offsets.include
|
||||
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
|
||||
|
||||
.PHONY: clean
|
||||
else
|
||||
offset-finder-m := offset-finder.o
|
||||
oldsrc := $(src)
|
||||
src := $(src)/../../../src
|
||||
include $(src)/compat/Kbuild.include
|
||||
src := $(oldsrc)
|
||||
endif
|
20
contrib/extract-handshakes/README
Normal file
20
contrib/extract-handshakes/README
Normal file
|
@ -0,0 +1,20 @@
|
|||
Handshake Extractor
|
||||
===================
|
||||
|
||||
This will extract private keys from outgoing handshake sessions, prior
|
||||
to them being sent, via kprobes. It exports the bare minimum to be
|
||||
able to then decrypt all packets in the handshake and in the subsequent
|
||||
transport data session.
|
||||
|
||||
Build:
|
||||
|
||||
$ make
|
||||
|
||||
Run (as root):
|
||||
|
||||
# ./extract-handshakes.sh
|
||||
New handshake session:
|
||||
LOCAL_STATIC_PRIVATE_KEY = QChaGDXeH3eQsbFAhueUNWFdq9KfpF3yl+eITjZbXEk=
|
||||
REMOTE_STATIC_PUBLIC_KEY = HzgTY6aWXtuSyW/PUquZtg8LB/DyMwEXGkPiEmdSsUU=
|
||||
LOCAL_EPHEMERAL_PRIVATE_KEY = UNGdRHuKDeqbFvmiV5FD4wP7a8PqI6v3Xnnz6Jc6NXQ=
|
||||
PRESHARED_KEY = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
80
contrib/extract-handshakes/extract-handshakes.sh
Executable file
80
contrib/extract-handshakes/extract-handshakes.sh
Executable file
|
@ -0,0 +1,80 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
# Copyright (C) 2017-2018 Peter Wu <peter@lekensteyn.nl>. All Rights Reserved.
|
||||
|
||||
set -e
|
||||
|
||||
ME_DIR="${BASH_SOURCE[0]}"
|
||||
ME_DIR="${ME_DIR%/*}"
|
||||
source "$ME_DIR/offsets.include" || { echo "Did you forget to run make?" >&2; exit 1; }
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64) ARGUMENT_REGISTER="%si" ;;
|
||||
i386|i686) ARGUMENT_REGISTER="%dx" ;;
|
||||
aarch64) ARGUMENT_REGISTER="%x1" ;;
|
||||
arm) ARGUMENT_REGISTER="%r1" ;;
|
||||
*) echo "ERROR: Unknown architecture" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
ARGS=( )
|
||||
REGEX=".*: idxadd: .*"
|
||||
for key in "${!OFFSETS[@]}"; do
|
||||
values="${OFFSETS[$key]}"
|
||||
values=( ${values//,/ } )
|
||||
for i in {0..3}; do
|
||||
value="$ARGUMENT_REGISTER"
|
||||
for indirection in "${values[@]:1}"; do
|
||||
value="+$indirection($value)"
|
||||
done
|
||||
value="+$((i * 8 + values[0]))($value)"
|
||||
ARGS+=( "${key,,}$i=$value:x64" )
|
||||
REGEX="$REGEX ${key,,}$i=0x([0-9a-f]+)"
|
||||
done
|
||||
done
|
||||
|
||||
turn_off() {
|
||||
set +e
|
||||
[[ -f /sys/kernel/debug/tracing/events/wireguard/idxadd/enable ]] || exit
|
||||
echo 0 > /sys/kernel/debug/tracing/events/wireguard/idxadd/enable
|
||||
echo "-:wireguard/idxadd" >> /sys/kernel/debug/tracing/kprobe_events
|
||||
exit
|
||||
}
|
||||
|
||||
trap turn_off INT TERM EXIT
|
||||
echo "p:wireguard/idxadd index_hashtable_insert ${ARGS[*]}" >> /sys/kernel/debug/tracing/kprobe_events
|
||||
echo 1 > /sys/kernel/debug/tracing/events/wireguard/idxadd/enable
|
||||
|
||||
unpack_u64() {
|
||||
local i expanded="$1"
|
||||
if [[ $ENDIAN == big ]]; then
|
||||
printf -v expanded "%.*s$expanded" $((16 - ${#expanded})) 0000000000000000
|
||||
for i in {0..7}; do
|
||||
echo -n "\\x${expanded:(i * 2):2}"
|
||||
done
|
||||
elif [[ $ENDIAN == little ]]; then
|
||||
(( ${#expanded} % 2 == 1 )) && expanded="0$expanded"
|
||||
expanded="${expanded}0000000000000000"
|
||||
for i in {0..7}; do
|
||||
echo -n "\\x${expanded:((7 - i) * 2):2}"
|
||||
done
|
||||
else
|
||||
echo "ERROR: Unable to determine endian" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
while read -r line; do
|
||||
[[ $line =~ $REGEX ]] || continue
|
||||
echo "New handshake session:"
|
||||
j=1
|
||||
for key in "${!OFFSETS[@]}"; do
|
||||
bytes=""
|
||||
for i in {0..3}; do
|
||||
bytes="$bytes$(unpack_u64 "${BASH_REMATCH[j]}")"
|
||||
((++j))
|
||||
done
|
||||
echo " $key = $(printf "$bytes" | base64)"
|
||||
done
|
||||
done < /sys/kernel/debug/tracing/trace_pipe
|
44
contrib/extract-handshakes/offset-finder.c
Normal file
44
contrib/extract-handshakes/offset-finder.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* Copyright (C) 2015-2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
|
||||
*/
|
||||
|
||||
struct def {
|
||||
const char *name;
|
||||
unsigned long offset;
|
||||
unsigned long indirection_offset;
|
||||
};
|
||||
extern const struct def defs[];
|
||||
|
||||
#ifdef __KERNEL__
|
||||
#include "../../../src/noise.h"
|
||||
|
||||
const struct def defs[] = {
|
||||
{ "LOCAL_STATIC_PRIVATE_KEY", offsetof(struct noise_static_identity, static_private), offsetof(struct noise_handshake, static_identity) },
|
||||
{ "LOCAL_EPHEMERAL_PRIVATE_KEY", offsetof(struct noise_handshake, ephemeral_private), -1 },
|
||||
{ "REMOTE_STATIC_PUBLIC_KEY", offsetof(struct noise_handshake, remote_static), -1 },
|
||||
{ "PRESHARED_KEY", offsetof(struct noise_handshake, preshared_key), -1 },
|
||||
{ NULL, 0 }
|
||||
};
|
||||
#else
|
||||
#include <stdio.h>
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
puts("declare -A OFFSETS=(");
|
||||
for (const struct def *def = defs; def->name; ++def) {
|
||||
printf("\t[%s]=%ld", def->name, def->offset);
|
||||
if (def->indirection_offset != -1)
|
||||
printf(",%ld", def->indirection_offset);
|
||||
putchar('\n');
|
||||
}
|
||||
puts(")");
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
puts("ENDIAN=big");
|
||||
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
puts("ENDIAN=little");
|
||||
#else
|
||||
#error "Unsupported endianness"
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue