GOT表覆写技术
GOT表:
概念:每一个外部定义的符号在全局偏移表(Global offset Table)中有相应的条目,GOT位于ELF的数据段中,叫做GOT段。
作用:把位置无关的地址计算重定位到一个绝对地址。程序首次调用某个库函数时,运行时连接编辑器(rtld)找到相应的符号,并将它重定位到GOT之后每次调用这个函数都会将控制权直接转向那个位置,而不再调用rtld。
过程连接表(Procedure Linkage Table),一个PLT条目对应一个GOT条目
当main()函数开始,会请求plt中这个函数的对应GOT地址,如果第一次调用那么GOT会重定位到plt,并向栈中压入一个偏移,程序的执行回到_init()函数,rtld得以调用就可以定位printf的符号地址,第二次运行程序再次调用这个函数时程序跳入plt,对应的GOT入口点就是真实的函数入口地址。
动态连接器并不会把动态库函数在编译的时候就包含到ELF文件中,仅仅是在这个ELF被加载的时候,才会把那些动态函库数代码加载进来,之前系统只会在ELF文件中的GOT中保留一个调用地址.
攻击原理 :由于GOT表是可以写入的,所以将GOT表中要调用的函数地址覆盖成我们shell code的地址就可以了 ,攻击姿势来源: http://jing0107.lofter.com/post/1cbc869f_8b3d8a5
用pwnable.kr的pass code来理解这个技术
连接上服务器后 查看服务器中的文件
发现有三个文件 flag , passcode, passcode.c
尝试cat flag 发现不行
查看passcode.c
passcode开启了NX 防护机制 和 CANARY
源文件里面主要有两个函数 login 和 welcome
输入用户名后 再输入passcode1和passcode2 然后将passcode1和passcode2的值和 338150 ,13371337进行比较 ,如果相等就执行system('cat flag')输出flag
尝试执行passcode的可执行文件 ./passcode
在输入用户后 输入完第一个passcode 程序就终止执行了 ,有些地方出来问题
将passcode.c 编译一下 发现有警告 说scanf()函数的第二个参数没有加& 不是地址
如果scanf('%d',passcode1) 第二个参数没有加&符号或者是不是一个地址 那么scanf函数会从栈中读取四个字节作为scanf取的地址 漏洞就在这里
我选择覆盖flush函数的GOT表地址
用 objdump -R passcode 导出GOT表信息
flush_add = 0x0804a004
system函数的地址可以通过查看文件的汇编代码 来找到地址
system_add= 0x080485e3
用objdump -d passcode 查看汇编代码
不难发现welcome和login两个函数都是使用相同的一个ebp作为栈的起始地址
三个变量基于ebp的偏移是分别是
0x70 0x10 0xc
username 最后四个字节刚好覆盖到passcode1
计算出username到passcode1的距离 0x70-0x10
构造payload 'a'*96+p32(flush_add)+str(system_add)
因为scanf是按照%d格式读取数据 所以要将system_add转换成整数
python -c "print 'a'*96+'\x04\xa0\x04\x08'+str(sysetm_add)"| ./passcode