Skip to content

Commit 1601e1b

Browse files
committed
core: add streamline artifact to tcp feature
1 parent b2fffc7 commit 1601e1b

1 file changed

Lines changed: 126 additions & 10 deletions

File tree

LFC/LFC.sh

Lines changed: 126 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,41 +2,69 @@
22

33
# Function to display usage information
44
usage() {
5-
echo "Usage: $0 [OUTPUT_DIRECTORY] [--no-osquery]"
5+
echo "Usage: $0 [OUTPUT_DIRECTORY] [--no-osquery] [--tcp-stream IP:PORT]"
66
echo " OUTPUT_DIRECTORY: Optional. Directory where forensic artifacts will be collected."
77
echo " Default: /tmp/result"
88
echo " --no-osquery: Optional. Skip osquery collection."
9+
echo " --tcp-stream: Optional. Stream tarball to specified IP:PORT over TCP."
10+
echo " Format: IP:PORT (e.g., 192.168.1.100:8080)"
911
echo ""
1012
echo "Examples:"
1113
echo " $0 # Use default output directory (/tmp/result) and run osquery"
1214
echo " $0 /var/output # Use custom output directory and run osquery"
1315
echo " $0 --no-osquery # Use default output directory and skip osquery"
1416
echo " $0 /var/output --no-osquery # Use custom output directory and skip osquery"
17+
echo " $0 --tcp-stream 192.168.1.100:8080 # Stream artifacts over TCP"
18+
echo " $0 /var/output --no-osquery --tcp-stream 10.0.0.5:9999 # Custom dir, no osquery, TCP stream"
1519
exit 1
1620
}
1721

1822
# Parse command line arguments
1923
SKIP_OSQUERY=false
2024
TEMP_OUTPUT_DIR=""
25+
TCP_STREAM=""
2126

22-
for arg in "$@"; do
23-
case $arg in
27+
while [[ $# -gt 0 ]]; do
28+
case $1 in
2429
-h|--help)
2530
usage
2631
;;
2732
--no-osquery)
2833
SKIP_OSQUERY=true
2934
shift # Remove --no-osquery from processing
3035
;;
36+
--tcp-stream)
37+
# Next argument should be IP:PORT
38+
shift
39+
TCP_STREAM="$1"
40+
if [[ ! "$TCP_STREAM" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+$ ]]; then
41+
echo "Error: Invalid TCP stream format. Expected IP:PORT (e.g., 192.168.1.100:8080)"
42+
usage
43+
fi
44+
shift
45+
;;
46+
--tcp-stream=*)
47+
# Handle --tcp-stream=IP:PORT format
48+
TCP_STREAM="${1#*=}"
49+
if [[ ! "$TCP_STREAM" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+:[0-9]+$ ]]; then
50+
echo "Error: Invalid TCP stream format. Expected IP:PORT (e.g., 192.168.1.100:8080)"
51+
usage
52+
fi
53+
shift
54+
;;
55+
-*)
56+
echo "Error: Unknown option $1"
57+
usage
58+
;;
3159
*)
3260
# If an argument is not a flag, and TEMP_OUTPUT_DIR is not set, it's the output directory
33-
if [[ ! "$arg" =~ ^- ]] && [ -z "$TEMP_OUTPUT_DIR" ]; then
34-
TEMP_OUTPUT_DIR="$arg"
35-
# If it's an unknown flag or a second positional argument
36-
elif [[ "$arg" =~ ^- ]] || [ -n "$TEMP_OUTPUT_DIR" ]; then
37-
echo "Error: Too many arguments provided or invalid argument: $arg"
61+
if [ -z "$TEMP_OUTPUT_DIR" ]; then
62+
TEMP_OUTPUT_DIR="$1"
63+
else
64+
echo "Error: Too many arguments provided: $1"
3865
usage
3966
fi
67+
shift
4068
;;
4169
esac
4270
done
@@ -249,6 +277,60 @@ check_if_value_in_blacklist() {
249277
return 0
250278
}
251279

