【问题标题】:Returning a byte from /dev/random in assembly在汇编中从 /dev/random 返回一个字节
【发布时间】:2014-06-14 17:07:46
【问题描述】:

我正在尝试打开/dev/random,从中读取一个字节并以状态退出...在 x86 程序集中。 这似乎返回随机数,但我不确定它是否符合我的想法。

# Where do we get our random numbers from
.data
    random: .ascii "/dev/random\0"

# Program goes here
.text
    .global _start
    _start:

    # Get /dev/random fd
    movl $5, %eax      # sys_open (originally $0 by accident)
    movl $random, %ebx # Filename string
    movl $0, %ecx      # O_RDONLY flag
    int $0x80

    # Read one byte onto stack
    movl %eax, %ebx    # The result of sys_open
    movl $3, %eax      # sys_read
    subl $1, %esp      # Make stack space
    movl %esp, %ecx    # Make stack our buffer
    movl $1, %edx      # size_t bytes? only 1
    int $0x80

    # Exit with a random result
    movl %esp, %ebx    # random result as exit status
    movl $1, %eax      # sys_exit
    int $0x80

当我通过strace 运行它时,我得到以下信息:

execve("./random", ["./random"], [/* 44 vars */]) = 0
fstat(0, NULL)                          = 3
close(0)                                = -1 EFAULT (Bad address)
write(0, NULL, 1 <unfinished ...>
+++ exited with 12 +++

注意缺少open()read()!还有,exit()去哪儿了?

我做错了什么?

【问题讨论】:

  • 您的问题似乎更多是关于“如何从 /dev/random 读取”而不是关于“获取随机数”。请更改标题,以免误导未来的读者。 [如果你的目的是快速获得一个随机数,这可能不是这样做的方法。]
  • 好的。更改为“在程序集中从 /dev/random 返回一个字节”

标签: linux assembly io x86


【解决方案1】:

要进行系统调用,您必须遵循内核的系统调用 API。由于我不知道它是什么,我总是look it up online。然后我发现sys_open应该是这样的:

mov $5, %eax          ;; syscall number "open"
mov $random, %ebx     ;; arg 1: char * filename
mov $0, %ecx          ;; arg 2: int flags
int $0x80

【讨论】:

  • 是的,抱歉,这是个意外。我知道了,编辑了问题代码。
【解决方案2】:

好的。谢谢大家。

minuteman3 建议使用pop。虽然它没有直接解决我的问题,但它让我想到了另一个涉及在 64 位机器上使用 32 位代码的问题。很少有汇编标志以后一切正常。这是任何有兴趣的人的最终代码:

# Where do we get our random numbers from
.code32
.data
    random: .ascii "/dev/random\0"

# Program goes here
.text
    .global _start
    _start:

    # Get our random number
    movl $5, %eax      # sys_open
    movl $random, %ebx # Filename string
    movl $0, %ecx      # O_RDONLY flag
    int $0x80

    # Read one random number
    movl %eax, %ebx    # The result of sys_open
    movl $3, %eax      # sys_read
    pushl $0           # Make space on stack and clear it
    movl %esp, %ecx    # The stack is our buffer
    movl $1, %edx      # size_t bytes?
    int $0x80

    # Exit with a random result
    popl %ebx          # Get the number back
    movl $1, %eax      # sys_exit
    int $0x80

编译

as random.s --32 -W -g -o random.o && ld random.o -o random -melf_i386

【讨论】:

  • 有趣的是,.code32 指令使代码在没有额外标志的情况下编译得很好......之后它只是“不起作用”
【解决方案3】:

在参考资料中,我的 edx 寄存器需要文件打开模式掩码。

此外,你永远不会在添加 1 后恢复 sp。

我也会减去/加 4 而不是 1。Linux 可能无法很好地处理未对齐的 esp 值。

此外,您似乎返回的是 esp 的低字节,而不是 esp 的内存。将 %esp 放在括号中的 movl 指令中。

【讨论】:

  • 这是 AT&T 语法,所以我认为是括号。你确定吗?这样做似乎会使程序崩溃,我无法访问该内存。
  • 对。您确实需要从内存中获取值。崩溃可能是因为您从未恢复堆栈指针。另请参阅有关设置 edx reg 的附加说明。
  • 标志值是多少?不过我不确定。根据内核源代码,最后一个参数是“如果设置了 O_CREAT,则新文件的模式,否则忽略”。我只设置了 O_RDONLY,所以没关系,而且确实似乎没有什么区别。
  • 我正在查看 cs.smith.edu/dftwiki/images/e/e3/CSC231_File_IO_In_Assembly.pdf 第 5 页上的文件打开宏。它使用mov edx, S_IRUSR|S_IWUSR|S_IXUSR 但我同意其他文档暗示该模式仅用于文件创建。
猜你喜欢
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多