Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
A system tap script to detect UDP beacons
#! /usr/bin/env stap
/*
/\ \ /\ \__
\ \ \____ __ __ ___ ___ ___ __ \ \ ,_\ ___ _ __
\ \ '__`\ /'__`\ /'__`\ /'___\ / __`\ /' _ `\ /'__`\ \ \ \/ / __`\/\`'__\
\ \ \L\ \/\ __//\ \L\.\_/\ \__//\ \L\ \/\ \/\ \/\ \L\.\_\ \ \_/\ \L\ \ \ \/
\ \_,__/\ \____\ \__/.\_\ \____\ \____/\ \_\ \_\ \__/.\_\\ \__\ \____/\ \_\
\/___/ \/____/\/__/\/_/\/____/\/___/ \/_/\/_/\/__/\/_/ \/__/\/___/ \/_/
*/
/*System Tap arrays must all be global*/
global procnames //holds a list of processes we've seen making udp calls
global curr_timestamps //holds the last UDP timestamp seen per process
global process_count //holds the number of times we've seen each process make a UDP call*/
global delta_list /*Lookup a time delta by supplying a process_name and which time we saw it
IE: {ping:3} = the time delta the 3rd time ping caused a UDP call*/
global ip_lookup_table /* Lookup an IP_address by supplying a process_name and delta
IE{process_name, delta} = ip_address */
global beacon_count //Lookup the number of times we've seen a process and a specific time delta
global confirmed_beacons //Lookup processes by proc_name and delta that we've confirmed are consistently beaconing
/* begin is executed after the kernel module is loaded */
probe begin
{
println("Tracking UDP Calls...")
}
/*Set up a handler for UDP sends*/
probe udp.sendmsg{
ts = gettimeofday_s()
procname = execname()
procnames[procname] <<< 1
printf(" %15s %15s %15s %5d %5d %15s UDP\n", ctime(ts), saddr, daddr, sport, dport, execname())
/*If the process that made the UDP call is already one we're tracking*/
if (procname in curr_timestamps)
{
delta = ts - curr_timestamps[procname]
if (delta != 0){
process_count[procname]++
ip_lookup_table[procname,delta] = daddr
delta_list[procname, process_count[procname]] = delta
}
}
curr_timestamps[procname] = ts
}
/* beacon_check function will check for beaconing every 30 seconds */
function beacon_check(){
//for every process we've seen
foreach(procname in procnames){
i=0
cached_time_delta = 0
//while i is less than the total number of times we saw the process make a udp call
while (i < process_count[procname])
{
current_time_delta = delta_list[procname,i]
//Ignore cases where our time delta was 0. Likely duplicate UDP event
if (current_time_delta != 0)
{
//If we are dealing with the first UDP event, we have nothing to compare it to. Store and move to next pass
if (cached_time_delta == 0)
{
cached_time_delta = current_time_delta
}
else
{
//If we've seen the same amount of space between two beacons
if (cached_time_delta == current_time_delta)
beacon_count[procname,current_time_delta]++
//If we've seen this beacon 3 times at a consistent rate
if (beacon_count[procname,current_time_delta] > 2)
{
if ([procname,current_time_delta] in confirmed_beacons){
;
}
else
{
confirmed_beacons[procname,current_time_delta] = 1
printf("%s is beaconing every %d seconds to %s\n", procname, current_time_delta, ip_lookup_table[procname,current_time_delta])
}
}
}
//save this time delta so we can compare it to the next pass
cached_time_delta = current_time_delta
}
i++
}
}
}
/* Creating a timer that runs our beacon_check every 30 seconds */
probe timer.s(30)
{
//print it in red
ansi_set_color(31)
beacon_check()
ansi_reset_color()
}
/* end runs right before the kernel module is unloaded (ctrl+c) */
probe end
{
println("Done!")
beacon_check()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment