前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux启动分析器

Linux启动分析器

原创
作者头像
Khan安全团队
发布2021-12-30 10:59:57
7190
发布2021-12-30 10:59:57
举报
文章被收录于专栏:Khan安全团队Khan安全团队

受 Sysinternals 的“Autoruns”的启发,RCLocals 分析所有 Linux 启动可能性以查找后门,还执行进程完整性验证、扫描 DLL 注入进程等等

·列出系统信任的GPG密钥

·安装包

·文件完整性

·进程完整性(进程和库加载在不属于任何已安装包的进程中)

·名称被欺骗的进程(使用 prctl() 在 /bin/ps 中更改其名称的进程)

· CRON 条目

· RC文件

· X系统启动文件

·主动系统单元

· 系统定时器单元

· tmpfiles.d

·留存用户

用法

仅针对可疑信息:

#python3 rclocals.py --triage

有关详细信息:

#python3 rclocals.py --all

rclocals.py

代码语言:javascript
复制
import colorama
from colorama import init
init()
from colorama import Fore, Back, Style
import os
import re
import subprocess
import filecmp
import re
import argparse
from os import walk



ap = argparse.ArgumentParser()

ap.add_argument('--triage', dest='triage', action='store_true')
ap.add_argument("--all", dest='allinfo', action='store_true')

args = ap.parse_args()

debian = '/etc/debian_version'
redhat = '/etc/redhat-release'

def TestIntegrity(File):
	
	if os.path.exists(redhat) : 
	
		command = 'rpm -Vf "'+File+'"' 
					
		processrpm = subprocess.Popen([command], stdout=subprocess.PIPE,shell=True)
		outputrpm = processrpm.communicate()[0]
        
		thisfile = re.search(File, outputrpm.decode('utf-8'))
					
		if thisfile :
			
			print(Back.RESET + Fore.CYAN + "\tTesting %s integrity\n" % File)			
			print(Back.RESET + Fore.RED + "Integrity compromised\n")
								
		
		if not thisfile and args.allinfo:
			
			print(Back.RESET + Fore.CYAN + "\tTesting %s integrity\n" % File)
			print(Back.RESET + Fore.GREEN + "Integrity OK\n")

	else :	
		
		commandDPKG = 'dpkg -S "'+File+'"'
						
						
		DEVNULL = open(os.devnull, 'wb')
		processdpkg = subprocess.Popen([commandDPKG], stdout=subprocess.PIPE,shell=True, stderr=DEVNULL)
		outputdpkg = processdpkg.communicate()[0]
						
		if processdpkg.returncode == 1:
							
			#dpkg is buggy to find package files 
							
			fixdpkgbug= re.sub('/usr',  '',    File)
							
			commandDPKG2 = 'dpkg -S "'+fixdpkgbug+'"'
						
							
			DEVNULL = open(os.devnull, 'wb')
			processdpkg2 = subprocess.Popen([commandDPKG2], stdout=subprocess.PIPE,shell=True, stderr=DEVNULL)
			outputdpkg2 = processdpkg2.communicate()[0]
							
			outputdpkg = outputdpkg2
							
			if processdpkg2.returncode == 1:
				
				print(Back.RESET + Fore.CYAN + "\tTesting %s integrity\n" % File)			
				print(Back.RESET + Fore.RED + "Integrity compromised\n")
				return(0)
								
				
		packagename = outputdpkg.decode().split(":")
						
		commandDEBSUM = 'dpkg --verify "'+packagename[0]+'"'
						
							
		processdebsum = subprocess.Popen([commandDEBSUM], stdout=subprocess.PIPE,shell=True)
		outputdebsum = processdebsum.communicate()[0]
		
		#print (outputdebsum)
						
		if outputdebsum :
			
			print(Back.RESET + Fore.CYAN + "\tTesting %s integrity\n" % File)
			print(Back.RESET + Fore.RED + "Integrity compromised\n")
						
		if not outputdebsum and args.allinfo:
			
			print(Back.RESET + Fore.CYAN + "\tTesting %s integrity\n" % File)
			print(Back.RESET + Fore.GREEN + "Integrity OK\n")
						
		

