我的问候和对所有人的问候.我有一个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>则将调用专用于执行任何必要操作的特殊功能,例如报告问题并终止程序.
Run Code Online (Sandbox Code Playgroud)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
gs 段可用于线程本地存储.例如,它用于errno,因此多线程程序中的每个线程都有效地拥有自己的errno变量.
上面的函数名称是一个很大的线索.这必须是堆栈金丝雀.
(leave是一些CISC指令,可以在实际返回之前执行您需要执行的所有操作.我不知道详细信息).