繁体   English   中英

使用LD_PRELOAD重定向system()函数调用

[英]Redirecting system() function call using LD_PRELOAD

我想使用LD_PRELOAD替换程序对system()函数的调用。

因此,我在共享库中创建了以下包装器函数以进行测试。

// syshook.c

int system(const char * command)
{
    printf("system() called for %s ************************************\n", command);
    return 55;
}

char * getenv (const char* name)
{
    printf("my getenv() *********************");
    return 0;
}

并使用gcc编译并链接到共享库libsyshook.so。

gcc -Wall -fPIC -c *.c
gcc -shared -Wl,-soname,libsyshook.so -o libsyshook.so.1.0
ln -s libsyshook.so libsyshook.so.1.0

但是,当我使用LD_PRELOAD如下所示运行程序时,未调用我的system()包装函数,而是调用了getenv()包装函数。

LD_PRELOAD="libsyshook.so" myprog

当我连接调试器时,可以看到该system()调用在libpthread.so中调用实现。 那么为什么重定向system()无法正常工作。 我认为对此没有任何限制?

编辑:我的测试程序编译到上面的myprog看起来像这样。 评论表明了我的看法。

void TestClass::testMethod()
{
    string cmdLine = "date";
    if (!mainWin) cmdLine = "time";

    int retFromSys = system(cmdLine.c_str());   // goes into libpthread when stepped in.
    cout << "return from system " << retFromSys << endl; // prints 0, not 55  
    getenv("DEBUG_SYS");  // Wrapper function called for this. Prints "my getenv ****** ..."

与LD_PRELOAD链接不良的最常见情况是,当GCC认为另一种函数可以使您的代码执行速度更快时,他用另一种函数替换了该函数。

例如,如果GCC在您的代码中读取了这一行:

printf("%d", strlen("toto"));

它将在编译之前替换为此行:

puts("4");

因为它知道printfstrlen函数,并认为输出与puts函数相同。

在此示例中,如果您在加载了LD_PRELOAD的库中创建了自己的printfstrlen函数,则编译后将不会调用该函数,因为GCC会替换掉函数调用。

我认为您的问题是出于同样的原因。 system是一个非常繁重的函数,GCC可能会用另一个函数代替您的函数调用。 例如,如果您尝试过:

system("ls");

GCC可能会将您的行替换为:

execlp("ls", "ls");

可以这样做,但是不那么麻烦。 它不知道您要使用自己的system功能。 尝试反汇编您的代码以检查是否是问题所在。

作为解决方案,我建议您尝试使用更“随机”的参数调用system ,以使GCC认为不应尝试替换它。 也许像:

int main(int argc, char** argv)
{
    char* line = NULL;

    // Useless condition to make GCC think the parameter is variable
    if (argc == 1)
        line = "ls";

    return (system(line));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM