明天的网址,四处都是反爬,大家这么些爬虫的日常须求和她俩斗智斗勇,就看哪个人越来越厉害。那不,就连字体也弄成了反爬,况且还不住贰个网址,常见的就有猫眼和人人车。可是,字体反爬也从未用,终归我们会破!哈哈。

图片 1

一直在用1.7.5本子的抖音,慢慢地升高并动用了一些个版本,中间有二位同学谈到抖音出席了反调试成效。作者说本身动态调度好好的,未有会面过呀!直到眼前1.9.0本子动态调治时发掘lldb连接符合规律,后边操作app就能够闪退的地方。那跟作者常常超出的反动态调节和测试效果有一些不一样哎,然后就钻研了下那几个主题材料,开采抖音使用了sysctl这种反调节和测量试验技术。

字体反爬

点击这里步入人工智能嘚吧嘚目录,观察整个稿子

抖音的字体反爬是在一个分享个人主页的链接中,其余链接一时未有测量试验,然而破了一个其余的也就破了。

网樱笋时经有相当多优质的稿子论述了那么些话题,笔者在此地也只是轻巧的罗列下那二种能力。

字体反爬也正是自定义字体反爬,通过调用自定义的书体文件来渲染网页中的文字,而网页中的文字不再是文字,而是相应的书体编码,通过复制大概轻松的征集是敬谢不敏搜聚到编码后的文字内容的。

应聘网租房网选取了字体反爬机制,利用字体对页面上的有个别数字(如房价、面积平方米数)实行了加密管理。

享用主页可以这么得到:

  • ptrace那是本人最常蒙受的反调节和测量试验工夫,它亦可对经过张开追踪与调整,通过传播的参数来支配进程被调和后的操作。
  • sysctl进程有一个情景标志是不是正在被疗养,而sysctl正是由此读取该状态值来剖断进度的调理情形。
  • syscall该方案的面目是直接调用sysctl来达到指标,但想比于上一方案,本方案越发隐讳一些。
  • arm末遭逢过,其现实原理英特网也大概含含糊糊的没说知道

未来相似不菲网址都有应用这种反爬机制,大家经过猫眼的实际情况来解释一下。

图片 2

1). 点击小胖迪个人主页

ptrace能力在漫天程序的生命周期中都会举办监察,产生的景色就是lldb刚连上程序,程序就退出了。从这么些场景来剖断,抖音应该时时选用了这种方案。

下图的是猫眼网页上的来得:

下边包车型地铁代码包括了爬取房源基本消息并保存为文件的一切代码,在mac下运作有效,windows系统供给参谋这里做些须求调度。

图片 3image

sysctl/syscall本质上是一样种方案,只是在程序调用该接口时才恐怕是做调节和测验判别,这一点跟抖音闪退的场景比较日常。

图片 4

以下是抓取房源列表页面并保存为多少个html文件,注意转换你的headers内容。

2).点击左上角

最棒的查实方法是进行,lldb连接到抖音后,在ptrace/sysctl上一直下断点,随意操作抖音app,发现其很轻易触发sysctl断点,而ptrace断点未有接触。

反省成分看一下

header_str='''accept: text/html...user-agent: Mozilla/5.0'''#字符串转dictdef str2dict(s,s1=';',s2='='): li=s.split res={} for kv in li: li2=kv.split if len>1: res[li2[0]]=li2[1] return resheaders=str2dict(header_str,'\n',': ')#每页保存为本地html页面待用import requestsimport time#地址为苏州市urlstr = 'https://su.58.com/zufang/pn2/?PGTID=0d300008-0000-5965-8ce1-1873463f7758&ClickID={}'def getPages: for i in range: print('GETING...', i) url = urlstr.format res = requests.get(url, headers=headers) with open(r'./pages/{}.html'.format as f: f.write time.sleep printgetPages

图片 5image

图片 6给ptrace/sysctl都下断点图片 7sysctl断点很轻易就接触了

图片 8

以下是用以破解字体反爬加密的代码。需求先安装模块,conda install -c mwcraig fonttools

3).再点击左上角分享以链接方式复制

选取bt命令查看该断点的调用饭店,通过Aweme关键字定位属于抖音代码的调用分支地址,使用image
list命令查看Aweme的摇动地址,通过总括器计算出hopper中的集散地址,再用hopper跳转到该偏移地址,然后就足以分析抖音调用sysctl接口的现实性用途了。

那是怎么样鬼,关键音讯全部是乱码。

