当前位置 : 主页 > 手机开发 > 无线 >

是否有一个链接器脚本指令允许我移动我的堆栈起始地址?

来源:互联网 收集:自由互联 发布时间:2021-06-10
我正在尝试使用x86_64上的链接描述文件来更改堆栈的起始位置. 我能够使用这个移动我的可执行起始地址: PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x200000)); . = SEGMENT_START("text-seg
我正在尝试使用x86_64上的链接描述文件来更改堆栈的起始位置.
我能够使用这个移动我的可执行起始地址:

PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x200000)); . = SEGMENT_START("text-segment", 0x200000) + SIZEOF_HEADERS;

我改变了我的全局变量:

.data ALIGN(0x10000000)           :
{
*(.data .data.* .gnu.linkonce.d.*)
 SORT(CONSTRUCTORS)
}

我试图使用以下内容来移动堆栈区域:

. = 0x50000000;
.stack    :
{
 stack_start = .;

  PROVIDE( stack_start = . );
  *(.stack)
      . += 0x2000;
  stack_end = . ;
  PROVIDE( stack_end = . );
}

但那并没有把我带到任何地方.

这是我用来测试堆栈位置的测试程序:

#include <stdio.h>
 #include <stdlib.h>

int global_var = 555;

void test()
{
   int local_test = 666;

   printf("address of global_var: %p\n", &global_var);
   printf("address of local_test: %p\n", &local_test);

}

int main()
{
   int local_main = 5;
   printf("address of local_main: %p\n", &local_main);
   printf("address of test(): %p\n", &test);
   printf("address of main(): %p\n", &main);
   test();
   return 0;
}

这是我从gcc的默认链接器脚本输出的(没有修改):

address of local_main: 0x7fffffffe26c  <---- I want to move local vars
address of test(): 0x40050c
address of main(): 0x400547
address of global_var: 0x600a10
address of local_test: 0x7fffffffe24c <----  I want to move local vars

这是我的链接器脚本的输出:

address of local_main: 0x7fffffffe26c   <--- unchanged
address of test(): 0x2005ac
address of main(): 0x2005e7
address of global_var: 0x10000010
address of local_test: 0x7fffffffe24c   <--- unchanged

我很困惑,因为nm输出新的位置:

$nm -n test.out
             w _ITM_deregisterTMCloneTable
             w _ITM_registerTMCloneTable
             w _Jv_RegisterClasses
             w __gmon_start__
             U __libc_start_main@@GLIBC_2.2.5
             U printf@@GLIBC_2.2.5
0000000000200460 T _init
00000000002004a0 T _start
00000000002004cc t call_gmon_start
00000000002004f0 t deregister_tm_clones
0000000000200520 t register_tm_clones
0000000000200560 t __do_global_dtors_aux
0000000000200580 t frame_dummy
00000000002005ac T test
00000000002005e7 T main
0000000000200650 T __libc_csu_fini
0000000000200660 T __libc_csu_init
00000000002006ec T _fini
00000000002006f8 R _IO_stdin_used
0000000000200870 r __FRAME_END__
0000000000400878 t __frame_dummy_init_array_entry
0000000000400878 t __init_array_start
0000000000400880 t __do_global_dtors_aux_fini_array_entry
0000000000400880 t __init_array_end
0000000000400888 d __JCR_END__
0000000000400888 d __JCR_LIST__
0000000000400890 d _DYNAMIC
0000000000400a78 d _GLOBAL_OFFSET_TABLE_
0000000010000000 D __data_start
0000000010000000 W data_start
0000000010000008 D __dso_handle
0000000010000010 D global_var
0000000010000018 D __TMC_END__
0000000020000000 A __bss_start
0000000020000000 A _edata
0000000020000000 b completed.6092
0000000050000000 B stack_start
0000000050002000 A _end
0000000050002000 B stack_end

虽然我甚至不确定stack_start和stack_end在x86_64上是否有效,因为我从arm online的链接器脚本教程中得到了这一部分.我的链接器脚本没有错误或警告,所以我不确定发生了什么.

如果你想知道为什么会这样做 – 它对安全研究有影响.

有没有办法用链接器脚本做我想做的事情?我简直无法相信我可以移动我的.text,.bss和.data部分,但不能移动堆栈.

更新:以下是从http://www.lurklurk.org/linkers/linkers.html#os开始解释为什么链接器无法实现的原因:

“You may have noticed that all of the discussion of object files and
linkers so far has only talked about global variables; there’s been no
mention of the local variables and dynamically allocated memory
mentioned earlier.These pieces of data don’t need any linker
involvement, because their lifetime only occurs when the program is
running—long after the linker has finished its business.”

Is there a linker script directive that allows me to move my stack start address?

在Linux上(您似乎正在使用):没有.

Linux上的堆栈位置由内核和ulimit -s的当前值决定;它不以任何方式编码到主可执行文件中.

In case you are wondering why would anyone do this – it has implications for security research.

如果你想显式地控制堆栈位置,你必须编写一个自定义的ELF加载器,它将mmap()并按照内核的方式设置堆栈(以及glibc期望它设置的方式),然后将控制转移到.out或ld-linux.

What about Windows?

自从我触及Windows以来已经很长时间了,但我相信那里的情况类似 – 内核决定了堆栈的位置.

网友评论