【问题标题】:Why does my data section appear twice in the compiled binary? Ubuntu, x86, nasm, gdb, reaelf为什么我的数据部分在编译后的二进制文件中出现两次? Ubuntu、x86、nasm、gdb、reaelf
【发布时间】:2020-11-03 05:04:11
【问题描述】:

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

---------- 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>

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

【问题讨论】:

  • 这是映射的副作用。由于不同的保护设置,文件中的相同字节被映射两次。我相信较新的工具链版本会填充该部分,因此不会发生这种情况。请注意,0x6e69622f 不是标签或地址,而是实际的字符串。那是由于数据类型不匹配。 p/s msg 可能会起作用。
  • 另见my answer here
  • @Jester,我会去研究更多关于类型不匹配和 p/s msg 的知识。我可以在 .text 部分看到数据(只读)。我仍然希望发现位于 .data 部分(可写)中的副本的地址。在实践中,我在链接时将 .text 指定为可写,并在此处使用数据副本。

标签: assembly x86 gdb nasm shellcode


【解决方案1】:

让我们看看LOAD 段:

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

第一个指示加载器将文件偏移量0mmap 0x9d 字节写入地址0x08048000 的虚拟内存中。

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

这意味着在偏移量0x9d 之后的文件中.text 之后的任何.data 都将出现在地址0x0804809d 及以后,但具有错误 权限(Read 和@ 987654337@xecute)。

第二个LOAD 段指示加载器到mmap 文件内容,从虚拟地址0x0804909d 处的偏移量0x9d 开始。

出于相同的“页面粒度”原因,加载器不能完全这样做。

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

这意味着文件中.text 之前的.data 将出现在地址之前 0x0804909d,再次使用错误的权限(Read 和Write this时间)。

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

您还可以观察到使用strace 执行的加载程序实际的mmap 系统调用。

【讨论】:

    猜你喜欢
    • 2020-10-31
    • 2011-01-09
    • 2020-07-28
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    • 2011-06-24
    • 1970-01-01
    相关资源
    最近更新 更多