我是靠谱客的博主 虚幻咖啡,最近开发中收集的这篇文章主要介绍TJCTF之Secure Secrets,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

博客已经转移

https://noone-hub.github.io/

百度你查的到的writeup都是说很简单,然后给代码,对于我等新手很不友好,谷歌搜索可以搜索到详细的writeup,也是解释的一半一半,对于新手也不是很友好,看了个youtube的视频,发觉讲的不错,代码简洁,最后懂了,不过就是全英文的,有点难听懂

回到正题:这道题可以用ida打开,审查代码发觉有格式化字符串漏洞,或者自己运行调试下试试,在输入密码过后 输入%x %x多个查看,是否有漏洞

先补充下点知识,避免踩坑,因为自己花了很长时间才懂,其实很简单

基本的格式化字符串参数

%c:输出字符,配上%n可用于向指定地址写数据。

%d:输出十进制整数,配上%n可用于向指定地址写数据。

%x:输出16进制数据,如%i$x表示要泄漏偏移i处4字节长的16进制数据,%i$lx表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样。

%p:输出16进制数据,与%x基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit。

%s:输出的内容是字符串,即将偏移处指针指向的字符串输出,如%i$s表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息。

%n:将%n之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置,如%100×10$n表示将0x64写入偏移10处保存的指针所指向的地址(4字节),而%$hn表示写入的地址空间为2字节,%$hhn表示写入的地址空间为1字节,%$lln表示写入的地址空间为8字节,在32bit和64bit环境下一样。有时,直接写4字节会导致程序崩溃或等候时间过长,可以通过%$hn或%$hhn来适时调整。

%n是通过格式化字符串漏洞改变程序流程的关键方式,而其他格式化字符串参数可用于读取信息或配合%n写数据。

 

以上加粗的知识是重点要知道的,因为这道题就用到了这个,测试一波程序

中间那段%x完全是由个人决定的,用来查偏移位置,4个字节为一个偏移,你可以计算到 41414141这里,总共是11个偏移,也就是说%11$x就输出41414141,不信你可以试试,然后该怎么办呢,objdump -d secure一下,

发觉

有个函数很奇怪,fopen打开文件,而且名字叫getsecret,不懂汇编的可以打开ida查看一下,我前面的文章教了你ida如何使用,具体自己翻,发觉这就是打开flag文件的一个函数,在checksec secure一下,发觉

No Pie,是无aslr,也就是地址不会随机化,可是事实并非如此吧,网上writeup跟我的地址老是有出入(这里待更新)

反正我们可以用got表覆写技术,具体就是

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中保留一个调用地址.

 

攻击原理 :由于GOT表是可以写入的,所以将GOT表中要调用的函数地址覆盖成我们shell code的地址就可以了 

从题目中看,我们可以从exit函数出发,反汇编看到的,因为exit是最后调用的,结束的时候打印出flag就可以,思路理清了,然后就是操作了,首先我们要输入的是exit的地址,在测试中,我用4个A替代的那个位置,然后你看下exit跟get_secret的地址,差值有多少这是get_secret地址0x08048713 而exit地址 0x8048580 意思我们只需要覆盖后面两个字节就可以了,因为0x8048是一样的,所以第一个输入exit地址,然后输入的是我标注的重点内容,%34579x%11$hn ,最后在输入exit地址,这样就可以达到覆盖了,贴上完整代码

#!/usr/bin/env python
# coding=utf-8
from pwn import *
sh=remote('problem1.tjctf.org',8008)
addr=0x804a02c
payload='%34579x%11$hn'
sh.sendlineafter('> ',p32(addr) )
sh.sendlineafter('> ', payload)
sh.sendlineafter('> ', p32(addr))
sh.interactive()

 

34579是0x8713转成10进制的数值,p32是为了小端输入,输入字符

最后

以上就是虚幻咖啡为你收集整理的TJCTF之Secure Secrets的全部内容,希望文章能够帮你解决TJCTF之Secure Secrets所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部