Skip to content

Commit

Permalink
Merge pull request #88 from Wenzel/ci_build_windows_38
Browse files Browse the repository at this point in the history
ci: build_windows based on Python 3.7
  • Loading branch information
Wenzel authored Oct 27, 2020
2 parents 65a8efc + 951beb3 commit d5a6c19
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 21 deletions.
28 changes: 16 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.6 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.6'
python-version: '3.7'

- name: Install Nox
run: python -m pip install nox==2020.8.22
Expand All @@ -35,10 +35,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.6 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.6'
python-version: '3.7'

- name: Install Nox
run: python -m pip install nox==2020.8.22
Expand All @@ -53,10 +53,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.6 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.6'
python-version: '3.7'

- name: Build 🔨
run: |
Expand All @@ -71,10 +71,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.9 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.9'
python-version: '3.7'

- name: Install PyInstaller
run: python -m pip install pyinstaller==4.0
Expand All @@ -93,17 +93,21 @@ jobs:
name: checksec.exe
path: dist/checksec.exe

# TODO: can't test rich output: UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-78: character maps to <undefined>
- name: Smoke test
run: ./dist/checksec.exe C:\Windows --json

test:
needs: build
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v1

- name: Set up Python 3.6 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.6'
python-version: '3.7'

- name: Install Nox
run: python -m pip install nox==2020.8.22
Expand Down Expand Up @@ -177,10 +181,10 @@ jobs:
steps:
- uses: actions/checkout@v1

- name: Set up Python 3.6 🐍
- name: Set up Python 3.7 🐍
uses: actions/setup-python@v1
with:
python-version: '3.6'
python-version: '3.7'

- name: Build 🔨
run: |
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ Check `--help` for more options (_JSON output_, _recursive walk_, _workers count

| | checksec.py | checksec.sh |
|----------------------------|:-----------:|:-----------:|
| Distributed workload |||
| Cross-Platform support |||
| Distributed workload |||
| Scan file |||
| Scan directory |||
| Scan directory recursively |||
| Specify libc path |||
| Scan process |||
| Scan process libs |||
| Scan kernel config |||
Expand All @@ -144,6 +146,7 @@ Check `--help` for more options (_JSON output_, _recursive walk_, _workers count

| | checksec.py | winchecksec |
|-----------------------------|:-----------:|:-----------:|
| Cross-Platform support |||
| Distributed workload |||
| Scan file |||
| Scan directory |||
Expand Down
18 changes: 16 additions & 2 deletions checksec/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import os
from concurrent.futures import ProcessPoolExecutor, as_completed
from pathlib import Path
from typing import Iterator, List, Union
from typing import Iterator, List, Optional, Union

from docopt import docopt

Expand Down Expand Up @@ -52,6 +52,18 @@ def checksec_file(filepath: Path) -> Union["ELFChecksecData", "PEChecksecData"]:
return binary.checksec_state


def worker_initializer(libc_path: Optional[Path] = None):
"""Routine to initialize some context in a worker process"""
# this function is used to set global object in the worker's process context
# multiprocessing has different behaviors on Windows and Linux
# on Windows, the global object __LIBC_OBJ in elf.py is found to be uninitialized,
# even after we explicitely initialized it in the main function.
#
# this function ensures that the object is initialized with the libc_path passed as cmdline argument
logging.debug("Worker %s: initializer", os.getpid())
get_libc(libc_path)


def main(args):
filepath_list = [Path(entry) for entry in args["<file/directory>"]]
debug = args["--debug"]
Expand Down Expand Up @@ -93,7 +105,9 @@ def main(args):
check_output.enumerating_tasks_start()
count = sum(1 for i in walk_filepath_list(filepath_list, recursive))
check_output.enumerating_tasks_stop(count)
with ProcessPoolExecutor(max_workers=workers) as pool:
with ProcessPoolExecutor(
max_workers=workers, initializer=worker_initializer, initargs=(libc_path,)
) as pool:
try:
check_output.processing_tasks_start()
future_to_checksec = {
Expand Down
8 changes: 7 additions & 1 deletion checksec/elf.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
from collections import namedtuple
from enum import Enum
from functools import lru_cache
Expand Down Expand Up @@ -48,12 +49,16 @@ def get_libc(libc_path: Optional[Path] = None) -> Optional["Libc"]:
try:
__LIBC_OBJ["libc"]
except KeyError:
logging.debug("Libc object not set")
try:
libc = Libc(libc_path)
except (LibcNotFoundError, ErrorParsingFailed):
except (LibcNotFoundError, ErrorParsingFailed) as e:
logging.debug("Failed to init Libc object: %s", e)
__LIBC_OBJ["libc"] = None
else:
logging.debug("Libc object initialized")
__LIBC_OBJ["libc"] = libc
logging.debug(__LIBC_OBJ)
return __LIBC_OBJ["libc"]


Expand All @@ -79,6 +84,7 @@ def __init__(self, libpath: Path = None):
libpath = Path(find_libc())
if not libpath:
raise LibcNotFoundError
logging.debug("Initializing Libc from %s", libpath)
self.libc = lief.parse(str(libpath))
if not self.libc:
raise ErrorParsingFailed(libpath)
Expand Down
2 changes: 2 additions & 0 deletions checksec/output.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import json
import logging
from abc import ABC, abstractmethod
from pathlib import Path
from typing import List, Union
Expand Down Expand Up @@ -137,6 +138,7 @@ def processing_tasks_start(self):
self.process_task_id = self.process_bar.add_task("Checking", total=self.total)

def add_checksec_result(self, filepath: Path, checksec: Union[ELFChecksecData, PEChecksecData]):
logging.debug("result for %s: %s", filepath, checksec)
if isinstance(checksec, ELFChecksecData):
row_res: List[str] = []
# display results
Expand Down
14 changes: 12 additions & 2 deletions checksec/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
from pathlib import Path

import lddwrap
# cannot use is_elf because of circular dependency
import lief


class LibcNotFoundError(Exception):
Expand Down Expand Up @@ -37,11 +39,19 @@ def find_libc():
# or other errors
try:
libc_path = find_libc_ldd()
except FileNotFoundError:
except (FileNotFoundError, RuntimeError):
# test hardcoded paths
logging.debug("Finding libc path: hardcoded paths")
for maybe_libc in LIBC_PATH_POSSIBILITIES:
if Path(maybe_libc).resolve().exists():
logging.debug("Testing libc at %s", maybe_libc)
maybe_libc_path = Path(maybe_libc)
if maybe_libc_path.exists():
# symlink
if maybe_libc_path.is_symlink():
dst = os.readlink(str(maybe_libc_path))
logging.debug("Resolve symlink %s -> %s", maybe_libc_path, dst)
maybe_libc_path = Path(dst)
if lief.is_elf(str(maybe_libc_path)):
libc_path = maybe_libc
break
if libc_path is None:
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

setuptools.setup(
name="checksec.py",
version="0.4.5",
version="0.5.0",
author="Mathieu Tarral",
author_email="[email protected]",
description="Checksec tool implemented in Python",
Expand All @@ -21,10 +21,10 @@
"console_scripts": ["checksec = checksec.__main__:entrypoint"],
},
classifiers=[
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Development Status :: 4 - Beta",
"Typing :: Typed",
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
],
python_requires=">=3.6",
python_requires=">=3.7",
)

0 comments on commit d5a6c19

Please sign in to comment.