puts中调用的got表

puts中调用的got表

RocketDev

去千岛湖团建的时候和男孩聊起上次强网杯中_exit的题中用到了puts@got@libc, 当时不是很理解,于是就提起了这件事,然后发现,这个类似于got表一样的东西与puts没啥关系, 倒是与strlen有关系

省流:看下文粗体结论

先是在nameless师傅的博客里找到的灵感:
cyberprinter

于是我就在本地调了一下,也是类似有个跳表存在,不过Arch的libc不能改这一项(因为开了Full RELRO)

what is ABS? can not write

可以看到出现跳表的位置对应源码是在strlen的位置,在elixir中, 原始的puts函数是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int
_IO_puts (const char *str)
{
int result = EOF;
size_t len = strlen (str);
_IO_acquire_lock (stdout);

if ((_IO_vtable_offset (stdout) != 0
|| _IO_fwide (stdout, -1) == -1)
&& _IO_sputn (stdout, str, len) == len
&& _IO_putc_unlocked ('\n', stdout) != EOF)
result = MIN (INT_MAX, len + 1);

_IO_release_lock (stdout);
return result;
}

检查strlen的交叉引用,在string.h里只有一个声明

1
2
3
/* Return the length of S.  */
extern size_t strlen (const char *__s)
__THROW __attribute_pure__ __nonnull ((1));

那么真正调用的是什么函数呢?在文件sysdeps/x86_64/multiarch/strlen.c中,有一些提示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/* Define multiple versions only for the definition in libc.  */
#if IS_IN (libc)
# define strlen __redirect_strlen
# include <string.h>
# undef strlen

# define SYMBOL_NAME strlen
# include "ifunc-avx2.h"

libc_ifunc_redirected (__redirect_strlen, strlen, IFUNC_SELECTOR ());
# ifdef SHARED
__hidden_ver1 (strlen, __GI_strlen, __redirect_strlen)
__attribute__((visibility ("hidden"))) __attribute_copy__ (strlen);
# endif
#endif

接着跟进到ifunc-avx2.h,其针对经常调用的函数做了cpu针对性的优化。回到gdb, 跟进strlen,实际调用的函数是__strlen_avx2,对应的文件是sysdeps/x86_64/multiarch/strlen-avx2.S, 这下答案已经呼之欲出了:glibc通过ifunc将优化版本的strlen嵌入到库中, 方便后期绑定优化版本,而这个跳表*ABS*就是在libc的got中,在一些Ubuntu的libc中,只启用了Partial RELRO,就可以通过修改这一项,达到执行libc中的puts时,从跳表中运行任意代码

这也让我想起了前不久刚过去的xz风波,xz同样是借助了glibc的ifunc机制来修改了liblzma中的函数, 达到嵌入代码的目的

在源码中,除了strlen以外,strcpy等函数都有其对应的优化版本,调用到这些函数的库函数同样应该会被插入跳表, 存在利用的可能性。但要注意的是,直接调用strcpy是不会有跳表的,经过dl_runtime_resolve会直接解析成 __strcpy_avx2

  • 标题: puts中调用的got表
  • 作者: RocketDev
  • 创建于 : 2024-04-15 23:48:00
  • 更新于 : 2024-07-25 12:34:56
  • 链接: https://rocketmadev.github.io/2024/04/15/ifuncInPuts/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
puts中调用的got表