def OpenAndPrint(File) :
	
	filetoprint = open(File, "r")

	print(Back.RESET + Fore.CYAN + "\t%s content :\n" % File)

	for lines in filetoprint.readlines():
	
		print(Back.RESET + Fore.GREEN + "%s" % lines)
	

def WalkAndTest(Dir, Int=False, Print=False):
	
	filesdir = []
	
	for r, d, f in os.walk(Dir):
		for file in f:
			
			filesdir.append(os.path.join(r, file))
		
		for f in filesdir:
			
			filereal = os.path.realpath(f)
			
			if os.path.isfile(filereal): 
		
				if Print:
					
					OpenAndPrint(filereal)	

				if Int:
					
					TestIntegrity(filereal)


def CompareRC(File, DestFile):
	
	if os.path.isfile(File):
	
		if not filecmp.cmp(File, DestFile):
				
			print(Back.RESET + Fore.RED + "%s Integrity compromised\n" % File)
		
			if args.allinfo :
				OpenAndPrint(File)
		
	

print(Back.RESET + Fore.GREEN + "RcLocals 2.0")
print(Back.RESET + Fore.GREEN + "https://github.com/YJesus/RCLocals\n")
		

print(Back.RESET + Fore.YELLOW + "[*Listing GPG keys*]\n")

if os.path.exists(debian) :
	commandDEBKEY = 'apt-key list'
							
	outputdebkey = subprocess.check_output(commandDEBKEY, shell=True)
    
	print(Back.RESET + Fore.GREEN + "%s" % outputdebkey.decode())
	
else:
	
	commandRPMKEY = 'rpm -q --queryformat "%{SUMMARY}\n" $(rpm -q gpg-pubkey)'
							
	outputrpmkey = subprocess.check_output(commandRPMKEY, shell=True)
	
	print(Back.RESET + Fore.GREEN + "%s" % outputrpmkey.decode())
	

print(Back.RESET + Fore.YELLOW + "[*Installed Packages*]\n")

if os.path.exists(debian) :
	commandDEBPACK= "dpkg-query -W -f=\'${binary:Package} ${Version}\\t${Maintainer}\\n\'"
							
	outputdebpack= subprocess.check_output(commandDEBPACK, shell=True)
	
	print(Back.RESET + Fore.GREEN + "%s" % outputdebpack.decode())
	
else:
	
	commandRPMPACK = r'rpm -qa --qf "%{INSTALLTIME:date} %{name}-%{version}-%{release}.%{arch} %|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|\n"'

	outputrpmpack= subprocess.check_output(commandRPMPACK, shell=True)
    
	print(Back.RESET + Fore.GREEN + "%s" % outputrpmpack.decode())


print(Back.RESET + Fore.YELLOW + "[*Checking file integrity*]\n")


if os.path.exists(debian) :
	commandDEBFILE = r'debsums -c'
							
	processdebfile = subprocess.Popen([commandDEBFILE], stdout=subprocess.PIPE,shell=True)
	outputdebfile = processdebfile.communicate()[0]
	
	print(Back.RESET + Fore.RED + "%s" % outputdebfile.decode())
	
else:
	
	commandRPMFILE = r'rpm -Va'
									
	processrpmfile = subprocess.Popen([commandRPMFILE], stdout=subprocess.PIPE,shell=True)
	outputrpmfile = processrpmfile.communicate()[0]
	
	print(Back.RESET + Fore.RED + "%s" % outputrpmfile.decode())

print(Back.RESET + Fore.YELLOW + "[*Checking process integrity*]\n")

