扩展并运行 PHP 的 C 程序

发布于 2024-11-18 14:29:32 字数 228 浏览 4 评论 0原文

我如何在 Linux 上制作一个 GCC C 程序:

  • 内部有一个 PHP 程序脚本,而不是作为一个单独的文件
  • 将其自身扩展到 /tmp
  • shells 到 php CLI 命令行来运行 PHP 脚本
  • 传递 C 的命令行参数 程序作为 PHP 程序的命令行参数会很好地显示错误并显示一条消息
  • 如果系统上无法使用 php CLI,则

How would I make a GCC C program on Linux that:

  • has a PHP program script inside itself, not as a separate file
  • expands itself out to /tmp
  • shells out to php CLI command line to run the PHP script
  • passes command line arguments of the C program as command line arguments of the PHP program
  • errors out nicely with a message if php CLI is not possible on the system

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

横笛休吹塞上声 2024-11-25 14:29:32

PHP 程序脚本可以存储为全局 char *,使用 fopenfwrite 函数打开并写出全局变量。然后使用 popen 执行 php 解释器(这几乎会执行您发送给它的任何命令)并指定一个文件描述符,您可以从中读取以获取输出。如果您的程序不需要输出(或者这不是本意),那么您可以利用 exec 套件来执行命令并将 /tmp/filename 作为参数传递。

要从 C 程序获取参数,您将在 int main(int argc, char *argv[]) 中使用 *argv[],只需记住 argv[ 0] 是您的应用程序名称(我总是忘记这一点)。

exec 函数将返回 -1 并且 errno 将被设置。手册页应该回答其中每一个的实现。但以防万一你迷路了。

char *script = "here are your script contents";

char *php_application_name = "pear";

int main(int argc, char *argv[]) {
  FILE *fd;
  char *filename = create_random_filename("/tmp/");
  fd = fopen(filename, "rw");

  fwrite(script, sizeof(char), strlen(script), fd);

  fclose(fd);

  /* Assuming application executes like
     pear <script> <arguments>
   */
  char *script_args[argc];
  int i = 1;
  script_args[0] = php_application_name;
  script_args[1] = filename;
  for(i = 1; i < argc; i++) {
    script_args[i+1] = argv[i];
  }

  execvp(php_application_name, script_args);
}

PHP program script could be stored as a global char * use the fopen, fwrite functions to open and write the global variable out. Then use popen to execute the php interpreter (this will pretty much execute whatever command you send to it) and specify a file descriptor that you could read from to get the output. If you don't need the output for your program (or that is not the intention) than you can utilize the exec suite to execute the command and pass the /tmp/filename as an argument.

To get the arguments from the C program, you'll use the *argv[] in int main(int argc, char *argv[]) just remember that argv[0] is YOUR applications name (I always forget that).

The exec functions will return -1 and errno will be set. Man pages should answer the implementation of each of these. but just in case you get lost.

char *script = "here are your script contents";

char *php_application_name = "pear";

int main(int argc, char *argv[]) {
  FILE *fd;
  char *filename = create_random_filename("/tmp/");
  fd = fopen(filename, "rw");

  fwrite(script, sizeof(char), strlen(script), fd);

  fclose(fd);

  /* Assuming application executes like
     pear <script> <arguments>
   */
  char *script_args[argc];
  int i = 1;
  script_args[0] = php_application_name;
  script_args[1] = filename;
  for(i = 1; i < argc; i++) {
    script_args[i+1] = argv[i];
  }

  execvp(php_application_name, script_args);
}
稀香 2024-11-25 14:29:32

我想支持 @Suroot 以及这篇很棒的文章: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

但是,整个过程在Linux命令中是这样的line:

...首先,您需要在 Linux 上,需要启用 PHP 命令行 (CLI),并且当您执行“php -v”或向其传递测试脚本时,命令行中的 PHP 不应出现任何错误您知道通常可以在命令行下工作。

...其次,您需要安装 GCC 来编译 C 程序。

...创建一个工作目录并“cd”到其中。

...创建一个文件 script.php,其中包含以下测试代码:

<?php

$s1 = @ $argv[1];
$s2 = @ $argv[2];
$s3 = @ $argv[3];

for($i=0;$i<=10;$i++){
    echo "($s1) ($s2) ($s3)\n";
}

...注意,这只是我们的测试。一旦证明测试有效,您可以稍后将自己的 PHP 代码放入其中。

...请注意,“script.php”的命名至关重要,否则 main.c 在到达 _binary_script_php_start 行时将无法工作。一开始我循环了一遍,因为我没有在这个过程中建立变量名称粘合的心理联系。

...创建一个 C 代码文件 main.c,其中包含以下代码:

#include <stdio.h>
#include <stdlib.h>

extern char _binary_script_php_start;
extern char _binary_script_php_end;

int main(int argc, char *argv[]) {
    // EXTRACT OUR RESOURCE OBJECT INTO /tmp/test.php
    char *p = &_binary_script_php_start;
    FILE *fp = fopen("/tmp/test.php","wb");
    while ( p != &_binary_script_php_end ) {
        fputc(*p++,fp);
    }
    fclose(fp);
    // NOW READ IN OUR STANDARD ARGUMENTS AND LAUNCH OUR COMMAND
    int i = 1;
    char *cmd = "php /tmp/test.php";
    char *s = NULL;
    asprintf(&s, "%s",cmd);
    for(i = 1; i < argc; i++) {
        asprintf(&s, "%s \"%s\"",s,argv[i]);
    }
    system(s);
    free(s);
    unlink("/tmp/test.php"); // comment me out for debugging if you want
}

