0x00 背景介绍

最早的爬虫,只需要能够从服务端获取到HTML代码,进行分析即可,随着Web2.0的普及,越来越多的网站都必须JavaScript解析之后才能正常显示。因此这也对爬虫提出了新的要求,当前前人们已经在爬虫中集成Webkit等框架来满足这样的需求。
本文将从实际漏洞扫描器项目中,爬虫遇到的一个问题作为切入点,简单的介绍一下爬虫过程中一些JavaScript上Mock或者Hook的技巧。

0x01 需求

这里需求主要有两个:

场景一:弹框阻碍流程

在网页中存在alert,prompt等弹出框,如果没有取消会造成webkit某些API运行异常。当前针对alert的情况,通常的框架都提供一些额外的解决方案,比如PhantomJS的onAlert()函数,Selenium的switch_to.alert().accept()。但是我们还是想和场景二一起使用Hook的方法来解决。

场景二:记录指定函数被调用情况

存储型XSS的验证过程通常分为Payload的注入和执行情况验证。作为一款优秀的扫描器(没错,说的就是华为云漏洞扫描服务),注入的Payload一定不能对目标系统有危害,因此我们通常会选用一些温柔的函数,比如console.log,而非alert或者随机不存在的函数。但是当第二次爬虫在爬取过程中,如何统计Payload触发的情况,就会成为一个难题。

0x02 JavaScript Hook

函数的Hook,其实就是在函数被调用前,对函数进行替换。

var old_alert = window.alert;
window.alert = function(message){console.log("receive: " + message);old_alert(message);
}

上面的例子是对alert函数增加一个日志打印的功能。
Hook很简单,现在唯一的问题就是要在函数执行之前就进行替换,很多函数是在网页加载中(head部分)或者网页加载完成后立即就执行了,没有空隙给我们替换函数。

0x03 注入实战

PhantomJS

