@@ -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,187 @@ 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
+ }
2218
+
2219
+ static PyObject * yara_process_memory_iterator (
2220
+ PyObject * self ,
2221
+ PyObject * args ,
2222
+ PyObject * keywords )
2223
+ {
2224
+ static char * kwlist [] = {
2225
+ "pid" , NULL };
2226
+
2227
+ unsigned int pid = UINT_MAX ;
2228
+ int err ;
2229
+
2230
+ ProcessMemoryIterator * result ;
2231
+
2232
+ if (!PyArg_ParseTupleAndKeywords (
2233
+ args ,
2234
+ keywords ,
2235
+ "|I" ,
2236
+ kwlist ,
2237
+ & pid ))
2238
+ {
2239
+ return PyErr_Format (
2240
+ PyExc_TypeError ,
2241
+ "Error parsing arguments." );
2242
+ }
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 ;
2266
+ }
2085
2267
2086
2268
void finalize (void )
2087
2269
{
@@ -2102,6 +2284,13 @@ static PyMethodDef yara_methods[] = {
2102
2284
METH_VARARGS | METH_KEYWORDS ,
2103
2285
"Loads a previously saved YARA rules file and returns an instance of class Rules"
2104
2286
},
2287
+ {
2288
+ "process_memory_iterator" ,
2289
+ (PyCFunction ) yara_process_memory_iterator ,
2290
+ METH_VARARGS | METH_KEYWORDS ,
2291
+ "Returns an iterator over blocks of memory of a process.\n"
2292
+ "Signature: process_memory_iterator(pid=None)"
2293
+ },
2105
2294
{ NULL , NULL }
2106
2295
};
2107
2296
0 commit comments