Skip to content

Commit 598cb74

Browse files
Fds close (kevoreilly#2820)
* close_fds * close_fds * Update lib/cuckoo/core/log.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update utils/process.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * Update utils/process.py Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> * close_fds * close_fds * close_fds * close_fds * dead cod * more FDs leaks * more FDs leaks * more FDs leaks * more FDs leaks * more FDs leaks * more FDs leaks --------- Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent f45d5f1 commit 598cb74

26 files changed

Lines changed: 341 additions & 316 deletions

docs/book/src/usage/monitor.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,8 @@ One example procedure is as follow:
211211
212212
.. image:: ../_images/screenshots/debugger2disassembler.png
213213
:align: center
214+
215+
216+
The Art of Detonation Debugging: A Strategic Guide for CAPE Sandbox
217+
===================================================================
218+
Coming soon

lib/cuckoo/common/cape_utils.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,13 @@ def hash_file(method, path: str) -> str:
122122
@param path: file path
123123
@return: computed hash string
124124
"""
125-
f = open(path, "rb")
126125
h = method()
127-
while True:
128-
buf = f.read(BUFSIZE)
129-
if not buf:
130-
break
131-
h.update(buf)
126+
with open(path, "rb") as f:
127+
while True:
128+
buf = f.read(BUFSIZE)
129+
if not buf:
130+
break
131+
h.update(buf)
132132
return h.hexdigest()
133133

134134

@@ -335,7 +335,8 @@ def static_config_lookup(file_path: str, sha256: str = False) -> dict:
335335
dict or None: A dictionary containing the configuration information if found, otherwise None.
336336
"""
337337
if not sha256:
338-
sha256 = hashlib.sha256(open(file_path, "rb").read()).hexdigest()
338+
with open(file_path, "rb") as f:
339+
sha256 = hashlib.sha256(f.read()).hexdigest()
339340

340341
if repconf.mongodb.enabled:
341342
document_dict = mongo_find_one(

lib/cuckoo/common/integrations/file_extra_info.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ def static_file_info(
187187

188188
# ToDo we need type checking as it wont work for most of static jobs
189189
if HAVE_PEFILE and ("PE32" in data_dictionary["type"] or "MS-DOS executable" in data_dictionary["type"]):
190-
data_dictionary["pe"] = PortableExecutable(file_path).run(task_id)
190+
with PortableExecutable(file_path) as pe:
191+
data_dictionary["pe"] = pe.run(task_id)
191192

192193
if HAVE_FLARE_CAPA:
193194
# https://github.com/mandiant/capa/issues/2620
@@ -965,7 +966,13 @@ def RarSFX_extract(file, *, data_dictionary, options: dict, **_) -> ExtractorRet
965966

966967
@time_tracker
967968
def office_one(file, **_) -> ExtractorReturnType:
968-
if not HAVE_ONE or open(file, "rb").read(16) not in (
969+
if not HAVE_ONE:
970+
return
971+
972+
with open(file, "rb") as f:
973+
header = f.read(16)
974+
975+
if header not in (
969976
b"\xE4\x52\x5C\x7B\x8C\xD8\xA7\x4D\xAE\xB1\x53\x78\xD0\x29\x96\xD3",
970977
b"\xA1\x2F\xFF\x43\xD9\xEF\x76\x4C\x9E\xE2\x10\xEA\x57\x22\x76\x5F",
971978
):

lib/cuckoo/common/integrations/parse_pe.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,16 @@ def __init__(self, file_path: str = False, data: bytes = False):
164164
log.debug("PE type not recognised: %s", e)
165165
# self.results = results
166166

167+
def __enter__(self):
168+
return self
169+
170+
def __exit__(self, exc_type, exc_val, exc_tb):
171+
self.close()
172+
173+
def close(self):
174+
if self.pe:
175+
self.pe.close()
176+
167177
@property
168178
def file_data(self):
169179
if not self._file_data and path_exists(self.file_path):

lib/cuckoo/common/mapTTPs.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
ttps_map_file = os.path.join(CUCKOO_ROOT, "data", "mitre", "TTPs.json")
99
if os.path.exists(ttps_map_file):
1010
try:
11-
ttpDict = json.loads(open(ttps_map_file, "r").read())
11+
with open(ttps_map_file, "r") as f:
12+
ttpDict = json.load(f)
1213
except Exception as e:
1314
print("Can't load TTPs.json file", e)
1415

lib/cuckoo/common/quarantine.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,8 +721,10 @@ def unquarantine(f):
721721

722722
tmp_path = unquarantine(sys.argv[1])
723723
if tmp_path:
724-
original = hashlib.sha256(open(sys.argv[1], "rb").read()).hexdigest()
725-
unq = hashlib.sha256(open(tmp_path, "rb").read()).hexdigest()
724+
with open(sys.argv[1], "rb") as f:
725+
original = hashlib.sha256(f.read()).hexdigest()
726+
with open(tmp_path, "rb") as f:
727+
unq = hashlib.sha256(f.read()).hexdigest()
726728
if original == unq:
727729
print("Unsuported quarantine file format")
728730
else:

lib/cuckoo/common/saztopcap.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,13 +163,15 @@ def saz_to_pcap(sazpath):
163163
src = m.group("clientip")
164164
elif m and m.group("hostip"):
165165
dst = m.group("hostip")
166-
req = open(f"{fiddler_raw_dir}{fid}_c.txt").read()
166+
with open(f"{fiddler_raw_dir}{fid}_c.txt") as f:
167+
req = f.read()
167168
m = re.match(r"^(?P<verb>[^\r\n\s]+)\s+(?P<host_and_port>https?\:\/\/[^\/\r\n\:]+(\:(?P<dport>\d{1,5}))?)\/", req)
168169
if m and m.group("verb") != "CONNECT":
169170
req = req.replace(m.group("host_and_port"), "", 1)
170171
if m.group("dport") and int(m.group("dport")) <= 65535:
171172
dport = int(m.group("dport"))
172-
resp = open(f"{fiddler_raw_dir}{fid}_s.txt").read()
173+
with open(f"{fiddler_raw_dir}{fid}_s.txt") as f:
174+
resp = f.read()
173175
(seq, ack) = build_handshake(src, dst, sport, dport, pktdump, smac, dmac)
174176
(seq, ack) = make_pkts(src, dst, sport, dport, seq, ack, req, pktdump, smac, dmac)
175177
(seq, ack) = make_pkts(dst, src, dport, sport, seq, ack, resp, pktdump, dmac, smac)
@@ -192,13 +194,15 @@ def saz_to_pcap(sazpath):
192194
log.error("Failed to find fiddler ID tag")
193195
return None
194196

195-
req = open(f"{fiddler_raw_dir}{fid}_c.txt").read()
197+
with open(f"{fiddler_raw_dir}{fid}_c.txt") as f:
198+
req = f.read()
196199
m = re.match(r"^(?P<verb>[^\r\n\s]+)\s+(?P<host_and_port>https?\:\/\/[^\/\r\n\:]+(\:(?P<dport>\d{1,5}))?)\/", req)
197200
if m and m.group("verb") != "CONNECT":
198201
req = req.replace(m.group("host_and_port"), "", 1)
199202
if m.group("dport") and int(m.group("dport")) <= 65535:
200203
dport = int(m.group("dport"))
201-
resp = open(f"{fiddler_raw_dir}{fid}_s.txt").read()
204+
with open(f"{fiddler_raw_dir}{fid}_s.txt") as f:
205+
resp = f.read()
202206
(seq, ack) = build_handshake(src, dst, sport, dport, pktdump, smac, dmac)
203207
(seq, ack) = make_pkts(src, dst, sport, dport, seq, ack, req, pktdump, smac, dmac)
204208
(seq, ack) = make_pkts(dst, src, dport, sport, seq, ack, resp, pktdump, dmac, smac)

lib/cuckoo/common/utils.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -602,10 +602,11 @@ def store_temp_file(filedata: bytes, filename: str, path=None) -> bytes:
602602
with open(tmp_file_path, "wb") as tmp_file:
603603
# If filedata is file object, do chunked copy.
604604
if hasattr(filedata, "read"):
605-
chunk = filedata.read(1024)
606-
while chunk:
607-
tmp_file.write(chunk)
605+
with filedata:
608606
chunk = filedata.read(1024)
607+
while chunk:
608+
tmp_file.write(chunk)
609+
chunk = filedata.read(1024)
609610
else:
610611
tmp_file.write(filedata)
611612

lib/cuckoo/common/web_utils.py

Lines changed: 42 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,53 +1605,54 @@ def process_new_task_files(request, samples: list, details: dict, opt_filename:
16051605
"""
16061606
list_of_files = []
16071607
for sample in samples:
1608-
# Error if there was only one submitted sample, and it's empty.
1609-
# But if there are multiple and one was empty, just ignore it.
1610-
if not sample.size:
1611-
details["errors"].append({sample.name: "You uploaded an empty file."})
1612-
continue
1608+
with sample:
1609+
# Error if there was only one submitted sample, and it's empty.
1610+
# But if there are multiple and one was empty, just ignore it.
1611+
if not sample.size:
1612+
details["errors"].append({sample.name: "You uploaded an empty file."})
1613+
continue
16131614

1614-
size = sample.size
1615-
if size > web_cfg.general.max_sample_size and not (
1616-
web_cfg.general.allow_ignore_size and "ignore_size_check" in details["options"]
1617-
):
1618-
if not web_cfg.general.enable_trim:
1615+
size = sample.size
1616+
if size > web_cfg.general.max_sample_size and not (
1617+
web_cfg.general.allow_ignore_size and "ignore_size_check" in details["options"]
1618+
):
1619+
if not web_cfg.general.enable_trim:
1620+
details["errors"].append(
1621+
{
1622+
sample.name: f"Uploaded file exceeds the maximum allowed size in conf/web.conf. Sample size is: {size / float(1 << 20):,.0f} Allowed size is: {web_cfg.general.max_sample_size / float(1 << 20):,.0f}"
1623+
}
1624+
)
1625+
continue
1626+
1627+
data = sample.read()
1628+
1629+
if opt_filename:
1630+
filename = opt_filename
1631+
else:
1632+
filename = sanitize_filename(sample.name)
1633+
1634+
# Moving sample from django temporary file to CAPE temporary storage for persistence, if configured by user.
1635+
try:
1636+
path = store_temp_file(data, filename)
1637+
target_file = File(path)
1638+
sha256 = target_file.get_sha256()
1639+
except OSError:
16191640
details["errors"].append(
1620-
{
1621-
sample.name: f"Uploaded file exceeds the maximum allowed size in conf/web.conf. Sample size is: {size / float(1 << 20):,.0f} Allowed size is: {web_cfg.general.max_sample_size / float(1 << 20):,.0f}"
1622-
}
1641+
{filename: "Temp folder from cuckoo.conf, disk is out of space. Clean some space before continue."}
16231642
)
16241643
continue
16251644

1626-
data = sample.read()
1627-
1628-
if opt_filename:
1629-
filename = opt_filename
1630-
else:
1631-
filename = sanitize_filename(sample.name)
1632-
1633-
# Moving sample from django temporary file to CAPE temporary storage for persistence, if configured by user.
1634-
try:
1635-
path = store_temp_file(data, filename)
1636-
target_file = File(path)
1637-
sha256 = target_file.get_sha256()
1638-
except OSError:
1639-
details["errors"].append(
1640-
{filename: "Temp folder from cuckoo.conf, disk is out of space. Clean some space before continue."}
1641-
)
1642-
continue
1643-
1644-
if (
1645-
not request.user.is_staff
1646-
and (web_cfg.uniq_submission.enabled or unique)
1647-
and db.check_file_uniq(sha256, hours=web_cfg.uniq_submission.hours)
1648-
):
1649-
details["errors"].append(
1650-
{filename: "Duplicated file, disable unique option on submit or in conf/web.conf to force submission"}
1651-
)
1652-
continue
1645+
if (
1646+
not request.user.is_staff
1647+
and (web_cfg.uniq_submission.enabled or unique)
1648+
and db.check_file_uniq(sha256, hours=web_cfg.uniq_submission.hours)
1649+
):
1650+
details["errors"].append(
1651+
{filename: "Duplicated file, disable unique option on submit or in conf/web.conf to force submission"}
1652+
)
1653+
continue
16531654

1654-
list_of_files.append((data, path, sha256))
1655+
list_of_files.append((data, path, sha256))
16551656

16561657
return list_of_files, details
16571658

@@ -1690,78 +1691,6 @@ def process_new_dlnexec_task(url: str, route: str, options: str, custom: str):
16901691
return path, response, ""
16911692

16921693

1693-
def submit_task(
1694-
target: str,
1695-
package: str = "",
1696-
timeout: int = 0,
1697-
task_options: str = "",
1698-
priority: int = 1,
1699-
machine: str = "",
1700-
platform: str = "",
1701-
memory: bool = False,
1702-
enforce_timeout: bool = False,
1703-
clock: str = None,
1704-
tags: str = None,
1705-
parent_id: int = None,
1706-
tlp: bool = None,
1707-
distributed: bool = False,
1708-
filename: str = "",
1709-
server_url: str = "",
1710-
):
1711-
"""
1712-
ToDo add url support in future
1713-
"""
1714-
if not path_exists(target):
1715-
log.info("File doesn't exist")
1716-
return
1717-
1718-
task_id = False
1719-
if distributed:
1720-
options = {
1721-
"package": package,
1722-
"timeout": timeout,
1723-
"options": task_options,
1724-
"priority": priority,
1725-
# "machine": machine,
1726-
"platform": platform,
1727-
"memory": memory,
1728-
"enforce_timeout": enforce_timeout,
1729-
"clock": clock,
1730-
"tags": tags,
1731-
"parent_id": parent_id,
1732-
"filename": filename,
1733-
}
1734-
1735-
multipart_file = [("file", (os.path.basename(target), open(target, "rb")))]
1736-
try:
1737-
res = requests.post(server_url, files=multipart_file, data=options)
1738-
if res and res.ok:
1739-
task_id = res.json()["data"]["task_ids"][0]
1740-
except Exception as e:
1741-
log.error(e)
1742-
else:
1743-
task_id = db.add_path(
1744-
file_path=target,
1745-
package=package,
1746-
timeout=timeout,
1747-
options=task_options,
1748-
priority=priority,
1749-
machine=machine,
1750-
platform=platform,
1751-
memory=memory,
1752-
enforce_timeout=enforce_timeout,
1753-
parent_id=parent_id,
1754-
tlp=tlp,
1755-
filename=filename,
1756-
)
1757-
if not task_id:
1758-
log.warning("Error adding CAPE task to database: %s", package)
1759-
return task_id
1760-
1761-
log.info('CAPE detection on file "%s": %s - added as CAPE task with ID %s', target, package, task_id)
1762-
return task_id
1763-
1764-
17651694
# https://stackoverflow.com/questions/14989858/get-the-current-git-hash-in-a-python-script/68215738#68215738
17661695
def get_running_commit() -> str:
17671696
"""

lib/cuckoo/core/analysis_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,8 @@ def build_options(self):
257257
options["file_name"] = file_obj.get_name()
258258
options["file_type"] = file_obj.get_type()
259259
# if it's a PE file, collect export information to use in more smartly determining the right package to use
260-
options["exports"] = PortableExecutable(self.task.target).get_dll_exports()
260+
with PortableExecutable(self.task.target) as pe:
261+
options["exports"] = pe.get_dll_exports()
261262
del file_obj
262263

263264
# options from auxiliary.conf

0 commit comments

Comments
 (0)