iOS Objective-c 类名混淆

现在iOS应用审核越来越严格了,并且很多应用都开始上架马甲包,为防止苹果扫描到马甲包的代码跟线上版本类似而遭到4.3审核拒绝,都使用代码混淆的方法了。

下面就介绍一种类名混淆的方法:

objc_runtime_name

objc_runtime_name属性可以在编译时,将ClassProtocol指定为另一个名字,并且新名字不受命名规范制约,可以以数字开头。

如:

运行时,会把类名转为用objc_runtime_name里的名称替换掉原先的类名了。

当然,类名替换最好不要用上图这么怪的,起码要是几个单词的组合,不然苹果也可能会拒掉App,理由就是有混淆 -_-!

为实现自动把类名用object_runtime_name替换,我写了这个python 脚本,可以把类名批量替换,脚本里有个单词库,替换的类名起码不会这么的怪。

#encoding:utf-8 # 支持中文输入
import re
import os
import string
import random
s = os.sep

##获取当前工作目录
root = os.path.abspath('.')
#需要忽略的文件后缀
ignoredTrail = [".py",".c"]
#需要忽略的文件夹
ignoredDirPath   = ["lib",".git"]
#需要匹配的文件后缀
containTrail   = [".h",".m"]


#获取文件名和后缀
def getFileNameAndExt(filename):
 (filepath,tempfilename) = os.path.split(filename);
 (shotname,extension) = os.path.splitext(tempfilename);
 return shotname,extension

#是否是需要根据后缀忽略的文件
def isIgnoredByTrail(filePath):
  file = getFileNameAndExt(filePath)
  for trail in ignoredTrail:
    if file[1] == trail:
      # print "忽略文件:" + filePath
      return bool(1)
  return bool(0)

#是否是需要根据后缀匹配的文件
def isContainByTrail(filePath):
  file = getFileNameAndExt(filePath)
  for trail in containTrail:
    if file[1] == trail:
      # print "忽略文件:" + filePath
      return bool(1)
  return bool(0)
  
#是否根据文件夹路径葫芦
def isIgnoredByDirPath(dirpath):
  for path in ignoredDirPath:
    if string.find(dirpath,path) != -1:
      # print "忽略目录:" + dirpath
      return bool(1)
    else:
      # print "匹配目录:" + dirpath
      continue
  return bool(0)

#获取所有文件名
def getAllFiles(path):
 allfile=[]
 for dirpath,dirnames,filenames in os.walk(path):
  # print 'dirpath: ' + dirpath 
  if isIgnoredByDirPath(dirpath):
    continue
     
  for name in filenames:
    if isIgnoredByTrail(name):
      continue
    elif isContainByTrail(name):
      allfile.append(os.path.join(dirpath, name))
    
 return allfile


#获取所有XIB文件名
def getAllFilesXIB(path):
 allfile=[]
 for dirpath,dirnames,filenames in os.walk(path):
  # print 'dirpath: ' + dirpath 
  if isIgnoredByDirPath(dirpath):
    continue
     
  for name in filenames:
    if name.endswith('.xib'):
      allfile.append(os.path.join(dirpath, name))
    
 return allfile 

def randomString():

  return string.join(random.sample(['a','b','c','d','e','f','g','h','i','j'], 3)).replace(" ","") + (''.join(random.sample(string.ascii_letters + string.digits, 8)))



endVC = ['VC','vc','viewController','ViewController', 'VIEWCONTROLLER']

endData = ['Data', 'data', 'Model','MODEL','MO']

endView = ['VIEW', 'View', 'view']

endEngine = ['Engine','engine','Manager','MA','manager','Center','center']

endCell = ['Cell','cell','CELL']

endDelegate = ['Delegate','delegate','del','gate','Protocol','PROTOCOL','procotol']

endTool = ['Tool', 'tool', 'Util','util','helper','Helper','Browser','browser','Photo','photo','LIB','lib', 'Image','image','Button']

endArray = [endVC,endData,endView,endEngine,endCell,endDelegate,endTool]


ranDomName1 = ['ZYH','ZYH','ZYH','ZYH','ZYH','ZYH','SYSTEM','COA','TOP','LEFT','MON','CON','ZZZ','KKK','OPP','AAA','BBB','LOM','CIRCLE','PLUS','MEE','NES','MY','YMD','ALIBABA']

ranDomName2 = ['The','Fog','TR','Haode','Xitong','Lunbotu','Shitu','Picture','Photo','Xieyi','Text','Rich','Line','Sys','Turn','Rever', 'Tiaozhuan','Control','Noname','Name','Waker','Date','Weak','XML','Hob','File','Function','Fanfa','Hob','COO','Program','Net','Device','SheBei','Didian','People','Thing','Shijian','Shang','Shangbao','Other','Yanse','Color','Object','Animate','Dongzuo','Word','Act','Different','Plus','Sub', 'Age','Newer','Login','Register','Huanxiao','Length','Count','Jihuoma','Fly','Loop','Star','Get','Set','Get','Set','Get','Set','Get','Set','Shenhe','Read','Write','Laker','Shanghai','Some','Get','Set','In','This','That','String','Number','AAA','Main','Work','Enable','Disable','Check','Ment']

