这条指令的作用是什么?: - mov%gs:0x14,%eax

kri*_*iss 5 c x86 assembly

我的问候和对所有人的问候.我有一个C程序,基本上是为了测试缓冲区溢出而写的.

    #include<stdio.h>
    void display()
    {
            char buff[8];
            gets(buff);
            puts(buff);
    }
    main()
    {
        display();
        return(0);
    }
Run Code Online (Sandbox Code Playgroud)

现在我使用GDB反汇编它的显示和主要部分.代码:-

函数main的汇编代码转储:

    0x080484ae <+0>:    push   %ebp        # saving ebp to stack
    0x080484af <+1>:    mov    %esp,%ebp   # saving esp in ebp
    0x080484b1 <+3>:    call   0x8048474 <display>   # calling display function
    0x080484b6 <+8>:    mov    $0x0,%eax   # move 0 into eax , but WHY ????
    0x080484bb <+13>:   pop    %ebp        # remove ebp from stack
    0x080484bc <+14>:   ret                # return
Run Code Online (Sandbox Code Playgroud)

汇编程序转储结束.

用于功能显示的汇编代码转储:

    0x08048474 <+0>:    push   %ebp          #saves ebp to stack        
    0x08048475 <+1>:    mov    %esp,%ebp     # saves esp to ebp
    0x08048477 <+3>:    sub    $0x10,%esp    # making 16 bytes space in stack
    0x0804847a <+6>:    mov    %gs:0x14,%eax  # what does it mean ????
    0x08048480 <+12>:   mov    %eax,-0x4(%ebp) # move eax contents to 4 bytes lower in stack
    0x08048483 <+15>:   xor    %eax,%eax       # xor eax with itself (but WHY??)
    0x08048485 <+17>:   lea    -0xc(%ebp),%eax  #Load effective address of 12 bytes 
                                              lower placed value ( WHY???? )

    0x08048488 <+20>:   mov    %eax,(%esp)      #make esp point to the address inside of eax
    0x0804848b <+23>:   call   0x8048374 <gets@plt>  # calling get, what is "@plt" ????
    0x08048490 <+28>:   lea    -0xc(%ebp),%eax       # LEA of 12 bytes lower to eax
    0x08048493 <+31>:   mov    %eax,(%esp)         # make esp point to eax contained address
    0x08048496 <+34>:   call   0x80483a4 <puts@plt>  # again what is "@plt" ????
    0x0804849b <+39>:   mov    -0x4(%ebp),%eax    # move (ebp - 4) location's contents to eax
    0x0804849e <+42>:   xor    %gs:0x14,%eax         # # again what is this ????
    0x080484a5 <+49>:   je     0x80484ac <display+56> # Not known to me
    0x080484a7 <+51>:   call   0x8048394 <__stack_chk_fail@plt>  # not known to me
    0x080484ac <+56>:   leave                        # a new instruction, not known to me
    0x080484ad <+57>:   ret                          # return to MAIN's next instruction
Run Code Online (Sandbox Code Playgroud)

汇编程序转储结束.

伙计们,你应该考虑我的作业.休息所有代码都是我所知道的,除了几行.我加了一个大"为什么????" 每行前面的评论中还有一些问题.对我来说,第一个障碍是"mov%gs:0x14,%eax"指令,我不能在此指令后制作流程图.有人解释一下,这几条指令是什么意思,并在程序中做什么?谢谢...

Ale*_*nze 11

0x080484b6 <+8>:    mov    $0x0,%eax   # move 0 into eax , but WHY ????
Run Code Online (Sandbox Code Playgroud)

你有这个吗?:

return(0);
Run Code Online (Sandbox Code Playgroud)

它们可能是相关的.:)

0x0804847a <+6>:    mov    %gs:0x14,%eax  # what does it mean ????
Run Code Online (Sandbox Code Playgroud)

这意味着从地址gs:0x14的内存中读取4个字节到eax.gs是一个段寄存器.最有可能TLS通过此寄存器引用线程本地存储(AKA ).

0x08048483 <+15>:   xor    %eax,%eax       # xor eax with itself (but WHY??)
Run Code Online (Sandbox Code Playgroud)

不知道.可能与优化相关.

