assembly 编辑ELF二进制调用指令

d8tt03nd  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(124)

我正在尝试操作一个二进制文件的调用函数。我有下面的代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void myfunc2(char *str2, char *str1) {

    // enter code here
}

void myfunc(char *str2, char *str1)
{
    memcpy(str2 + strlen(str2), str1, strlen(str1));
}

int main(int argc, char **argv)
{
    char str1[4] = "tim";
    char str2[10] = "hello ";

    myfunc((char *)&str2, (char *)&str1);

    printf("%s\n", str2);
    
    myfunc2((char *)&str2, (char *)&str1);

    printf("%s\n", str2);

    return 0;
}

void myfunc2(char *str2, char *str1)
{
    memcpy(str2, str1, strlen(str1));
}

我已经编译了二进制文件,并使用readelf或objdump可以看到我的两个函数位于:
46:000000000040072 c52函数全局默认值13我的函数2**
54:000000000040064 d77函数全局默认值13我的函数**
使用命令objdump -D test(我的二进制文件名),我可以看到main有两个callq函数,我试图使用上面的地址72 c编辑第一个函数,使其指向mymunc 2,但这不起作用;导致二进制文件失败。

000000000040069a <main>:
  40069a:   55                      push   %rbp
  40069b:   48 89 e5                mov    %rsp,%rbp
  40069e:   48 83 ec 40             sub    $0x40,%rsp
  4006a2:   89 7d cc                mov    %edi,-0x34(%rbp)
  4006a5:   48 89 75 c0             mov    %rsi,-0x40(%rbp)
  4006a9:   64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
  4006b0:   00 00 
  4006b2:   48 89 45 f8             mov    %rax,-0x8(%rbp)
  4006b6:   31 c0                   xor    %eax,%eax
  4006b8:   c7 45 d0 74 69 6d 00    movl   $0x6d6974,-0x30(%rbp)
  4006bf:   48 b8 68 65 6c 6c 6f    movabs $0x206f6c6c6568,%rax
  4006c6:   20 00 00 
  4006c9:   48 89 45 e0             mov    %rax,-0x20(%rbp)
  4006cd:   66 c7 45 e8 00 00       movw   $0x0,-0x18(%rbp)
  4006d3:   48 8d 55 d0             lea    -0x30(%rbp),%rdx
  4006d7:   48 8d 45 e0             lea    -0x20(%rbp),%rax
  4006db:   48 89 d6                mov    %rdx,%rsi
  4006de:   48 89 c7                mov    %rax,%rdi
  4006e1:   e8 67 ff ff ff          callq  40064d <myfunc>
  4006e6:   48 8d 45 e0             lea    -0x20(%rbp),%rax
  4006ea:   48 89 c7                mov    %rax,%rdi
  4006ed:   e8 0e fe ff ff          callq  400500 <puts@plt>
  4006f2:   48 8d 55 d0             lea    -0x30(%rbp),%rdx
  4006f6:   48 8d 45 e0             lea    -0x20(%rbp),%rax
  4006fa:   48 89 d6                mov    %rdx,%rsi
  4006fd:   48 89 c7                mov    %rax,%rdi
  400700:   e8 27 00 00 00          callq  40072c <myfunc2>
  400705:   48 8d 45 e0             lea    -0x20(%rbp),%rax
  400709:   48 89 c7                mov    %rax,%rdi
  40070c:   e8 ef fd ff ff          callq  400500 <puts@plt>
  400711:   b8 00 00 00 00          mov    $0x0,%eax
  400716:   48 8b 4d f8             mov    -0x8(%rbp),%rcx
  40071a:   64 48 33 0c 25 28 00    xor    %fs:0x28,%rcx
  400721:   00 00 
  400723:   74 05                   je     40072a <main+0x90>
  400725:   e8 f6 fd ff ff          callq  400520 <__stack_chk_fail@plt>
  40072a:   c9                      leaveq 
  40072b:   c3                      retq

我怀疑我需要通过相对位置或使用莱亚/mov指令来计算地址信息。
任何帮助,以了解如何修改调用函数将不胜感激-请没有指针编辑字符串一样的howto遍布大部分互联网...

a1o7rhls

a1o7rhls1#

为了重写地址,您必须知道callq指令的确切编码方式。
让我们看看第一个调用的反汇编输出:

4006e1: e8 67 ff ff ff          callq  40064d <myfunc>
4006e6: ...

可以清楚地看到,该指令是用5个字节编码的,其中e8字节是指令操作码,67 ff ff ff是跳转到的地址。此时,人们会问这样一个问题:67 ff ff ff0x40064d有什么关系?
答案是,e8编码了一个所谓的“相对调用”,跳转是相对于下一条指令的位置执行的。为了重写地址,你必须计算4006e6和被调用函数之间的距离。如果调用是绝对的(ff),你可以把函数地址放在这4个字节中。
要证明这是事实,请考虑以下算法:

0x004006e6 + 0xffffff67 == 0x10040064d

相关问题