为什么我的数据部分在编译的二进制文件中出现两次? Ubuntu、x86、nasm、gdb、readelf

问题描述 投票:0回答:1

之前的相关问题已得到解答。谢谢你! 然而,这给我带来了一个新问题。 为什么 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) 之后的内存位置获取。然而,msg 标签映射到 0x6e69622f,这是我的数据的标签。 如何使用gdb查看第二个地址的数据? nasm 是否将数据放在两个不同的位置? 为什么?

assembly x86 gdb nasm shellcode
1个回答
10
投票

让我们看看

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

第一个指示加载程序将文件偏移量

mmap
中的
0x9d
0
字节放入地址
0x08048000
处的虚拟内存中。

加载器不能做到完全那样,因为内存映射仅在一页(4096 字节)粒度上工作。所以它

mmap
.text
,以及 文件中紧随其后的所有内容,最多一页,地址为
0x08048000

这意味着文件中偏移量

.data
之后的
.text
后面的任何内容都将出现在地址
0x9d
及以后,但具有
错误
权限(0x0804809dead和
R
xecute)。
第二个

E

段指示加载器加载

LOAD
文件内容,从虚拟地址
mmap
处的偏移量
0x9d
开始。
加载器

不能

完全,因为同样的“页面粒度”原因。 相反,它将向下舍入偏移量和地址,并且

0x0804909d

文件内容从地址

mmap
处的偏移量
0
开始。
这意味着文件中

0x08049000

之前的任何内容都将出现在地址

before
.text
处,同样具有错误的权限(这次是.dataead和
0x0804909d
rite)。
您可以使用 GDB 
R
来确认所发生的情况 - 您将看到与

W

完全相同
相同的说明。 您还可以观察加载程序使用
x/10i 0x8049080
执行的实际

x/10i 0x8048080

系统调用。

    

© www.soinside.com 2019 - 2024. All rights reserved.