0

I have a binary sample (VirusShare_00238010bb86fd0bf4014c3d19f114b2) used in my research that behaves oddly when I try to measure its runtime

When I run it directly with /usr/bin/time, it exits almost instantly:

$ time /home/runner/samples/VirusShare_00238010bb86fd0bf4014c3d19f114b2
BUILD DONGS

real    0m0.001s
user    0m0.001s
sys     0m0.000s

But when I attach with strace -f, the program prints BUILD DONGS and then the terminal keeps populating with repeated connect() and nanosleep() syscalls - example below so you can focus on my question and make it clear :) I had to press Ctrl-C to stop it. It looks like the binary forks off a child process that keeps retrying network connections in the background.

My question is how can I accurately measure the program run time which I run in LXC container? I came up with this:

start=$(date +%s%3N)

/home/runner/samples/VirusShare_00238010bb86fd0bf4014c3d19f114b2 &

limit=$((start + 10000))  # 10 sec timeout

while pgrep -f VirusShare_00238010bb86fd0bf4014c3d19f114b2 >/dev/null; do
    now=$(date +%s%3N)
    if (( now >= limit )); then
        echo "[!] Timeout reached, killing all VirusShare processes"
        pkill -f VirusShare_00238010bb86fd0bf4014c3d19f114b2
        break
    fi
    sleep 0.1
done

end=$(date +%s%3N)
echo "runtime=$((end-start)) ms"

