@@ -28,6 +28,7 @@ limitations under the License.
28
28
29
29
#include <time.h>
30
30
#include <yara.h>
31
+ #include <yara/proc.h>
31
32
32
33
#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN )
33
34
typedef int Py_ssize_t ;
@@ -2082,6 +2083,138 @@ static PyObject* yara_load(
2082
2083
return (PyObject * ) rules ;
2083
2084
}
2084
2085
2086
+ typedef struct
2087
+ {
2088
+ PyObject_HEAD
2089
+ PyObject * externals ;
2090
+ YR_MEMORY_BLOCK_ITERATOR * block_iterator ;
2091
+ YR_MEMORY_BLOCK * block ;
2092
+ } ProcessMemoryIterator ;
2093
+
2094
+ static PyObject * ProcessMemoryIterator_getattro (
2095
+ PyObject * self ,
2096
+ PyObject * name )
2097
+ {
2098
+ return PyObject_GenericGetAttr (self , name );
2099
+ }
2100
+
2101
+ static void ProcessMemoryIterator_dealloc (PyObject * self );
2102
+
2103
+ static PyObject * ProcessMemoryIterator_next (PyObject * self );
2104
+
2105
+ static PyTypeObject ProcessMemoryIterator_Type = {
2106
+ PyVarObject_HEAD_INIT (NULL , 0 )
2107
+ "yara.ProcessMemoryIterator" , /*tp_name*/
2108
+ sizeof (ProcessMemoryIterator ), /*tp_basicsize*/
2109
+ 0 , /*tp_itemsize*/
2110
+ (destructor ) ProcessMemoryIterator_dealloc , /*tp_dealloc*/
2111
+ 0 , /*tp_print*/
2112
+ 0 , /*tp_getattr*/
2113
+ 0 , /*tp_setattr*/
2114
+ 0 , /*tp_compare*/
2115
+ 0 , /*tp_repr*/
2116
+ 0 , /*tp_as_number*/
2117
+ 0 , /*tp_as_sequence*/
2118
+ 0 , /*tp_as_mapping*/
2119
+ 0 , /*tp_hash */
2120
+ 0 , /*tp_call*/
2121
+ 0 , /*tp_str*/
2122
+ ProcessMemoryIterator_getattro , /*tp_getattro*/
2123
+ 0 , /*tp_setattro*/
2124
+ 0 , /*tp_as_buffer*/
2125
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /*tp_flags*/
2126
+ "ProcessMemoryIterator" , /* tp_doc */
2127
+ 0 , /* tp_traverse */
2128
+ 0 , /* tp_clear */
2129
+ 0 , /* tp_richcompare */
2130
+ 0 , /* tp_weaklistoffset */
2131
+ PyObject_SelfIter , /* tp_iter */
2132
+ (iternextfunc ) ProcessMemoryIterator_next , /* tp_iternext */
2133
+ 0 , /* tp_methods */ // TODO????
2134
+ 0 , /* tp_members */
2135
+ 0 , /* tp_getset */
2136
+ 0 , /* tp_base */
2137
+ 0 , /* tp_dict */
2138
+ 0 , /* tp_descr_get */
2139
+ 0 , /* tp_descr_set */
2140
+ 0 , /* tp_dictoffset */
2141
+ 0 , /* tp_init */
2142
+ 0 , /* tp_alloc */
2143
+ 0 , /* tp_new */
2144
+ };
2145
+
2146
+ static ProcessMemoryIterator * ProcessMemoryIterator_NEW (void )
2147
+ {
2148
+ ProcessMemoryIterator * it = PyObject_NEW (ProcessMemoryIterator , & ProcessMemoryIterator_Type );
2149
+ if (it == NULL )
2150
+ return NULL ;
2151
+
2152
+ it -> block_iterator = NULL ;
2153
+ it -> block = NULL ;
2154
+
2155
+ return it ;
2156
+ }
2157
+
2158
+ static void ProcessMemoryIterator_dealloc (
2159
+ PyObject * self )
2160
+ {
2161
+ ProcessMemoryIterator * it = (ProcessMemoryIterator * ) self ;
2162
+
2163
+ if (it -> block_iterator != NULL )
2164
+ {
2165
+ yr_process_close_iterator (it -> block_iterator );
2166
+ PyMem_Free (it -> block_iterator );
2167
+ it -> block_iterator = NULL ;
2168
+ }
2169
+ PyObject_Del (self );
2170
+ }
2171
+
2172
+ static PyObject * ProcessMemoryIterator_next (
2173
+ PyObject * self )
2174
+ {
2175
+ ProcessMemoryIterator * it = (ProcessMemoryIterator * ) self ;
2176
+ int err ;
2177
+
2178
+ // This indicates that the iterator has been used.
2179
+ if (it -> block_iterator == NULL )
2180
+ {
2181
+ PyErr_SetNone (PyExc_StopIteration );
2182
+ return NULL ;
2183
+ }
2184
+
2185
+ // During the first invocation, we need to use get_first_memory_block.
2186
+ if (it -> block == NULL )
2187
+ it -> block = yr_process_get_first_memory_block (it -> block_iterator );
2188
+ else
2189
+ it -> block = yr_process_get_next_memory_block (it -> block_iterator );
2190
+
2191
+ if (it -> block == NULL )
2192
+ {
2193
+ PyErr_SetNone (PyExc_StopIteration );
2194
+ return NULL ;
2195
+ }
2196
+
2197
+ uint8_t * data_ptr = yr_process_fetch_memory_block_data (it -> block );
2198
+ if (data_ptr == NULL )
2199
+ {
2200
+ // This is how we are notified that the process is done.
2201
+ it -> block = NULL ;
2202
+ err = yr_process_close_iterator (it -> block_iterator );
2203
+ PyMem_Free (it -> block_iterator );
2204
+ it -> block_iterator = NULL ;
2205
+ if (err != 0 )
2206
+ {
2207
+ return handle_error (err , NULL );
2208
+ }
2209
+
2210
+ PyErr_SetNone (PyExc_StopIteration );
2211
+ return NULL ;
2212
+ }
2213
+
2214
+ return PyBytes_FromStringAndSize (
2215
+ (const char * ) data_ptr ,
2216
+ it -> block -> size );
2217
+ }
2085
2218
2086
2219
static PyObject * yara_process_memory_iterator (
2087
2220
PyObject * self ,
@@ -2092,6 +2225,9 @@ static PyObject* yara_process_memory_iterator(
2092
2225
"pid" , NULL };
2093
2226
2094
2227
unsigned int pid = UINT_MAX ;
2228
+ int err ;
2229
+
2230
+ ProcessMemoryIterator * result ;
2095
2231
2096
2232
if (!PyArg_ParseTupleAndKeywords (
2097
2233
args ,
@@ -2104,7 +2240,29 @@ static PyObject* yara_process_memory_iterator(
2104
2240
PyExc_TypeError ,
2105
2241
"Error parsing arguments." );
2106
2242
}
2107
- return Py_BuildValue ("I" , pid );
2243
+
2244
+ result = ProcessMemoryIterator_NEW ();
2245
+
2246
+ result -> block_iterator = PyMem_Malloc (sizeof (YR_MEMORY_BLOCK_ITERATOR ));
2247
+ if (result -> block_iterator == NULL )
2248
+ return PyErr_NoMemory ();
2249
+
2250
+ // Fail early if we can't access the process with the given pid.
2251
+ err = yr_process_open_iterator (pid , result -> block_iterator );
2252
+ if (err != 0 )
2253
+ {
2254
+ PyMem_Free (result -> block_iterator );
2255
+ return handle_error (err , NULL );
2256
+ }
2257
+
2258
+ result -> block = yr_process_get_first_memory_block (result -> block_iterator );
2259
+ if (result -> block == NULL )
2260
+ {
2261
+ PyMem_Free (result -> block_iterator );
2262
+ result -> block_iterator = NULL ;
2263
+ return PyErr_NoMemory ();
2264
+ }
2265
+ return (PyObject * ) result ;
2108
2266
}
2109
2267
2110
2268
void finalize (void )
0 commit comments