什么是原讼法庭指令是什么意思? (和一些更多的问题) [英] What do the CFI directives mean? (and some more questions)

查看:348
本文介绍了什么是原讼法庭指令是什么意思? (和一些更多的问题)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,这会是一个长期的问题。我想了解缓冲区溢出是如何工作的。我读粉碎堆栈的乐趣和aleph1获利以及刚刚得到了以下的反汇编code:

  void函数(INT A,INT B,INT C){
   炭缓冲器1 [5];
   炭缓冲器2 [10];
}无效的主要(){
  函数(1,2,3);
}

GCC的disameembly使用 -S 标志给我:

  .fileexample1.c
    。文本
    .globl功能
    .TYPE功能,@function
功能:
.LFB0:
    .cfi_startproc
    pushq%RBP
    .cfi_def_cfa_offset 16
    .cfi_offset 6,-16
    MOVQ%RSP,RBP%
    .cfi_def_cfa_register 6
    SUBQ $ 48%RSP
    MOVL%EDI,-36(RBP%)
    MOVL%ESI,-40(RBP%)
    MOVL%EDX,-44(RBP%)
    MOVQ%FS:40%RAX
    MOVQ%RAX,-8(%RBP)
    xorl%EAX,EAX%
    MOVQ -8(%RBP),RAX%
    xorq%FS:40%RAX
    JE .L2
    调用__stack_chk_fail
.L2:
    离开
    .cfi_def_cfa 7,8
    RET
    .cfi_endproc
.LFE0:
    .size功能。功能
    .globl主
    .TYPE为主,@function
主要:
.LFB1:
    .cfi_startproc
    pushq%RBP
    .cfi_def_cfa_offset 16
    .cfi_offset 6,-16
    MOVQ%RSP,RBP%
    .cfi_def_cfa_register 6
    MOVL $ 3%EDX
    MOVL $ 2,%ESI
    MOVL $ 1,EDI%
    通话功能
    popq%RBP
    .cfi_def_cfa 7,8
    RET
    .cfi_endproc
.LFE1:
    .size为主,。,主
    .identGCC:(Ubuntu的4.8.2-19ubuntu1)4.8.2
    .section伪.note.GNU堆栈,,@ PROGBITS

.cfi 指令不是由Aleph1的文件,我想他们都没有使用当时的情况。我已阅读<一个href=\"http://stackoverflow.com/questions/2529185/what-are-cfi-directives-in-gnu-assembler-gas-used-for\">this问题的SO ,我得到了他们由GCC进行异常处理使用。我也看过<一个href=\"http://stackoverflow.com/questions/5168680/questions-re-assembly-generated-from-my-c-by-gcc\">another问题的SO ,我得到.LFB0,.LFE0,.LFE1和.LFB1是标签,但是我有以下疑问:


  1. 我得到.cfi指令用于异常处理,但是我不明白他们的意思。我一直这里,我看到一些定义这样的:


  

.cfi_def_cfa注册,偏移


  
  

.cfi_def_cfa定义的规则计算CFA为:取地址从
  注册并添加偏移到它。


不过,如果你看看,我在上面已经把拆卸的你没有找到任何寄存器名称的(如:EAX,EBX等),而不是你发现了一些存在(我普遍发现'6'),我不知道怎么说应该是一个寄存器。特别是,任何人都可以解释什么 .cfi_def_cfa_offset 16 .cfi_offset 6,-16 。 cfi_def_cfa_register 6 .cfi_def_cfa 7,8 是什么意思?此外,这是什么 CFA 是什么意思?我问这个,因为大多是在书本/论文的过程Prolog是这样的:

  pushl%EBP
 MOVL%ESP,EBP%
 subl $ 20%ESP

不过,现在我觉得在现代计算机程序序言如下:

  .cfi_startproc
    pushq%RBP
    .cfi_def_cfa_offset 16
    .cfi_offset 6,-16
    MOVQ%RSP,RBP%
    .cfi_def_cfa_register 6
    SUBQ $ 48%RSP

