首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >这个跳转指令有什么问题?

这个跳转指令有什么问题?
EN

Stack Overflow用户
提问于 2022-11-02 20:08:10
回答 2查看 107关注 0票数 3

我得到以下指示:

  1. 使代码中的第一条指令成为jmp
  2. 使该jmp从其当前位置相对跳转到0x51字节。
  3. 在0x51处编写以下代码:
  4. 将堆栈上的最高值放置到寄存器RDI中。
  5. jmp到绝对地址0x403000

到目前为止我所做的是:

代码语言:javascript
运行
复制
.intel_syntax noprefix
    .global _start
    _start:
        jmp $+0x51
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        nop
        pop rdi
        mov eax, 0x403000
        jmp rax

这不正是作业所要求的吗?相对跳跃或绝对跳跃有问题吗?

编辑:

我试图用以下方法更改绝对跳转,但仍然没有结果:

代码语言:javascript
运行
复制
    . . .
    nop
    pop rdi
    mov rax, 0x403000
    jmp fword ptr [eax]

如果可以的话,就是从组装的文件中派生出来的对象转储。

EN

回答 2

Stack Overflow用户

发布于 2022-11-02 23:18:02

$+0x51看起来像NASM语法。你想要的汽油是jmp . + 0x51. 但是事实证明,jmp $+0x51碰巧在没有警告的情况下正确地使用了气体。我不知道GAS是如何在英特尔语法noprefix模式下解释$的!见气体手册re:“特殊点符号”。手册说,您甚至可以指定它跳过输出中的字节,比如. = . + 0x51-2。(-2,因为跳转本身是2个字节。)

clang拒绝$+0x51,但奇怪的是也拒绝. + 0x51。如果自动平地机脚本在Mac上运行,您可能需要做一些其他的事情。

除此之外,在我看来,您的代码是正确的;这就是我解释该任务的方式。你应该给你的老师发电子邮件询问你的代码出了什么问题,以及为什么自动评分程序不接受它。你确定他们要64位代码吗?你最初给nasm贴上标签,他们想要NASM源而不是气体吗?这就是为什么在当前位置使用$而不是.的原因吗?

指令中有几个小的歧义,例如“使jmp相对于其当前位置的0x51字节跳转”;x86相对跳转相对于指令的末尾。因此,他们是否希望jmp . + 0x53从jmp的开始向前跳0x53字节,也就是从jmp的末尾向前跳0x51,并使用机器代码EB 51 (https://felixcloutier.com/x86/jmp)。

但是他们说将代码放在“0x51”上,这意味着在部分中偏移,然后跳到.+0x53就会跳到指令的中间,做一些奇怪的事情。因此,我认为它们确实意味着您应该跳到0x51 jmp 指令的 start 之前的字节,就像您正在做的那样。

当我将其转换为一个用于Linux的静态可执行文件( assemble+link )并在gdb ./a.out (然后是layout reg / layout next / starti / stepi)下运行它时,我看到了相对于0x401051的跳转,跳过了所有的NOPs。下一个指令是pop的argc进入RDI,然后是mov+jmp离开RIP=0x403000。(然后再次跳转会引发SIGSEGV,因为从该地址获取的代码出现了故障。)

所以它对我有效,做所有任务应该做的事情。

你不需要把每个NOP分别写出来

我会用.rept 0x51-2nop.endr或什么的。或.fill 0x51-2, 1, 0x90来填充值0x90 (nop)的1字节模式的0x4f重复。(https://sourceware.org/binutils/docs/as/Fill.html)。

或者装满零,因为你要跳过它们。(.space.zero)。

另外,您也可以在分支目标和jmp after_padding上添加一个标签!这将是一种不处理jmp . + 0x51的clang内置汇编程序的工作方式。

你链接了64 asm,但那是关于跳远的。您不想跳转到新的CS:RIP (或者CS:EIP,就像您用6字节FWORD编写的那样)。作业告诉你要跳转“到0x403000",而不是从那里加载一个函数指针。

几乎跳转到绝对地址的正常方法实际上是mov reg, imm32 / jmp reg。还有其他方法,如push/ret,但效率较低。例如:

  • 调用x86机器代码中的绝对指针 -在GAS和NASM中,jmp 0x403000只是起作用,假设您将它链接到一个非饼级的可执行文件中,以便目的地位于jmp rel32的范围内。(可达+-2 2GiB) 要达到这个绝对地址(从已知的代码地址,所以它不适用于ASLR),这是一个相对的跳转,但不清楚这是否是他们想要的。
  • 如何在x64和x32的英特尔语法中跳转到内存位置 - jmp qword ptr [RIP+destination]destination: .quad 0x403000用RIP相对寻址模式执行内存间接跳转,将一个8字节指针加载到RIP中.您甚至可以将指针放在jmp之后,而不是在.rodata中。
  • JMP到绝对地址(op代码) --首先展示了效率低下的推/转方式,而没有指出分支预测的效率问题。
票数 3
EN

Stack Overflow用户

发布于 2022-11-03 22:08:16

解决方案有点恼人:使用的指令实际上是正确的,甚至是使用简单寄存器的绝对跳转。请求的文本不正确或不明确,pop指令被要求位于0x51位置,但这句话的真正含义(根据组织者)是,必须有0x51 nop指令。

这意味着nops的总数和确切数量是81,第一个跳转的偏移量(除了考虑jmp指令本身的大小之外)必须考虑到添加的nops,因此它成为jmp $ + 0x53

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74295110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档