Skip to content

Commit 5e4e7f2

Browse files
committed
Merge branch 'master' of https://github.com/memflow/memflow-py
2 parents 8d6fa7c + f3e00f1 commit 5e4e7f2

File tree

3 files changed

+138
-12
lines changed

3 files changed

+138
-12
lines changed

examples/jupyter_tutorial.ipynb

Lines changed: 122 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,85 @@
7171
"metadata": {},
7272
"outputs": [],
7373
"source": [
74-
"conn = inventory.connector(\"kvm\", \":win11:\")\n"
74+
"connector = inventory.create_connector(name=\"kvm\", args=\":win11:\")"
75+
]
76+
},
77+
{
78+
"attachments": {},
79+
"cell_type": "markdown",
80+
"id": "bb246aa8",
81+
"metadata": {},
82+
"source": [
83+
"Without the `target` argument the kvm connector will just pick the first virtual machine it finds. It is also possible on some connectors to retrieve a list of all available targets (whereas the resulting `name` is the name of the target):"
84+
]
85+
},
86+
{
87+
"cell_type": "code",
88+
"execution_count": null,
89+
"id": "760b6687",
90+
"metadata": {},
91+
"outputs": [],
92+
"source": [
93+
"inventory.connector_target_list(\"qemu\")"
94+
]
95+
},
96+
{
97+
"attachments": {},
98+
"cell_type": "markdown",
99+
"id": "150e13f0",
100+
"metadata": {},
101+
"source": [
102+
"It is also possible to retrieve a Help-Text for Plugins, this is especially useful when writing CLI applications:"
103+
]
104+
},
105+
{
106+
"cell_type": "code",
107+
"execution_count": 19,
108+
"id": "7c2d9f98",
109+
"metadata": {},
110+
"outputs": [
111+
{
112+
"data": {
113+
"text/plain": [
114+
"'The `qemu` connector implements a memflow plugin interface\\nfor QEMU on top of the Process Filesystem on Linux.\\n\\nThis connector requires access to the qemu process via the linux procfs.\\nThis means any process which loads this connector requires\\nto have at least ptrace permissions set.\\n\\nThe `target` argument specifies the target qemu virtual machine.\\nThe qemu virtual machine name can be specified when starting qemu with the -name flag.\\n\\nAvailable arguments are:\\nmap_base: override of VM memory base\\nmap_size: override of VM memory size'"
115+
]
116+
},
117+
"execution_count": 19,
118+
"metadata": {},
119+
"output_type": "execute_result"
120+
}
121+
],
122+
"source": [
123+
"inventory.connector_help(\"qemu\")"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": 20,
129+
"id": "e7f09308",
130+
"metadata": {},
131+
"outputs": [
132+
{
133+
"name": "stderr",
134+
"output_type": "stream",
135+
"text": [
136+
"ERROR memflow.error 2022-12-18 21:00:09,824 error.rs:31 connector: not supported (Os-Plugin `win32` does not support help text.)\n"
137+
]
138+
},
139+
{
140+
"ename": "Exception",
141+
"evalue": "connector: not supported",
142+
"output_type": "error",
143+
"traceback": [
144+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
145+
"\u001b[0;31mException\u001b[0m Traceback (most recent call last)",
146+
"Cell \u001b[0;32mIn[20], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m inventory\u001b[39m.\u001b[39;49mos_help(\u001b[39m\"\u001b[39;49m\u001b[39mwin32\u001b[39;49m\u001b[39m\"\u001b[39;49m)\n",
147+
"\u001b[0;31mException\u001b[0m: connector: not supported"
148+
]
149+
}
150+
],
151+
"source": [
152+
"inventory.os_help(\"win32\")"
75153
]
76154
},
77155
{
@@ -80,7 +158,7 @@
80158
"id": "2c510e26",
81159
"metadata": {},
82160
"source": [
83-
"The next step is to utilize the previously created connector to initialize an OS. In the given example we try to find Windows running in memory. "
161+
"The previously created connector can now be utilized to initialize an Os. In the given example we try to find Windows running in memory in the KVM Virtual Machine."
84162
]
85163
},
86164
{
@@ -90,7 +168,7 @@
90168
"metadata": {},
91169
"outputs": [],
92170
"source": [
93-
"os = inventory.os(\"win32\", conn)"
171+
"os = inventory.create_os(name=\"win32\", input=connector)"
94172
]
95173
},
96174
{
@@ -112,8 +190,17 @@
112190
"from pprint import pprint\n",
113191
"\n",
114192
"drivers = os.module_info_list()\n",
115-
"for driver in drivers: # TODO: implement str for module list\n",
116-
" pprint(driver.name)"
193+
"pprint(drivers)"
194+
]
195+
},
196+
{
197+
"cell_type": "code",
198+
"execution_count": null,
199+
"id": "88aa478d-d24c-46d0-b419-3310663834fd",
200+
"metadata": {},
201+
"outputs": [],
202+
"source": [
203+
"kernel = os # TODO:"
117204
]
118205
},
119206
{
@@ -128,14 +215,22 @@
128215
{
129216
"cell_type": "code",
130217
"execution_count": null,
131-
"id": "88aa478d-d24c-46d0-b419-3310663834fd",
218+
"id": "0dc364fa",
132219
"metadata": {},
133220
"outputs": [],
134221
"source": [
135-
"kernel = os # TODO:\n",
136222
"process = os.process_from_name(\"explorer.exe\")"
137223
]
138224
},
225+
{
226+
"attachments": {},
227+
"cell_type": "markdown",
228+
"id": "d0ef57bf",
229+
"metadata": {},
230+
"source": [
231+
"A Process also features the same functions for retrieving modules:"
232+
]
233+
},
139234
{
140235
"cell_type": "code",
141236
"execution_count": null,
@@ -145,10 +240,17 @@
145240
"source": [
146241
"from pprint import pprint\n",
147242
"\n",
148-
"# List all modules in the process:\n",
149243
"modules = process.module_info_list()\n",
150-
"for mod in modules: # TODO: implement str for module list\n",
151-
" pprint(mod.name)"
244+
"pprint(modules)"
245+
]
246+
},
247+
{
248+
"attachments": {},
249+
"cell_type": "markdown",
250+
"id": "9194330f",
251+
"metadata": {},
252+
"source": [
253+
"It is also possible to get a module by it's name:"
152254
]
153255
},
154256
{
@@ -158,10 +260,18 @@
158260
"metadata": {},
159261
"outputs": [],
160262
"source": [
161-
"# Load module 'Explorer.EXE':\n",
162263
"module = process.module_from_name(\"Explorer.EXE\")"
163264
]
164265
},
266+
{
267+
"attachments": {},
268+
"cell_type": "markdown",
269+
"id": "b612a8d1",
270+
"metadata": {},
271+
"source": [
272+
"Finally we are able to read Data from the process/module. In the following example we read parts of the COFF Header from the PE Header of the primary module:"
273+
]
274+
},
165275
{
166276
"cell_type": "code",
167277
"execution_count": null,
@@ -187,7 +297,7 @@
187297
],
188298
"metadata": {
189299
"kernelspec": {
190-
"display_name": "Python 3",
300+
"display_name": "Python 3 (ipykernel)",
191301
"language": "python",
192302
"name": "python3"
193303
},

src/inventory.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ impl PyTargetInfo {
165165
fn __str__(&self) -> String {
166166
format!("{:?}", self.0)
167167
}
168+
169+
fn __repr__(&self) -> String {
170+
format!("{:?}", self.0)
171+
}
168172
}
169173

170174
impl From<TargetInfo> for PyTargetInfo {

src/process.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ impl PyProcess {
7878
fn __str__(&self) -> String {
7979
self.info().__str__()
8080
}
81+
82+
fn __repr__(&self) -> String {
83+
format!("{:?}", self.0.info())
84+
}
8185
}
8286

8387
#[derive(Clone)]
@@ -166,6 +170,10 @@ impl PyProcessInfo {
166170
fn __str__(&self) -> String {
167171
format!("{} ({}) @ {:#04x}", self.name(), self.pid(), self.address())
168172
}
173+
174+
fn __repr__(&self) -> String {
175+
format!("{:?}", self.0)
176+
}
169177
}
170178

171179
impl From<ProcessInfo> for PyProcessInfo {
@@ -263,6 +271,10 @@ impl PyModuleInfo {
263271
fn __str__(&self) -> String {
264272
format!("{} @ {:#04x}", self.name(), self.base())
265273
}
274+
275+
fn __repr__(&self) -> String {
276+
format!("{:?}", self.0)
277+
}
266278
}
267279

268280
impl From<ModuleInfo> for PyModuleInfo {

0 commit comments

Comments
 (0)