Levon 发表于 2018-1-1 19:07:03

基于C#实现的简易式广告拦截器之实现思路

本帖最后由 Levon 于 2018-1-1 19:08 编辑

大家好,好久没上来啦,最近写了个小程序-广告过滤器,分享给大家,程序已经在我个人博客里发布得也有一段时间啦,今天特将其分享到这里,希望能分享给更多的朋友,如果您正愁着如何实现广告过滤或者是请求转发等问题,那么相信我,它会是你想要的。。。。。
so....开始吧,想必大家平日里也没少看“x酷”、“x奇艺”、“x讯云视频”、等等各大国内视频站的广告吧?它们从以前的几秒钟慢慢的演变成了现在的几十秒,X讯云视频更夸张,今天测试的时候,我看到超过100秒的广告时间,真是可恶之极啊,当然,现在的浏览器基本自带去除广告的功能,但我为什么要再造轮子呢?其原因很简单,市面上提供的广告过滤器不是不好,有的不够灵活,就像某广告管家就挺不错的,但我自造轮子的原因,一方面为了学习并掌握传包的原理、一方面可以在这过程中更纯熟的掌握抓包技术,先声明下,我没有怎么系统的学习过C#,因工作需要,近期大量的使用它,对其还是稍有些理解,促使我开发这个广告过滤器的原因是因最近写的一个浏览器请求劫持项目接触到的“中间代理”件,而我也深知市面上的广告过滤器事实上也都是基于它实现的,于是便有了开发这个过滤器的念头,好了,废话就说到这吧,咱先来看看这个过滤器的效果,后面我将分享我的代码,以便于大家可以学习!
https://www.itmaohome.com/wp-content/uploads/2017/12/TIM%E5%9B%BE%E7%89%8720171216221406.png
从上图可以看出,本程序是基于Console的,自从学了python后我不怎么在乎UI了,而且用控制台写程序多方便,只是对于小白用户而言没那么方便操作罢了,程序的实现思路很简单,就是像上面说的借助的“中间件”来实现的,那么说了那么久,什么叫做中间件呢?这个所谓的中间件就是我们平时所说的代理服务器,意思就是说,当您的客户端接入该代理服务器后,所有的请求都将通过它来传达,那么步骤就是:你从浏览器点击发送请求 —> 中间件将请求拿下(这里可以随意篡改里面的内容)—>待中间件处理完毕后,将请求传送到远程服务器 —> 远程服务器接收到请求后根据请求返回相应的response数据 —> 中间件收到由远程服务器返回的数据(这里可以随意篡改里面的内容)—>中间件将修改后的内容传回给客户端。整个流程大概就是这个样子,那么这个中间件,我想写过爬虫的朋友都应该知道“Fiddler”这个抓包神器吧?如果你不知道,那么说明你才刚接触爬虫或没掌握,这个神器是基于C#开发的,适用于Windows,是一个非常方便的调试神器,最主要的是它提供了API接口,那么这就表示,通过它的API,我们可以完全在程序中嵌入一个Fiddler的,那么本程序就是以FiddlerCore作为核心开发的,有兴趣的朋友可以前往:https://www.telerik.com/fiddler/fiddlercore了解,请注意,我在开发期间留意到,该组件的资料较少,如果有不懂的地方,欢迎大家交流。
https://www.itmaohome.com/wp-content/uploads/2017/12/TIM%E6%88%AA%E5%9B%BE20171216223247.png
上图为Fiddler for Windows 客户端,如果您是爬虫师或刚接触爬虫,我建议您使用该神器,它可以很方便的抓取到所有发送给网站端的请求,同时,作为网址的调试,它也是非常的方便,比如,在浏览器像服务器发送请求之前,我们可以修改其传送的header或cookie、或者body等一切数据,传送完毕后,我们也可以按需求选择返回的结果,这个案例通常适用于避免小朋友观看不和谐的视频、或不良的信息,Fiddler可以轻松将其替换成别的网页。
https://www.itmaohome.com/wp-content/uploads/2017/12/TIM%E6%88%AA%E5%9B%BE20171216224041.png
上图为部分代码截图,在使用FiddlerCore之前,我们需要安装相应的NuGet包,该包可以从VS的官方安装包管理中心获得,使用方式也很简单,我们需要记住以下几个常用的接口函数即可。

