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
 | 
					*.nam
 | 
				
			||||||
*.til
 | 
					*.til
 | 
				
			||||||
*.pro.user
 | 
					*.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