but I got many problems with it, it looks over complicated (isn't there a built in command for that?) and it waits 0.1 seconds which hurts accuracy (using smaller numbers won't help as sleep isn't so accurate)

close(4)                                = 0
ioctl(3, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr={sa_family=ARPHRD_ETHER, sa_data=00:16:3e:93:88:c7}}) = 0
close(3)                                = 0
fork(strace: Process 647368 attached
)                                  = 647368
[pid 647368] fork( <unfinished ...>
[pid 647366] wait4(647368, strace: Process 647369 attached
 <unfinished ...>
[pid 647368] <... fork resumed>)        = 647369
[pid 647369] setsid( <unfinished ...>
[pid 647368] exit(0 <unfinished ...>
[pid 647369] <... setsid resumed>)      = 647369
[pid 647368] <... exit resumed>)        = ?
[pid 647369] chdir("/" <unfinished ...>
[pid 647368] +++ exited with 0 +++
[pid 647366] <... wait4 resumed>[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 647368
[pid 647369] <... chdir resumed>)       = 0
[pid 647369] rt_sigaction(SIGPIPE, {sa_handler=SIG_IGN, sa_mask=[PIPE], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0x40ad5c},  <unfinished ...>
[pid 647366] --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=647368, si_uid=0, si_status=0, si_utime=0, si_stime=0} ---
[pid 647369] <... rt_sigaction resumed>{sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
[pid 647366] exit(0 <unfinished ...>
[pid 647369] socket(AF_INET, SOCK_STREAM, IPPROTO_IP <unfinished ...>
[pid 647366] <... exit resumed>)        = ?
[pid 647369] <... socket resumed>)      = 3
[pid 647366] +++ exited with 0 +++
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
connect(3, {sa_family=AF_INET, sin_port=htons(23), sin_addr=inet_addr("206.189.30.49")}, 16) = -1 EINPROGRESS (Operation now in progress)
select(4, NULL, [3], NULL, {tv_sec=30, tv_usec=0}) = 1 (out [3], left {tv_sec=29, tv_usec=904908})
getsockopt(3, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
**nanosleep**({tv_sec=5, tv_nsec=0}, 0x7ffe11750770) = 0
close(3)                                = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
fcntl(3, F_GETFL)                       = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK)    = 0
connect(3, {sa_family=AF_INET, sin_port=htons(23), sin_addr=inet_addr("206.189.30.49")}, 16) = -1 EINPROGRESS (Operation now in progress)
select(4, NULL, [3], NULL, {tv_sec=30, tv_usec=0}) = 1 (out [3], left {tv_sec=29, tv_usec=905455})
getsockopt(3, SOL_SOCKET, SO_ERROR, [ECONNREFUSED], [4]) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {sa_handler=SIG_DFL, sa_mask=[], sa_flags=0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
**nanosleep**({tv_sec=5, tv_nsec=0}, ^Cstrace: Process 647369 detached
 <detached ...>

root@sandbox0:~# ^C
6
  • How about time bash -c '/home/runner/samples/VirusShare_00238010bb86fd0bf4014c3d19f114b2' Commented Sep 6 at 21:58
  • @LMC Same thing, i guess because child processes change guid or so they are trying to hide Commented Sep 6 at 22:02
  • How about indirectly with tcpdump? Commented Sep 6 at 22:12
  • Or strace -tt .. or strace -r ... Commented Sep 6 at 22:16
  • Infact, better strace -tt -ff -o trace.txt .. or strace -ff -r -o trace-txt ... Commented Sep 6 at 22:21

1 Answer 1

0

Monitor process to kill excessively long tasks matching name (re).

I would like to suggest another approach:

cmd="Virus[S]hare"
maxSec=10
LANG=C ps axho pid,etime,cmd |
    sed -nEe '1i cnt=0' -e '$a return $((cnt>0))' -e "
  /^ *([0-9]+) +((([0-9]+)-)?([0-9]+):)?([0-9]+):([0-9]+) .*$cmd.*$/ {
    s//if (( \1 != $$ )); then\n\
     if ((10#0\3*86400+10#0\5*3600+10#\6*60+10#\7>$maxSec));then\n\
       echo 'Killing &'\n\
       kill \1\n\
     else\n\
       ((cnt++))\n\
     fi\n\
    fi/p}"

Could produce a script like this (if some VirusShare command is running):

cnt=0
if (( 90793 != 91007 )); then
     if ((10#0*86400+10#0*3600+10#00*60+10#15>10));then
       echo 'Killing  90793  00:15  /path/to/VirusShare_00238010bb86fd0bf4014c3d19f114b2'
       kill 90793
     else
       ((cnt++))
     fi
    fi
return $((cnt>0))

Note: between cnt=0 and return $((cnt>0)) you may found as many if ((... fi\nfi group your system have *VirusShare* process currently running.

So you could use:

maxSec=10
cmd="Virus[S]hare"
. <(sed -nEe '1i cnt=0' -e '$a return $((cnt>0))' -e "
/^ *([0-9]+) +((([0-9]+)-)?([0-9]+):)?([0-9]+):([0-9]+) .*$cmd.*$/ {
    s//if (( \1 != $$ )); then\n\
     if ((10#0\3*86400+10#0\5*3600+10#\6*60+10#\7>$maxSec));then\n\
       echo 'Killing &'\n\
       kill \1\n\
     else\n\
       ((cnt++))\n\
     fi\n\
    fi/p}" <(ps axho pid,etime,cmd))

Note: Result code will be 0 if no VirusShare task where found!

Then in a loop...

Full reuseable bash script:

#!/bin/bash

cmd="[${1:0:1}]${1:1}"
maxSec=${2:-10}
dryrun=${3:-.}
shapes=(- \\ \| /)

while ! $dryrun <(
    sed -nEe '1i cnt=0' -e '$a return $((cnt>0))' -e "
        /^ *([0-9]+) +((([0-9]+)-)?([0-9]+):)?([0-9]+):([0-9]+) .*$cmd.*$/ {
            s//if (( \1 != $$ )); then\n\
                 if ((10#0\3*86400+10#0\5*3600+10#\6*60+10#\7>$maxSec));then\n\
                   echo 'Killing &'\n\
                   kill \1\n\
                 else\n\
                   ((cnt++))\n\
                 fi\n\
            fi/p}" <(ps axho pid,etime,cmd)); do
    printf '%s Still %d proc...\r' ${shapes[sct++%4]} $cnt
    sleep .1
done

Usage:

./killLonger VirusShare 10
- Still 1 proc... # Spinner until process found reached 10 seconds...
\ Still 1 proc...
| Still 1 proc...
/ Still 1 proc...
Killing  106078       00:11 /path/to/VirusShare_00238010bb86fd0bf4014c3d19f114b2

Note: For tests purpose, I've added a 3rd parameter, which could by cat:

./killLonger VirusShare 10 cat

This will print intermediary script, instead of execute them:

cnt=0
if (( 141228 != 141422 )); then
                 if ((10#0*86400+10#0*3600+10#00*60+10#05>10));then
                   echo 'Killing  141228       00:05 /path/to/VirusShare_00238010bb86fd0bf4014c3d19f114b2'
                   kill 141228
                 else
                   ((cnt++))
                 fi
            fi
if (( 141370 != 141422 )); then
                 if ((10#0*86400+10#0*3600+10#00*60+10#01>10));then
                   echo 'Killing  141370       00:01 /path/to/VirusShare_00238010bb86fd0bf4014c3d19f114b2'
                   kill 141370
                 else
                   ((cnt++))
                 fi
            fi
if (( 141422 != 141422 )); then
                 if ((10#0*86400+10#0*3600+10#00*60+10#00>10));then
                   echo 'Killing  141422       00:00 /bin/bash ./killLonger VirusShare 10 cat'
                   kill 141422
                 else
                   ((cnt++))
                 fi
            fi
return $((cnt>0))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.