diff options
Diffstat (limited to 'iv/orodja/napad/exploit.sh')
-rwxr-xr-x | iv/orodja/napad/exploit.sh | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/iv/orodja/napad/exploit.sh b/iv/orodja/napad/exploit.sh new file mode 100755 index 0000000..9e2cafb --- /dev/null +++ b/iv/orodja/napad/exploit.sh @@ -0,0 +1,151 @@ +#!/bin/sh +if [ x$1 = x ] +then +cat >&2 <<EOF +No command. Usage: $0 <subcommand> [args ...] Subcommands: + once <service> <exploit> [team=$GAME_NOP_TEAM] # runs exploit once + loop <service> <exploit> # once per team per round, waits for next round +<exploit> is an executable file. Flags, grepped from stdout, are submitted. +It is called for every target with the following environment variables: + TARGET_IP: target IP address (uses game_target_ip from config) + TARGET_EXTRA: Flag IDs JSON object (uses game_flag_ids_url in config) + FLAG_ID_<key>: Every JSON value from flag IDs individually +Example environment is therefore: + TARGET_IP=1.1.1.1 TARGET_EXTRA='{"a": "1", "b": "2"}' FLAG_ID_a=1 FLAG_ID_b=2 +In loop mode, exploit is first exec'd rapidly for still valid old rounds. +Max execution time is $EXPLOIT_TIMEOUT seconds (EXPLOIT_TIMEOUT in config) +Exploits are not run in parallel. +Make sure that your system time is set CORRECTLY TO THE SECOND, it's used + to get the current round id. Check this on http://time.is +Configuration values are also available in environment of exploits. +<service> is the name of the service (used for getting flag IDs) +Set the following environment variables to alter behaviour: + EXPLOIT_STDOUT=1: stdout of exploit will be printed to stderr/terminal + EXPLOIT_LOOP_ONCE=1: exit after executing for all valid rounds instead of + waiting for the next round. Only valid for loop subcommand. + EXPLOIT_VERBOSE=1: print _every_ line executed by $0 (set -x) + EXPLOIT_NOTPARALLEL=1: disable parallel even if parallel is available +$EXPLOIT_ADDITIONAL_HELP_TEXT +EOF + exit 1 +fi +[ ${EXPLOIT_VERBOSE:-false} = false ] || set -x +set -euo pipefail +current_round_id() +{ # BREAKS WHEN THERE ARE LEAP SECONDS DURING GAME + startunix=`date +%s --utc --date $GAME_START` + current=`date +%s --utc` + echo $((($current-$startunix)/$ROUND_DURATION)) +} +if [ ${ROUND_ID:-x} = x ] +then + export ROUND_ID=`current_round_id` +fi +subcommand=$1 +service=$2 +exploit=$3 +# tees stdout, collects flags, puts stdout to stderr, prints counts +# args: team +exploit_pipe() +{ + stdoutwhere=/dev/null + [ ! ${EXPLOIT_STDOUT:-false} = false ] && stdoutwhere=/dev/stderr + tee $stdoutwhere | { grep -Eo "$FLAG_REGEX_SEARCH" || :; } | while read -r line + do + echo $line $1 $ROUND_ID $service $exploit `whoami`@`hostname``pwd` + done | { nc -N $SUBMISSION_HOST $SUBMISSION_PORT || return $((200+$?)); } | cut -d\ -f1,2 | sort | uniq -c | tr $'\n' ' ' | cat <(printf "team=%-2d round=%d: " $1 $ROUND_ID) /dev/stdin <(echo) >&2 +} +# args: team round +get_flag_ids() +{ + set +e + output_flagids=$(curl --fail-with-body --no-progress-meter "`game_flag_ids_url "$service" $1 $2`") + curl_exit_code=$? + set -e + echo $output_flagids + if [ ! $curl_exit_code -eq 0 ] + then + send_error $1 "round=$round failed to get flag ids: $output_flagids" >&2 + return 99 + fi +} +# args: team message +send_error() +{ + echo [$0] ERROR: team=$1: $2 + exploit_error_handler "$service" $1 `pwd` `whoami`@`hostname` $2 +} +case $subcommand in + once) + target_team=$GAME_NOP_TEAM + if [ $# -ge 4 ] + then + target_team=$4 + fi + export TARGET_IP=`game_target_ip $target_team` + export TARGET_EXTRA="`get_flag_ids $target_team $ROUND_ID`" + source <(echo "$TARGET_EXTRA" | jq -r 'to_entries|map("export FLAG_ID_\(.key|sub("'"'"'";""))='"'"'\(.value|tostring|sub("'"'"'";"'"'\\\"'\\\"'"'"))'"'"'")|.[]') + set +e + timeout $EXPLOIT_TIMEOUT $exploit | exploit_pipe $target_team + exit_code=$? + set -e + if [ $exit_code -gt 200 ] + then + send_error $target_team "submission netcat failed with $(($exit_code-200))" + exit $exit_code + fi + if [ ! $exit_code -eq 0 ] && [ ! $exit_code -eq 124 ] + then + send_error $target_team "$exploit exited with $exit_code" + fi + if [ $exit_code -eq 124 ] + then + echo [$0] team=$target_team $exploit timed out >&2 + fi + exit $exit_code + ;; + loop) + if parallel --version > /dev/null && [ ${EXPLOIT_NOTPARALLEL:-false} = false ] + then + commands_evaluator="parallel --color-failed" + commands_output="/dev/stdout" + have_parallel=true + echo "[$0] using parallel executions (:" >&2 + else + commands_evaluator="cat /dev/stdin" + commands_output="/dev/null" + have_parallel=false + echo "[$0] parallel not found or disabled! zaporedno izvajanje ):" >&2 + fi + round=$(($ROUND_ID-$GAME_VALID_ROUNDS)) + while : + do + for target_team in $GAME_TEAMS + do + cmd2exec="ROUND_ID=$round $0 once '$service' $exploit $target_team" + if $have_parallel + then + echo $cmd2exec + else + eval $cmd2exec + fi + done | $commands_evaluator > $commands_output + round=$(($round+1)) + we_slept=false + while [ `current_round_id` -lt $round ] + do # oh no we pollin thats ugly af, who cares we have + if [ ! ${EXPLOIT_LOOP_ONCE:-false} = false ] + then + echo [$0] breaking due to EXPLOIT_LOOP_ONCE + break + fi + we_slept=true + sleep 1 # INFINITE CPU POWAH! + done + if $we_slept + then # execute exploit at random time instead of at start + sleep $(($RANDOM%$ROUND_DURATION/2)) + fi + done + ;; +esac |