为什么我的数据部分在编译后的二进制文件中出现两次? Ubuntu、x86、nasm、gdb、reaelf
Why does my data section appear twice in the compiled binary? Ubuntu, x86, nasm, gdb, reaelf
先前的 得到了回答。谢谢!然而,这给我带来了一个新问题。为什么 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
= {<text variable, no debug info>} 0x8048080 <zero>
gdb-peda$ p one
= {<text variable, no debug info>} 0x8048082 <one>
gdb-peda$ p two
= {<text variable, no debug info>} 0x8048098 <two>
gdb-peda$ p $ebx
= 0x804809d
gdb-peda$ p msg
= 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 是否将数据放在两个不同的位置?为什么?
让我们看看 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
第一个指示加载程序从文件偏移量 0
mmap
0x9d
字节到地址 0x08048000
.
的虚拟内存中
加载程序不能完全那样做,因为内存映射只能在一页(4096 字节)粒度上工作。所以它 mmap
是 .text
,文件中它后面的所有内容 ,最多一页,地址 0x08048000
.
这意味着文件中偏移量0x9d
之后.data
后面跟在.text
的任何内容都会出现在地址0x0804809d
及以后的地址,但是是错误的 权限(R
ead 和 E
xecute)。
第二个 LOAD
段指示加载程序 mmap
文件内容,从虚拟地址 0x0804909d
.
的偏移量 0x9d
开始
出于相同的“页面粒度”原因,加载器不能完全。
相反,它将向下舍入偏移量和地址,mmap
文件内容从地址 0x08049000
处的偏移量 0
开始。
这意味着文件中 .data
之前的任何 .text
将出现在地址 之前 0x0804909d
,同样是错误的权限(这次 R
阅读并 W
仪式)。
您可以通过使用 GDB x/10i 0x8049080
确认这就是正在发生的事情——您将看到 完全 与 x/10i 0x8048080
.[=44 相同的指令=]
您还可以观察加载程序使用 strace
执行的实际 mmap
系统调用。
先前的
---------- 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
= {<text variable, no debug info>} 0x8048080 <zero>
gdb-peda$ p one
= {<text variable, no debug info>} 0x8048082 <one>
gdb-peda$ p two
= {<text variable, no debug info>} 0x8048098 <two>
gdb-peda$ p $ebx
= 0x804809d
gdb-peda$ p msg
= 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 是否将数据放在两个不同的位置?为什么?
让我们看看 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
第一个指示加载程序从文件偏移量 0
mmap
0x9d
字节到地址 0x08048000
.
加载程序不能完全那样做,因为内存映射只能在一页(4096 字节)粒度上工作。所以它 mmap
是 .text
,文件中它后面的所有内容 ,最多一页,地址 0x08048000
.
这意味着文件中偏移量0x9d
之后.data
后面跟在.text
的任何内容都会出现在地址0x0804809d
及以后的地址,但是是错误的 权限(R
ead 和 E
xecute)。
第二个 LOAD
段指示加载程序 mmap
文件内容,从虚拟地址 0x0804909d
.
0x9d
开始
出于相同的“页面粒度”原因,加载器不能完全。
相反,它将向下舍入偏移量和地址,mmap
文件内容从地址 0x08049000
处的偏移量 0
开始。
这意味着文件中 .data
之前的任何 .text
将出现在地址 之前 0x0804909d
,同样是错误的权限(这次 R
阅读并 W
仪式)。
您可以通过使用 GDB x/10i 0x8049080
确认这就是正在发生的事情——您将看到 完全 与 x/10i 0x8048080
.[=44 相同的指令=]
您还可以观察加载程序使用 strace
执行的实际 mmap
系统调用。