为什么我的数据部分在编译后的二进制文件中出现两次?Ubuntu、x86、nasm、gdb、reaelf [英] Why does my data section appear twice in the compiled binary? Ubuntu, x86, nasm, gdb, reaelf

查看:12
本文介绍了为什么我的数据部分在编译后的二进制文件中出现两次?Ubuntu、x86、nasm、gdb、reaelf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

之前的 相关问题已回答.谢谢!然而,这给我带来了一个新问题.为什么 nasm 将数据字节放在两个不同的内存位置?我在下面包含程序信息和其他数据转储.

---------- 使用 nasm, ld 编译的代码片段 -----部分 .text...零:jmp 短二一:流行ebxxor eax, eaxmov [ebx+12], eaxmov [ebx+8], ebxmov [ebx+7], 人lea ecx, [ebx+8]lea edx, [ebx+12]移动,11整数 0x80二:叫一节 .data 对齐=1味精:分贝'/bin/sh0argvenvp'-------- readelf 输出以显示加载位置 --------readelf -Wl myshdbElf 文件类型为 EXEC(可执行文件)入口点 0x8048080有 2 个程序头,从偏移量 52 开始程序标题:类型 偏移 VirtAddr PhysAddr FileSiz MemSiz Flg Align加载 0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000加载 0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 读写 0x1000段到段映射:分段部分...00.文本01.数据-------------- 使用 gdb 运行并调试到 mov 指令的步骤 -------------------------寄存器--------------EAX: 0x0EBX:0x804809d(/bin/sh0argvenvp")------------ 内存地址检查 ------------gdb-peda$ p 零$15 = {<文本变量,无调试信息>} 0x8048080 <零>gdb-peda$ p 一$16 = {<文本变量,无调试信息>} 0x8048082 <one>gdb-peda$ p 2$17 = {<文本变量,无调试信息>} 0x8048098 <两个>gdb-peda$ p $ebx$18 = 0x804809dgdb-peda$ p 味精$19 = 0x6e69622fgdb-peda$ x 0x804809d0x804809d:/bin/sh0argvenvp"gdb-peda$ x 味精0x6e69622f:<错误:无法访问地址 0x6e69622f 处的内存>

换句话说,字符串消息可以直接从代码(0x804809d)之后的内存位置获得.然而,味精标签映射到 0x6e69622f,这是我数据的标签.如何使用gdb查看第二个地址的数据?nasm 是否将数据放在两个不同的位置?为什么?

解决方案

我们来看看LOAD段:

<块引用>

类型偏移 VirtAddr PhysAddr FileSiz MemSiz Flg Align
加载 0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000
加载 0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 RW 0x1000

第一个指示加载器将 mmap 0x9d 字节从文件偏移量 0 到地址 0x08048000.

加载器不能完全做到这一点,因为内存映射只能在一页(4096 字节)粒度上工作.所以它mmaps .text,以及文件中跟随它的所有内容,最多一页,地址为0x08048000.

这意味着在文件中偏移0x9d之后的任何.data后面的.text都将出现在地址0x0804809d 及更高版本,但具有错误 权限(Read 和 Execute).

第二个LOAD段指示加载器mmap文件内容,从虚拟地址0x0804909d0x9d开始>.

加载器不能做到完全对于相同的页面粒度".原因.

相反,它将向下舍入偏移量和地址,以及从地址0x08049000处的偏移量0开始的mmap文件内容.p>

这意味着文件中 .text 之前的任何 .data 都将出现在地址 before 0x0804909d,再次使用错误的权限(这次是 Read 和 Write).

您可以通过使用 GDB x/10i 0x8049080 来确认正在发生的事情——您将看到完全x/10i 0x8048080.

您还可以观察到实际的 mmap 系统调用加载器执行的 strace.

A prior related question was answered. Thank you! However this creates a new question for me. Why does nasm put data bytes at two different memory locations? I include program information and other data dump below.

---------- code snippet compiled with nasm, ld -----------------
section .text
...
zero: jmp short two
one:  pop ebx
      xor eax, eax
      mov [ebx+12], eax
      mov [ebx+8], ebx
      mov [ebx+7], al
      lea ecx, [ebx+8]
      lea edx, [ebx+12]
      mov al, 11
      int 0x80
two:  call one
section .data align=1
msg:   db '/bin/sh0argvenvp' 

-------- readelf output to show load locations --------
readelf -Wl myshdb

Elf file type is EXEC (Executable file)
Entry point 0x8048080
There are 2 program headers, starting at offset 52

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000
  LOAD           0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     .text 
   01     .data 

-------------- run with gdb and debug step to mov instructions ----------
---------------registers--------------
EAX: 0x0 
EBX: 0x804809d ("/bin/sh0argvenvp")

----------- memory address checks ------------
gdb-peda$ p zero
$15 = {<text variable, no debug info>} 0x8048080 <zero>
gdb-peda$ p one
$16 = {<text variable, no debug info>} 0x8048082 <one>
gdb-peda$ p two
$17 = {<text variable, no debug info>} 0x8048098 <two>
gdb-peda$ p $ebx
$18 = 0x804809d
gdb-peda$ p msg
$19 = 0x6e69622f
gdb-peda$ x 0x804809d
0x804809d:  "/bin/sh0argvenvp"
gdb-peda$ x msg
0x6e69622f: <error: Cannot access memory at address 0x6e69622f>

In other words, the string message is available from a memory location directly after code (0x804809d). Yet msg label maps to 0x6e69622f, which is the label to my data. How can use gdb to see data at the second address? Is nasm putting the data at two different locations? Why?

解决方案

Let's look at the LOAD segments:

Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x08048000 0x08048000 0x0009d 0x0009d R E 0x1000
LOAD 0x00009d 0x0804909d 0x0804909d 0x00010 0x00010 RW 0x1000

The first one instructs the loader to mmap 0x9d bytes from file offset 0 into virtual memory at address 0x08048000.

The loader can't do exactly that, because memory mapping only works at one page (4096 bytes) granularity. So it mmaps the .text, and everything that follows it in the file, up to one page, at address 0x08048000.

This means that whatever .data followed .text in the file after offset 0x9d will appear at address 0x0804809d and later, but with wrong permissions (Read and Execute).

The second LOAD segment instructs the loader to mmap file contents, starting at offset 0x9d at virtual address 0x0804909d.

The loader can't do exactly that either for the same "page granularity" reason.

Instead, it will round down the offset and the address, and mmap file contents starting from offset 0 at address 0x08049000.

That that means that whatever .text preceded .data in the file will appear at address before 0x0804909d, again with the wrong permissions (Read and Write this time).

You can confirm that that's what's happening by using GDB x/10i 0x8049080 -- you will see exactly the same instructions as with x/10i 0x8048080.

You can also observe the actual mmap system calls the loader performed with strace.

这篇关于为什么我的数据部分在编译后的二进制文件中出现两次?Ubuntu、x86、nasm、gdb、reaelf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