diff --git a/common.d/apt_options.sh b/common.d/apt_options.sh index 5e7f1f4..01a805f 100644 --- a/common.d/apt_options.sh +++ b/common.d/apt_options.sh @@ -1,21 +1,23 @@ #!/usr/bin/env bash -cat > "${work_dir:=}"/etc/apt/apt.conf.d/apt_opts <"${work_dir:=}"/etc/apt/apt.conf.d/apt_opts < "${work_dir:=}"/etc/apt/apt.conf.d/99_norecommends <"${work_dir:=}"/etc/apt/apt.conf.d/99_norecommends < "${work_dir:=}"/etc/apt/apt.conf.d/66proxy + echo "Acquire::http { Proxy \"$proxy_url\" };" >"${work_dir:=}"/etc/apt/apt.conf.d/66proxy + fi diff --git a/common.d/base_image.sh b/common.d/base_image.sh index 5e34127..7156ddc 100644 --- a/common.d/base_image.sh +++ b/common.d/base_image.sh @@ -21,6 +21,7 @@ source ./common.d/variables.sh # If there is any issues, run check_trap (from ./common.d/functions.sh) trap check_trap INT ERR SIGTERM SIGINT + # Always at the end, run clean_build (from ./common.d/functions.sh) trap clean_build EXIT @@ -41,14 +42,14 @@ include apt_options # Disable suspend/resume - speeds up boot massively mkdir -p "${work_dir}/etc/initramfs-tools/conf.d/" -echo "RESUME=none" > "${work_dir}/etc/initramfs-tools/conf.d/resume" +echo "RESUME=none" >"${work_dir}/etc/initramfs-tools/conf.d/resume" # Copy directory bsp into build dir status "Copy directory bsp into build dir" cp -rp bsp "${work_dir}" # Third stage -cat < "${work_dir}/third-stage" +cat <"${work_dir}/third-stage" #!/usr/bin/env bash # Stop on error set -e @@ -74,13 +75,14 @@ EOF if [ "${desktop}" != "none" ]; then log "Desktop mode enabled: ${desktop}" green - cat <> "${work_dir}/third-stage" + cat <>"${work_dir}/third-stage" status_stage3 'Install desktop packages' eatmydata apt-get install -y ${desktop_pkgs} ${extra} || eatmydata apt-get install -y --fix-broken EOF + fi -cat <> "${work_dir}/third-stage" +cat <>"${work_dir}/third-stage" status_stage3 'ntp does not always sync the date, but systemd-timesyncd does, so we remove ntp and reinstall it with this' eatmydata apt-get install -y systemd-timesyncd --autoremove @@ -134,13 +136,16 @@ status_stage3 'Install powershell 7.1.3' if [[ ${architecture} != armel ]]; then if [[ ${architecture} == "arm64" ]]; then curl -L -o /tmp/powershell.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v7.1.3/powershell-7.1.3-linux-arm64.tar.gz + else curl -L -o /tmp/powershell.tar.gz https://github.com/PowerShell/PowerShell/releases/download/v7.1.3/powershell-7.1.3-linux-arm32.tar.gz + fi mkdir -p /opt/microsoft/powershell/7 tar -xf /tmp/powershell.tar.gz -C /opt/microsoft/powershell/7 chmod +x /opt/microsoft/powershell/7/pwsh ln -s /opt/microsoft/powershell/7/pwsh + fi status_stage3 'Try and make the console a bit nicer. Set the terminus font for a bit nicer display' diff --git a/common.d/build_deps.sh b/common.d/build_deps.sh index a9c4e83..93899c5 100755 --- a/common.d/build_deps.sh +++ b/common.d/build_deps.sh @@ -19,16 +19,20 @@ apt-wait() { if [ "$1" == "update" ]; then echo -e "\n[i] Updating apt" apt-get update + elif [ "$1" == "install_deps" ]; then echo -e "\n[i] Installing: $deps" apt-get install -y $deps + # Don't think this is used? elif [ "$1" == "remove" ]; then echo -e "\n[i] Removing: $@" apt-get -y --purge "$@" + else echo "\n[-] Unknown option: $1" >&2 exit 1 + fi } @@ -36,8 +40,9 @@ apt-wait() { clean_build() { mkdir -p ./local/ clean_script=${backup_packages/list-pkgs/remove-pkgs}.sh + echo -e "\n[i] Creating clean up script: ${clean_script}" - cat << EOF > ${clean_script} + cat <${clean_script} #!/usr/bin/env bash set -e @@ -62,6 +67,7 @@ case \$yn in * ) exit;; esac EOF + chmod 0755 ${clean_script} #rm -f "${backup_packages}" @@ -74,24 +80,27 @@ function check_trap() { clean_build exit 1 } + # If there is an issue, run the above function trap check_trap INT ERR SIGTERM SIGINT - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Check permissions script if [[ $EUID -ne 0 ]]; then echo "[-] This script must be run as root" >&2 exit 1 + else echo -e "\n[i] Kali-ARM build-script machine preparation" + fi # Check compatible systems -if ! which dpkg > /dev/null; then - echo "[-] Script only compatible with Debian-based systems" >&2 - exit 1 +if ! which dpkg >/dev/null; then + echo "[-] Script only compatible with Debian-based systems" >&2 + exit 1 + fi # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -101,10 +110,12 @@ backup_packages=./local/build-deps-list-pkgs-$(date +"%Y-%m-%d-%H-%M") mkdir -pv ./local/ # Create a current list of installed packages -dpkg --get-selections > ${backup_packages} +dpkg --get-selections >${backup_packages} compilers="crossbuild-essential-arm64 crossbuild-essential-armhf crossbuild-essential-armel gcc-arm-none-eabi" + libpython2_dev="libexpat1-dev libpython2.7 libpython2.7-dev libpython2.7-minimal libpython2.7-stdlib" + dependencies="gnupg flex bison gperf build-essential zip curl libncurses5-dev zlib1g-dev \ parted kpartx debootstrap pixz qemu-user-static abootimg cgpt vboot-kernel-utils vboot-utils \ u-boot-tools bc lzma lzop automake autoconf m4 rsync schedtool git dosfstools e2fsprogs \ @@ -115,15 +126,18 @@ deps="${dependencies} ${compilers}" # Update list deb packages apt-wait update + # Install dependencies apt-wait install_deps # Check minimum version debootstrap debootstrap_ver=$(debootstrap --version | grep -o '[0-9.]\+' | head -1) + if dpkg --compare-versions "$debootstrap_ver" lt "1.0.105"; then echo "[-] Currently your version of debootstrap ($debootstrap_ver) does not support the script" >&2 echo "[-] The minimum version of debootstrap is 1.0.105" >&2 exit 1 + fi # Install kali-archive-keyring @@ -136,13 +150,16 @@ if [ ! -f /usr/share/keyrings/kali-archive-keyring.gpg ]; then cp -v kali-archive-keyring.gpg /usr/share/keyrings/ #make install cd $OLDPWD/ rm -rf $temp_key + else echo -e "\n[i] Already have: kali-archive-keyring" + fi # Install packages i386 if [ $(arch) == 'x86_64' ]; then echo -e "\n[i] Detected x64" + if [ -z $(dpkg --print-foreign-architectures | grep i386) ]; then echo -e "\n[i] Adding x86 support" dpkg --add-architecture i386 @@ -150,15 +167,19 @@ if [ $(arch) == 'x86_64' ]; then deps="-o APT::Immediate-Configure=0 libstdc++6:i386 libc6:i386 libgcc1:i386 zlib1g:i386 libncurses5:i386" apt-wait install_deps del_arch_i386="dpkg --remove-architecture i386" + elif [[ $(dpkg --print-foreign-architectures | grep i386) == 'i386' ]]; then echo -e "\n[i] Already found x86 support" deps="-o APT::Immediate-Configure=0 libstdc++6:i386 libc6:i386 libgcc1:i386 zlib1g:i386 libncurses5:i386" apt-wait install_deps + fi + elif [ $(arch) == 'i386' ]; then echo -e "\n[i] Detected x86" deps="libstdc++6 libc6 libgcc1 zlib1g libncurses5" apt-wait install_deps + fi # Create the script to clean the system diff --git a/common.d/check.sh b/common.d/check.sh index 40331c8..0e4edf1 100644 --- a/common.d/check.sh +++ b/common.d/check.sh @@ -4,47 +4,64 @@ if [[ $EUID -ne 0 ]]; then log "This script must be run as root or have super user permissions" red log "Use: $(tput sgr0)sudo $0" green + exit 1 + fi # Check for systemd-nspawn if [ ! -e /usr/bin/systemd-nspawn ]; then log "Error: missing systemd-nspawn" red log "Please run ./common.d/build_deps.sh" red + exit 1 + fi + # Check for qemu-user-static if [ ! -e /usr/bin/qemu-aarch64-static ]; then log "Error: missing QEMU" red log "Please run ./commond.d/build_deps.sh" red + exit 1 + fi + # Check for the kali archive keyring if [ ! -e /usr/share/keyrings/kali-archive-keyring.gpg ]; then log "Error: missing kali-archive-keyring" red log "Please download the latest version from" red log "https://kali.download/kali/pool/main/k/kali-archive-keyring" red log "and install it manually." red + exit 1 + fi # Check exist bsp directory. if [ ! -e "bsp" ]; then log "Error: missing bsp directory structure" red log "Please clone the full repository ${kaligit}/build-scripts/kali-arm" green + exit 255 + fi # Check directory build if [ -e "${base_dir}" ]; then log "${base_dir} directory exists, will not continue" red + exit 1 + elif [[ ${repo_dir} =~ [[:space:]] ]]; then log "The directory "\"${repo_dir}"\" contains whitespace. Not supported." red + exit 1 + else print_config mkdir -p ${base_dir} + fi # Detect architecture @@ -52,49 +69,69 @@ case ${architecture} in arm64) qemu_bin="/usr/bin/qemu-aarch64-static" lib_arch="aarch64-linux-gnu" + ;; + armhf) qemu_bin="/usr/bin/qemu-arm-static" lib_arch="arm-linux-gnueabihf" + ;; + armel) qemu_bin="/usr/bin/qemu-arm-static" lib_arch="arm-linux-gnueabi" + ;; + esac # Check systemd-nspawn version nspawn_ver=$(systemd-nspawn --version | awk '{if(NR==1) print $2}') + if [[ $nspawn_ver -ge 245 ]]; then extra_args="--hostname=$hostname -q -P" + elif [[ $nspawn_ver -ge 241 ]]; then extra_args="--hostname=$hostname -q" + else extra_args="-q" + fi # Check CPU cores to use if [ "$cpu_cores" = "0" ]; then num_cores=$(nproc --all) + elif [[ "$cpu_cores" =~ ^[0-9]{1,2}$ ]]; then if [ "$cpu_cores" -le $(nproc --all) ]; then num_cores="$cpu_cores" + else num_cores=$(nproc --all) + fi + elif [[ "$cpu_cores" =~ ^[-0-9]{1,2}$ ]]; then num_cores=$(nproc --ignore="${cpu_cores/-/}") + else num_cores="1" + fi # Automatic configuration to use an http proxy, such as apt-cacher-ng. apt_cacher=${apt_cacher:-"$(lsof -i :3142 | cut -d ' ' -f3 | uniq | sed '/^\s*$/d')"} + if [ -n "$proxy_url" ]; then export http_proxy=$proxy_url + elif [[ "$apt_cacher" =~ (apt-cacher-ng|root) ]]; then if [ -z "$proxy_url" ]; then proxy_url=${proxy_url:-"http://127.0.0.1:3142/"} export http_proxy=$proxy_url + fi + fi diff --git a/common.d/clean_system.sh b/common.d/clean_system.sh index df481da..4ff7d3c 100644 --- a/common.d/clean_system.sh +++ b/common.d/clean_system.sh @@ -3,7 +3,9 @@ if [ "${debug}" = 1 ]; then log "Skipping due to debug mode ($0 -d) being enabled" yellow - return + + return + fi status "clean system" diff --git a/common.d/eatmydata.sh b/common.d/eatmydata.sh index e41ea1c..85e7001 100644 --- a/common.d/eatmydata.sh +++ b/common.d/eatmydata.sh @@ -7,6 +7,7 @@ for archive in "${work_dir}"/var/cache/apt/archives/*eatmydata*.deb; do dpkg-deb --fsys-tarfile "$archive" >"${work_dir}"/eatmydata tar -xkf "${work_dir}"/eatmydata -C "${work_dir}" rm -f "${work_dir}"/eatmydata + done # Prepare dpkg to use eatmydata @@ -25,4 +26,5 @@ done export LD_PRELOAD exec "\$0-eatmydata" --force-unsafe-io "\$@" EOF + chmod 0755 "${work_dir}"/usr/bin/dpkg diff --git a/common.d/finish_image.sh b/common.d/finish_image.sh index ee6b1e0..3fbc9ed 100644 --- a/common.d/finish_image.sh +++ b/common.d/finish_image.sh @@ -18,13 +18,16 @@ umount_partitions # Check filesystem status "Check filesystem partitions ($rootfstype)" -if [ -n "${bootp}" ] && [ "${extra}" = 1 ]; then - log "Check filesystem boot partition:$(tput sgr0) (${bootfstype})" green - if [ "$bootfstype" = "vfat" ]; then - dosfsck -w -r -a -t "${bootp}" - else - e2fsck -y -f "${bootp}" - fi +if [ -n "${bootp}" ] && [ "${extra}" = 1 ]; then + log "Check filesystem boot partition:$(tput sgr0) (${bootfstype})" green + + if [ "$bootfstype" = "vfat" ]; then + dosfsck -w -r -a -t "${bootp}" + + else + e2fsck -y -f "${bootp}" + + fi fi log "Check filesystem root partition:$(tput sgr0) ($rootfstype)" green @@ -37,7 +40,8 @@ losetup -d "${loopdevice}" # Create sha256sum file of the UNCOMPRESSED image file log "Generate sha256sum: $(tput sgr0) ($img)" green cd "${image_dir}" -shasum -a 256 "${image_name}.img" > "${image_name}.img.sha256sum" + +shasum -a 256 "${image_name}.img" >"${image_name}.img.sha256sum" cd "${repo_dir}" # Compress image compilation @@ -46,9 +50,11 @@ compress_img # Create sha256sum file of the COMPRESSED image file if [ -f "${image_dir}/${image_name}.img.$compress" ]; then log "Generate sha256sum: $(tput sgr0) ($img.$compress)" green + cd "${image_dir}" - shasum -a 256 "${image_name}.img.$compress" > "${image_name}.img.$compress.sha256sum" + shasum -a 256 "${image_name}.img.$compress" >"${image_name}.img.$compress.sha256sum" cd "${repo_dir}" + fi # Clean up all the temporary build stuff and remove the directories diff --git a/common.d/functions.sh b/common.d/functions.sh index d32c209..24cd028 100644 --- a/common.d/functions.sh +++ b/common.d/functions.sh @@ -4,31 +4,68 @@ # Print color echo function log() { local set_color="$2" + case $set_color in - bold) color=$(tput bold) ;; - red) color=$(tput setaf 1) ;; - green) color=$(tput setaf 2) ;; - yellow) color=$(tput setaf 3) ;; - cyan) color=$(tput setaf 6) ;; - gray) color=$(tput setaf 8) ;; - white) color=$(tput setaf 15) ;; - *) text="$1" ;; + bold) + color=$(tput bold) + + ;; + + red) + color=$(tput setaf 1) + + ;; + + green) + color=$(tput setaf 2) + + ;; + + yellow) + color=$(tput setaf 3) + + ;; + + cyan) + color=$(tput setaf 6) + + ;; + + gray) + color=$(tput setaf 8) + + ;; + + white) + color=$(tput setaf 15) + + ;; + + *) + text="$1" + + ;; + esac ## --no-color if [ "$colour_output" == "no" ]; then echo -e "$1" + elif [ -z "$text" ]; then echo -e "$color $1 $(tput sgr0)" + else echo -e "$text" + fi } # Usage function function usage() { log "Usage commands:" bold - cat << EOF + + cat < >(tee -a "${log}") 2>&1 + # Print all commands inside of script set -x debug=1 @@ -72,42 +111,102 @@ function debug_enable() { # Validate desktop function validate_desktop() { case $1 in - xfce|gnome|kde|i3|i3-gaps|lxde|mate|e17) true ;; - none) variant="minimal" ;; - *) log "\n ⚠️ Unknown desktop:$(tput sgr0) $1\n" red; usage ;; + xfce | gnome | kde | i3 | i3-gaps | lxde | mate | e17) + true + + ;; + + none) + variant="minimal" + + ;; + + *) + log "\n ⚠️ Unknown desktop:$(tput sgr0) $1\n" red + usage + + ;; + esac } # Arguments function function arguments() { while [[ $# -gt 0 ]]; do - opt="$1"; - shift; + opt="$1" + + shift + case "$(echo ${opt} | tr '[:upper:]' '[:lower:]')" in - "--") break 2;; - -a | --arch) - architecture="$1"; shift;; - --arch=*) - architecture="${opt#*=}";; - --desktop) - validate_desktop $1; desktop="$1"; shift;; - --desktop=*) - validate_desktop "${opt#*=}"; desktop="${opt#*=}";; - -m | --minimal) - variant="minimal"; minimal="1"; desktop="minimal" ;; - -s | --slim) - variant="slim"; desktop="slim"; minimal="1"; slim="1";; - -d | --debug) - debug_enable;; - -x | --extra) - log "Extra Checks: Enabled" green - extra="1";; - --no-color | --no-colour) - colour_output="no";; - -h | -help | --help) - usage;; - *) - log "Unknown option: ${opt}" red; exit 1;; + "--") + break 2 + + ;; + + -a | --arch) + architecture="$1" + shift + + ;; + + --arch=*) + architecture="${opt#*=}" + + ;; + + --desktop) + validate_desktop $1 + desktop="$1" + shift + + ;; + + --desktop=*) + validate_desktop "${opt#*=}" + desktop="${opt#*=}" + + ;; + + -m | --minimal) + variant="minimal" + minimal="1" + desktop="minimal" + + ;; + + -s | --slim) + variant="slim" + desktop="slim" + minimal="1" + slim="1" + + ;; + + -d | --debug) + debug_enable + + ;; + + -x | --extra) + log "Extra Checks: Enabled" green + extra="1" + + ;; + + --no-color | --no-colour) + colour_output="no" + + ;; + + -h | -help | --help) + usage + + ;; + + *) + log "Unknown option: ${opt}" red + exit 1 + ;; esac done } @@ -115,15 +214,21 @@ function arguments() { # Function to include common files function include() { local file="$1" + if [[ -f "common.d/${file}.sh" ]]; then log " ✅ Load common file:$(tput sgr0) ${file}" green + # shellcheck source=/dev/null source "common.d/${file}.sh" "$@" return 0 + else log " ⚠️ Fail to load ${file} file" red + [ "${debug}" = 1 ] && pwd || true + exit 1 + fi } @@ -132,12 +237,14 @@ function include() { function systemd-nspawn_exec() { log "systemd-nspawn $*" gray ENV="RUNLEVEL=1,LANG=C,DEBIAN_FRONTEND=noninteractive,DEBCONF_NOWARNINGS=yes" + systemd-nspawn --bind-ro "$qemu_bin" $extra_args --capability=cap_setfcap -E $ENV -M "$machine" -D "$work_dir" "$@" } # Create the rootfs - not much to modify here, except maybe throw in some more packages if you want. function debootstrap_exec() { status " debootstrap ${suite} $*" + eatmydata debootstrap --merged-usr --keyring=/usr/share/keyrings/kali-archive-keyring.gpg --components="${components}" \ --include="${debootstrap_base}" --arch "${architecture}" "${suite}" "${work_dir}" "$@" } @@ -148,8 +255,10 @@ function disable_proxy() { log "Disable proxy" gray unset http_proxy rm -rf "${work_dir}"/etc/apt/apt.conf.d/66proxy + elif [ "${debug}" = 1 ]; then log "Proxy enabled" yellow + fi } @@ -157,13 +266,16 @@ function disable_proxy() { function restore_mirror() { if [[ -n "${replace_mirror}" ]]; then export mirror=${replace_mirror} + elif [[ -n "${replace_suite}" ]]; then export suite=${replace_suite} + fi + log "Mirror & suite replacement" gray # For now, restore_mirror will put the default kali mirror in, fix after 2021.3 - cat < "${work_dir}"/etc/apt/sources.list + cat <"${work_dir}"/etc/apt/sources.list # See https://www.kali.org/docs/general-use/kali-linux-sources-list-repositories/ deb http://http.kali.org/kali kali-rolling main contrib non-free @@ -178,34 +290,43 @@ function limit_cpu() { cpu_limit=-1 log "CPU limiting has been disabled" yellow eval "${@}" + return $? + elif [[ ${cpu_limit:=} -gt "100" ]]; then log "CPU limit (${cpu_limit}) is higher than 100" yellow cpu_limit=100 + fi -if [[ -z $cpu_limit ]]; then + if [[ -z $cpu_limit ]]; then log "CPU limit unset" yellow local cpu_shares=$((num_cores * 1024)) local cpu_quota="-1" + else log "Limiting CPU (${cpu_limit}%)" yellow local cpu_shares=$((1024 * num_cores * cpu_limit / 100)) # 1024 max value per core local cpu_quota=$((100000 * num_cores * cpu_limit / 100)) # 100000 max value per core + fi + # Random group name local rand rand=$( tr -cd 'A-Za-z0-9' "${work_dir}"/etc/apt/sources.list + cat <"${work_dir}"/etc/apt/sources.list deb ${mirror} ${suite} ${components//,/ } #deb-src ${mirror} ${suite} ${components//,/ } EOF @@ -234,11 +359,14 @@ EOF # Choose a locale function set_locale() { LOCALES="$1" + log "locale:$(tput sgr0) ${LOCALES}" gray sed -i "s/^# *\($LOCALES\)/\1/" "${work_dir}"/etc/locale.gen + #systemd-nspawn_exec locale-gen echo "LANG=$LOCALES" >"${work_dir}"/etc/locale.conf echo "LC_ALL=$LOCALES" >>"${work_dir}"/etc/locale.conf + cat <<'EOM' >"${work_dir}"/etc/profile.d/default-lang.sh if [ -z "$LANG" ]; then source /etc/locale.conf @@ -255,10 +383,12 @@ function set_hostname() { if [[ "$1" =~ ^[a-zA-Z0-9-]{2,63}+$ ]]; then log " Created /etc/hostname" white echo "$1" >"${work_dir}"/etc/hostname + else log "$1 is not a correct hostname" red log "Using kali to default hostname" bold echo "kali" >"${work_dir}"/etc/hostname + fi } @@ -266,12 +396,14 @@ function set_hostname() { function add_interface() { interfaces="$*" for netdev in $interfaces; do - cat < "${work_dir}"/etc/network/interfaces.d/"$netdev" + cat <"${work_dir}"/etc/network/interfaces.d/"$netdev" auto $netdev allow-hotplug $netdev iface $netdev inet dhcp EOF + log " Configured /etc/network/interfaces.d/$netdev" white + done } @@ -284,7 +416,7 @@ function basic_network() { echo "alias net-pf-10 off" >>"${work_dir}"/etc/modprobe.d/ipv6.conf fi - cat < "${work_dir}"/etc/network/interfaces + cat <"${work_dir}"/etc/network/interfaces source-directory /etc/network/interfaces.d auto lo @@ -296,8 +428,9 @@ EOF function make_hosts() { set_hostname "${hostname}" + log " Created /etc/hosts" white - cat < "${work_dir}"/etc/hosts + cat <"${work_dir}"/etc/hosts 127.0.1.1 ${hostname:=} 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback @@ -313,9 +446,12 @@ function make_swap() { if [ "$swap" = yes ]; then log "Make swap" green echo 'vm.swappiness = 50' >>"${work_dir}"/etc/sysctl.conf + #sed -i 's/#CONF_SWAPSIZE=/CONF_SWAPSIZE=128/g' ${work_dir}/etc/dphys-swapfile + else [[ -f ${work_dir}/swapfile.img ]] || log "Make Swap:$(tput sgr0) Disabled" yellow + fi } @@ -323,11 +459,13 @@ function make_swap() { function print_config() { log "\n Compilation info" bold name_model="$(sed -n '3'p $0)" + log "Hardware model: $(tput sgr0)${name_model#* for}" cyan log "Architecture: $(tput sgr0)$architecture" cyan log "OS build: $(tput sgr0)$suite $version" cyan log "Desktop manager: $(tput sgr0)$desktop" cyan log "The base_dir thinks it is: $(tput sgr0)${base_dir}\n" cyan + sleep 1.5 } @@ -338,6 +476,7 @@ function make_image() { root_extra=$((root_size * 5 * 1024 / 5 / 1024 / 1000)) raw_size=$(($((free_space * 1024)) + root_extra + $((bootsize * 1024)) + 4096)) img_size=$(echo "${raw_size}"Ki | numfmt --from=iec-i --to=si) + # Create the disk image log "Creating image file:$(tput sgr0) ${image_name}.img (Size: ${img_size})" white [ -d ${image_dir} ] || mkdir -p "${image_dir}/" @@ -348,47 +487,62 @@ function make_image() { function make_loop() { img="${image_dir}/${image_name}.img" num_parts=$(fdisk -l $img | grep "${img}[1-2]" | wc -l) + if [ "$num_parts" = "2" ]; then extra=1 - part_type1=$(fdisk -l $img | grep ${img}1 | awk '{print $6}') - part_type2=$(fdisk -l $img | grep ${img}2 | awk '{print $6}') + part_type1=$(fdisk -l $img | grep ${img}1 | awk '{print $6}') + part_type2=$(fdisk -l $img | grep ${img}2 | awk '{print $6}') + if [[ "$part_type1" == "c" ]]; then bootfstype="vfat" + elif [[ "$part_type1" == "83" ]]; then bootfstype=${bootfstype:-"$fstype"} + fi + rootfstype=${rootfstype:-"$fstype"} loopdevice=$(losetup --show -fP "$img") bootp="${loopdevice}p1" rootp="${loopdevice}p2" + elif [ "$num_parts" = "1" ]; then - part_type1=$(fdisk -l $img | grep ${img}1 | awk '{print $6}') + part_type1=$(fdisk -l $img | grep ${img}1 | awk '{print $6}') + if [[ "$part_type1" == "83" ]]; then rootfstype=${rootfstype:-"$fstype"} + fi + rootfstype=${rootfstype:-"$fstype"} loopdevice=$(losetup --show -fP "$img") rootp="${loopdevice}p1" + fi } # Create fstab file. function make_fstab() { status "Create /etc/fstab" - cat < "${work_dir}"/etc/fstab + cat <"${work_dir}"/etc/fstab # proc /proc proc defaults 0 0 UUID=$root_uuid / $rootfstype errors=remount-ro 0 1 EOF + if ! [ -z "$bootp" ]; then - echo "LABEL=BOOT /boot $bootfstype defaults 0 2" >> "${work_dir}"/etc/fstab + echo "LABEL=BOOT /boot $bootfstype defaults 0 2" >>"${work_dir}"/etc/fstab + fi + make_swap + if [ -f "${work_dir}/swapfile.img" ]; then - cat << EOF >> ${work_dir}/etc/fstab + cat <>${work_dir}/etc/fstab /swapfile.img none swap sw 0 0 EOF + fi } @@ -396,25 +550,50 @@ EOF function mkfs_partitions() { status "Formatting partitions" # Formatting boot partition. - if [ -n "${bootp}" ] ; then - case $bootfstype in - vfat) mkfs.vfat -n BOOT -F 32 "${bootp}" ;; - ext4) features="^64bit,^metadata_csum" - mkfs -O "$features" -t "$fstype" -L BOOT "${bootp}" ;; - ext2 | ext3) features="^64bit" - mkfs -O "$features" -t "$fstype" -L BOOT "${bootp}" ;; + if [ -n "${bootp}" ]; then + case $bootfstype in + vfat) + mkfs.vfat -n BOOT -F 32 "${bootp}" + + ;; + + ext4) + features="^64bit,^metadata_csum" + mkfs -O "$features" -t "$fstype" -L BOOT "${bootp}" + + ;; + + ext2 | ext3) + features="^64bit" + mkfs -O "$features" -t "$fstype" -L BOOT "${bootp}" + + ;; + esac + bootfstype=$(blkid -o value -s TYPE $bootp) + fi + # Formatting root partition. - if [ -n "${rootp}" ] ; then - case $rootfstype in - ext4) features="^64bit,^metadata_csum" ;; - ext2 | ext3) features="^64bit" ;; + if [ -n "${rootp}" ]; then + case $rootfstype in + ext4) + features="^64bit,^metadata_csum" + + ;; + + ext2 | ext3) + features="^64bit" + + ;; + esac + yes | mkfs -U "$root_uuid" -O "$features" -t "$fstype" -L ROOTFS "${rootp}" root_partuuid=$(blkid -s PARTUUID -o value ${rootp}) rootfstype=$(blkid -o value -s TYPE $rootp) + fi } @@ -422,30 +601,39 @@ function mkfs_partitions() { function compress_img() { if [ "${compress:=}" = xz ]; then status "Compressing file: ${image_name}.img" + if [ "$(arch)" == 'x86_64' ] || [ "$(arch)" == 'aarch64' ]; then limit_cpu pixz -p "${num_cores:=}" "${image_dir}/${image_name}.img" # -p Nº cpu cores use + else xz --memlimit-compress=50% -T "$num_cores" "${image_dir}/${image_name}.img" # -T Nº cpu cores use + fi + img="${image_dir}/${image_name}.img.xz" + fi + chmod 0644 "$img" } # Calculate total time compilation. total_time() { local T=$1 - local H=$((T/60/60%24)) - local M=$((T/60%60)) - local S=$((T%60)) + local H=$((T / 60 / 60 % 24)) + local M=$((T / 60 % 60)) + local S=$((T % 60)) + printf '\nFinal time: ' + [[ $H -gt 0 ]] && printf '%d hours ' $H [[ $M -gt 0 ]] && printf '%d minutes ' $M [[ $D -gt 0 || $H -gt 0 || $M -gt 0 ]] && printf 'and ' + printf '%d seconds\n' $S } -function umount_partitions(){ +function umount_partitions() { # Make sure we are somewhere we are not going to unmount cd "${repo_dir}/" @@ -453,9 +641,9 @@ function umount_partitions(){ log "Unmount filesystem..." green # If there is boot partition, unmount that first. Else continue as not every ARM device has one - [ -n "${bootp}" ] \ - && ! mountpoint -q "${base_dir}/root/boot" || umount -q "${base_dir}/root/boot" \ - || true + [ -n "${bootp}" ] && + ! mountpoint -q "${base_dir}/root/boot" || umount -q "${base_dir}/root/boot" || + true ! mountpoint -q "${base_dir}/root" || umount -q "${base_dir}/root" } @@ -480,12 +668,13 @@ function clean_build() { function check_trap() { log "\n ⚠️ An error has occurred!\n" red clean_build + exit 1 } # Show progress status() { - status_i=$((status_i+1)) + status_i=$((status_i + 1)) [[ $debug = 1 ]] && timestamp="($(date +"%Y-%m-%d %H:%M:%S"))" || timestamp="" log " ✅ ${status_i}/${status_t}:$(tput sgr0) $1 $timestamp" green } diff --git a/common.d/packages.sh b/common.d/packages.sh index a053c18..3b49eaa 100644 --- a/common.d/packages.sh +++ b/common.d/packages.sh @@ -5,34 +5,48 @@ log " selecting packages ..." gray debootstrap_base="kali-archive-keyring,eatmydata" # This is the bare minimum if you want to start from very scratch -minimal_pkgs="ca-certificates iw network-manager parted wpasupplicant sudo" +minimal_pkgs="ca-certificates iw network-manager parted sudo wpasupplicant" # This is the list of minimal common packages -common_min_pkgs="$minimal_pkgs apt-transport-https command-not-found firmware-linux firmware-realtek \ -firmware-atheros firmware-libertas fontconfig ifupdown initramfs-tools kali-defaults kali-tweaks \ -man-db mlocate netcat-traditional net-tools pciutils psmisc rfkill screen snmpd snmp tftp tmux unrar \ -usbutils vim wireless-regdb zerofree zsh zsh-autosuggestions zsh-syntax-highlighting" -# This is the list of common packages -common_pkgs="$minimal_pkgs kali-linux-core apt-transport-https bluez bluez-firmware dialog \ -ifupdown initramfs-tools inxi libnss-systemd man-db mlocate net-tools network-manager \ -pciutils psmisc rfkill screen snmpd snmp tftp triggerhappy unrar usbutils whiptail wireless-regdb \ -zerofree" +common_min_pkgs="$minimal_pkgs apt-transport-https command-not-found \ +firmware-atheros firmware-libertas firmware-linux firmware-realtek fontconfig \ +ifupdown initramfs-tools kali-defaults kali-tweaks man-db mlocate net-tools \ +netcat-traditional pciutils psmisc rfkill screen snmp snmpd tftp tmux unrar \ +usbutils vim wireless-regdb zerofree zsh zsh-autosuggestions \ +zsh-syntax-highlighting" -services="apache2 atftpd ssh openvpn tightvncserver" +# This is the list of common packages +common_pkgs="$minimal_pkgs apt-transport-https bluez bluez-firmware dialog \ +ifupdown initramfs-tools inxi kali-linux-core libnss-systemd man-db mlocate \ +net-tools network-manager pciutils psmisc rfkill screen snmp snmpd tftp \ +triggerhappy unrar usbutils whiptail wireless-regdb zerofree" + +services="apache2 atftpd openvpn ssh tightvncserver" # This is the list of minimal cli based tools -cli_min_tools="aircrack-ng crunch cewl dnsrecon dnsutils ethtool exploitdb hydra john \ -libnfc-bin medusa metasploit-framework mfoc ncrack nmap passing-the-hash proxychains recon-ng \ -sqlmap tcpdump theharvester tor tshark whois windows-binaries winexe wpscan" +cli_min_tools="aircrack-ng cewl crunch dnsrecon dnsutils ethtool exploitdb hydra \ +john libnfc-bin medusa metasploit-framework mfoc ncrack nmap passing-the-hash \ +proxychains recon-ng sqlmap tcpdump theharvester tor tshark whois windows-binaries \ +winexe wpscan" + # This is the list of most cli based tools cli_tools_pkgs="kali-linux-arm" # Desktop packages to install case $desktop in - xfce|gnome|kde|i3|i3-gaps|lxde|mate|e17) - desktop_pkgs="kali-linux-default kali-desktop-$desktop alsa-utils xfonts-terminus \ - xinput xserver-xorg-video-fbdev xserver-xorg-input-libinput" ;; - none|slim|miminal) variant="minimal"; minimal="1"; desktop_pkgs="" ;; +xfce | gnome | kde | i3 | i3-gaps | lxde | mate | e17) + desktop_pkgs="kali-linux-default kali-desktop-$desktop alsa-utils xfonts-terminus \ + xinput xserver-xorg-video-fbdev xserver-xorg-input-libinput" + + ;; + +none | slim | miminal) + variant="minimal" + minimal="1" + desktop_pkgs="" + + ;; + esac # Installed kernel sources when using a kernel that isn't packaged. @@ -41,11 +55,13 @@ custom_kernel_pkgs="bc bison libssl-dev" rpi_pkgs="fake-hwclock ntpdate u-boot-tools" # Packages specific to the boards and using the GPIO on it -gpio_pkgs="i2c-tools python3-configobj python3-pip python3-requests python3-rpi.gpio python3-smbus" +gpio_pkgs="i2c-tools python3-configobj python3-pip python3-requests \ +python3-rpi.gpio python3-smbus" # Add swap packages if [ "$swap" = yes ]; then minimal_pkgs+=" dphys-swapfile" + fi extra="$custom_kernel_pkgs" @@ -56,23 +72,35 @@ packages="$common_pkgs $cli_tools_pkgs $services $extra_custom_pkgs" # Do not add re4son_pkgs to this list, as we do not have his repo added when these are installed if [[ "$hw_model" == *rpi* ]]; then extra+=" $gpio_pkgs $rpi_pkgs" + fi + if [ "$minimal" = "1" ]; then image_mode="minimal" + if [ "$slim" = "1" ]; then cli_min_tools="" image_mode="slim" packages="$common_min_pkgs $cli_min_tools ssh" + else packages="$common_min_pkgs $cli_min_tools $services $extra_custom_pkgs" + fi + log " selecting $image_mode mode ..." gray + fi # Basic packages third stage -third_stage_pkgs="binutils ca-certificates console-common console-setup locales libterm-readline-gnu-perl git wget curl" +third_stage_pkgs="binutils ca-certificates console-common console-setup curl git \ +libterm-readline-gnu-perl locales wget" # Re4son packages -re4son_pkgs="kalipi-kernel kalipi-bootloader kalipi-re4son-firmware kalipi-kernel-headers kalipi-config kalipi-tft-config pi-bluetooth bluetooth bluez bluez-firmware" +re4son_pkgs="bluetooth bluez bluez-firmware kalipi-bootloader kalipi-config \ +kalipi-kernel kalipi-kernel-headers kalipi-re4son-firmware kalipi-tft-config \ +pi-bluetooth" # PiTail specific packages -pitail_pkgs="bluelog bluesnarfer blueranger bluez-tools bridge-utils wifiphisher cmake mailutils libusb-1.0-0-dev htop locate pure-ftpd tigervnc-standalone-server dnsmasq darkstat" +pitail_pkgs="bluelog blueranger bluesnarfer bluez-tools bridge-utils cmake darkstat \ +dnsmasq htop libusb-1.0-0-dev locate mailutils pure-ftpd tigervnc-standalone-server \ +wifiphisher" diff --git a/common.d/radxa_zero.sh b/common.d/radxa_zero.sh index 0d523a5..0981cf8 100644 --- a/common.d/radxa_zero.sh +++ b/common.d/radxa_zero.sh @@ -1,16 +1,28 @@ case $2 in - sdcard) format="sdcard" ;; - emmc) format="emmc" ;; - *) - echo -e "\n[-] Unsupported format: $2" >&2; - exit 1;; +sdcard) + format="sdcard" + + ;; + +emmc) + format="emmc" + + ;; + +*) + echo -e "\n[-] Unsupported format: $2" >&2 + + exit 1 + + ;; + esac # Network configs basic_network # Third stage -cat <> "${work_dir}"/third-stage +cat <>"${work_dir}"/third-stage status_stage3 'Install u-boot tools' eatmydata apt-get install -y u-boot-menu u-boot-tools @@ -19,7 +31,7 @@ eatmydata apt-get install -y u-boot-menu u-boot-tools # so install alsa-utils for amixer and alsactl availability. eatmydata apt-get install -y file alsa-utils -# Note: This just creates an empty /boot/extlinux/extlinux.conf for us to use +# Note: This just creates an empty /boot/extlinux/extlinux.conf for us to use # later when we install the kernel, and then fixup further down status_stage3 'Run u-boot-update' u-boot-update @@ -54,7 +66,7 @@ include clean_system status "Kernel stuff" git clone --depth 1 -b radxa-zero-linux-5.10.y https://github.com/steev/linux.git ${work_dir}/usr/src/kernel cd ${work_dir}/usr/src/kernel -git rev-parse HEAD > ${work_dir}/usr/src/kernel-at-commit +git rev-parse HEAD >${work_dir}/usr/src/kernel-at-commit rm -rf .git export ARCH=arm64 export CROSS_COMPILE=aarch64-linux-gnu- @@ -63,15 +75,19 @@ make -j $(grep -c processor /proc/cpuinfo) LOCALVERSION="" bindeb-pkg make mrproper make radxa_zero_defconfig cd .. + # Cross building kernel packages produces broken header packages # so only install the headers if we're building on arm64 if [ "$(arch)" == 'aarch64' ]; then # We don't need to install the linux-libc-dev package, we just want kernel and headers rm linux-libc-dev*.deb dpkg --root "${work_dir}" -i linux-*.deb + else dpkg --root "${work_dir}" -i linux-image-*.deb + fi + rm linux-*_* cd "${repo_dir}/" @@ -91,6 +107,7 @@ make_loop # Create file systems status "Formatting partitions" mkfs_partitions + # Make fstab make_fstab @@ -117,8 +134,8 @@ sed -i -e "s/root=UUID=.*/root=UUID=$(blkid -s UUID -o value ${rootp})/" ${work_ sed -i -e "s/LABEL=BOOT/UUID=$(blkid -s UUID -o value ${bootp})/" ${work_dir}/etc/fstab status "Set the default options in /etc/default/u-boot" -echo 'U_BOOT_MENU_LABEL="Kali Linux"' >> ${work_dir}/etc/default/u-boot -echo 'U_BOOT_PARAMETERS="earlyprintk console=ttyAML0,115200 console=tty1 swiotlb=1 coherent_pool=1m ro rootwait"' >> ${work_dir}/etc/default/u-boot +echo 'U_BOOT_MENU_LABEL="Kali Linux"' >>${work_dir}/etc/default/u-boot +echo 'U_BOOT_PARAMETERS="earlyprintk console=ttyAML0,115200 console=tty1 swiotlb=1 coherent_pool=1m ro rootwait"' >>${work_dir}/etc/default/u-boot status "Rsyncing rootfs into image file" rsync -HPavz -q --exclude boot "${work_dir}"/ "${base_dir}"/root/ @@ -133,24 +150,30 @@ cd "${work_dir}" git clone https://github.com/radxa/fip.git git clone https://github.com/u-boot/u-boot.git --depth 1 cd u-boot + # Remove amlogic from the config, this matches what LibreElec does, as well as the vendor u-boot -patch -p1 --no-backup-if-mismatch < "${repo_dir}"/patches/u-boot/radxa/0001-HACK-configs-meson64-remove-amlogic.patch +patch -p1 --no-backup-if-mismatch <"${repo_dir}"/patches/u-boot/radxa/0001-HACK-configs-meson64-remove-amlogic.patch + # Enable USB at preboot, so we can use usb keyboard to interrupt boot sequence, with the nifty side effect # that USB boot *should* also work, but untested. -patch -p1 --no-backup-if-mismatch < "${repo_dir}"/patches/u-boot/radxa/0002-boards-amlogic-enable-usb-preboot.patch +patch -p1 --no-backup-if-mismatch <"${repo_dir}"/patches/u-boot/radxa/0002-boards-amlogic-enable-usb-preboot.patch make distclean make radxa-zero_config make ARCH=arm -j$(nproc) cp u-boot.bin ../fip/radxa-zero/bl33.bin cd ../fip/radxa-zero/ make + # https://wiki.radxa.com/Zero/dev/u-boot if [ "$format" == "sdcard" ]; then dd if=u-boot.bin.sd.bin of=${loopdevice} conv=fsync,notrunc bs=1 count=442 dd if=u-boot.bin.sd.bin of=${loopdevice} conv=fsync,notrunc bs=512 skip=1 seek=1 + else dd if=u-boot.bin of=${loopdevice} conv=fsync,notrunc bs=512 seek=1 + fi + cd "${repo_dir}/" rm -rf "${work_dir}"/{fip,u-boot} diff --git a/common.d/rpi_firmware.sh b/common.d/rpi_firmware.sh index ebbde44..c356ebf 100644 --- a/common.d/rpi_firmware.sh +++ b/common.d/rpi_firmware.sh @@ -37,4 +37,5 @@ kernel=kernel8l-alt.img # Tell firmware to go 64-bit mode arm_64bit=1 EOF + fi diff --git a/common.d/variables.sh b/common.d/variables.sh index 9baef45..57318ac 100644 --- a/common.d/variables.sh +++ b/common.d/variables.sh @@ -96,6 +96,7 @@ export MALLOC_CHECK_=0 # Load build configuration if [ -f "${repo_dir}"/builder.txt ]; then echo "Loading: "${repo_dir}"/builder.txt" + # shellcheck source=/dev/null source "${repo_dir}"/builder.txt @@ -103,6 +104,7 @@ if [ -f "${repo_dir}"/builder.txt ]; then && grep -v '#' "${repo_dir}"/builder.txt \ | sort -u \ || true + fi # Incase `su` was used