5
5
from opcache_disassembler import OPcacheDisassembler
6
6
import sys
7
7
import os
8
- import re
9
- from termcolor import colored
10
-
11
- dangerous_keywords = [
12
- "(eval)" ,
13
- "(exec)" ,
14
- "(preg_replace).*(?=SEND_VAL\(.*/e.*\);)" ,
15
- "(system)" ,
16
- "(assert)" ,
17
- "(str_rot13)" ,
18
- "(base64_encode)"
19
- ]
8
+ import subprocess
9
+ import shutil
20
10
21
- def show_help ():
22
- """ Show the help menu"""
23
-
24
- print "Usage : {0} [file|directory]" .format (sys .argv [0 ])
25
-
26
- def check_dangerous_keywords (ast , disassembler ):
27
- """ Check for dangerous keywords
28
-
29
- Arguments :
30
- ast : The AST to check against
31
- disassembler : The disassembler to use
32
- """
33
-
34
- main_op_array = disassembler .convert_branch_to_pseudo_code (ast , "main_op_array" )
35
- function_table = disassembler .convert_branch_to_pseudo_code (ast , "function_table" )
36
- class_table = disassembler .convert_branch_to_pseudo_code (ast , "class_table" )
37
-
38
- code = main_op_array + function_table + class_table
39
-
40
- for keyword in dangerous_keywords :
41
- result = re .search (keyword , code , re .DOTALL )
42
- if result :
43
- print colored ("\t Found potentially dangerous keyword '{0}'." .format (result .group (1 )), 'yellow' )
44
-
45
- if __name__ == "__main__" :
46
-
47
- if len (sys .argv ) < 2 :
48
- show_help ()
49
- exit (0 )
11
+ hunt_source_files = "hunt_source_files.tmp"
12
+ hunt_ini = "hunt.ini.tmp"
13
+ hunt_opcache = "hunt_opcache"
50
14
51
- path = sys .argv [1 ]
15
+ def list_opcache_files (path ):
16
+ """ List every opcache (.php.bin) file found in a given path """
52
17
53
- # Create a disassembler
54
- disassembler = OPcacheDisassembler ()
18
+ opcache_files = []
55
19
56
20
# Check if arg[1] is a folder or a file
57
21
if os .path .isdir (path ):
@@ -63,38 +27,107 @@ def check_dangerous_keywords(ast, disassembler):
63
27
# Only check .php.bin files
64
28
if file .endswith (".php.bin" ):
65
29
file = os .path .join (subdir , file )
30
+ opcache_files += [file ]
66
31
67
- print "Checking " + file
32
+ else :
33
+ # Only check .php.bin files
34
+ if path .endswith (".php.bin" ):
35
+ opcache_files += [path ]
68
36
69
- try :
70
- # Create an AST from the compiled file
71
- ast = disassembler .create_ast (file )
72
- except KeyboardInterrupt :
73
- exit (0 )
37
+ return opcache_files
74
38
75
- except :
76
- print "Unable to parse file " + file
77
- continue
39
+ def dump_source_file_list (list ):
78
40
79
- # Check the ast for dangerous keywords
80
- check_dangerous_keywords (ast , disassembler )
41
+ with open (hunt_source_files , 'w' ) as f :
42
+ for file in list :
43
+ f .write (file + "\n " )
81
44
82
- else :
83
- # Only check .php.bin files
84
- if path .endswith (".php.bin" ):
45
+ def setup_env (phpini_path ):
46
+
47
+ # hunt.ini
48
+ with open (phpini_path , "r" ) as f :
49
+ with open (hunt_ini , "w" ) as h :
50
+ for line in f .readlines ():
51
+
52
+ # opcache.file_cache
53
+ if "opcache.file_cache=" in line :
54
+ line = "opcache.file_cache=" + os .path .join (os .getcwd (), hunt_opcache )
55
+
56
+ # opcache.enable_cli
57
+ if "opcache.enable_cli=" in line :
58
+ line = "opcache.enable_cli=1"
59
+
60
+ # opcache.enable_cli
61
+ if "opcache.enable=" in line :
62
+ line = "opcache.enable=1"
63
+
64
+ h .write (line )
65
+
66
+ # cache folder location
67
+ os .mkdir (hunt_opcache )
68
+ os .chmod (hunt_opcache , 0o777 )
69
+
70
+ def cleanup ():
71
+
72
+ # Remove cache folder
73
+ try :
74
+ shutil .rmtree (hunt_opcache )
75
+ except :
76
+ pass
77
+
78
+ # Remove hunt.ini
79
+ try :
80
+ os .remove (hunt_ini )
81
+ except :
82
+ pass
83
+
84
+ # Remove source files list
85
+ try :
86
+ os .remove (hunt_source_files )
87
+ except :
88
+ pass
89
+
90
+ def compile_source_files ():
91
+ command = "php -c {0} compile.php {1}" .format (hunt_ini , hunt_source_files )
92
+ subprocess .call (command .split (), shell = False )
93
+
94
+ def show_help ():
95
+ """ Show the help menu"""
96
+
97
+ print "Usage : {0} [opcache_folder] [system_id] [php.ini] " .format (sys .argv [0 ])
98
+
99
+ if __name__ == "__main__" :
100
+
101
+ if len (sys .argv ) < 3 :
102
+ show_help ()
103
+ exit (0 )
104
+
105
+ # Remove temporary files and folders
106
+ cleanup ()
107
+
108
+ # Paths to analyse
109
+ opcache_folder = sys .argv [1 ]
110
+ system_id = sys .argv [2 ]
111
+ phpini_path = sys .argv [3 ]
112
+
113
+ # Setup a new phpini for compilation
114
+ setup_env (phpini_path )
115
+
116
+ # OPcache file list
117
+ opcache_files = list_opcache_files (opcache_folder )
85
118
86
- print "Checking " + path
87
- try :
88
- # Create an AST from the compiled file
89
- ast = disassembler .create_ast (path )
90
- except :
91
- print "Unable to parse file " + path
92
- exit (0 )
119
+ # Get location of source folder
120
+ prefix = os .path .commonprefix (opcache_files )
121
+ source_folder = prefix .split (system_id , 1 )[1 ]
93
122
94
- # Check AST for dangerous files
95
- check_dangerous_keywords (ast , disassembler )
96
- else :
97
- print "File is not a .php.bin file"
123
+ # Source files list
124
+ source_files = [source_folder + file .split (source_folder , 1 )[1 ][:- 4 ] for file in opcache_files ]
98
125
126
+ # Dump source files
127
+ dump_source_file_list (source_files )
99
128
129
+ # Compile source files
130
+ compile_source_files ()
100
131
132
+ # Remove temporary files and folders
133
+ cleanup ()
0 commit comments