@@ -28,6 +28,7 @@ limitations under the License.
2828
2929#include <time.h>
3030#include <yara.h>
31+ #include <yara/proc.h>
3132
3233#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN )
3334typedef int Py_ssize_t ;
@@ -2082,6 +2083,138 @@ static PyObject* yara_load(
20822083 return (PyObject * ) rules ;
20832084}
20842085
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+ }
20852218
20862219static PyObject * yara_process_memory_iterator (
20872220 PyObject * self ,
@@ -2092,6 +2225,9 @@ static PyObject* yara_process_memory_iterator(
20922225 "pid" , NULL };
20932226
20942227 unsigned int pid = UINT_MAX ;
2228+ int err ;
2229+
2230+ ProcessMemoryIterator * result ;
20952231
20962232 if (!PyArg_ParseTupleAndKeywords (
20972233 args ,
@@ -2104,7 +2240,29 @@ static PyObject* yara_process_memory_iterator(
21042240 PyExc_TypeError ,
21052241 "Error parsing arguments." );
21062242 }
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 ;
21082266}
21092267
21102268void finalize (void )
0 commit comments