【问题标题】:Why does this NASM code print my environment variables?为什么这个 NASM 代码会打印我的环境变量?
【发布时间】:2008-12-03 16:50:56
【问题描述】:

本学期我刚刚完成了一门计算机体系结构课程,除其他外,我们一直在涉足 MIPS 汇编并在 MARS 模拟器中运行它。今天,出于好奇,我开始在我的 Ubuntu 机器上摆弄 NASM,基本上只是从教程中拼凑起来,感受 NASM 与 MIPS 的不同之处。这是我目前正在查看的代码 sn-p:

global _start

_start:

    mov eax, 4
    mov ebx, 1
    pop ecx
    pop ecx
    pop ecx
    mov edx, 200
    int 0x80
    mov eax, 1
    mov ebx, 0
    int 0x80

这被保存为 test.asm,并与nasm -f elf test.asm 组装并与ld -o test test.o 链接。当我使用./test anArgument 调用它时,它会按预期打印'anArgument',然后是将该字符串填充到总共200 个字符所需的字符数(因为mov edx, 200 语句)。不过,有趣的是,这些填充字符(我原以为会是乱码)实际上来自我的环境变量的开头,如env 命令所显示的那样。为什么这会打印出我的环境变量?

【问题讨论】:

    标签: linux assembly nasm


    【解决方案1】:

    在不知道实际答案或没有时间查找的情况下,我猜测环境变量在命令行参数之后存储在内存中。您的代码只是缓冲区溢出到环境变量字符串中并打印它们。

    这实际上是有道理的,因为命令行参数由系统/加载器处理,环境变量也是如此,因此它们彼此靠近存储是有意义的。要解决这个问题,您需要找到命令行参数的长度,并且只打印那么多字符。或者,因为我假设它们是空终止的字符串,所以打印直到达到零字节。

    编辑: 我假设命令行参数和环境变量都存储在初始化数据部分(我相信 NASM 中的 .data)

    【讨论】:

    • 是的,考虑到有一个原型为'int main(int argc, char *argv[], char *envp[]);'的C主函数版本,这听起来很合理
    【解决方案2】:

    为了了解为什么要获取环境变量,您需要了解内核在进程启动时如何安排内存。 Here 是一个很好的图片解释(向下滚动到“堆栈布局”)。

    【讨论】:

    • 该网站非常有用且内容丰富,非常感谢。
    【解决方案3】:

    只要你好奇,你可能想弄清楚如何打印你的字符串的地址(我认为它是传入的并且你将它从堆栈中弹出)。另外,编写一个十六进制转储例程,这样您就可以查看您感兴趣的内存和其他地址。这可以帮助您发现有关程序空间的信息。

    好奇心可能是程序员工具箱中最重要的东西。

    我没有调查启动进程的细节,但我认为每次启动一个新的 shell 时,都会为它制作一个环境副本。您可能会看到由您运行的命令或您编写的脚本等启动的 shell 的剩余部分。

    【讨论】:

    • AFAIK 每个进程都获得其父级环境的副本,因此他看到了他运行程序的 shell 的环境。
    猜你喜欢
    • 2020-08-07
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 2017-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多