- Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpython_convert.py
More file actions
Latest commit
192 lines (149 loc) · 7.09 KB
/
Copy pathpython_convert.py
File metadata and controls
192 lines (149 loc) · 7.09 KB
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
184
185
186
187
188
189
190
191
192
importast
importrandom
importstring
# 用于生成随机函数名称和库别名
defrandom_function_name():
return''.join(random.choices(string.ascii_lowercase, k=8))
defrandom_lib_name():
return''.join(random.choices(string.ascii_lowercase, k=6))
# 用于生成随机的 Python 内置库
builtin_libraries= [
'os', 'sys', 'math', 'time', 'random', 'collections', 'functools', 'itertools', 'pickle', 'socket'
]
# 随机生成无意义的注释,确保不会嵌套引号
defrandom_comment():
# 随机决定使用字符串字面量还是传统的 # 注释
ifrandom.choice([True, False]):
# 字符串注释形式:确保注释不包含 ''' 或 """ 或单引号
comment=''.join(random.choices(string.ascii_lowercase+string.digits, k=20))
while"'''"incommentor'"""'incommentor"'"incomment:
comment=''.join(random.choices(string.ascii_lowercase+string.digits, k=20))
returnf"''' {comment} '''"
else:
# # 注释形式:确保注释不包含单引号
comment=''.join(random.choices(string.ascii_lowercase+string.digits, k=20))
while"'"incommentor'"'incomment:
comment=''.join(random.choices(string.ascii_lowercase+string.digits, k=20))
returnf"# {comment}"
classShitCodeTransformer(ast.NodeTransformer):
def__init__(self):
self.imports= [] # 存储修改后的导入语句
self.global_vars=set() # 存储全局变量名称,避免冲突
self.remove_comments=random.choice([True, False]) # 随机决定是否去除注释
defvisit_Import(self, node):
# 只修改别名部分,而不修改库名
foraliasinnode.names:
ifalias.asname:
alias.asname=random_lib_name() # 修改别名
returnnode
defvisit_ImportFrom(self, node):
# 对from ... import ... 语句做同样处理,只修改别名部分
foraliasinnode.names:
ifalias.asname:
alias.asname=random_lib_name() # 修改别名
returnnode
defvisit_FunctionDef(self, node):
# 修改函数名称为随机的无意义名称
old_name=node.name
node.name=random_function_name()
# 在函数体中使用全局变量替代局部变量
fori, stmtinenumerate(node.body):
ifisinstance(stmt, ast.Assign):
fortargetinstmt.targets:
ifisinstance(target, ast.Name):
# 如果目标变量已经存在于全局变量中,跳过
iftarget.idnotinself.global_vars:
target.id=random.choice(['global_'+''.join(random.choices(string.ascii_lowercase, k=6)) for_inrange(3)])
self.global_vars.add(target.id)
# 修改函数调用时的名称为新的随机名称
self.replace_function_calls(old_name, node.name)
# 添加无意义的注释
node.body.insert(random.randint(0, len(node.body)), ast.Expr(value=ast.Str(s=random_comment())))
returnnode
defvisit_Call(self, node):
ifisinstance(node.func, ast.Name):
# 确保不替换 print 函数
ifnode.func.id!='print':
node.func.id=random_function_name()
returnnode
defvisit_Assign(self, node):
# 替换变量名称为全局变量,且不与现有全局变量冲突
ifisinstance(node.targets[0], ast.Name):
new_name=random.choice(['global_'+''.join(random.choices(string.ascii_lowercase, k=6)) for_inrange(3)])
whilenew_nameinself.global_vars: # 确保新变量名不冲突
new_name=random.choice(['global_'+''.join(random.choices(string.ascii_lowercase, k=6)) for_inrange(3)])
node.targets[0].id=new_name
self.global_vars.add(new_name)
# 添加无意义的注释
node.value=ast.Call(func=ast.Name(id=random_function_name(), ctx=ast.Load()), args=[], keywords=[])
node.value.lineno=node.lineno# 保证注释不影响代码格式
returnnode
defreplace_function_calls(self, old_name, new_name):
# 遍历AST树中的所有节点,替换函数调用
fornodeinast.walk(self.tree):
ifisinstance(node, ast.Call) andisinstance(node.func, ast.Name) andnode.func.id==old_name:
node.func.id=new_name
defadd_random_imports(self):
# 随机选择并导入一些内置库(未使用)
for_inrange(random.randint(1, 3)):
lib=random.choice(builtin_libraries)
alias=random_lib_name()
import_node=ast.Import(names=[ast.alias(name=lib, asname=alias)])
self.imports.append(import_node)
defvisit_Module(self, node):
# 首先添加随机导入
self.add_random_imports()
# 将所有的导入语句添加到模块体的开头
node.body=self.imports+node.body
# 处理代码体中的所有节点
forstmtinnode.body:
self.visit(stmt)
# 如果需要去除注释,删除所有注释节点
ifself.remove_comments:
node.body= [stmtforstmtinnode.bodyifnotisinstance(stmt, ast.Expr) ornotisinstance(stmt.value, ast.Str)]
else:
# 否则,替换注释为随机注释
forstmtinnode.body:
ifisinstance(stmt, ast.Expr) andisinstance(stmt.value, ast.Str):
stmt.value.s=random_comment() # 替换注释内容
# 始终插入一些无意义的注释
foriinrange(random.randint(1, 3)): # 随机添加1到3个无意义注释
node.body.insert(random.randint(0, len(node.body)), ast.Expr(value=ast.Str(s=random_comment())))
returnnode
defvisit_BinOp(self, node):
# 递归访问左右操作数
self.generic_visit(node)
# 随机生成空格
left_spaces=' '*random.randint(0, 3)
right_spaces=' '*random.randint(0, 3)
# 创建新的操作符节点
new_node=ast.BinOp(
left=ast.BinOp(left=node.left, op=node.op, right=ast.Str(s=left_spaces)),
op=node.op,
right=ast.BinOp(left=ast.Str(s=right_spaces), op=node.op, right=node.right)
)
returnnew_node
defvisit(self, node):
# 处理二元操作符
ifisinstance(node, ast.BinOp):
returnself.visit_BinOp(node)
returnself.generic_visit(node)
defgenerate_shitcode(code):
tree=ast.parse(code)
transformer=ShitCodeTransformer()
transformer.tree=tree# 给转换器提供完整的AST树,以便替换函数调用
transformed_tree=transformer.visit(tree)
ast.fix_missing_locations(transformed_tree)
returntransformed_tree
defunparse_ast(tree):
returnast.unparse(tree)
# 原始干净的 Python 代码
original_code="""
print("Hello, world!")
print(1124+1)
"""
# 生成 Shitcode
transformed_tree=generate_shitcode(original_code)
# 将 AST 转换回代码并输出
shity_code=unparse_ast(transformed_tree)
print(shity_code)