Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 如何找到ret地址_Assembly_Buffer_X86 64_Buffer Overflow - Fatal编程技术网

Assembly 如何找到ret地址

Assembly 如何找到ret地址,assembly,buffer,x86-64,buffer-overflow,Assembly,Buffer,X86 64,Buffer Overflow,在这个程序中,我想做的是重写返回寄存器地址,这样程序的结果是打印“0”而不是“1”作为主文件中x的值 但是我没有找到返回地址——缓冲区的偏移量和返回地址的偏移量 以下是汇编语言的一部分: void function(int a, int b, int c) { char buffer[1]; int *ret; ret = buffer + 20; (*ret) += 7; } void main() { int x; x = 0; fu

在这个程序中,我想做的是重写返回寄存器地址,这样程序的结果是打印“0”而不是“1”作为主文件中x的值

但是我没有找到返回地址——缓冲区的偏移量和返回地址的偏移量

以下是汇编语言的一部分:

void function(int a, int b, int c)
{    char buffer[1];
     int *ret;
     ret = buffer + 20;
     (*ret) += 7;
}
void main()
{    int x;
    x = 0;
    function(1, 2, 3);
    x = 1;
    printf("%d\n", x);
}
以及

编译之后,我使用gdb查找返回地址

main:
.LFB1:
.cfi_startproc
pushq   %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq    %rsp, %rbp
.cfi_def_cfa_register 6
subq    $16, %rsp
movl    $0, -4(%rbp)
movl    $3, %edx
movl    $2, %esi
movl    $1, %edi
call    function
movl    $1, -4(%rbp)
movl    $.LC0, %eax
movl    -4(%rbp), %edx
movl    %edx, %esi
movq    %rax, %rdi
movl    $0, %eax
call    printf
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
0x000000000040054e:推送%rbp
0x000000000040054f:mov%rsp,%rbp
0x0000000000400552:子$0x10,%rsp
0x0000000000400556:movl$0x0,-0x4(%rbp)
0x000000000040055d:mov$0x3,%edx
0x0000000000400562:mov$0x2,%esi
0x0000000000400567:mov$0x1,%edi
0x000000000040056c:callq 0x400524
0x0000000000400571:movl$0x1,-0x4(%rbp)
0x0000000000400578:mov$0x400694,%eax
0x000000000040057d:mov-0x4(%rbp),%edx
0x0000000000400580:mov%edx,%esi
0x0000000000400582:mov%rax,%rdi
0x0000000000400585:mov$0x0,%eax
0x000000000040058a:callq 0x400418
0x000000000040058f:LEVEQ
0x0000000000400590:retq

这就是我选择“20”和“7”的原因。但它不起作用,它说的是“段错误”。我试过很多数字,有时会出现“总线错误”。我不知道为什么,我怎么能找到它。我正在64位机器上运行它。

请看带有我注释的代码:

   0x000000000040054e <+0>: push   %rbp
0x000000000040054f <+1>:    mov    %rsp,%rbp
0x0000000000400552 <+4>:    sub    $0x10,%rsp
0x0000000000400556 <+8>:    movl   $0x0,-0x4(%rbp)
0x000000000040055d <+15>:   mov    $0x3,%edx
0x0000000000400562 <+20>:   mov    $0x2,%esi
0x0000000000400567 <+25>:   mov    $0x1,%edi
0x000000000040056c <+30>:   callq  0x400524 <function>
0x0000000000400571 <+35>:   movl   $0x1,-0x4(%rbp)
0x0000000000400578 <+42>:   mov    $0x400694,%eax
0x000000000040057d <+47>:   mov    -0x4(%rbp),%edx
0x0000000000400580 <+50>:   mov    %edx,%esi
0x0000000000400582 <+52>:   mov    %rax,%rdi
0x0000000000400585 <+55>:   mov    $0x0,%eax
0x000000000040058a <+60>:   callq  0x400418 <printf@plt>
0x000000000040058f <+65>:   leaveq 
0x0000000000400590 <+66>:   retq   
请注意,最后两条指令(pop和ret)从堆栈中弹出两项,即rbp的上一个/保存的值和返回地址

这意味着返回地址正好位于堆栈上保存的rbp值之上,或者位于rbp+8

但是您正在修改rbp+11的内存

此外,您只修改了4个字节,而所有指针都是64位(8字节)

所以,你需要改变

function:
pushq   %rbp ; save rbp on the stack
movq    %rsp, %rbp ; rbp = address of previous value of rbp on the stack
movl    %edi, -20(%rbp)
movl    %esi, -24(%rbp)
movl    %edx, -28(%rbp)
leaq    -9(%rbp), %rax ; rax = address of buffer = rbp - 9
addq    $20, %rax ; rax = buffer + 20 = rbp - 9 + 20 = rbp + 11
movq    %rax, -8(%rbp)
movq    -8(%rbp), %rax
movl    (%rax), %eax ; read 4 bytes from address rbp + 11, WHY 4? 8-byte pointers!
leal    7(%rax), %edx ; add 7 to those
movq    -8(%rbp), %rax
movl    %edx, (%rax) ; store the sub back
popq    %rbp ; restore rbp from the stack
ret ; return

然后更正常量,这样就可以在地址rbp+8处修改8个字节,而不是在rbp+11或rbp+其他位置


火箭科学?不。只要阅读代码,一步一步地看,看看会发生什么,然后思考。你有调试器

> p>如果使用VisualStudio,请考虑调用编译器固有的

unsigned long long *ret;

非常感谢!我还有一些问题要问。什么是movl%rax,-8(%rbp)和movl-8(%rbp),%rax do?在rax和rbp-8的内存之间移动4个字节。阅读汇编教程和CPU手册。”
int *ret;
unsigned long long *ret;
void* _ReturnAddress(void);
#pragma intrinsic(_ReturnAddress);

function main()
{
    void* ret = _ReturnAddress();
    printf("%p", ret);
}