0x08048485 <+17>:   lea    -0xc(%ebp),%eax  #Load effective address of 12 bytes 
                                          lower placed value ( WHY???? )
Run Code Online (Sandbox Code Playgroud)

它使eax指向一个存在于堆栈中的局部变量.sub $0x10,%esp为他们分配了一些空间.

0x08048488 <+20>:   mov    %eax,(%esp)      #make esp point to the address inside of eax
Run Code Online (Sandbox Code Playgroud)

错误.它将eax写入堆栈,堆栈顶部.它将作为堆栈参数传递给被调用函数:

0x0804848b <+23>:   call   0x8048374 <gets@plt>  # calling get, what is "@plt" ????
Run Code Online (Sandbox Code Playgroud)

我不知道.可能是一些名字毁了.

到现在为止你应该猜到了什么是局部变量.buff还有什么呢?

0x080484ac <+56>:   leave                        # a new instruction, not known to me
Run Code Online (Sandbox Code Playgroud)

为什么不在CPU手册中查找?

现在,我可以解释一下gs/TLS的事情......

0x08048474 <+0>:    push   %ebp          #saves ebp to stack        
0x08048475 <+1>:    mov    %esp,%ebp     # saves esp to ebp
0x08048477 <+3>:    sub    $0x10,%esp    # making 16 bytes space in stack
0x0804847a <+6>:    mov    %gs:0x14,%eax  # what does it mean ????
0x08048480 <+12>:   mov    %eax,-0x4(%ebp) # move eax contents to 4 bytes lower in stack
...
0x0804849b <+39>:   mov    -0x4(%ebp),%eax    # move (ebp - 4) location's contents to eax
0x0804849e <+42>:   xor    %gs:0x14,%eax         # # again what is this ????
0x080484a5 <+49>:   je     0x80484ac <display+56> # Not known to me
0x080484a7 <+51>:   call   0x8048394 <__stack_chk_fail@plt>  # not known to me
0x080484ac <+56>
Run Code Online (Sandbox Code Playgroud)

因此,此代码从TLS获取一个值(在gs:0x14处)并将其存储在保存的ebp值(ebp-4)的正下方.再有就是用你的东西get()put().然后,此代码检查来自TLS的值的副本是否未更改.xor %gs:0x14,%eax做比较.

如果XORed值相同,则XOR的结果为0且flags.zf为1.否则,结果不为0且flags.zf为0.

je 0x80484ac <display+56>call 0x8048394 <__stack_chk_fail@plt>如果flags.zf = 1,则检查flags.zf并跳过.IOW,如果来自TLS的值的副本未更改,则跳过此调用.

那是什么一回事?这是一种尝试捕获缓冲区溢出的方法.如果写入超出缓冲区末尾,则会覆盖从TLS复制到堆栈的值.

为什么我们从TLS中获取这个值,为什么不只是一个恒定的硬编码值呢?我们可能希望使用不同的非硬编码值来更频繁地捕获溢出(因此TLS中的值将从程序的运行更改为另一个运行程序,并且在程序的不同线程中它将有所不同).如果每次程序运行时随机选择值,这也会降低攻击者成功利用缓冲区溢出的几率.

最后,如果发现由于缓冲区溢出而覆盖了值的副本,call 0x8048394 <__stack_chk_fail@plt>则将调用专用于执行任何必要操作的特殊功能,例如报告问题并终止程序.


sou*_*edi 7

0x0804849e <+42>:   xor    %gs:0x14,%eax         # # again what is this ????
0x080484a5 <+49>:   je     0x80484ac <display+56> # Not known to me
0x080484a7 <+51>:   call   0x8048394 <__stack_chk_fail@plt>  # not known to me
0x080484ac <+56>:   leave                        # a new instruction, not known to me
0x080484ad <+57>:   ret                          # return to MAIN's next instruction
Run Code Online (Sandbox Code Playgroud)

gs 可用于线程本地存储.例如,它用于errno,因此多线程程序中的每个线程都有效地拥有自己的errno变量.

上面的函数名称是一个很大的线索.这必须是堆栈金丝雀.

(leave是一些CISC指令,可以在实际返回之前执行您需要执行的所有操作.我不知道详细信息).