Loading... <!-- wp:paragraph --> <p>这道题对我而言有两个新知识点,中级rop——<span class="external-link"><a class="no-external-link" href="https://ctf-wiki.github.io/ctf-wiki/pwn/linux/stackoverflow/medium-rop-zh/" target="_blank">ret2csu<i data-feather='external-link'></i></a></span>和DynELF工具的使用。同时这道题也做了我非常久,让我心态有点小崩。为啥会做这么久呢,还是因为我对plt,got和动态链接之类的知识认知太过于匮乏。所以从今天开始我放缓刷题,先看完《程序员的自我修养》一书。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>先来谈谈ret2csu,几乎所有的Linux C程序都会调用libc,这样的程序中总会有一个init函数,比如下面这个(不同的程序会不一样)</p> <!-- /wp:paragraph --> <!-- wp:code --> <pre class="wp-block-code"><code>.text:0000000000400700 ; void init(void) .text:0000000000400700 init proc near ; DATA XREF: start+16↑o .text:0000000000400700 ; __unwind { .text:0000000000400700 push r15 .text:0000000000400702 mov r15d, edi .text:0000000000400705 push r14 .text:0000000000400707 mov r14, rsi .text:000000000040070A push r13 .text:000000000040070C mov r13, rdx .text:000000000040070F push r12 .text:0000000000400711 lea r12, off_600E10 .text:0000000000400718 push rbp .text:0000000000400719 lea rbp, off_600E18 .text:0000000000400720 push rbx .text:0000000000400721 sub rbp, r12 .text:0000000000400724 xor ebx, ebx .text:0000000000400726 sar rbp, 3 .text:000000000040072A sub rsp, 8 .text:000000000040072E call _init_proc .text:0000000000400733 test rbp, rbp .text:0000000000400736 jz short loc_400756 .text:0000000000400738 nop dword ptr [rax+rax+00000000h] .text:0000000000400740 .text:0000000000400740 loc_400740: ; CODE XREF: init+54↓j .text:0000000000400740 mov rdx, r13 .text:0000000000400743 mov rsi, r14 .text:0000000000400746 mov edi, r15d .text:0000000000400749 call qword ptr [r12+rbx*8] .text:000000000040074D add rbx, 1 .text:0000000000400751 cmp rbx, rbp .text:0000000000400754 jnz short loc_400740 .text:0000000000400756 .text:0000000000400756 loc_400756: ; CODE XREF: init+36↑j .text:0000000000400756 add rsp, 8 .text:000000000040075A pop rbx .text:000000000040075B pop rbp .text:000000000040075C pop r12 .text:000000000040075E pop r13 .text:0000000000400760 pop r14 .text:0000000000400762 pop r15 .text:0000000000400764 retn .text:0000000000400764 ; } // starts at 400700 .text:0000000000400764 init endp</code></pre> <!-- /wp:code --> <!-- wp:paragraph --> <p>这个函数我们主要关心后面两个local函数。可以发现,先调用loc_400756,通过对r13,r14赋值后retn到loc_400740后,我们便可以操纵rdx和rsi两个寄存器,他们正好是x64传参时的第三个和第二个参数,若改变r15的值,可以控制rdi(传递第一个参数的寄存器)的低32位(高32位会自动清零),改变r12则可以让loc_400740调用一个指定的函数。值得注意的是,call qword ptr [r12+rbx*8]语句进行的是call,也就是说r12应该指向被调函数的got表处,当然这么有点形而上学,准确地说是r12需要指向一个储存了被调函数的函数指针的地址</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>但是在构造payload的时候需要注意,因为在执行loc_400740时,loc_400756会再执行一次,所以需要在尾部(最后的return address之前)填充7*8个字节的垃圾数据来让寄存器出栈。当时我不太明白为什么是56个字节,原因是<code>add rsp, 8</code>这个指令让栈顶变化了,所以要多8个字节。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>在这道题中,我们主要利用这两个函数来调用write函数向内存写入"/bin/sh"</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>说回题目,先检查一下安全措施</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":452,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201107163159.png" alt="" class="wp-image-452"/></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>发现只有栈不可执行。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>再到ida里面看一下</p> <!-- /wp:paragraph --> <!-- wp:image {"id":453,"sizeSlug":"large"} --> <figure class="wp-block-image size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201107163317.png" alt="" class="wp-image-453"/></figure> <!-- /wp:image --> <!-- wp:paragraph --> <p>发现有这么一个函数,可以读200个字节,但是<img class="wp-image-454" style="width: 150px;" src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201107165304.png" alt="">只有0x40,也就是说这里有溢出点,可以考虑做rop。但是我们发现,程序中既没有system又没有/bin/sh,于是我们考虑用libc中的system来调用shell。但是我们又没有服务器的libc,这个时候可以考虑使用libcsearcher来获取地址,但是我发现我的libcsearcher无法找到对应的libc,所以最后使用DynELF来暴力搜索。使用DynELF的前提条件是必须能够多次输出指定内存地址的内容,这道题是满足条件的。</p> <!-- /wp:paragraph --> <!-- wp:image {"id":458,"sizeSlug":"large"} --> <figure class="wp-block-image size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201107203819-1024x624.png" alt="" class="wp-image-458"/></figure> <!-- /wp:image --> <!-- wp:paragraph --> <p>蓝框中的leak函数用来可重复地泄露指定地址的内存,注意里面的timeout我设置成了0.01,这在本地基本没什么问题,但是在连接服务器的时候最好开大一些(比如0.1)</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>红框中即为调用函数,会内存空间进行多次泄露。然后我们就可以通过橙框中的方法来获取所需的函数。</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>下一步进行对输入的构造,我选择这么构造</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":461,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/QQ截图20201107214324-1024x126.png" alt="" class="wp-image-461"/></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>先调用</p> <!-- /wp:paragraph --> <!-- wp:code --> <pre class="wp-block-code"><code>.text:000000000040075A pop rbx .text:000000000040075B pop rbp .text:000000000040075C pop r12 .text:000000000040075E pop r13 .text:0000000000400760 pop r14 .text:0000000000400762 pop r15 .text:0000000000400764 retn .text:0000000000400764 ; } // starts at 400700 .text:0000000000400764 init endp</code></pre> <!-- /wp:code --> <!-- wp:paragraph --> <p>由read的定义 <code>ssize_t read(int fd, void * buf, size_t count);</code>我们可以构造payload</p> <!-- /wp:paragraph --> <!-- wp:list --> <ul><li>我们让rbx=0,rbp=1(为了通过下一个函数的判断)</li><li>让r12=got["read"],在下一个gadget<code>call qword ptr [r12+rbx*8]</code>的时候调用read函数</li><li>让r13=8,read的第三个参数,指定读取的字节数(/bin/sh\x00共计8个字节)</li><li>让r14=bin_sh_addr,将读入的数据放入指定的内存空间中</li><li>让r15=0,即read的第一个参数,设置read从标准输入中读入</li></ul> <!-- /wp:list --> <!-- wp:paragraph --> <p>然后设置retn到下一个gadget,并填充56个空字节(原因在开头提到了),再返回到main</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p><code>payload = 'a'<em>0x40 + 'b'</em>0x8 + p64(csu_init_1) + p64(0) + p64(1) + p64(read_got) + p64(8) + p64(bin_sh_addr) + p64(0) + p64(csu_init_2) + '\x00'*56 + p64(mainaddr)#最后的payload</code></p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>这样我们就写入了/bin/sh,然后就是简单的调用system,这里需要使用rdi的gadget,可以使用<code>ROPgadget --binary pwn-100 --only "pop|ret"</code>来查找</p> <!-- /wp:paragraph --> <!-- wp:paragraph --> <p>最后的exp</p> <!-- /wp:paragraph --> <!-- wp:image {"align":"center","id":465,"sizeSlug":"large"} --> <div class="wp-block-image"><figure class="aligncenter size-large"><img src="https://www.cjovi.icu/usr/uploads/2020/11/屏幕截图-2020-11-09-133057-1024x603.png" alt="" class="wp-image-465"/></figure></div> <!-- /wp:image --> <!-- wp:paragraph --> <p>这道题做的很卡,原因是对底层的了解还不够,所以确实还需要加强基础知识。</p> <!-- /wp:paragraph --> 最后修改:2021 年 02 月 15 日 08 : 01 PM © 允许规范转载 赞赏 如果觉得我的文章对你有用,那听听上面我喜欢的歌吧 ×Close 赞赏作者 扫一扫支付 支付宝支付 微信支付