for processPid in os.listdir("/proc"):
	
	maps = '/proc/'+processPid+'/maps'
	
	if os.path.exists(maps) : 
		
		file = open(maps, "r")

		for libs in file.readlines():
			
			match = re.search(r'.*\d\s(.{4})\s\d.*\s*\s(\/.*)' , libs)
            
			if match:
                
				matchexe = re.search(r'.*x.*', match.group(1))
				matchrwx = re.search(r'rwx.*', match.group(1))
                
			if  match and matchrwx:
                
				print(Back.RESET + Fore.RED + "Suspicious memory region in process %s in PID %s" % (match.group(2), processPid))
								
				exefile = '/proc/'+processPid+'/exe'
				exepath = os.path.realpath(exefile)
				print(Fore.RED + "Exefile %s\n" % exepath)
				continue 
            
			if  match and matchexe:

				isdeleted = re.search(r'\(deleted\)' , match.group(2))
				
				if not isdeleted:
                    
					if os.path.exists(redhat) : 
						command = 'rpm -Vf "'+match.group(2)+'"' 
					
						processrpm = subprocess.Popen([command], stdout=subprocess.PIPE,shell=True)
						outputrpm = processrpm.communicate()[0]
					
						if outputrpm :

							thisfile = re.search(match.group(2), outputrpm.decode('utf-8'))
						
							if thisfile:
								print(Back.RESET + Fore.RED + "Suspicious lib or process %s in PID %s" % (match.group(2), processPid))
								
								exefile = '/proc/'+processPid+'/exe'
								exepath = os.path.realpath(exefile)
								print(Fore.RED + "Exefile %s\n" % exepath)
								
					if os.path.exists(debian) :
						
						commandDPKG = 'dpkg -S "'+match.group(2)+'"'
						
						
						DEVNULL = open(os.devnull, 'wb')
						processdpkg = subprocess.Popen([commandDPKG], stdout=subprocess.PIPE,shell=True, stderr=DEVNULL)
						outputdpkg = processdpkg.communicate()[0]
						
						
						if processdpkg.returncode == 1:
							
							#dpkg is buggy to find package files 
							
							fixdpkgbug= re.sub('/usr',  '',    match.group(2))
							
							commandDPKG2 = 'dpkg -S "'+fixdpkgbug+'"'
						
							
							DEVNULL = open(os.devnull, 'wb')
							processdpkg2 = subprocess.Popen([commandDPKG2], stdout=subprocess.PIPE,shell=True, stderr=DEVNULL)
							outputdpkg2 = processdpkg2.communicate()[0]
							
							outputdpkg = outputdpkg2
							
							if processdpkg2.returncode == 1:
							
								print(Back.RESET + Fore.RED + "Suspicious lib or process %s in PID %s" % (match.group(2), processPid))
								
								exefile = '/proc/'+processPid+'/exe'
								exepath = os.path.realpath(exefile)
								print(Fore.RED + "Exefile %s\n" % exepath)
						
							else:
								
								packagename = outputdpkg.decode().split(":")
						
								commandDEBSUM = 'dpkg --verify "'+packagename[0]+'"'
						
							
								processdebsum = subprocess.Popen([commandDEBSUM], stdout=subprocess.PIPE,shell=True)
								outputdebsum = processdebsum.communicate()[0]
						
								if outputdebsum :
						
									print(Back.RESET + Fore.RED + "Suspicious lib or process %s in PID %s" % (match.group(2), processPid))
										
									exefile = '/proc/'+processPid+'/exe'
									exepath = os.path.realpath(exefile)
									print(Fore.RED +  "Exefile %s\n" % exepath)
							
							
						elif processdpkg.returncode == 0: 	
								
							packagename = outputdpkg.decode().split(":")
						
							commandDEBSUM = 'dpkg --verify "'+packagename[0]+'"'
						
							
							processdebsum = subprocess.Popen([commandDEBSUM], stdout=subprocess.PIPE,shell=True)
							outputdebsum = processdebsum.communicate()[0]
						
							if outputdebsum :
						
								print(Back.RESET + Fore.RED + "Suspicious lib or process %s in PID %s" % (match.group(2), processPid))
										
								exefile = '/proc/'+processPid+'/exe'
								exepath = os.path.realpath(exefile)
								print(Fore.RED +  "Exefile %s\n" % exepath)
								

print(Back.RESET + Fore.YELLOW + "[*Searching process with name spoofed*]\n")
				