FiddlerCore组件函数:

Fiddler.FiddlerApplication.Startup(8887,FiddlerCoreStartupFlags.Default);

FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oSession);

FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oSession);

oSession.GetRequestBodyAsString();

oSession.GetResponseBodyAsString();

oSession.RequestHeaders[“”] = “”;

oSession.RequestHeaders.Remove(“Cookie”);

oSession.utilSetResponseBody();

FiddlerApplication.Shutdown();

Fiddler.CertMaker.rootCertExists();

Fiddler.CertMaker.createRootCert();

Fiddler.CertMaker.rootCertExists();

1、Fiddler.FiddlerApplication.Startup 函数用于开启Fiddler组件,提供了3个重载的方式,其中比较常用的是 int,bool,bool,或者int FiddlerCoreStartupFlags.Flags (Default表示修改全局代理)

同时为了方便他人使用,我建议大家使用 FiddlerCoreStartupFlags.AllowRemoteClients (表示支持远程客户端接入),值得注意的是使用完代理后,请必须记得关闭哦,否则将导致您的浏览器无法正常使用!关闭的函数为:FiddlerApplication.Shutdown(); 该函数一般在处理完后调用。

2、FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oSession) 函数,该接口函数负责处理请求前的数据,即:通过该接口函数,可以定义其将发送到远程服务器之前的数据篡改后发送,适用于爬虫调试、接口拼接、URL请求劫持、广告屏蔽时使用,更多的方式大家请自行挖掘。这里要说明下:FiddlerApplication.BeforeRequest 接口函数通常出现在 “+=” 的左边,也就意味着,大家需要以上面的形式编写,后边可以是定义一个函数或与上面的那样以delegate()开头,注意,无论以哪种形式写,请务必使用Fiddler.Session oSession作为参数,该接口不支持oSession类型之外的参数,也就意味着只能在参数里写入Session,单独的写法应为:public void interface(Fiddler.oSession oSession){},值得注意的时,在调用时不需要填写参数,直接+= interface即可。

3、FiddlerApplication.BeforeResponse += delegate(Fiddler.Session oSession);接口函数用作数据请求后操作,即:通过该接口函数,可以定义将远程服务器返回的数据进行一系列的修改后,将其转发给客户端,该接口适用于过滤不良信息、劫持返回结果等场景使用,更多功能请自行挖掘。这里要说明下:FiddlerApplication.BeforeResponse 接口函数与上述的FiddlerApplication.BeforeRequest 接口类似,前者在请求前触发,后者在请求后触发,无论选择哪个,都可以实现我们的目的,返回的参数我们可以通过一个内置的接口函数:oSession.GetResponseBodyAsString;来获得,得到返回的数据后,可以通过替换、正则匹配等形式将其替换,最后用:oSession.utilSetResponseBody();接口将其设置回去,request方式一致。

4、oSession.RequestHeaders[“”] = “”; 接口函数用于修改请求头部的信息,这个与普通的请求函数修改类似,没啥好说的,值得注意的是,Cookie也在里面,如果你了解Http传输协议的话,我相信你会明白的,所以修改Cookie的话,也是通过该接口进行修改,但请注意,Cookie不支持单个修改,但支持Remove,意味着只能删除或添加,删除的方式为:oSession.RequestHeaders.Remove(“Cookie”); 也就是说添加也是如此,如需修改Cookie的值,可以借助正则、或者Replace方法进行替换即可,实在不懂欢迎交流。

