为什么LD_PRELOAD的值在堆栈上 [英] why is the value of LD_PRELOAD on the stack
问题描述
我正在研究缓冲区溢出并解决一些战争游戏. 存在一个问题,除了main的返回地址外,缓冲区上方的所有堆栈内存都设置为0,
I'm studying buffer overflow and solving some wargames. There was a problem that all of the stack memory above the buffer is set to 0 except return address of main, which will be:
buffer
[0000000...][RET][000000...]
,我可以覆盖该RET. 因此,我找到了一些解决此问题的提示. 那是使用LD_PRELOAD. 有人说LD_PRELOAD的值不仅在堆栈的环境变量区域中,而且还在堆栈的某个位置. 因此,我设置了LD_PRELOAD并进行搜索,并使用gdb找到了它.
and I can overwrite that RET. So I found some hints for solving this problem. It was to use LD_PRELOAD. Some people said that LD_PRELOAD's value is in somewhere of stack not only in environment variable area of stack. So I set LD_PRELOAD and search it and found it using gdb.
$ export LD_PRELOAD=/home/coffee/test.so
$ gdb -q abcde
(gdb) b main
Breakpoint 1 at 0x8048476
(gdb) r
Starting program: /home/coffee/abcde
Breakpoint 1, 0x8048476 in main ()
(gdb) x/s 0xbffff6df
0xbffff6df: "@èC\001@/home/coffee/test.so"
(gdb) x/s 0xbffffc59
0xbffffc59: "LD_PRELOAD=/home/coffee/test.so"
(gdb) q
The program is running. Exit anyway? (y or n) y
$
就这样! 现在我知道LD_PRELOAD的值在缓冲区下方的堆栈中,现在我可以利用它了!
So there is! Now I know that LD_PRELOAD's value is on stack below the buffer and now I can exploit!
但是我不知道为什么LD_PRELOAD加载到该内存地址上. 该值也位于堆栈的环境变量区域!
But I wonder why LD_PRELOAD is loaded on that memory address. The value is also on environment variable area of the stack!
这是什么目的? 谢谢.
What is the purpose of this? Thanks.
推荐答案
探索堆栈布局的代码:
#include <inttypes.h>
#include <stdio.h>
// POSIX 2008 declares environ in <unistd.h> (Mac OS X doesn't)
extern char **environ;
static void dump_list(const char *tag, char **list)
{
char **ptr = list;
while (*ptr)
{
printf("%s[%d] 0x%.16" PRIXPTR ": %s\n",
tag, (ptr - list), (uintptr_t)*ptr, *ptr);
ptr++;
}
printf("%s[%d] 0x%.16" PRIXPTR "\n",
tag, (ptr - list), (uintptr_t)*ptr);
}
int main(int argc, char **argv, char **envp)
{
printf("%d\n", argc);
printf("argv 0x%.16" PRIXPTR "\n", (uintptr_t)argv);
printf("argv[argc+1] 0x%.16" PRIXPTR "\n", (uintptr_t)(argv+argc+1));
printf("envp 0x%.16" PRIXPTR "\n", (uintptr_t)envp);
printf("environ 0x%.16" PRIXPTR "\n", (uintptr_t)environ);
dump_list("argv", argv);
dump_list("envp", envp);
return(0);
}
将程序编译为x
,然后在经过消毒的环境中运行它:
With the program compiled as x
, I ran it with a sanitized environment:
$ env -i HOME=$HOME PATH=$HOME/bin:/bin:/usr/bin LANG=$LANG TERM=$TERM ./x a bb ccc
4
argv 0x00007FFF62074EC0
argv[argc+1] 0x00007FFF62074EE8
envp 0x00007FFF62074EE8
environ 0x00007FFF62074EE8
argv[0] 0x00007FFF62074F38: ./x
argv[1] 0x00007FFF62074F3C: a
argv[2] 0x00007FFF62074F3E: bb
argv[3] 0x00007FFF62074F41: ccc
argv[4] 0x0000000000000000
envp[0] 0x00007FFF62074F45: HOME=/Users/jleffler
envp[1] 0x00007FFF62074F5A: PATH=/Users/jleffler/bin:/bin:/usr/bin
envp[2] 0x00007FFF62074F81: LANG=en_US.UTF-8
envp[3] 0x00007FFF62074F92: TERM=xterm-color
envp[4] 0x0000000000000000
$
如果仔细研究,您会发现main()
的argv
参数是一系列指向字符串的指针的起点,该指针进一步指向堆栈. envp
(在POSIX机器上main()
的可选第三个参数)与全局变量environ
和argv[argc+1]
相同,并且也是一系列指向字符串的指针的起点,该字符串进一步指向堆栈.并且argv
和envp
指针指向的字符串遵循两个数组.
If you study that carefully, you'll see that the argv
argument to main()
is the start of a series of pointers to strings further up the stack; the envp
(optional third argument to main()
on POSIX machines) is the same as the global variable environ
and argv[argc+1]
, and is also the start of a series of pointers to strings further up the stack; and the strings pointed at by the argv
and envp
pointers follow the two arrays.
这是Mac OS X上的布局(如果重要,则为10.7.5,可能没有关系),但我可以肯定地说,在其他类似Unix的系统上也可以找到相同的布局.
This is the layout on Mac OS X (10.7.5 if it matters, which it probably doesn't), but I'm tolerably sure you'd find the same layout on other Unix-like systems.
这篇关于为什么LD_PRELOAD的值在堆栈上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!