在GDB中断点而不是最初发送管道输入

时间:2017-04-07 20:31:15

标签: c++ perl gdb stdin

我已经研究过这个问题,我能找到的最接近的答案是这个。 gdb - debugging with piped input (not arguments)

我需要完全按照这个人的要求行事,但是,我需要能够在已经查看我的程序运行部分之后发送输入。

这是我在GDB中看到的代码

#define SECRET1 0x44
#define SECRET2 0x55

int main(int argc, char *argv[])
{
char user_input[100];

int *secret;
int int_input;
int a, b, c, d; /* other variables, not used here.*/

/* The secret value is stored on the heap */
secret = (int *) malloc(2*sizeof(int));

/* getting the secret */
secret[0] = SECRET1; secret[1] = SECRET2;

printf("The variable secret’s address is 0x%8x (on stack)\n", &secret);
printf("The variable secret’s value is 0x%8x (on heap)\n", secret);
printf("secret[0]’s address is 0x%8x (on heap)\n", &secret[0]);
printf("secret[1]’s address is 0x%8x (on heap)\n", &secret[1]);

printf("Please enter a decimal integer\n");
scanf("%d", &int_input);  /* getting an input from user */

printf("Please enter a string\n");
scanf("%s", user_input); /* getting a string from user */

/* Vulnerable place */
printf(user_input);
printf("\n");

/* Verify whether your attack is successful */
printf("The original secrets: 0x%x -- 0x%x\n", SECRET1, SECRET2);
printf("The new secrets:      0x%x -- 0x%x\n", secret[0], secret[1]);

return 0;
}

我试图在我的虚拟机上执行格式化字符串攻击。要做到这一点,我需要知道存储秘密的地址。该程序通过这些行的输出告诉我

  printf("The variable secret’s address is 0x%8x (on stack)\n", &secret);
  printf("The variable secret’s value is 0x%8x (on heap)\n", secret);
  printf("secret[0]’s address is 0x%8x (on heap)\n", &secret[0]);
  printf("secret[1]’s address is 0x%8x (on heap)\n", &secret[1]);

攻击的性质要求我发送非ASCII十六进制值作为第二次扫描的输入,所以我不能自己输入输入。我已经完成了使用perl设置我的输入,

ramtest@ramtest-VirtualBox:/tmp$ perl -e 'print "5\x0a"; print "\x08\xb0\x04\x08%x.%x.%x.%x.%x.%x.%x";' > /tmp/input
然后我跑

$gdb ./vul_prog < /tmp/input

我已经让我的方法在内存随机化关闭的环境中工作,因为我可以运行程序一次,查看内存地址,然后更改perl脚本,然后再次运行它。但是,启用内存随机化后,在运行之前我无法知道地址的位置,因此我需要能够看到程序中的部分,它告诉我在创建和发送输入之前运行的地址

我试图以最直观的方式尝试这样做,但我只是语法错误。

Starting program: /home/ramtest/Downloads/vulprog 
The variable secret’s address is 0xbfffefd8 (on stack)
The variable secret’s value is 0x 804b008 (on heap)
secret[0]’s address is 0x 804b008 (on heap)
secret[1]’s address is 0x 804b00c (on heap)
Please enter a decimal integer
1
Please enter a string

Breakpoint 2, 0x0804858f in main ()
(gdb) c > /tmp/input
A syntax error in expression, near `> /tmp/input'.
(gdb) c < /tmp/input
A syntax error in expression, near `< /tmp/input'.

我可以在提示输入之前在GDB中设置断点,然后以某种方式将/ tmp /输入信息作为输入发送吗?

如果是这样,我该怎么做呢?

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

只需使用run命令即可​​。我将通过将/bin/cat提供给gdb并打破其main(),并重定向标准输入来演示:

示例:

$ gdb /bin/cat
GNU gdb (GDB) Fedora 7.12.1-47.fc25
[ ... ]
(gdb) b main
Breakpoint 1 at 0x1bc0
(gdb) run </etc/issue
Starting program: /usr/bin/cat </etc/issue

Breakpoint 1, 0x0000555555555bc0 in main ()
(gdb) c
Continuing.
\S
Kernel \r on an \m (\l)

[Inferior 1 (process 18190) exited normally]
(gdb) 

您应该可以在gdb下启动程序,在scanf之前设置断点,然后在run处使用从空文件重定向的标准输入。我不希望您的程序在此之前尝试从其标准输入读取,因此它不会在其重定向的标准输入上看到文件结束条件。

当断点命中时你应该有你的内存地址,然后准备你的有效负载并简单地将它附加到零长度文件,然后

c

执行,然后继续执行,并尝试读取现在可用于其标准输入的有效负载。

这种技术的一种变体甚至不需要调试器就是使用一个命名管道,它可以提前打开,然后运行这个程序,其标准输入从命名管道重定向。预期的结果是程序打印内存地址,然后在从管道读取时阻塞。此时,您可以准备有效负载,并将其写入管道。