【问题标题】:How to debug a C program which execute bash shell script with GDB?如何调试使用 GDB 执行 bash shell 脚本的 C 程序?
【发布时间】:2018-06-06 07:24:28
【问题描述】:

我使用 -g 386 shared --prefix=/usr 选项构建 OpenSSL-1.0.2n(用于基本程序集版本)以生成共享库 libcrypto.so.1.0.0。

在 crypto/aes 文件夹中,生成了 aes-x86_64.s。

为了执行 AES 加密和解密,我在 linux 终端中使用了以下命令。

/usr/bin/openssl enc -aes-128-cbc -in secrets.txt -out cipher.bin
/usr/bin/openssl enc -d -aes-128-cbc  -in cipher.bin -out decrypt_cip2.txt 

使用 GDB,我可以调试上述命令的执行,如下所示

gdb openssl

gdb> set args enc -d -aes-128-cbc  -in cipher.bin -out decrypt_cip2.txt 
gdb> b AES_cbc_encrypt
gdb> run
Breakpoint 1, AES_cbc_encrypt () at aes-x86_64.s:1300
1300        cmpq    $0,%rdx

从上面的gdb调试输出,验证aes-x86_64.s文件的AES_cbc_encrypt函数被调用。

我需要验证一下,如果我使用系统调用执行bash脚本的C程序进行AES解密,的AES_cbc_encrypt函数会不会aes-x86_64.s 文件仍然调用?

//test.c
    #include <stdio.h>
    #include <stdlib.h> 

    int main()
    {
    char cmd[500];
    sprintf(cmd, "/usr/bin/openssl enc -d -aes-128-cbc  -in cipher.bin -out decrypt_cip2.txt ");
    system(cmd);
    return 0;
      }
    gcc test.c -o test
    ./test

我错了,如果我说当我执行这个C程序时,它间接调用openssl库(libcrypto.so)并进行解密。所以它必须调用aes-x86_64的AES_cbc_encrypt函数。 o 文件。

但是,当我使用 GDB 调试此程序时,它没有显示对 aes-x86_64.o 文件的 AES_cbc_encrypt 函数的任何调用。它只是对 /sysdeps/posix/system 进行了一些调用。 c、/sysdeps/unix/sysv/linux/x86_64/sigaction.c等

gdb test

gdb> b AES_cbc_encrypt
Function "AES_cbc_encrypt" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (AES_cbc_encrypt) pending.

所以,这是我的问题

  1. 如何使用 gdb 调试上述 C 代码,使其在已安装 OpenSSL 的断点 AES_cbc_encrypt 处停止?

  2. 我是否应该使用 C 程序中的系统调用以外的方法来运行那些 bash 命令,以确保间接调用 aes-x86_64.s 文件的 AES_cbc_encrypt 函数?

任何解决此问题的帮助或链接都将不胜感激。

我在 OpenSSL version-1.0.2n 中使用带有调试符号的 Ubuntu 16.04、gcc-7.0。

【问题讨论】:

  • 为什么你没有 fork/exec(v) 到 openssl?
  • 好的。让我试试 exec 。在这种情况下,我将检查 gdb 是否在断点 AES_cbc_encrypt 处停止。
  • @克劳斯,谢谢。 exec 为我工作。

标签: c linux gdb


【解决方案1】:

但是,当我使用 GDB 调试此程序时,它没有显示对 aes-x86_64.o 文件的 AES_cbc_encrypt 函数的任何调用。它只是对 /sysdeps/posix/system.c 进行一些调用

默认情况下,GDB 只会调试一个进程(test 程序),并且该进程不会调用AES_cbc_encrypt——而是创建一个新进程——$SHELL,而后者又会创建另一个进程—— /usr/bin/openssl,只有那个孙进程调用AES_cbc_encrypt。

由于您正在调试openssl 的祖父母,完全预期 GDB 没有观察到AES_cbc_encrypt 被链接到您正在调试的进程中,并且AES_cbc_encrypt 上的断点永远不会建立,也永远不会“触发”。

如何使用 gdb 调试上述 C 代码,使其在已安装 OpenSSL 的断点 AES_cbc_encrypt 处停止?

有几种方法:

  1. 一种方法是修改test,使其调用gdb,而不是调用openssl:

    sprintf(cmd, "gdb --args /usr/bin/openssl enc -d -aes-128-cbc -in cipher.bin -out decrypt_cip2.txt"); system(cmd);

  2. 如果您不能或不想修改test 程序,您可以将/usr/bin/openssh 重命名为/usr/bin/openssl.exe 并将外壳包装器放入/usr/bin/openssl:

    #!/bin/sh exec gdb --args /usr/bin/openssl.exe "$@"

  3. 如果您不想执行以上任一操作,您可以使用 GDB 多重劣质支持。文档here 和here。

更新:

我有点想知道它将如何执行 ..exe 文件

UNIX 系统不关心文件扩展名(它们查看内部文件,即查看文件内容,以确定如何运行它)。

因此,您可以将可执行文件重命名为任何您想要的:openssl.foo、openssl.bar、openssl.exe、openssl.orig 等,它仍然可以正常运行。

【讨论】:

  • 在 openssl 安装期间你使用过 -g 选项
  • @Employed Russiana ,第一个选项证明我调用系统调用执行bash shell命令时间接调用了AES_cbc_encrypt,所以我现在确认。当我使用 linux 系统时,我有点想知道它将如何执行 ..exe 文件?在我的 gdb 中,信息内部返回 null。我接受这个答案,因为它解释得很好。
猜你喜欢
  • 2011-06-30
  • 1970-01-01
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 2012-05-19
  • 2015-07-28
  • 2020-09-05
  • 1970-01-01
相关资源
最近更新 更多