from fontTools.ttLib import TTFontimport base64import reimport iodef getKey: try: return re.findall(r"base64,.format", script)[0] except: return Nonedef getFont: data = base64.b64decode fonts = TTFont(io.BytesIO return fonts.getBestCmap()def getDigit: d = re.findall', str)[0] return int - 1def getRealValue(script, string): key = getKey fontMap = getFont newMap = dict() #微软雅黑的对应的编码 font58 = { '閏': '0x958f', '鸺': '0x9e3a', '麣': '0x9ea3', '餼': '0x993c', '鑶': '0x9476', '龤': '0x9fa4', '齤': '0x9f64', '龥': '0x9fa5', '龒': '0x9f92', '驋': '0x9a4b', } for key in fontMap.keys(): value = getDigit(fontMap[key]) key = hex newMap[key] = value result = '' for char in string: temp = font58[char] value = newMap[temp] result = '%s%d' % (result, value) return int

图片 9image

图片 10行使bt命令查看断点时的货仓调用音信图片 11查阅应用的撼动地址

熟习 CSS
的同学会知道,CSS 中有三个@font-face,它同意网页开垦者为其网页钦命在线字体。原来是用来祛除对顾客Computer字体的信任性,以往有了新职能——反爬。

以下是从本地html文件读取数据并解密在那之中的数字。

做完以往您就能够收获这么一条链接:

浅析这段代码发现,原本sysctl原本不止只是用来查看进程的调弄整理意况的,其也被用在了获得机器ip地址的接口中,这也是sysctl断点很轻便触及的因由所在了。

汉字光常用字就有好几千,假若全勤放到自定义的字体中,那么字体文件就能够变得相当大,必然影响网页的加载速度,因而平常网址会选取关键内容加以有限支撑,如上海教室,知道了格外不精晓。

from bs4 import BeautifulSoupimport osfiles = os.listdir(r'./pages/')file_li = [r'./pages/' + s for s in files]items = []for fp in file_li: with open as f: html = f.read() soup = BeautifulSoup li = soup.find('ul', 'listUl').find_all[:-1] script = soup.find.find_all[-1:] for item in li: title = item.find.text.strip() money = item.find('div', 'money').b.text.strip() money = getRealValue(script[0].text, money) roomtag = item.find('p', 'room strongbox') m2 = roomtag.text.split[-1:][0].replace('\xa0', '').replace m2li = m2.split m2li2 = [] for m in m2li: m2li2.append(str(getRealValue(script[0].text, m))) size = '.'.join items.append(dict( title=title, money=money, size=size, ))print

在浏览器张开药方可知到:

图片 12getifaddrs内部贯彻中一致调用了sysctl接口

此地的乱码是由于
unicode 编码导致的,查看源文件能够看到实际的编码音讯。

最终是将items对象写入json文件并测量试验读取。

图片 13image

如上所述本次接触的断点,不是意料中的反调节和测量检验功用。保持耐心,断续C下去,每每数13遍并发这种处境后,反调节和测验的断点终于出现了。重复下面的操作进程,就能牢固到抖音的-[UIViewController
dolphin_viewDidLoad]函数中,剖判下其代码完毕,其显明无疑正是反调试效用代码。

图片 14

import jsonwith open('items.json', 'w') as f: f.write(json.dumpsprint('Write OK!')with open('items.json', 'r') as f: readItems=json.loads print(readItems[10])print('Read OK!')

链接编制程序了那般:

该函数会使用sysctl判别当前使用是还是不是被调护医疗,是的话从来退出程序,不然检查程序是还是不是加载有IPAPatch或然IPAPatchEntry模块,加载了的话同样会脱离程序。至于这么些IPAPatch是怎么用,那是其他叁个话题了,参见这里。

搜索 stonefont,找到
@font-face 的定义:

点击这里步入人工智能DBD嘚吧嘚目录,观察整个稿子

基于经验很轻巧精晓前边的参数正是客商的 id
号,前边的便是岁月戳,能够去掉的。

原则性到了反调节和测验的技术后,应对的破解花招就有无数了。举例直接行使register
write命令修改贮存器值,使代码不再进入exit分支。比方通过hook
sysctl函数,使其回到的论断值不再是调理景况等。

图片 15

种种人的智能新时期

假如你开采文章错误,请不吝留言指正;要是您感到可行,请点喜欢;假设你感到很有用,迎接转发~

END

有了那几个页面之后怎么将个人主页的名目、客官、点赞量等爬下来呢?接下去正是教你那么些,请继续往下看!

此处选拔了hook
sysctl花招的有血有肉原因是,抖音将反调节和测量检验的论断逻辑加入到了与顾客交互的逻辑中,导致sysctl很频仍的调用,使用register
write修改寄放器值的方法会修改到您猜忌人生。废话少之甚少说,上代码。

此地的 .woff
文件就是字体文件,大家将其下载下来,利用

网页将其开采,显示如下:

1. 深入分析破解反爬字体

打开开垦者调试工具,很轻便就能够观望数据所在的伏乞的链接

图片 16image图片 17image

点击大家需求获得的听众数,你能够看来:

图片 18image

能够观望,字体都改为了星型,很刚毅这些做了反爬。这我们再看看诉求重返来的
html 新闻。

图片 19image

能够阅览一群编码,而且都以数字产生了那般,全数抖音将那几个数字的数目都做了字体实行映射,用了他们本人的字体,那大家得以看看开垦者工具的
network 查看她所用的书体,平日都以 wolf 大概 ttf 结尾的,能够看看:

图片 20image

在浏览器输入上面地址就足以下载该字体了。

下载完事后大家能够用 Python 的三个工具包 fontTools 来查看字体映射。

借让你未有这几个包的话,可在命令行输入下边代码实行下载工具包:

pip install fontTools

使用 fontTools 将字体文件转为 XML 文件,上面为代码:

图片 21image

更动之后查看文件,你就足以看出里边的映射了,如下:

图片 22image

code 为我们在伸手中显示的编码,name为照射,到大家要求找的是数字,num_
代表的又是何许数字呢?,即使您再找找,你会意识这么些:

图片 23image

是否深感已经找到了,恭喜你,你被坑了,这几个而不是,若是您首先次遇上的话,估算都会被它坑三遍,那一个并非刚刚的怎样数字映射,只是有的
id 名字而已。

那会儿就要求大家另借助叁个字体软件了:FontCreator,
软件百度官方网站下载安装就能够。

用那些软件展开字体,能够见到新陆地:

图片 24image

本条正是大家须求找的投射,协作地点在 XML
文件中找的映射,一齐用,那些就破解了。

int (*orig_sysctl)(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize);int new_sysctl(int * name, u_int namelen, void * info, size_t * infosize, void * newinfo, size_t newinfosize){ int ret = orig_sysctl(name,namelen,info,infosize,newinfo,newinfosize); if(namelen == 4 && name[0] == 1 && name[1] == 14 && name[2] == 1){ struct kinfo_proc *info_ptr = (struct kinfo_proc *)info; if(info_ptr && (info_ptr->kp_proc.p_flag & P_TRACED) != 0){ NSLog(@"wxq - sysctl query trace status."); info_ptr->kp_proc.p_flag ^= P_TRACED; if((info_ptr->kp_proc.p_flag & P_TRACED) == 0){ NSLog(@"wxq trace status reomve success!"); } } } return ret;}%ctor{ %init; MSHookFunctionsysctl,new_sysctl,&orig_sysctl);}

图片 25

2.代码落到实处

用 Python
代码只需求把它们中间的映射搞领悟就行了,所以大家得以选取字典来保存这个多少。

图片 26image

以此就是在软件上见到的投射关系,再来弄弄在 XML 中的编码对应关系

图片 27image

由此一行一行地读取 XML
文件的内容,找寻映射并积存在对应的字典中,那就足以了,马到成功。

时至明天,抖音的反调节和测量检验效用就成安放了,尽情的揉虐它吗。

网页源码中展现的
 跟这里显得的是还是不是有一点点像?事实上确实如此,去掉最早的 &#x
和最后的 ; 后,剩余的4个16进制展现的数字拉长 uni
正是字体文件中的编码。所以 &#xea0b 对应的就是数字“9”。

3.别样数据的拿走

小编策动爬的是抖音的客商数据,先找了 1000个抖音大号来爬取,接着会经过她们的观者列表再来爬取别的顾客,那样就多数能够把抖音的相当多顾客获得了,具体怎么着爬取观者列表,下篇小说告诉您!期望的就点个「美观」协理下?

上面是 一千 个抖音大号的片段爬代替码:

图片 28image

上边的便是本身急需仓库储存的内容。

鉴于篇幅难题,别的的就不放出来了,想要源码的关心大伙儿号举办获取

「以下内容,自身仅供就学沟通,切勿用于商业用途」

图片 29image

明白了规律,我们来看下如何促成。

管理字体文件,咱们供给用到
FontTools 库。

先将字体文件转换为 xml
文件看下:

from fontTools.ttLib import TTFontfont = TTFont('bb70be69aaed960fa6ec3549342b87d82084.woff')font.saveXML('bb70be69aaed960fa6ec3549342b87d82084.xml')

打开 xml 文件

图片 30

开班呈现的正是一切的编码,这里的 id
仅仅是编号而已,千万别当成是对应的真实值。实际上,整个字体文件中,未有别的地点是注解EA0B 对应的真实值是啥的。

见状上边

图片 31

此地就是各种字对应的字体消息,Computer突显的时候,根本无需知道那个字是啥,只供给精通哪位像素是黑的,哪个像素是白的就足以了。

猫眼的书体文件是动态加载的,每一遍刷新都会变,纵然字体中定义的独有0-9
那9个数字,不过编码和顺序都以会变的。正是说,这么些字体文件中“EA0B”代表“9”,在其他文件中就不是了。

不过,有同样是不改变的,正是其一字的样子,也正是上海教室中定义的这几个点。

大家先随意下载三个字体文件,命名为base.woff,然后利用 fontstore
网站查看编码和实际值的附和关系,手工做成字典并保留下去。爬虫爬取的时候,下载字体文件,依据网页源码中的编码,在字体文件中找到“字形”,再循环跟
base.woff 文件中的“字形”做相比较,“字形”同样那就认证是同一个字了。在
base.woff
中找到“字形”后,获取“字形”的编码,而从前大家曾经手工业做好了编码跟值的映射表,因此就能够收获大家实际上想要的值了。

这里的前提是种种字体文件中所定义的“字形”没什么差别的(猫眼近来是那样的,以往或然还有或许会变动攻略),固然更扑朔迷离一点,每一种字体中的“字形”都加一小点的随机形变,那这么些点子就不曾用了,只好祭出剑客锏“OCOdyssey”了。

上边是完全的代码,抓取的是猫眼二〇一八年影片的率先页,由于关键是身先士卒破解字体反爬,所以未有抓取全部的多少。

代码中选拔的 base.woff
文件跟上面截图展现的不是同多少个,所以会看见编码跟值跟上面是对不上的。

import osimport timeimport reimport requestsfrom fontTools.ttLib import TTFontfrom fake_useragent import UserAgentfrom bs4 import BeautifulSouphost = 'http://maoyan.com'def main():    url = 'http://maoyan.com/films?yearId=13&offset=0'    get_moviescoreos.makedirs('font', exist_ok=True)regex_woff = re.compile("(?<=url\.*\.woff")regex_text = re.compile('(?<=).*?(?=)')regex_font = re.compile('(?<=&#x).{4}')basefont = TTFont('base.woff')fontdict = {'uniF30D': '0', 'uniE6A2': '8', 'uniEA94': '9', 'uniE9B1': '2', 'uniF620': '6',            'uniEA56': '3', 'uniEF24': '1', 'uniF53E': '4', 'uniF170': '5', 'uniEE37': '7'}def get_moviescore:    # headers = {"User-Agent": UserAgent(verify_ssl=False).random}    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '                             'Chrome/68.0.3440.106 Safari/537.36'}    html = requests.get(url, headers=headers).text    soup = BeautifulSoup(html, 'lxml')    ddlist = soup.find_all('dd')    for dd in ddlist:        a = dd.find('a')        if a is not None:            link = host + a['href']            time.sleep(5)            dhtml = requests.get(link, headers=headers).text            msg = {}            dsoup = BeautifulSoup(dhtml, 'lxml')            msg['name'] = dsoup.find(class_='name').text            ell = dsoup.find_all('li', {'class': 'ellipsis'})            msg['type'] = ell[0].text            msg['country'] = ell[1].text.split('/')[0].strip()            msg['length'] = ell[1].text.split('/')[1].strip()            msg['release-time'] = ell[2].text[:10]            # 下载字体文件            woff = regex_woff.search.group()            wofflink = 'http:' + woff            localname = 'font\\' + os.path.basename            if not os.path.exists(localname):                downloads(wofflink, localname)            font = TTFont(localname)            # 其中含有 unicode 字符,BeautifulSoup 无法正常显示,只能用原始文本通过正则获取            ms = regex_text.findall            if len < 3:                msg['score'] = '0'                msg['score-num'] = '0'                msg['box-office'] = '0'            else:                msg['score'] = get_fontnumber(font, ms[0])                msg['score-num'] = get_fontnumber(font, ms[1])                msg['box-office'] = get_fontnumber(font, ms[2]) + dsoup.find('span', class_='unit').text            printdef get_fontnumber(newfont, text):    ms = regex_font.findall    for m in ms:        text = text.replace(f'&#x{m};', get_num(newfont, f'uni{m.upper()}'))    return textdef get_num(newfont, name):    uni = newfont['glyf'][name]    for k, v in fontdict.items():        if uni == basefont['glyf'][k]:            return vdef downloads(url, localfn):    with open(localfn, 'wb+') as sw:        sw.write(requests.get.content)if __name__ == '__main__':    main()

也能够扫码关注自己的私人商品房群众号,后台回复
“猫眼”获取源码,及代码中作者动用的 basefont。


相关博文推荐:

Python爬虫实例:爬取B站《工作细胞》短评——异步加载音信的爬取

Python爬虫实例:爬取豆瓣Top250

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图