起初我还以为原讼法庭指令,而不是助记符设置偏移但事实并非如此;在命令仍在尽管使用CFI指令的使用。

<醇开始=2>
  • 我了解,目前每个过程标签。然而,为什么是一个过程内部多层嵌套的标签?在我的情况主要有.LFB1和.LFE2标签。什么是需要多个标签?同样,函数程序具有标签.LFB0,.L2和.LFE0


  • 最后3线两个过程似乎被用于一些日常功能(说的是程序的大小,也许?),但我不知道它们意味着什么。任何人能解释它们意味着什么,什么是自己用呢?


  • 编辑:

    (添加一个问题)

    <醇开始=4>
  • 执行原讼法庭指令占用任何空间?因为在程序中功能,每个的int参数占用4个字节,它的数量为3,因此,所有参数取入存储器12字节。接下来,第一个字符阵列需要8个字节(四舍五入5bytes至8个字节),和一个字符阵列需要12bytes(围捕10bytes到12bytes),所以整个字符阵列需要20个字节。总结所有这些,参数和局部变量只需要12 + 20 = 32字节。

    但在过程功能,编译器减去48个字节来存储值。为什么呢?



  • 解决方案

    根据逆向工程我把我的意见的内容作为答案在这里你的要求(我不知道这是否将继续保持,因为我看到了严峻竞争向下票和向上投有你的问题)

    林迪舞者回答什么 CFI和CFA手段调用帧信息)和(c 所有帧地址

    .L&LT; NUM&GT; 表示标签按各种花絮在谷歌在64 GCC名字按以下格式的所有标签开始 .L 的数字结束所以 .L1,.L2,.L ....无穷是标签

    NUM&GT; 表示函数的开始和<$ C $根据谷歌和一些早期的 SO 答案 BF&LT

    C> EF&LT; NUM&GT; 表示功能-END

    所以 .LBF0,.LBF1。 LBF .....无穷 .LFE0,......,.LFE ....无穷

    表示功能开始,并在其中编译器可能需要除非有非常严重需要深入编译器内部采取的一些内部需要照顾,所以你应该在这一刻他们忘记了每个功能的函数结束

    其他标签 .L2 的存在是为了解决分支指令JE在功能

      JE .L2

    也是每个编译器对齐,并垫接入参数和当地人一定的边界

    我不能肯定,但默认64位对齐为16字节,我认为对GCC
    所以,如果你请求一个奇怪的预约像

    字符富[ 5 ]或结果
    BYTE等等[ 10 ]

    指数 5和10 不是为 86

    对齐连

    5 86的编译器将分配 8个字节的和10 16字节

    喜欢聪明的 64 GCC可以分配16个字节为每个请求

    你其实不应该担心,为什么编译器它做什么

    当你试图了解装配的逻辑,只是专注于地址

    如果编译器决定,将放置X在RBP +/- X 它将也是在同一地点访问通过了该变量的作用域和生命

    Ok, this is gonna be a long question. I'm trying to understand how "buffer overflow" works. I am reading Smashing the stack for fun and profit by aleph1 and have just got the disassembly of the following code:

    void function(int a, int b, int c) {
       char buffer1[5];
       char buffer2[10];
    }
    
    void main() {
      function(1,2,3);
    }
    

    The disameembly using -S flag of GCC gives me:

        .file   "example1.c"
        .text
        .globl  function
        .type   function, @function
    function:
    .LFB0:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $48, %rsp
        movl    %edi, -36(%rbp)
        movl    %esi, -40(%rbp)
        movl    %edx, -44(%rbp)
        movq    %fs:40, %rax
        movq    %rax, -8(%rbp)
        xorl    %eax, %eax
        movq    -8(%rbp), %rax
        xorq    %fs:40, %rax
        je  .L2
        call    __stack_chk_fail
    .L2:
        leave
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE0:
        .size   function, .-function
        .globl  main
        .type   main, @function
    main:
    .LFB1:
        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        movl    $3, %edx
        movl    $2, %esi
        movl    $1, %edi
        call    function
        popq    %rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
    .LFE1:
        .size   main, .-main
        .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"
        .section    .note.GNU-stack,"",@progbits
    

    the .cfi directives are not in the paper by Aleph1 and I guess that they were not used back then. I have read this question on SO and I get that they are used by GCC for exception handling. I have also read another question on SO and I get that .LFB0, .LFE0, .LFE1 and .LFB1 are labels however I have the following doubts:

    1. I get that .cfi directives are used for exception handling however I don't understand what they mean. I have been here and I see some definitions like:

    .cfi_def_cfa register, offset

    .cfi_def_cfa defines a rule for computing CFA as: take address from register and add offset to it.

    However, if you take a look at the disassembly that I have put above you don't find any register name (like EAX, EBX and so on) instead you find a number there (I have generally found '6') and I don't know how's that supposed to be a register. Especially, can anyone explain what .cfi_def_cfa_offset 16, .cfi_offset 6, -16, .cfi_def_cfa_register 6 and .cfi_def_cfa 7, 8 mean? Also, what does CFA mean? I am asking this because mostly in books/papers the procedure prolog is like :

     pushl %ebp
     movl %esp,%ebp
     subl $20,%esp
    

    However, now I think the procedure prolog in modern computers is as follows:

        .cfi_startproc
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register 6
        subq    $48, %rsp
    

    Initially I thought that the CFI directives are used instead of sub mnemonic to set the offset but that's not the case; the sub command is still being used in spite of using the CFI directives.

    1. I understood that there are labels for each procedure. However, why are multiple nested labels inside a procedure? In my case main has .LFB1 and .LFE2 labels. What is the need for multiple labels? Similarly the function procedure has the labels .LFB0, .L2 and .LFE0

    2. The last 3 lines for both the procedures seem to be used for some housekeeping functions (telling the size of the procedure, maybe?) but I am not sure what do they mean. Can anyone explain what do they mean and what's their use?

    EDIT:

    (adding one more question)

    1. Do the CFI directives take up any space? Because in the procedure "function", each int parameter take up 4 bytes and the number of it is 3, so all parameter takes 12 bytes in memory. Next, the first char array takes 8 bytes (round up 5bytes to 8bytes), and next char array takes 12bytes (round up 10bytes to 12bytes), so the whole char array takes 20 bytes. Summing these all, parameter and local variables only need 12+20=32 bytes.

      But in the procedure "function", compiler subtract 48 bytes to store values. Why?

    解决方案

    as per your request in reverse engineering i am putting the contents of my comments as answers here ( i dont know if this is going to remain as i see a severe competition to down-vote and up-vote your question there )

    Lindy Dancer Answered what cfi and cfa means (call frame information ) and (call frame address )

    .L<num> denotes labels as per various tidbits in Google in x64 GCC names all labels in the following format start with .L and end with a numeral so .L1 , .L2 , .L....infinity are labels

    according to Google and some earlier SO answers BF<num> indicates Function-Begin and EF<num> indicates FUNCTION-END

    so .LBF0 , .LBF1 . LBF.....infinity and .LFE0 ,......., .LFE....infinity

    denotes function begins and function ends in each function which the compiler probably requires to take care of some internal needs so you should forget them at this moment unless there is a very grave need to dig into compiler internals

    the other label .L2 exists to address the branching instruction je in your function

    je  .L2
    

    also every compiler aligns and pads the access to arguments and locals to certain boundary

    i can't be sure but x64 default align is 16 bytes I think for GCC so if you request an odd reservation like

    char foo[5] or
    BYTE blah [10]

    the indices 5 and 10 are not aligned even for x86

    for 5 x86 compiler will assign8 bytes and for 10 16 bytes

    like wise x64 gcc might assign 16 bytes for each of your requests

    you actually shouldn't be worrying about why compiler does what it does

    when you are trying to understand logic of assembly just concentrate on addresses

    if the compiler decided that it will put x at rbp +/- X it will also access it at the same location through out the scope or life of that variable

    这篇关于什么是原讼法庭指令是什么意思? (和一些更多的问题)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