5、Fiddler.CertMaker.rootCertExists() 该接口返回一个bool类型的参数,用于判断证书是否存在,如需监测ssl的流量,则需使用该函数进行判断,而FiddlerCore也提供了一个生成证书的接口,直接调用:Fiddler.CertMaker.createRootCert();方法即会弹出一个询问是否需要安装证书的窗口,点击后将创建证书,注意,该证书与Fiddler的证书不兼容,即如果您电脑已经安装了Fiddler,则该证书不适合,所以,在监测ssl流量之前,请务必使用该命令完成证书的创建。当然最后也别忘记了,清除证书哦,使用该方法可以清除证书:Fiddler.CertMaker.rootCertExists(); 当然如果您想留着也没大碍!

以上几个为FiddlerCore中最常用的接口函数,相信我熟练运用这些函数,您会事半功倍的,因为呢不知大家是否有发现,其实这些接口函数除了在C#中适用之外,其实也适用于FiddlerScript哦,语法就是一样的,所以说掌握了它,就算是没开VS,你也是同样可以很方便的进行抓包调试呢,今天的开发小经验就分享到这啦,请务必留意下方的代码,与程序案例哟,下次我将会给大家讲解如何更优雅的使用Fiddler进行抓包!

代码区域:
基于.Net 4.6.1版本
using System;
using System.Collections.Generic;
using System.Threading;
using Fiddler;
using System.Text.RegularExpressions;
using System.IO;
using Newtonsoft.Json;
namespace AdBolck
{
class FiddlerClass
{
private static bool Flag = true;
public void FiddlerProxy() {
if (!Fiddler.CertMaker.rootCertExists()) {
Fiddler.CertMaker.createRootCert();
}
var cert = Fiddler.CertMaker.GetRootCertificate().GetRawCertData();
File.WriteAllBytes(“root.crt”, cert);
if (!Fiddler.CertMaker.rootCertIsMachineTrusted()) {
Fiddler.CertMaker.trustRootCert();
}
Dictionary<string, string> AdBlockConfig = new Dictionary<string, string>();
AdBlockConfig.Add(“qiyi”, “t7z.cupid.iqiyi.com”);
AdBlockConfig.Add(“youku”, “valf.atm.youku.com/vf”);
AdBlockConfig.Add(“qq”, “vlive.qqvideo.tc.qq.com”);
AdBlockConfig.Add(“qqlive”, “variety.tc.qq.com”);
FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oSession) {
oSession.bBufferResponse = true;
foreach (var obj in AdBlockConfig) {
if (oSession.uriContains(obj.Value)) {
oSession.oRequest.FailSession(404, “Blocked”, “Fiddler blocked request”);
var NameLincal = this.ResedStr(obj.Key);
Console.WriteLine($”检测到{NameLincal}的广告,程序自动过滤中,您无需作任何操作!”);

}
}
};

Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress);
Console.WriteLine(“过滤器启动中……”);
Fiddler.FiddlerApplication.Startup(8887,FiddlerCoreStartupFlags.Default);
Console.WriteLine(“按Ctrl+C退出程序.”);
while (Flag) {

Thread.Sleep(1000);
}

}

public string ResedStr(string str) {

switch (str) {

case “youku”:
str = “优酷”;
break;
case “qiyi”:
str = “爱奇艺”;
break;
case “qq”:
str = “腾讯视频”;
break;
case “qqlive”:
str = “腾讯视频”;
break;
default:
str = “未知站点”;
break;
}
return str;
}

private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
{
Console.WriteLine(“程序即将退出…”);
e.Cancel = true;
FiddlerApplication.Shutdown();
Fiddler.CertMaker.rootCertExists();
Thread.Sleep(750);
Flag = false;
}

}
}

https://www.itmaohome.com/wp-content/uploads/2017/12/TIM%E6%88%AA%E5%9B%BE20171216234427.png



2018年01月01日更新
修复程序退出后证书失效的问题。
源代码下载:https://pan.baidu.com/s/1nu7CH6p 获取密码:rjra
Git仓库下载:https://github.com/juedi998/AdBolck/

像番茄加两个蛋 发表于 2018-1-1 20:03:06

感谢楼主分享的好东西!
页: [1]
查看完整版本: 基于C#实现的简易式广告拦截器之实现思路