1- # sys
2- import json
31import re
42import shutil
5- import subprocess
63from collections import Counter
74from dataclasses import dataclass
85from pathlib import Path
6+ from tempfile import NamedTemporaryFile
97
10- # 3rd
11- from see import Hook
128from checksec .elf import ELFSecurity , PIEType , RelroType
139from checksec .errors import ErrorNotAnElf , ErrorParsingFailed
10+ from see import Hook
1411
15- # local
12+ from hooks . filesystem import Inode
1613from oswatcher .model import OSType
1714
1815
@@ -49,6 +46,7 @@ def __init__(self, parameters):
4946 self .os_info = None
5047 self .stats = Counter ()
5148 self .stats ['total' ] = 0
49+ self .local_guest_libc = NamedTemporaryFile ()
5250 self .neo4j_enabled = self .configuration .get ('neo4j' , False )
5351 if self .neo4j_enabled :
5452 self .os_node = self .configuration ['neo4j' ]['OS' ]
@@ -62,11 +60,60 @@ def __init__(self, parameters):
6260 self .keep_binaries_dir = self .configuration .get ('keep_failed_dir' , default_checksec_failed_dir )
6361
6462 self .context .subscribe ('detected_os_info' , self .get_os_info )
63+ self .context .subscribe ('filesystem_capture_begin' , self .download_libc )
6564 self .context .subscribe ('filesystem_new_file' , self .check_file )
6665
6766 def get_os_info (self , event ):
6867 self .os_info = event .os_info
6968
69+ def download_libc (self , event ):
70+ """Locate and download the libc"""
71+ gfs = event .gfs
72+
73+ if not self .os_info :
74+ raise RuntimeError ('Expected OS Info' )
75+
76+ if not self .os_info ['os_type' ] == OSType .Linux :
77+ return
78+
79+ # find ldd
80+ cmd = ['which' , 'ldd' ]
81+ try :
82+ ldd_path = gfs .command (cmd ).strip ()
83+ except RuntimeError :
84+ self .logger .warning ("Libc detection: command %s failed" , cmd )
85+ return
86+ # find ls
87+ cmd = ['which' , 'ls' ]
88+ try :
89+ ls_path = gfs .command (cmd ).strip ()
90+ except RuntimeError :
91+ self .logger .warning ("Libc detection: command %s failed" , cmd )
92+ return
93+ cmd = [ldd_path , ls_path ]
94+ try :
95+ ldd_output = gfs .command (cmd ).strip ()
96+ except RuntimeError :
97+ self .logger .warning ("Libc detection: command %s failed" , cmd )
98+ return
99+
100+ libc_inode = None
101+ for ldd_line in ldd_output .splitlines ():
102+ m = re .match (r'\t*(?P<libname>.*)\s+(=>)?\s+(?P<libpath>\S+)?\s+\((?P<addr>.*)\)$' , ldd_line )
103+ if not m :
104+ self .logger .warn ("Libc detection: line \" %s\" doesn't match LDD regex" , ldd_line )
105+ continue
106+ if m .group ('libname' ).startswith ('libc.so' ):
107+ # found guest libc
108+ libc_inode = Inode (self .logger , gfs , Path (m .group ('libpath' )))
109+ break
110+ if libc_inode is None :
111+ self .logger .warning ("Libc detection: Couldn't locate libc !" )
112+ return
113+ # copy libc
114+ shutil .copy (libc_inode .local_file , self .local_guest_libc .name )
115+ self .logger .info ("Copied guest libc %s to %s" , libc_inode .path , self .local_guest_libc .name )
116+
70117 def check_file (self , event ):
71118 # event args
72119 inode = event .inode
0 commit comments