Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce a program's sleep() function

Tags:

linux

sleep

I have a binary program developed for Linux which reads lines from a server's network stream. Its communication is encrypted in a way that would take me too long to figure out, so I can't rewrite it.

After outputting each line, the program calls nanosleep(100000000) (I found this using strace) However, when the server sends multiple lines in quick succession, there's a big delay between the actual stream and the output.

Since I don't have the source code of the program, my question: is there a way to reduce the sleep time of this software? "Accelerating" it?

For reference, the program is Punkbuster's PBUcon

like image 651
Daniel Sorichetti Avatar asked May 18 '26 04:05

Daniel Sorichetti


1 Answers

You can try the LD_PRELOAD trick:

/* nosleep.c */
#include <time.h>
#include <unistd.h>

int sleep(unsigned int seconds)
{
    return 0;
}
int usleep(useconds_t usec)
{
    return 0;
}
int nanosleep(const struct timespec *req, struct timespec *rem)
{
    return 0;
}

Then compile with:

$ gcc -o libnosleep.so -shared nosleep.c -fpic

And then run your program with:

$ LD_PRELOAD=./libnosleep.so pbucon

There are a few things you should be aware of:

  1. It will replace every call to nanosleep, not only the ones you don't like, and that can have subtle undesired effects. You could check for the particular values of the argument, if you feel you need it.
  2. It will not work for suid/sgid programs.
  3. It will work only for dynamic-linked programs, Not for statically linked ones.

UPDATE: If you want to chain the call to the original function, you can do the following:

#define _GNU_SOURCE 

#include <stdio.h>
#include <unistd.h>
#include <dlfcn.h>

int usleep(useconds_t sec)
{
    typedef int (*usleep_f)(useconds_t);
    static usleep_f real_usleep = NULL;
    if (!real_usleep)
        real_usleep = (usleep_f)dlsym(RTLD_NEXT, "usleep");

    printf("%d\n", (int)sec);

    if (...)
        return real_usleep(sec);
    else
        return 0;
}

If you wanted to avoid GNU extensions (RTLD_NEXT is one) you would have to discover the name of the shared library that contains the function, with for example:

$ objdump -p pbucon.run | grep NEEDED
NEEDED           libc.so.6

And then, in the function do:

    if (!real_usleep)
    {
        void *libc_so = dopen("libc.so.6", RTLD_GLOBAL);
        real_usleep = (usleep_f)dlsym(libc_so, "usleep");
    }
like image 175
rodrigo Avatar answered May 19 '26 17:05

rodrigo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!