...注意,我对 C 有点生疏(自 20 世纪 80 年代以来就没有使用过它),并且不建议使用 strcpy(),因为它不安全。因此,我阅读了 StackOverflow 我们应该在 GNU Linux 系统上使用 asprintf()。 显然 asprintf() 处理缓冲区溢出和 malloc 问题?我当然希望如此——我不想在这里误导你。请研究一下!

...现在魔法开始了!

...我们需要使用此命令行命令将 script.php 嵌入到目标文件“data.o”中(因此从 $ 提示符开始):

$ objcopy -I binary -O elf32-i386 -B i386 script.php data.o

...现在我们在链接的位置构建命令“runme” “data.o”和“main.c”在一起:

$ gcc main.c data.o -o runme

...然后为我们生成了一个编译后的 C 程序,称为“runme”。然后我们可以执行它来测试它:

$ ./runme "test1" "test2 test3" "test4"

...您应该看到如下所示的输出:

(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)

...如您所见,双引号实际上很重要 - 它们告诉 C,进而告诉 PHP,参数应该被分组在一起。这就是为什么 test3 没有出现在最后一个括号中。如果没有双引号,您将看到完全不同的结果。

此时,您将看到我们如何制作一个内部嵌入 PHP 脚本并在 Linux 上运行的 C 程序。 (Mac、Windows - 您可能需要稍微调整此代码。)C 程序将 PHP 脚本扩展为 /tmp,执行它,并向其传递我们可以读入和使用的参数。从现在开始,您可以根据需要修改 script.php,并且您可以了解如何使用唯一的文件名,这样您就不会破坏其他人的 /tmp/test.php 文件,以防万一。

I want to give props to @Suroot and also this great article: http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

However, the entire process is like so at Linux command line:

...first, you need to be on Linux, PHP for command line (CLI) needs to be enabled, and PHP at command line should not have any errors when you do "php -v" or pass it a test script that you know typically would work at command line.

...second, you need to have GCC installed for compiling C programs.

...create a working directory and 'cd' into it.

...create a file script.php that has this test code inside:

<?php

$s1 = @ $argv[1];
$s2 = @ $argv[2];
$s3 = @ $argv[3];

for($i=0;$i<=10;$i++){
    echo "($s1) ($s2) ($s3)\n";
}

...note, this is only our test. You can put your own PHP code in there later on once you've proven that the test works.

...note that "script.php" is critical to be named that or the main.c won't work when it hits the _binary_script_php_start line. That through me for a loop at first because I didn't make the mental connection that the variable name is glued in by this process.

...create a C code file main.c that has this code inside:

#include <stdio.h>
#include <stdlib.h>

extern char _binary_script_php_start;
extern char _binary_script_php_end;

int main(int argc, char *argv[]) {
    // EXTRACT OUR RESOURCE OBJECT INTO /tmp/test.php
    char *p = &_binary_script_php_start;
    FILE *fp = fopen("/tmp/test.php","wb");
    while ( p != &_binary_script_php_end ) {
        fputc(*p++,fp);
    }
    fclose(fp);
    // NOW READ IN OUR STANDARD ARGUMENTS AND LAUNCH OUR COMMAND
    int i = 1;
    char *cmd = "php /tmp/test.php";
    char *s = NULL;
    asprintf(&s, "%s",cmd);
    for(i = 1; i < argc; i++) {
        asprintf(&s, "%s \"%s\"",s,argv[i]);
    }
    system(s);
    free(s);
    unlink("/tmp/test.php"); // comment me out for debugging if you want
}

...note, I'm sort of rusty with C (haven't used it since the 1980s), and strcpy() is not advised because it's unsafe. So, I read up on StackOverflow that we should use asprintf() on GNU Linux systems. Evidently asprintf() handles buffer overflow and malloc issues? I sure hope so -- I don't want to lead you wrong here. Please research that!

...and now the magic begins!

...we need to embed the script.php into an object file "data.o" with this command-line command (thus starting with the $ prompt):

$ objcopy -I binary -O elf32-i386 -B i386 script.php data.o

...now we build our command "runme" where we link in "data.o" and "main.c" together:

$ gcc main.c data.o -o runme

...this then made a compiled C program for us called "runme". We can then execute it to test it:

$ ./runme "test1" "test2 test3" "test4"

...You should see an output like the following:

(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)
(test1) (test2 test3) (test4)

...as you can see, the doublequotes actually are important -- they tell the C, and therefore the PHP, that the parameters should be grouped together. That's why test3 doesn't appear in the last parentheses. Without the doublequotes, you'll see a completely different result.

At this point, you see how we can make a C program that has an embedded PHP script inside and which runs on Linux. (Mac, Windows -- you'll likely need to tweak this code somewhat.) The C program expands our PHP script into /tmp, executes it, and passes it parameters that we can read in and use. From here on out, you can revise the script.php to do as you need, and you can see about using a unique filename so that you don't clobber someone else's /tmp/test.php file, just in case.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文