280+
stream_tarball_over_tcp() {
281+
# Streams tarball over TCP to specified IP:PORT
282+
# Uses /dev/tcp as primary method, falls back to nc/ncat if available
283+
local ip_port="$1"
284+
local tarball_path="$2"
285+
286+
# Extract IP and port from IP:PORT format
287+
local ip="${ip_port%:*}"
288+
local port="${ip_port#*:}"
289+
290+
write_log "INFO" "Attempting to stream tarball $tarball_path to $ip:$port"
291+
292+
# Method 1: Try /dev/tcp (built into bash)
293+
if exec 3<> "/dev/tcp/$ip/$port" 2>/dev/null; then
294+
write_log "INFO" "Connected using /dev/tcp method"
295+
if cat "$tarball_path" >&3 2>/dev/null; then
296+
write_log "INFO" "Successfully streamed tarball using /dev/tcp"
297+
exec 3>&- # Close the connection
298+
return 0
299+
else
300+
write_log "ERROR" "Failed to stream data using /dev/tcp"
301+
exec 3>&- # Close the connection
302+
fi
303+
else
304+
write_log "WARNING" "/dev/tcp connection failed, trying fallback methods"
305+
fi
306+
307+
# Method 2: Try netcat (nc)
308+
if command -v nc >/dev/null 2>&1; then
309+
write_log "INFO" "Attempting to use nc (netcat)"
310+
if cat "$tarball_path" | nc "$ip" "$port" 2>/dev/null; then
311+
write_log "INFO" "Successfully streamed tarball using nc"
312+
return 0
313+
else
314+
write_log "ERROR" "Failed to stream using nc"
315+
fi
316+
fi
317+
318+
# Method 3: Try ncat (from nmap)
319+
if command -v ncat >/dev/null 2>&1; then
320+
write_log "INFO" "Attempting to use ncat"
321+
if cat "$tarball_path" | ncat "$ip" "$port" 2>/dev/null; then
322+
write_log "INFO" "Successfully streamed tarball using ncat"
323+
return 0
324+
else
325+
write_log "ERROR" "Failed to stream using ncat"
326+
fi
327+
fi
328+
329+
# All methods failed
330+
write_log "ERROR" "All TCP streaming methods failed. Tarball remains locally at $tarball_path"
331+
return 1
332+
}
333+
252334
copy_configuration_files() {
253335
# Copy configuration files from a list of configuration files.
254336
for file in "${SYSTEM_FILES[@]}"; do
@@ -655,7 +737,41 @@ write_log "INFO" "Artifact collection completed in $ELAPSED_TIME seconds. Artifa
655737
# Create tar archive of the collected artifacts
656738
OUTPUT_BASENAME=$(basename "$OUTPUT_DIR")
657739
PARENT_DIR=$(dirname "$OUTPUT_DIR")
658-
tar -czf "$ZIP_DIR/${OUTPUT_BASENAME}.tar.gz" -C "$PARENT_DIR" "$OUTPUT_BASENAME"
740+
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
741+
HOSTNAME=$(hostname -s)
742+
TARBALL_FILENAME="lfc_${HOSTNAME}_${TIMESTAMP}.tar.gz"
743+
TARBALL_PATH="$ZIP_DIR/$TARBALL_FILENAME"
744+
tar -czf "$TARBALL_PATH" -C "$PARENT_DIR" "$OUTPUT_BASENAME"
659745

660746
# Delete uncompressed output directory
661-
rm -rf "$OUTPUT_DIR"
747+
rm -rf "$OUTPUT_DIR"
748+
749+
# Handle TCP streaming if requested
750+
if [ -n "$TCP_STREAM" ]; then
751+
# Create a temporary log file for post-processing operations since original log is now archived
752+
TEMP_LOGFILE="$ZIP_DIR/lfc_tcp_streaming.log"
753+
754+
# Temporarily redirect write_log to the temp log file
755+
ORIGINAL_LOGFILE="$LOGFILE"
756+
LOGFILE="$TEMP_LOGFILE"
757+
758+
write_log "INFO" "TCP streaming requested to $TCP_STREAM"
759+
760+
if stream_tarball_over_tcp "$TCP_STREAM" "$TARBALL_PATH"; then
761+
write_log "INFO" "Successfully streamed tarball over TCP. Removing local copy."
762+
rm -f "$TARBALL_PATH"
763+
write_log "INFO" "Forensic artifacts streamed to $TCP_STREAM and local tarball removed."
764+
echo "Forensic artifacts streamed to $TCP_STREAM and local tarball removed."
765+
echo "TCP streaming log saved at: $TEMP_LOGFILE"
766+
else
767+
write_log "ERROR" "TCP streaming failed. Tarball remains at $TARBALL_PATH"
768+
write_log "INFO" "Forensic artifacts collection completed. Local tarball saved at $TARBALL_PATH"
769+
echo "TCP streaming failed. Tarball remains at $TARBALL_PATH"
770+
echo "TCP streaming log saved at: $TEMP_LOGFILE"
771+
fi
772+
773+
# Restore original logfile variable (though it won't be used again)
774+
LOGFILE="$ORIGINAL_LOGFILE"
775+
else
776+
echo "Forensic artifacts collection completed. Tarball saved at $TARBALL_PATH"
777+
fi

0 commit comments

Comments
 (0)