for processPid in os.listdir("/proc"):
	
	comm = '/proc/'+processPid+'/comm'
	
	if os.path.exists(comm) : 
		
		file = open(comm, "r")
		
		commbin = file.read().replace('\n', '')
		
		exefile = '/proc/'+processPid+'/exe'
		try:
			exepath = os.path.realpath(exefile)
		
		except:
			pass
			
		else:
			
			exetest = os.path.basename(exepath)
			
			if commbin !=  exetest[0:15] :
				
				print(Back.RESET + Fore.RED + "Process name [%s]  it's not equal than exe name [%s] PID: %s \n" % (commbin, exepath, processPid) )

										
print(Back.RESET + Fore.YELLOW + "[*Searching CRON entries*]\n")

anacron = "/etc/anacrontab"
crontab = "/etc/crontab"
crondir = "/etc/cron.d/"
cronspool = "/var/spool/cron"
cronspooldebian = "/var/spool/cron/crontabs/"

if os.path.exists(anacron) : 

	if args.allinfo :
		OpenAndPrint(anacron)
	
	TestIntegrity(anacron)
	
if args.allinfo :
	OpenAndPrint(crontab)
	

TestIntegrity(crontab)


if os.path.exists(crondir) :  
	
	WalkAndTest(crondir, True, args.allinfo)

if os.path.exists(cronspool) :  
	
	WalkAndTest(cronspool, False, True)
			
if os.path.exists(cronspooldebian) :  
	
	WalkAndTest(cronspooldebian, False, True)
	
print(Back.RESET + Fore.YELLOW + "[*Searching RC files*]\n")

profile = "/etc/profile"
bashrc = "/etc/bashrc"
bashrcdebian = "/etc/bash.bashrc"
profiledir = "/etc/profile.d/"
skeldir ="/etc/skel/"
homedir = "/home/"

if args.allinfo :
	OpenAndPrint(profile)
	
TestIntegrity(profile)

if os.path.exists(redhat) :

	if args.allinfo :
		OpenAndPrint(bashrc)

	TestIntegrity(bashrc)

else:
	
	if args.allinfo :
		OpenAndPrint(bashrcdebian)

	TestIntegrity(bashrcdebian)

WalkAndTest(profiledir, True, args.allinfo)

WalkAndTest(skeldir, True, args.allinfo)			

print(Back.RESET + Fore.YELLOW + "\tTesting if /home's rc files are equal than skel dir\n")

listOfFile = os.listdir("/home/")
allFiles = list()

for entry in listOfFile:
	fullPath = os.path.join("/home/", entry)
	if os.path.isdir(fullPath):
		
		rcfile = fullPath+"/.bashrc"
		rcprofile = fullPath + "/.bash_profile"
		rclogout = fullPath + "/.bash_logout"
		
		if os.path.isfile(rcfile):
			
			CompareRC(rcfile, '/etc/skel/.bashrc')
		
		if os.path.isfile(rcprofile):
			
			CompareRC(rcprofile, '/etc/skel/.bash_profile')
				
		if os.path.isfile(rclogout):
			
			CompareRC(rclogout, '/etc/skel/.bash_logout')

CompareRC('/root/.bashrc', '/etc/skel/.bashrc')
CompareRC('/root/.bash_profile', '/etc/skel/.bash_profile')
CompareRC('/root/.bash_logout', '/etc/skel/.bash_logout')


print(Back.RESET + Fore.YELLOW + "[*Searching X system startup files*]\n")		

listOfFile = os.listdir("/home/")
allFiles = list()

for entry in listOfFile:
	fullPath = os.path.join("/home/", entry)
	if os.path.isdir(fullPath):
		
		xstartup = fullPath+"/.config/autostart/"
		xinitrcs = fullPath+"/.xinitrc"
		
		if os.path.isfile(xinitrcs):
			
			OpenAndPrint(xinitrcs)
		
		if os.path.isdir(xstartup):
			
			WalkAndTest(xstartup, False, True)
			