它是基于QT和Webkit的无头(Headless)浏览框架,因为其不依赖Xvfb,资源占用比较小,有段时间非常受大家欢迎。其Project的Owner已经宣布不维护了,现在版本定格在2.1.1。PhantomJS良好的接口,使其能够非常方便的支持JS代码注入。
假如某个网页(http://fake.hack.com/location.html) 会获取地理位置,只有指定位置的用户才会进行下一步处理。

var webPage = require('webpage');
var page = webPage.create();
//页面初始化之前插入一段JS
page.onInitialized = function(){//模拟地理定位.page.injectJs("fake-location.js");
};

fake-location.js的代码也非常简单,内容如下:

window.navigator.geolocation = {getCurrentPosition: function (success, failure) {success({coords: {                //模拟华中科技大学产学研基地latitude: 22.52902,longitude: 113.94376}, timestamp: Date.now()});},watchPosition: function(success, failure){success({coords: {                //模拟华中科技大学产学研基地latitude: 22.52902,longitude: 113.94376}, timestamp: Date.now()});}
};

从上面的例子可以看到我们Hook了getCurrentPosition函数,它只会返回指定的经纬度。当然这一切都依赖于PhantomJS提供了injectJs这个方法以及onInitialized这个事件。

Selenium

PhantomJS始终是小众的选择,Selenium才是主流,尤其是Chrome推出了Headless模式之后,大大提高了Selenium的效率。
由于时间原因,本文只研究了ChromeWebDriver的情况。首先看一段代码:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
# 定义Chrome和ChromeWebDriver的路径
DRIVER_PATH = "/Users/huangjacky/program/tools/chromedriver"
CHROME_PATH = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
URL = "http://127.0.0.1:8080/test.html"def main():# 创建一个WebDriver实例options = Options()options.add_argument("--headless")options.binary_location = CHROME_PATHdriver = webdriver.Chrome(executable_path=DRIVER_PATH, chrome_options=options)try:driver.get(URL)driver.get_screenshot_as_file("test.png")except Exception as e:print(e)    finally:driver.close()driver.quit()

代码很简单就是打开一个网页,然后截图。这个网页的内容就是一个弹框:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>test</title>
</head>
<body>
<script>alert("hacked by Helen");</script>
</body>
</html>

而运行结果并不符合预期:

截图失败了,因为有alert弹出框。
通过查看WebDriver的API,我们发现一个函数execute_script, 因此我们修改代码如下:

driver.execute_script('window.alert=null;')
driver.get(URL)
driver.get_screenshot_as_file("test.png")

结果肯定是不成功的,不然就不会有这篇文章了。
大概是因为driver.get之后才会有window对象,之前执行的js代码都无效。

Google了大半天,无果。看来从WebDriver上面入手是不行了,我们将目光回到Chrome浏览器自身来,它提供Chrome Devtools Protocol来方便我们这些开发者进行定制,通过官方文档 的查看,我发现了Page.addScriptToEvaluateOnNewDocument这个Method是可以满足我们需求的。
Chrome Devtools Protocol的一些细节,请读者自行Google或者等我下一篇文章吧。

新的代码如下:

resource = "/session/%s/chromium/send_command_and_get_result" % driver.session_id
url = driver.command_executor._url + resource
body = json.dumps({'cmd': 'Page.addScriptToEvaluateOnNewDocument','params': {"source": "window.alert=function(msg){console.log(msg)}"}
})
response = driver.command_executor._request('POST', url, body)
if response['status']:raise Exception(response.get('value'))
print(response.get('value'))
driver.get(URL)
driver.get_screenshot_as_file("test.png")

代码运行成功,截图OK啦。
这里需要注意几点:
1. url的获取以及session,这些WebDriver里面都有方法
2. 请求的通道,这个主要复用WebDriver.command_executor

0x04 结论

遇到问题,我们首先研究框架支持的情况,当框架不支持的时候,我们可以从事情本质出发,也就是框架的底座,Chrome浏览器自身。最重要的就是多Google,技术问题千万别百度。

来源:华为云社区  作者:HuangJacky

关于爬虫本地JS Hook的研究相关推荐

  1. Python爬虫之Js逆向案例(8)-某乎x-zst-81之webpack

    声明:某乎加密逆向分析仅用于研究和学习,如有侵权,可联系删除 大家好,相信各位童鞋通过上期<Python爬虫之Js逆向案例(7)-知hu最新x-zse-96之rpc方案>这篇文章了解了什么 ...

  2. Python爬虫之Js逆向案例(2)-某乎搜索

    Python爬虫之Js逆向案例(2)-知乎搜索 声明:某乎加密逆向分析仅用于研究和学习 大家好,今天继续分享关于某乎关键词搜索接口为案例的Js逆向实战.如果你是一名新手,而且还没有来得及看上一篇< ...

  3. Python爬虫之Js逆向案例(6)-某道翻译

    Python爬虫之Js逆向案例(6)-有道翻译 声明:某道翻译加密逆向分析仅用于研究和学习,如有侵权,可联系删除 大家好,距离上次分享js逆向案例已经有一个月了,在这期间每次在快要揭秘出来时.整理文章 ...

  4. react-native 为本地js和开源库的js编写.d.ts声明文件

    读书不觉已春深 !明日清明节 在使用Typescript编写程序RN过程中遇到困扰,且不论react,不论在浏览器中,只论写react-native的APP,怎么使用 declare声明文件 和 na ...

  5. Fiddler Classic 替换本地JS并远程调试

    背景 众所周知,下载的m3u8文件无法直接播放,一般来讲m3u8文件采用AES128对称加密,并提供key.iv.ts列表.当然文件中的key与iv均为加密后的结果,需配合相应的解密文件与偏移量.本文 ...

  6. 爬虫之JS的解析确定js的位置

    爬虫之JS的解析确定js的位置 对于前面人人网的案例( http://www.renren.com),我们知道了url地址中有部分参数,但是参数是如何生成的呢? 毫无疑问,参数肯定是js生成的,那么如 ...

  7. python毕业设计开题报告-基于python爬虫的影评情感分析研究开题报告

    论文(设计)题目 基于python爬虫的影评情感分析研究开题报告 选题的背景.意义及研究现状: 研究现状: 文本情感分析又称倾向性分析.情感挖掘,主观分析或评论挖掘,是对带有情感色彩的评论文本内容进行 ...

  8. underscore.js源码研究(5)

    概述 很早就想研究underscore源码了,虽然underscore.js这个库有些过时了,但是我还是想学习一下库的架构,函数式编程以及常用方法的编写这些方面的内容,又恰好没什么其它要研究的了,所以 ...

  9. 网易云音乐python爬虫(Js破解)

    网易云音乐下载python爬虫(Js破解) 最近做了一个网易云音乐下载的python爬虫,功能就是输入歌曲的名字,程序自动下载网易音乐搜索界面的第一首歌(一般都是原唱排第一位).本文很适合小白学习,写 ...

最新文章

  1. Linux 下 svn 的使用
  2. 关于dell - R710的磁盘管理
  3. x86 CPU内存屏障保证有序性
  4. 神经网络与深度学习——TensorFlow2.0实战(笔记)(四)(python文件)
  5. 关于统计时间切片标签的一些sql
  6. 解决VC++6.0打开文件或添加文件到工程出错的问题
  7. vasp和ms_科学网—小谈CASTEP(Linux), MS-CASTEP, VASP软件区别 - 张召富的博文
  8. android学习资料整理-----高级篇
  9. ROC曲线与PR曲线对比
  10. 手机连接wifi时使用固定mac地址
  11. 小米笔试题(句子反转)
  12. 生物信息学名词解释 | K-mer (长度为k的短序列)
  13. 可能是最通俗的Lempel-Ziv-Welch (LZW)无损压缩算法详述
  14. ARCGIS 给面文件“挖洞”——Erase的用法
  15. 如何将二维码巧妙放进海报里?
  16. 原理探究:Spring @Value注解详解
  17. React Native常用第三方组件汇总【建议收藏】
  18. python爬取新冠状病毒实时数据,绘制各省份疫情地图
  19. 如何安装CocoaPods
  20. 自己作为CA签署SSL证书

热门文章

  1. php的验证码要gd库,PHP通过GD库实现验证码功能
  2. 社团管理系统用c语言1000,图书馆管理系统C语言啊1000行啊,哪位老哥有啊??...
  3. PNP问题-位姿估计方法梳理(pose estimation)
  4. [转]如何让DIV固定在页面的某个位置而不随着滚动条随意滚动
  5. 4.2号 作业讲解
  6. Codeforces 576D. Flights for Regular Customers(倍增floyd+bitset)
  7. Python与自然语言处理搭建环境
  8. ECMAScript6 ES6语法
  9. IAR下μCosIII移植心得
  10. ip找计算机名 linux,如何从IP地址中查找LAN中的计算机名称?