0x00
写了一半的文章竟然手残没保存就退出了,一首凉凉送给自己。好了,回到正题。之前做过的pwnzble.kr上[Toddler's Bottle]系列。然后今天,噢不,昨天看的时候竟然有点生疏,所以来写个笔记。一来自己看的方便,二来大家也可以一起学习。由于刚入坑不久,文章有问题的地方还请大家指正
0x01
服务器上的文件是32位的,但我但机器是64位的,所以这样编译,生成elf文件丢到ida里,简单的看一下。
有两个函数,先去welcome看一下。
可以看到name的输入可以控制,
在来到login,首先定义了passcode1和passcode2,对输入的两个变量进行判断 if(passcode1==338150 && passcode2==13371337)--->get flag。当然,这个思路是不行的。因为scanf的第二个参数没有"&",会造成什么后果呢?程序会默认从栈中读取4个字节的数据当做scanf取的地址,passcode2在栈上申请的地址应该是ebp-ch=0xffffcf68-0xch ==0xFFFFCF5C
当前栈默认4字节位0xffffcc80,所以456会写到那里,造成程序非预期结束。
0x02
解决思路:如果这两个函数用的同一个ebp的话,可以控制name的输入将got表中的函数地址替换,用户输入的值是system("/bin/cat flag");函数的地址,这样,函数再次调用时,就会执行我们的shellcode。
什么是got表?
概念:每一个外部定义的符号在全局偏移表(Global offset Table)中有相应的条目,GOT位于ELF的数据段中,叫做GOT段。
作用:把位置无关的地址计算重定位到一个绝对地址。程序首次调用某个库函数时,运行时连接编辑器(rtld)找到相应的符号,并将它重定位到GOT之后每次调用这个函数都会将控制权直接转向那个位置,而不再调用rtld。
什么是plt表?
过程连接表(Procedure Linkage Table),一个PLT条目对应一个GOT条目
当main()函数开始,会请求plt中这个函数的对应GOT地址,如果第一次调用那么GOT会重定位到plt,并向栈中压入一个偏移,程序的执行回到_init()函数,rtld得以调用就可以定位printf的符号地址,第二次运行程序再次调用这个函数时程序跳入plt,对应的GOT入口点就是真实的函数入口地址。
动态连接器并不会把动态库函数在编译的时候就包含到ELF文件中,仅仅是在这个ELF被加载的时候,才会把那些动态函库数代码加载进来,之前系统只会在ELF文件中的GOT中保留一个调用地址.
0x03
ebp一样,那就构造payload吧。查看passcode的got表
程序在第二次输入前,调用了fflush和printf,所以覆盖哪个都可以,这里我们覆盖fflush。
name位于ebp-0x70,passcode1位于ebp-0x10。也就是说name这个字符串第96个字节后的4字节数据将会被作为passcode1的地址,system的地址是 0x08048628。
0x04
本机测试:
pwnable.kr测试:
领取专属 10元无门槛券
私享最新 技术干货