@@ -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,187 @@ 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+ }
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+ }
20852267
20862268void finalize (void )
20872269{
@@ -2102,6 +2284,13 @@ static PyMethodDef yara_methods[] = {
21022284 METH_VARARGS | METH_KEYWORDS ,
21032285 "Loads a previously saved YARA rules file and returns an instance of class Rules"
21042286 },
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+ },
21052294 { NULL , NULL }
21062295};
21072296
0 commit comments