if os.path.isfile("/root/.xinitrc/"):
			
	OpenAndPrint("/root/.xinitrc/")
		
if os.path.isdir("/root/.config/autostart/"):
			
	WalkAndTest("/root/.config/autostart/", False, True)
			
			
print(Back.RESET + Fore.YELLOW + "[*Listing active Systemd Units*]\n")			

systemdmulti = "/lib/systemd/system/multi-user.target.wants/"
systemdmulti2 = "/etc/systemd/system/multi-user.target.wants/"

systemdgrap = "/lib/systemd/system/graphical.target.wants/"
systemdgrap2 = "/etc/systemd/system/graphical.target.wants/"

systemdlogoffRH = "/usr/lib/systemd/system-shutdown/"
systemdlogoffDeb = "/lib/systemd/system-shutdown/"

WalkAndTest(systemdmulti, True, args.allinfo)
WalkAndTest(systemdmulti2, True, args.allinfo)

WalkAndTest(systemdgrap, True, args.allinfo)
WalkAndTest(systemdgrap2, True, args.allinfo)

if os.path.exists(debian) :
	
	WalkAndTest(systemdlogoffDeb, True, args.allinfo)
	
else :
	
	WalkAndTest(systemdlogoffRH, True, args.allinfo)			
			

listOfFile = os.listdir("/home/")
allFiles = list()

for entry in listOfFile:
	fullPath = os.path.join("/home/", entry)
	if os.path.isdir(fullPath):
		
		usersystemd = fullPath+"/.config/systemd/user/"
		
		if os.path.isdir(usersystemd):
			
			WalkAndTest(usersystemd, False, True)

if os.path.isdir("/root/.config/systemd/user/"):	
				 
	WalkAndTest("/root/.config/systemd/user/", False, True)
			
print(Back.RESET + Fore.YELLOW + "[*Listing Systemd Timer Units*]\n")		

timerdir = '/usr/lib/systemd/system/'
timerdir2 = '/lib/systemd/system/' 

if os.path.isdir(timerdir):
	
	for file in os.listdir(timerdir):
    	
		if file.endswith(".timer"):
        
			servicech = re.sub('timer', 'service', file)
		
			servicech = timerdir+servicech
		
			if args.allinfo :
				OpenAndPrint(servicech)
			
			TestIntegrity(servicech)			

if os.path.isdir(timerdir2):

	for file in os.listdir(timerdir2):
    	
		if file.endswith(".timer"):
        
			servicech = re.sub('timer', 'service', file)
		
			servicech = timerdir2+servicech
		
			if args.allinfo :
				OpenAndPrint(servicech)
			
			TestIntegrity(servicech)			


print(Back.RESET + Fore.YELLOW + "[*Searching tmpfiles.d*]\n")

etctmpfile = "/etc/tmpfiles.d/"
runtmpfile = "/run/tmpfiles.d/"
usertmpfile = "/usr/lib/tmpfiles.d/"

WalkAndTest(etctmpfile, True, args.allinfo)
WalkAndTest(runtmpfile, True, args.allinfo)
WalkAndTest(usertmpfile, True, args.allinfo)

listOfFile = os.listdir("/home/")
allFiles = list()

for entry in listOfFile:
	fullPath = os.path.join("/home/", entry)
	if os.path.isdir(fullPath):
		
		usertmpfiles = fullPath+"/.config/user-tmpfiles.d/"
		usertmpfiles2 = fullPath+"/.local/share/user-tmpfiles.d/"
		
		if os.path.isdir(usertmpfiles):
			
			WalkAndTest(usertmpfiles, False, True)
			
		if os.path.isdir(usertmpfiles2):
			
			WalkAndTest(usertmpfiles2, False, True)
			
	
print(Back.RESET + Fore.YELLOW + "[*Searching linger users*]\n")

lingerpath= "/var/lib/systemd/linger"

if os.path.exists(lingerpath):
    
	lingerusers = next(walk(lingerpath), (None, None, []))[2]
	print(Back.RESET + Fore.RED + "Linger users: %s\n" % lingerusers)    

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 用法
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档