ranDomName3 = ['Welcome','In' ,'Order','To', 'Get','First','1','2','3','4','5','6', 'Request', 'Some', 'Basic', 'Information','One','Comes','Three' 'Pieces', 'The','Suite', 'Head','LLV','MMO','RPG','Game','Random','Test','Length','FPS','Shumu','Tree','Heap','Value','Number','Ana','Bit','Use','For','Date','Shangbao','Other','Yanse','Color','Object','Button','View','Image','View','Load','Creat']

ranDomName4 = ['Welcome','In' ,'Order','To', 'Get','First','1','2','3','4','5','6', 'Object','Figure','Cele','Solider','Holiday','Calcute','Mean','Wee','Probably','Gate','World','Car','Rp','Age','Giving','Doing','Play','Add','Vce','Change','JSON','Standar','Adavance','Country','Check','SSS','Hos','Vic','Ter','Style','UI','UI','Style','CSS','Script','Test','Text','Tion','Animate','Button','View','Image','Image','Section','View','Section','Load','Mon']


ranDomName = [ranDomName1, ranDomName2,ranDomName3, ranDomName4]

dicOriginName = {}
dic = {}
def rechangeStr(matched):
  value = matched.group(2)

  randomNum = random.randint(2,4)

  if randomNum == 2:
    if random.random() < 0.38:
      randomNum = 3

  rname = ''

  for index in range(randomNum):
    rnameArr = ranDomName[index]

    rname += rnameArr[random.randint(0,len(rnameArr)-1)]
  
  endStr = ''

  for ends in endArray:
    find = False
    for endValue in ends:
      if value.endswith(endValue):
        endStr = endValue
        find = True
        break

    if find:
      break



  rname += endStr

  if dic.has_key(rname):
    rname = randomString()

  # jsonmodel用protocol与model同名来作处理的,所以要同名替换
  if dicOriginName.has_key(value):
    rname = dicOriginName[value]

  dic[rname] = 1

  dicOriginName[value] = rname   

  return '\n__attribute__((objc_runtime_name("' + rname + '"))) ' + matched.group(1)  



#重命名
def rename(oldName,newName,filePath):
  a = open(filePath,'r') #打开所有文件
  str = a.read()

  # searchObj = re.search(r'\n[ \t]*(@interface[ \t]+([a-zA-Z0-9-_]+)[ \t]*\:[ \t]*[a-zA-Z0-9-_]+[ \t]*\n)', str, re.M|re.I)

  # if searchObj:
  #   print searchObj.group(0)
  #   print rechangeStr(searchObj)

  # searchObj2 = re.search(r'\n[ \t]*(@protocol[ \t]+([a-zA-Z0-9-_]+)[ \t]*(<[a-zA-Z0-9-_]+>)*\n)', str, re.M|re.I)

  # if searchObj2:
  #   print searchObj2.group(0)
  #   print rechangeStr(searchObj2)


  str = re.sub(r'\n[ \t]*(@interface[ \t]+([a-zA-Z0-9-_]+)[ \t]*\:[ \t]*[a-zA-Z0-9-_]+[ \t]*(<[a-zA-Z0-9-_, \t]+>)*[ \t]*\n)', rechangeStr, str)

  str = re.sub(r'\n[ \t]*(@protocol[ \t]+([a-zA-Z0-9-_]+)[ \t]*(<[a-zA-Z0-9-_]+>)*\n)', rechangeStr, str)


  b = open(filePath,'w')
  b.write(str) #再写入
  b.close() #关闭文件
  print "============" + filePath + " finished"



def rechangeXIBStr(matched):
  value = matched.group(1)

  rname = value

  if dicOriginName.has_key(value):
    rname = dicOriginName[value]

  return 'customClass="' + rname + '"'

#重命名XIB里的类
def renameXIBWithHistory(filePath):
  a = open(filePath,'r') #打开所有文件
  str = a.read()

  str = re.sub(r'customClass="([a-zA-Z0-9-_]+)"', rechangeXIBStr, str, re.M|re.I)


  b = open(filePath,'w')
  b.write(str) #再写入
  b.close() #关闭文件
  print "============" + filePath + " finished"




def canChange(filePath):
  file = getFileNameAndExt(filePath)
  if file[1] != '.h':
    return bool(0)

  return bool(1)



fileList = getAllFiles(root)

print len(fileList)

for file in fileList:
  print file
  rename('','',file)

fileListXIB = getAllFilesXIB(root)
for filexib in fileListXIB:
  renameXIBWithHistory(filexib)

这是一个Python脚本,使用前请先注意前面的 ignoredDirPath(忽略文件夹)等内容,然后跟据自已的要求来改动。

把这个脚本保存到本地,命名为iOSRename.py, 放到工程主目录下,运行python iOSRename.py即可。

注意:

运行前请先备份原工程的代码。这个脚本还有待改进,各位也可拿其修改成自已工程合适的脚本啦。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值