【问题标题】:system function in c is not working for mec中的系统功能对我不起作用
【发布时间】:2010-08-22 05:03:40
【问题描述】:

我正在使用此代码提取受密码保护的 RAR 文件。我正在使用std::system() 函数来调用RAR 命令。如果我在std::system() 函数中使用password,它就可以工作。但是当试图将密码作为参数传递时,它没有。例如,如果在此代码中如果我使用密码pwd,则会出现此错误:

"pwd 不是内部或外部命令、可运行程序或批处理文件。"

但如果我将代码更改为system("rar e -ppwd wingen.rar"),它就可以工作。

谁能解释我犯了什么错误?提前致谢!

这是我的代码:

#include<stdio.h>
#include<stdlib.h>
int main(int argc, char **argv)
{
    char pword[20];
    printf("enter the pword : ");
    gets(pword);
    system(("rar e -p%s wingen.rar",pword));
    getchar();
    return 0;
}

【问题讨论】:

  • 你不应该使用gets()。手册页明确指出Never use gets(). [...] Use fgets() instead。如果gets() 读取的字符数超过了缓冲区的大小,它将继续将它们存储到末尾,这是很危险的。
  • 另外,阅读FAQ,尤其是上面写着的部分:“当您决定哪个答案对您最有帮助时,通过单击检查将其标记为已接受的答案答案左侧的方框轮廓。这让其他人知道您的问题得到了很好的回答。”

标签: c


【解决方案1】:

system() 只接受一个参数 - const char*。事实上,

system( "rar e -p%s wingen.rar", pword );

不会编译 - 编译器会抱怨您向 system() 传递了太多参数。原因是:

system( "rar e -p%s wingen.rar", pword );

compiles 是您将两个字符串包装在括号中。这具有评估内部表达式的效果,该表达式由对两个字符串进行操作的逗号运算符组成。逗号运算符具有返回第二个参数的值的效果,因此您最终会调用:

system( pword );

在您的示例中相当于:

system( "pwd" );

并且pwd 不是您系统上的命令(尽管在 POSIX 系统上它是...但我离题了)。您想要做什么已在其他答案中进行了解释,但为了完整起见,我也会提到它 - 您需要使用 sprintf 格式化您的字符串:

char buff[256];
sprintf( buff, "rar e -p%s wingen.rar", pword );

或者你可以连接字符串,这可能会快一点(虽然对于这么短的字符串,它可能不会有什么不同):

char buff[256] = "rar e -p";
strcat( buff, pword );
strcat( buff, " wingen.rar" );

【讨论】:

  • +1 用于正确诊断没有编译错误的原因。
  • 这是一个非常耐心和全面的答案。 +1
  • 我在解释中忽略了这一点,当使用 -Wall gcc 编译时,会给出“逗号表达式的左手操作数无效”
  • @RBerteig 是的,即使他像我的回答一样使用 snprintf,或者像这样使用 strcat,仍然存在注入攻击。 "rar e -pXX ; rm -rf * ; wingen.rar" 将从 pwd "XX ; rm -rf * ; "
  • @Sean,太真实了。任何想了解更多关于我们在这里的内容的人,都应该查看bobby-tables.com 以获取 xkcd 说明的经典示例。
【解决方案2】:

system() 函数接收一个字符串作为参数。

它的原型是:

int system(const char *command);

在传递之前构建字符串。或许使用 snprintf()

char buf[512];
snprintf(buf, sizeof(buf), "rar e -p%s wingen.rar", pword);
system(buf);

编辑
所有这些解决方案都是坏主意,因为使用未经处理的输入的系统存在注入漏洞。

即使他像我的回答一样使用snprintf,或者像其他人一样使用strcat,仍然存在问题,因为system()(至少在*nix系统上使用/bin/sh)可以执行多个命令单个函数调用。

system("rar e -pXX wingen.rar ; rm -rf * ; # wingen.rar")

将产生于:

pwd = "XX wingen.rar ; rm -rf * ; #"

【讨论】:

    【解决方案3】:

    system() 函数不像printf() 那样工作。你需要创建完整的字符串,然后调用system():

    char command[100];
    sprintf(command, "rar e -p%s wingen.rar", pword);
    system(command);
    

    您现在拥有的代码使用逗号运算符,这会导致您的“格式字符串”被您的程序完全忽略。你所拥有的100%相当于写作:

    system(pword);
    

    这可能不是你想要的。

    【讨论】:

    • 谢谢哥们,成功了。只是一点点改变。我用 e 代替 -e。再次非常感谢。
    • @user417552 - 抱歉打错了。现已修复。
    • 希望密码不超过 80 个字符。 ;) - 你应该使用snprintf。或者根据密码长度分配缓冲区。
    • @bertrand 是的,使用 gets() 的 OP 代码存在另一个缓冲区溢出;)
    猜你喜欢
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2021-12-30
    相关资源
    最近更新 更多