lure-analyze 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 0xusmanismail
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,159 @@
1
+ Metadata-Version: 2.4
2
+ Name: lure-analyze
3
+ Version: 0.2.0
4
+ Summary: Local Linux binary analysis tool for security researchers and CTF players
5
+ Author-email: Usman Ismail <0xusmanismail@proton.me>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/0xusmanismail/lure
8
+ Project-URL: Repository, https://github.com/0xusmanismail/lure
9
+ Project-URL: Issues, https://github.com/0xusmanismail/lure/issues
10
+ Keywords: security,malware,sandbox,linux,binary-analysis,strace,elf,ctf,reverse-engineering
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Information Technology
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Topic :: Security
19
+ Classifier: Topic :: System :: Monitoring
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: click>=8.1
24
+ Requires-Dist: rich>=13.7
25
+ Requires-Dist: pyelftools>=0.30
26
+ Dynamic: license-file
27
+
28
+ # lure
29
+
30
+ > Local Linux binary analysis. Zero cloud. Zero root. Zero cost.
31
+
32
+ ⚠️ **Early development (v0.2.0).** Core features (`inspect`, `run`,
33
+ `diff`) work end to end on x86_64 Linux. This is a young project —
34
+ expect rough edges, limited error handling on unusual inputs, and
35
+ missing features. Bug reports, feedback, and contributions are very
36
+ welcome. Network isolation is enforced. Filesystem isolation is
37
+ not — run inside a VM when analyzing untrusted samples.
38
+
39
+ ![Lure dangerous verdict](assets/dangerous-3.png)
40
+
41
+ ## What it does
42
+
43
+ Lure runs an untrusted Linux binary in a lightweight monitoring
44
+ environment (user + network namespaces + strace) and tells you
45
+ exactly what it did — which files it touched, what network
46
+ connections it tried, what processes it spawned — then gives you a
47
+ plain verdict: **CLEAN**, **SUSPICIOUS**, or **DANGEROUS**.
48
+
49
+ Everything happens on your machine. Nothing is uploaded anywhere.
50
+
51
+ ## Why
52
+
53
+ - **Privacy** — sensitive or client samples never leave your machine
54
+ - **Zero setup** — no VM, no Docker, no Cuckoo install process
55
+ - **Readable** — structured reports instead of raw strace noise
56
+ - **Free** — MIT licensed, runs on tools already on Kali Linux
57
+
58
+ ## Isolation model
59
+
60
+ Lure uses Linux user and network namespaces to prevent the binary
61
+ from making outbound network connections. The host filesystem
62
+ remains visible to the analyzed binary. For stronger isolation
63
+ (mount namespace, seccomp, cgroups), run Lure inside a VM or
64
+ container. Lure is primarily a behavioral observation tool, not a
65
+ hardened sandbox.
66
+
67
+ ## Install
68
+
69
+ ```bash
70
+ git clone https://github.com/0xusmanismail/lure.git
71
+ cd lure
72
+ pip install -e . --break-system-packages
73
+ ```
74
+
75
+ The `--break-system-packages` flag is required on Arch Linux and on
76
+ recent Debian/Ubuntu releases, which restrict installing into the
77
+ system Python environment by default (PEP 668).
78
+
79
+ Requires `strace` and `unshare` installed.
80
+
81
+ ## Usage
82
+
83
+ ### Inspect a binary
84
+
85
+ ```bash
86
+ lure inspect /bin/ls
87
+ ```
88
+
89
+ Reads ELF headers, architecture, security mitigations, linked libraries, and file hashes — without executing a single byte of code.
90
+
91
+ ![inspect](assets/inspect-1.png)
92
+
93
+ ### Run a binary in the sandbox
94
+
95
+ ```bash
96
+ lure run ./suspicious_binary
97
+ ```
98
+
99
+ Live feed of file access, network attempts, and spawned processes, followed by a full behavioral report.
100
+
101
+ ![run live feed](assets/run-1.png)
102
+
103
+ ![run report](assets/run-2.png)
104
+
105
+ ### Catch suspicious behavior
106
+
107
+ ```bash
108
+ lure run ./demo_dangerous
109
+ ```
110
+
111
+ Sensitive file access combined with network activity trips a DANGEROUS verdict, with the exact triggers listed.
112
+
113
+ ![dangerous analysis](assets/dangerous-1.png)
114
+
115
+ ![dangerous report](assets/dangerous-2.png)
116
+
117
+ ![dangerous verdict](assets/dangerous-3.png)
118
+
119
+ ### Compare two runs with lure diff
120
+
121
+ ```bash
122
+ lure run --save /bin/ls
123
+ lure run --save /bin/echo
124
+ lure diff report1.json report2.json
125
+ ```
126
+
127
+ Shows new/removed files, new connections, verdict changes, and syscall count differences between two saved runs.
128
+
129
+ ![diff output](assets/diff-1.png)
130
+
131
+ ### Save a report
132
+
133
+ ```bash
134
+ lure run --save ./binary
135
+ ```
136
+
137
+ Saves the full report to `~/.lure/reports/` as both a plain-text `.txt` file and a structured `.json` file.
138
+
139
+ ## Status & Roadmap
140
+
141
+ **Working now:**
142
+ - ELF inspection with security mitigation detection
143
+ - Sandboxed execution via `unshare` + `strace`
144
+ - Live event feed during execution
145
+ - Full behavioral report with CLEAN/SUSPICIOUS/DANGEROUS verdict
146
+ - Verdict shows exact triggering files and IPs
147
+ - Report saving (plain text + JSON)
148
+ - Report comparison via `lure diff`
149
+ - Non-ELF file detection with clean error messages
150
+ - Works on Arch Linux, Kali, Debian, Ubuntu
151
+
152
+ **Planned:**
153
+ - Demo GIF showing live execution
154
+ - PyPI package (`pip install lure-analyze`)
155
+ - Packaged releases
156
+
157
+ ## License
158
+
159
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,132 @@
1
+ # lure
2
+
3
+ > Local Linux binary analysis. Zero cloud. Zero root. Zero cost.
4
+
5
+ ⚠️ **Early development (v0.2.0).** Core features (`inspect`, `run`,
6
+ `diff`) work end to end on x86_64 Linux. This is a young project —
7
+ expect rough edges, limited error handling on unusual inputs, and
8
+ missing features. Bug reports, feedback, and contributions are very
9
+ welcome. Network isolation is enforced. Filesystem isolation is
10
+ not — run inside a VM when analyzing untrusted samples.
11
+
12
+ ![Lure dangerous verdict](assets/dangerous-3.png)
13
+
14
+ ## What it does
15
+
16
+ Lure runs an untrusted Linux binary in a lightweight monitoring
17
+ environment (user + network namespaces + strace) and tells you
18
+ exactly what it did — which files it touched, what network
19
+ connections it tried, what processes it spawned — then gives you a
20
+ plain verdict: **CLEAN**, **SUSPICIOUS**, or **DANGEROUS**.
21
+
22
+ Everything happens on your machine. Nothing is uploaded anywhere.
23
+
24
+ ## Why
25
+
26
+ - **Privacy** — sensitive or client samples never leave your machine
27
+ - **Zero setup** — no VM, no Docker, no Cuckoo install process
28
+ - **Readable** — structured reports instead of raw strace noise
29
+ - **Free** — MIT licensed, runs on tools already on Kali Linux
30
+
31
+ ## Isolation model
32
+
33
+ Lure uses Linux user and network namespaces to prevent the binary
34
+ from making outbound network connections. The host filesystem
35
+ remains visible to the analyzed binary. For stronger isolation
36
+ (mount namespace, seccomp, cgroups), run Lure inside a VM or
37
+ container. Lure is primarily a behavioral observation tool, not a
38
+ hardened sandbox.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ git clone https://github.com/0xusmanismail/lure.git
44
+ cd lure
45
+ pip install -e . --break-system-packages
46
+ ```
47
+
48
+ The `--break-system-packages` flag is required on Arch Linux and on
49
+ recent Debian/Ubuntu releases, which restrict installing into the
50
+ system Python environment by default (PEP 668).
51
+
52
+ Requires `strace` and `unshare` installed.
53
+
54
+ ## Usage
55
+
56
+ ### Inspect a binary
57
+
58
+ ```bash
59
+ lure inspect /bin/ls
60
+ ```
61
+
62
+ Reads ELF headers, architecture, security mitigations, linked libraries, and file hashes — without executing a single byte of code.
63
+
64
+ ![inspect](assets/inspect-1.png)
65
+
66
+ ### Run a binary in the sandbox
67
+
68
+ ```bash
69
+ lure run ./suspicious_binary
70
+ ```
71
+
72
+ Live feed of file access, network attempts, and spawned processes, followed by a full behavioral report.
73
+
74
+ ![run live feed](assets/run-1.png)
75
+
76
+ ![run report](assets/run-2.png)
77
+
78
+ ### Catch suspicious behavior
79
+
80
+ ```bash
81
+ lure run ./demo_dangerous
82
+ ```
83
+
84
+ Sensitive file access combined with network activity trips a DANGEROUS verdict, with the exact triggers listed.
85
+
86
+ ![dangerous analysis](assets/dangerous-1.png)
87
+
88
+ ![dangerous report](assets/dangerous-2.png)
89
+
90
+ ![dangerous verdict](assets/dangerous-3.png)
91
+
92
+ ### Compare two runs with lure diff
93
+
94
+ ```bash
95
+ lure run --save /bin/ls
96
+ lure run --save /bin/echo
97
+ lure diff report1.json report2.json
98
+ ```
99
+
100
+ Shows new/removed files, new connections, verdict changes, and syscall count differences between two saved runs.
101
+
102
+ ![diff output](assets/diff-1.png)
103
+
104
+ ### Save a report
105
+
106
+ ```bash
107
+ lure run --save ./binary
108
+ ```
109
+
110
+ Saves the full report to `~/.lure/reports/` as both a plain-text `.txt` file and a structured `.json` file.
111
+
112
+ ## Status & Roadmap
113
+
114
+ **Working now:**
115
+ - ELF inspection with security mitigation detection
116
+ - Sandboxed execution via `unshare` + `strace`
117
+ - Live event feed during execution
118
+ - Full behavioral report with CLEAN/SUSPICIOUS/DANGEROUS verdict
119
+ - Verdict shows exact triggering files and IPs
120
+ - Report saving (plain text + JSON)
121
+ - Report comparison via `lure diff`
122
+ - Non-ELF file detection with clean error messages
123
+ - Works on Arch Linux, Kali, Debian, Ubuntu
124
+
125
+ **Planned:**
126
+ - Demo GIF showing live execution
127
+ - PyPI package (`pip install lure-analyze`)
128
+ - Packaged releases
129
+
130
+ ## License
131
+
132
+ MIT — see [LICENSE](LICENSE)
@@ -0,0 +1,12 @@
1
+ # FILE: lure/__init__.py
2
+ """
3
+ Lure — local Linux binary analysis tool.
4
+
5
+ Runs untrusted ELF binaries and shows exactly what they did.
6
+ Files accessed. Network attempts. Processes spawned.
7
+ Zero cloud upload. Zero root. Zero cost.
8
+ """
9
+
10
+ __version__ = "0.2.0"
11
+ __author__ = "Lure"
12
+ __license__ = "MIT"
@@ -0,0 +1,123 @@
1
+ # FILE: lure/diff.py
2
+ """
3
+ Report comparison engine for 'lure diff'.
4
+ Compares two JSON reports produced by 'lure run --save' and shows
5
+ what changed between the two runs.
6
+ """
7
+
8
+ import json
9
+ from pathlib import Path
10
+
11
+ from rich.console import Console
12
+ from rich.panel import Panel
13
+ from rich.text import Text
14
+ from rich import box
15
+
16
+ console = Console()
17
+
18
+
19
+ # ── Loading ───────────────────────────────────────────────────────────────────
20
+
21
+ def _load_report(path):
22
+ """Load and parse a JSON report. Returns (data, error_message)."""
23
+ p = Path(path)
24
+ if not p.exists():
25
+ return None, f'file not found: {path}'
26
+ try:
27
+ with open(p, 'r') as f:
28
+ data = json.load(f)
29
+ except (OSError, json.JSONDecodeError) as exc:
30
+ return None, f'invalid JSON report — {exc}'
31
+ return data, None
32
+
33
+
34
+ # ── Panels ────────────────────────────────────────────────────────────────────
35
+
36
+ def _list_panel(title, items, style):
37
+ if not items:
38
+ body = Text(' (none)', style='dim italic')
39
+ else:
40
+ body = Text()
41
+ for item in items:
42
+ body.append(f' • {item}\n', style=style)
43
+ return Panel(
44
+ body,
45
+ title=f'[bold]{title}[/bold] ({len(items)})',
46
+ border_style='dim white',
47
+ box=box.ROUNDED,
48
+ padding=(0, 1),
49
+ )
50
+
51
+
52
+ # ── Main entry point ──────────────────────────────────────────────────────────
53
+
54
+ def run_diff(report1_path, report2_path):
55
+ """Full report comparison — called by the 'lure diff' command."""
56
+
57
+ r1, err1 = _load_report(report1_path)
58
+ if err1:
59
+ console.print(f'[red]Error:[/red] {report1_path} — {err1}')
60
+ return
61
+
62
+ r2, err2 = _load_report(report2_path)
63
+ if err2:
64
+ console.print(f'[red]Error:[/red] {report2_path} — {err2}')
65
+ return
66
+
67
+ console.print(Panel.fit(
68
+ f'[bold magenta]DIFF[/bold magenta] '
69
+ f'[white]{Path(report1_path).name}[/white] '
70
+ f'[dim]→[/dim] [white]{Path(report2_path).name}[/white]',
71
+ border_style='magenta',
72
+ box=box.ROUNDED,
73
+ ))
74
+
75
+ # ── Files ──────────────────────────────────────────────────────────────────
76
+ files1 = set(r1.get('files_accessed', []))
77
+ files2 = set(r2.get('files_accessed', []))
78
+ new_files = sorted(files2 - files1)
79
+ removed_files = sorted(files1 - files2)
80
+
81
+ console.print(_list_panel('New Files', new_files, 'green'))
82
+ console.print(_list_panel('Removed Files', removed_files, 'red'))
83
+
84
+ # ── Network ────────────────────────────────────────────────────────────────
85
+ net1 = {(n['ip'], n['port']) for n in r1.get('network_attempts', [])}
86
+ net2 = {(n['ip'], n['port']) for n in r2.get('network_attempts', [])}
87
+ new_conns = sorted(f'{ip}:{port}' for ip, port in (net2 - net1))
88
+
89
+ console.print(_list_panel('New Connections', new_conns, 'cyan'))
90
+
91
+ # ── Verdict ────────────────────────────────────────────────────────────────
92
+ verdict1 = r1.get('verdict', '?')
93
+ verdict2 = r2.get('verdict', '?')
94
+
95
+ if verdict1 != verdict2:
96
+ verdict_text = Text.assemble(
97
+ (verdict1, 'bold'), (' → ', 'dim'), (verdict2, 'bold'),
98
+ )
99
+ else:
100
+ verdict_text = Text.assemble((verdict2, 'bold'), (' (unchanged)', 'dim'))
101
+
102
+ console.print(Panel(
103
+ verdict_text,
104
+ title='[bold]Verdict[/bold]',
105
+ border_style='dim white',
106
+ box=box.ROUNDED,
107
+ padding=(0, 1),
108
+ ))
109
+
110
+ # ── Syscalls ───────────────────────────────────────────────────────────────
111
+ sc1 = r1.get('syscall_total', 0)
112
+ sc2 = r2.get('syscall_total', 0)
113
+ delta = sc2 - sc1
114
+ sign = '+' if delta >= 0 else ''
115
+
116
+ console.print(Panel(
117
+ Text(f' {sign}{delta} syscalls ({sc1} → {sc2})'),
118
+ title='[bold]Syscall Count[/bold]',
119
+ border_style='dim white',
120
+ box=box.ROUNDED,
121
+ padding=(0, 1),
122
+ ))
123
+ console.print()