Save
Saving
  • G
    guluting

    GuaikNet-怪客网络

    可配置微服务的HTTP网络服务端程序

    https://github.com/guaik/GuaikNet

    ⚙️安装说明:(CentOS7)

    yum -y install epel-release
    yum -y install git
    yum -y install python-tools
    yum -y install python-pip
    pip install --upgrade pip
    pip install tornado
    pip install gevent
    pip install pika
    
    git clone https://github.com/guaik/GuaikNet.git
    cd ./GuaikNet
    chmod +x ./start.sh
    ./start.sh
    
    # 如果显示如下信息,证明已经成功安装并运行
    # **********************************
    # @ Welcome to use <GuaikNet> system
    # @ website: https://bbs.guaik.org
    # @ email  : luting.gu@gmail.com
    # **********************************
    

    🚀系统测试:

    安装requests库

    pip install requests
    

    将项目根目录下的client.py文件复制到测试电脑,修改client.py中的http://localhost:8080,将其中的localhost改成你部署GuaikNet项目所在的服务器
    地址。

    然后运行:python ./client.py

    如果返回Welcome to use GuaikNet system则说明系统运行正常。


    📝使用说明

    GuaikNet的工作目录有两个,分别是http请求的处理目录./works和rpc的工作目录./rpc

    HTTP请求协议:

    示例:{"protocol":"json","version":"v1.01","action":"guaik.welcome","content":{}}

    protocol: 请求协议 选项:[json, aes, rsa] (当前只使用json,aes加密和rsa加密方式还未加入)。

    version : 版本号,如果客户端发起请求所使用的版本号与服务器当前版本号不同,服务端将不处理请求。

    action : 需要调用的服务,命名规则是以works目录为根目录: 子目录.文件名。以上面的请求"action":"guaik.welcome"为例,
    将会调用guaik目录下模块名为welcome的处理函数。

    content : 该字段为自定义字段,按照服务端的开发文档填写。

    HTTP处理例程:(./works/guaik/welcome.py)

    def handler(data,ctx):
        ctx.write("Welcome to use GuaiKNet system")
    

    处理例程函数定义统一写成:def handler(data,ctx): pass,否则无法被系统解析。

    参数:data 对应着客户端请求content字段

    参数:ctx http请求的上下文,通过该对象的write方法可以向客户端返回处理结果。


    RPC调用说明:

    需要安装RabbitMQ消息队列,一键安装脚本:

    curl -s -o rabbitmq.py https://raw.githubusercontent.com/guaik/GuaikInstaller/master/rabbitmq.py && python rabbitmq.py install

    RPC功能默认是关闭的,需要在./bootstrap.py文件中开启该功能:

    server.active_rpc("rpc_host", 5672, "/", "username", "passwd")

    找到该行,取消注释,填上消息队列的:(主机IP, 主机端口, 虚拟主机(vhost), 用户名, 密码)

    RPC处理例程的默认目录为:./rpc

    RPC处理例程调用规则:(以下是发送短信验证码的DEMO)

    from server.application import gm
    rpc = gm.get("rpc")
    rpc.call("sms.send_verify_code", "+8618888888888")
    

    从全局对象管理器(gm)中取出rpc对象,使用rpc对象的call方法,第一个参数是rpc的方法名,之后所有的参数是rpc方法对应的参数列表。原型为:
    def call(self,key,*args): ...

    方法名的规则是:模块名.函数名

    RPC方法定义规则:(以./rpc/sms.send_verify_code为例)

    import logging
    import requests
    import json
    from server.application import gm
    rpc = gm.get("rpc")
    
    api_key = "your_api_key"
    api_secret = "your_secret"
    brand = "Guaik"
    
    @rpc.route()
    def send_verify_code(number):
        request_id = None
        try:
            data = {"api_key":api_key,"api_secret":api_secret,"number":number,"brand":brand}
            headers = {'Content-Type': 'application/json'}
            r = requests.post("https://api.nexmo.com/verify/json",headers = headers, data = json.dumps(data))
            data = json.loads(r.text)
            if data["status"] == "0":
                request_id = data["request_id"]
        except Exception as e: logging.error(e)
        return request_id
    

    先从全局对象管理器gm中取出rpc对象,然后在send_verify_code的上方加上@rpc.route()注解,这时候send_verify_code将被注册到RpcManager中,
    成为RPC处理例程。


    🧙其他说明:

    ./bootstrap.py:

    LEVEL :当前服务器日志级别,作为Server的初始化参数传入。

    CUR_VERSION :当前解析器的版本号,作为Analysis的参数传入,用于判断客户端发送的请求版本是否正确。


    server.gen_http_process(8080,1,Analysis(CUR_VERSION)):
    以上代码生成http服务进程,默认监听8080端口。1代表启动一个进程,如果该参数为4,则启动4进程依次监听8080,8081,8082,8083端口。
    第三个参数传入解析器对象,该对象用于解析客户端请求并调用对应的处理例程,在该例程中存放着请求与处理例程的映射关系。也可以自定义解析器对象,
    基类在./base/analysis.py中。

    server.start(False)
    这边的False表示不以守护进程运行,如果需要以守护进程运行,则修改成True即可,守护进程默认只在Linux系统中生效。


    ./config目录下存放着可能会用到的配置文件,proxy.conf为Nginx反向代理的配置文件,可以修改它并将它放到/etc/nginx/conf.d下,
    然后重启Nginx服务使其生效。可以通过监听多个服务端口,配合Nginx实现服务端的多进程处理。

    upstream servers {
        server localhost:8001;
        server localhost:8002;
        server localhost:8003;
        server localhost:8004;
    }
    
    server {
        listen 8080;
        location / {
            proxy_pass  http://servers;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            proxy_set_header Host $http_host;
            proxy_set_header X-NginX-Proxy true;
            proxy_redirect off;
            # Socket.IO Support
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
       }
    }
    

    🎃PS:打了这么多字应该会有错别字,欢迎纠正:luting.gu@gmail.com

    posted in GuaiK项目 read more
  • G
    guluting

    📣🛠 为了确保《GuaiK实验室》的数据安全,以及国外主机的各种不稳定因素。本站会不定期的关闭并备份所有数据库及文件资料。

    posted in GuaiK新闻 read more
  • G
    guluting

    # -*- coding:utf-8 -*-
    # 作者:luting.gu@gmail.com
    # 倒排索引-搜索引擎 DEMO
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')
    
    # t1到t7都是待搜索的全文
    t1 = """
          在我们家族,各行各业从业者都有。从政的,从商的,人民教师的,农民的,企业职员的。从收入水平看,就目前而言,自然是从商的赚的钱稍微比其他人都多一些。但是,亲眼目睹过去几年几位兄弟从商的工作状态,我真的没有羡慕过他们收入比我高,因为,他们的那种工作强度,那种紧张忙碌,那种工作压力,是我根本承受不起的。
    """
    t2 = """
    处女座为了爱情付出的不是金钱又或者时间之类的东西,而是心态,她们的思维模式比较单一,向往平凡的爱情模式,对于金钱的向往是从来没有过的,两个人在一起开开心心就好,心愿纯真简单。但是如果遇到渣男,她就会患得患失的思考为什么会这样,会造成她经常纠结是否是自身的问题,不断否定自己,想不开,久而久之很容易得与抑郁症。
    """
    t3 = """
    狮子座天生的骄傲会自豪,随着她的恋情一步一步的消失殆尽,越来越迁就恋人,狮子认为在生命中如果没有一次奋不顾身的恋爱,是不完整的。可是一旦恋情失败,狮子会变成另一个极端的自己,越发的讨厌以前的自己,抛弃原来的自我。或许有一天,她遇见对的人,会再次重生吧。
    """
    t4 = """
    人心有真假,时间能见证,感情有冷暖,风雨能考验,时间带不走真正的朋友,岁月留不住虚幻的拥有,时光转换,体会到缘分善变,平淡无语,感受了人情冷暖,有心的人,不管你在与不在,都会惦念,无心的情,无论你好与不好,只是漠然,走过一段路,总能有一次领悟,经历一些事,才能看清一些人。
    """
    t5 = """
    总会有些不喜欢,又不得不去做的事,与其每次抱着自杀的心情去面对,不如把它们养成习惯。习惯跑步,习惯健身,习惯记录,习惯和一个人在一起。习惯能消磨一个人对事物的厌恶感,能让一个人与世界相安无事。“习惯了就好”不是无奈,而是学会了对自己体谅。—— 刘同
    """
    t6 = """
    想知道一个人爱不爱你,就给他自由。不要妄图拴住爱情,世上没有能拴得住的爱人。若是爱你,何需拴着他?若不爱你,拴住他干嘛!爱你的人,走到天涯也会回来找你。要费尽心机来挽留的,早晚有走丢的一天。
    """
    t7 = """
    我们都像小孩,胡闹是因为依赖你;懂礼貌,是因为你是外人。
    """
    
    
    def del_space(text):
        """
        去除无用的符号
        @param [in] test 待处理的字符串
        @retval 去除无用符号后的字符串
        """
        space_char = " `~!@#$%^&*()-_=+[{]}\\|\t;:'\",<.>/?……()——【】、;「」,。、"
        for c in space_char.decode('utf-8'):
            text = text.replace(c,'')
        return text
    
    def n_gram(text,n):
        """
        使用N_GRAM对全文进行分割
        @param [in] text 待分割的文本
        @param [in] n 1:uni-gram 2:bi-gram 3:tri-gram
        @return 分割后的字典列表[[词语,位置下标],......]
        """
        text = text.decode('utf-8')
        retlist = []
        for i in xrange(0,len(text)-n+1):
            short_text = ['',0]
            for j in xrange(0,n):
                short_text[0] += text[i+j]
            short_text[1] = i
            retlist.append(short_text)
        return retlist
    
    
    data = []       # 用于存储数据,将下标作为doc_id
    index = {}      # 用来记录词典及对应的倒排项
    def make_index(text):
        """
        制作倒排索引
        @param [in] text 待处理的文本
        """
        data.append(text)
        doc_id = len(data) - 1
        word_list = n_gram(del_space(text),2)
        for item in word_list:
            if not index.has_key(item[0]):
                index[item[0]] = set()
            index[item[0]].add(doc_id)
    
    
    def query(text):
        """
        查询
        @param [in] text 用于查询的短语或词语
        @return 匹配成功的文档下标doc_id
        """
        word_list = n_gram(del_space(text),2)
        doc_list = set()
        for item in word_list:
            if index.has_key(item[0]):
                if len(doc_list) == 0:
                    doc_list = index[item[0]]
                else:
                    doc_list = doc_list & index[item[0]]
        return doc_list
    
    
    if __name__ == "__main__":
        # 生成倒排索引
        make_index(t1)
        make_index(t2)
        make_index(t3)
        make_index(t4)
        make_index(t5)
        make_index(t6)
        make_index(t7)
        # 开始检索并遍历输出结果
        id_list = query("不要妄图拴住爱情")
        for item in id_list:
            print str(item)+':'+data[item]
    

    posted in GuaiK实验室 read more
  • G
    guluting

    RabbitMQ

    安装

    curl -s -o rabbitmq.py https://raw.githubusercontent.com/guaik/GuaikInstaller/master/rabbitmq.py && python rabbitmq.py install

    卸载

    curl -s -o rabbitmq.py https://raw.githubusercontent.com/guaik/GuaikInstaller/master/rabbitmq.py && python rabbitmq.py remove


    MongoDB

    安装

    curl -s -o mongodb.py https://raw.githubusercontent.com/guaik/GuaikInstaller/master/mongodb.py && python mongodb.py install

    卸载

    curl -s -o mongodb.py https://raw.githubusercontent.com/guaik/GuaikInstaller/master/mongodb.py && python mongodb.py remove

    posted in GuaiK机房 read more
  • G
    guluting

    其实当初想设计转发模块的时候是计划在框架内部实现负载均衡的功能的,但是经过测试发现效率并没有提升,我做了很多测试也尝试将代码在协程与多线程之间就行调优,但是速度始终不理想,最终还是使用Nginx去实现Tornado的多进程转发模式了。多进程配合Tornado的协程速度还是不错的。

    socket转发

    from tornado.tcpserver import TCPServer
    from tornado.ioloop  import IOLoop
    import tornado
    import socket
    import threading
    import logging
    from concurrent.futures import ThreadPoolExecutor
    import random
    
    from gevent import monkey
    monkey.patch_all()
    
    class Connection():
        def __init__(self,proxy, stream, address):
            print threading.current_thread()
            self._proxy = proxy
            self._proxy.clients.add(self)
            logging.debug("[connect] clients count:"+str(len(self._proxy.clients)))
            self._stream = stream
            self._address = address
            self._stream.set_close_callback(self.on_close)
            self.http_content = ""
            self.read_data()
    
        def read_data(self):
            self._stream.read_until("\r\n\r\n",self.analysis_head)
    
        def analysis_head(self, head):
            self.http_content = head
            fields = head.split("\r\n")
            field_map = {}
            for field in fields:
                kv = field.split(":")
                if len(kv) == 2:
                    field_map[kv[0].lower()] = kv[1]
            if field_map.has_key("content-length"):
                self._stream.read_bytes(int(field_map["content-length"]),self.proxy_data)
    
        def write_finish(self):
            if self._stream.closed():
                return
            self._stream.close()
    
        def recvall(self, sock):
            BUFF_SIZE = 1024
            data = b''
            while True:
                part = sock.recv(BUFF_SIZE)
                data += part
                if len(part) < BUFF_SIZE:
                    break
            return data
    
        def proxy_data(self, data):
            self.http_content += data
            logging.debug("http content:"+self.http_content)
            cur_server = ()
            if self._proxy.mode == 0:
                self._proxy.mutex.acquire()
                cur_server = self._proxy.server_list[self._proxy.cur_server]
                self._proxy.cur_server += 1
                if self._proxy.cur_server == self._proxy.server_count:
                    self._proxy.cur_server = 0
                self._proxy.mutex.release()
            if self._proxy.mode == 1:
                self._proxy.cur_server = random.randint(0,self._proxy.server_count-1)
                cur_server = self._proxy.server_list[self._proxy.cur_server]
    
            logging.debug("proxy -> "+cur_server[0]+":"+str(cur_server[1]))
    
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.connect(cur_server)
            s.send(self.http_content)
            ret_data = self.recvall(s)
            if not self._stream.closed():
                self._stream.write(ret_data,self.write_finish)
            s.close()
    
        def on_close(self):
            self._proxy.clients.remove(self)
            logging.debug("[close] clients count:"+str(len(self._proxy.clients)))
    
    
    class Proxy(TCPServer):
        def __init__(self, port, server_list, mode):
            super(Proxy,self).__init__()
            self.clients = set()
            self.port = port
            self.server_list = server_list
            self.mode = mode
            self.cur_server = 0
            self.server_count = len(server_list)
            self.mutex = threading.Lock()
            self.executor = ThreadPoolExecutor()
    
        def worker(self, stream, address):
            Connection(self,stream, address)
    
        def handle_stream(self, stream, address):
            # self.executor.submit(self.worker, stream, address)
            Connection(self,stream, address)
    
        def start(self):
            self.listen(self.port)
            IOLoop.instance().start()
    

    tornado.httpclient.AsyncHTTPClient()转发

    import tornado.ioloop
    import tornado.web
    import tornado.httpclient
    import tornado.gen
    import logging
    import threading
    
    from gevent import monkey
    monkey.patch_all()
    
    
    class MainHandler(tornado.web.RequestHandler):
    
        def get(self, *args, **kwargs):
            try:
                logging.debug(str(self.request.remote_ip)+"\n"+"-"*80+"\n"+str(self.request.body)+"\n"+"-"*80)
                self.application.analysis.decrypt_http(self.request.body,self)
            except Exception as e: logging.error(str(e))
    
        def handle_request(self, response):
            if not response.error:
                self.write(response.body)
            self.finish()
    
        @tornado.web.asynchronous
        def post(self, *args, **kwargs):
            try:
                logging.debug(str(self.request.remote_ip)+"\n"+"-"*80+"\n"+str(self.request.body)+"\n"+"-"*80)
                if self.application.mode == 0:
                    self.application.mutex.acquire()
                    cur_server = self.application.servers[self.application.cur_server]
                    self.application.cur_server += 1
                    if self.application.cur_server == self.application.server_count:
                        self.application.cur_server = 0
                    self.application.mutex.release()
                    logging.debug("proxy -> "+cur_server)
                    headers = self.request.headers
                    body = self.request.body
                    request = tornado.httpclient.HTTPRequest(cur_server,
                                                     method="POST", headers=headers, body=body, validate_cert=False)
                    tornado.httpclient.AsyncHTTPClient().fetch(request,self.handle_request)
            except Exception as e: logging.error(str(e))
    
    def make_app():
        return tornado.web.Application([
            (r"/", MainHandler),
        ])
    
    class Proxy():
        def __init__(self, port, servers, mode):
            self._port = port
            self._servers = servers
            self._mode = mode
    
        def start(self):
            app = make_app()
            app.listen(self._port)
            app.mode = self._mode
            app.servers = self._servers
            app.cur_server = 0
            app.server_count = len(self._servers)
            app.mutex = threading.Lock()
            tornado.ioloop.IOLoop.current().start()
    

    posted in GuaiK实验室 read more
  • G
    guluting

    @pipi vscode还是比较好用的,我现在都很少用IDE了,除了开发Qt程序会用QtCreator😐

    posted in GuaiK重灾区 read more
  • G
    guluting

    哈哈,其实我没看懂😀 可以介绍下作品吗

    posted in GuaiK工厂 read more
  • G
    guluting

    重点讲解:
    装饰器(@)是Python中非常重要的『东西』,你在微博中艾特谁,她还是她,你改变不了她。但是在python中你艾特了某个函数,你将对它拥有控制权,哪怕把它改的面目全非也是可以的。
    装饰器是什么意思呢?
    装饰器就是一个接受函数对象的函数,好吧,有点绕口,请看代码:

    class Girl():
        def __init__(self):
            self.msg = "Girl:I dislike you!"
        def output(self):
            return self.msg
    
    def Change(obj):
        # 洗脑模式
        obj.msg = "Girl:I like you!"
        return obj
    
    print Change(Girl()).output()
    # 输出结果:Girl:I like you!
    

    那么显然写成Change(Girl()).output()不是很直观,我们来换一种更Pythoner的:
    直接通过装饰器去改写输出函数output,在函数输出前修改msg数据

    def ChangeOutput(msg):
        def change_output(func):
            def new_output(s):
                s.msg = "Girl:I like you!"
                return func(s)
            return new_output
        return change_output
    
    class Girl():
        instance = None
        def __init__(self):
            self.msg = "Girl:I dislike you!"
    
        @ChangeOutput("Girl:I link you!")
        def output(self):
            return self.msg
    
    print Girl().output()
    

    下面就是用装饰器来模拟Flask的原理了。

    # -*- coding: utf-8 -*-
    class GuaikNet():
        def __init__(self):
            # URI与处理函数的映射
            self._func_map = {}
    
        def route(self, uri):       # 装饰器,用来接受参数
            def _new_func(func):    # 新的函数对象,用来替代被装饰的函数,参数为被装饰的函数对象
                self._func_map[uri] = func
                return func
            return _new_func
    
        def server(self, uri):
            func = self._func_map[uri]
            if func:
                return func()
            else:
                raise ValueError('Route "{}" has not been registered'.format(uri))
    
    app = GuaikNet()
    @app.route("/")
    def hello():
        return "Hello GuaikNet"
    
    print app.server("/")
    

    posted in GuaiK实验室 read more
  • G
    guluting

    VSCode是微软出品的一款比较轻量的文本编辑工具,和Github出品的Atom类似,而且都提供了很强大的插件功能。
    CMake是一款跨平台的编译工具,它能够生成各种项目文件或makefile文件。
    决定使用VSCode+CMake编译驱动的主要原因是感觉Visual Studio太过于臃肿了吧,自从写驱动程序以来都经历过了使用文本编辑器或者VC++6.0开发,微软的产品功能越来越全面的同时也会让产品变得太臃肿了。开发驱动程序脚本编辑器足矣。


    下面需要准备的工具(自行安装):

    下载WDK

    https://docs.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk

    下载VSCode

    https://code.visualstudio.com/

    下载CMake

    https://cmake.org/download/

    下载FindWDK项目(用来搜索WDK相关路径)

    https://github.com/SergiusTheBest/FindWDK.git


    建立工程目录:

    NetFilter(主目录)
    |--cmake
        |--FindWdk.cmake     # 在FindWDK中复制过来
    |--network               # FWPM网络过滤模块
        |--main.c
        |--CMakeLists.txt
    |--CMakeLists.txt        # CMake配置文件
    |--build.bat             # 自动编译脚本
    

    相关代码

    network->main.c

    #pragma once
    #pragma warning(push)
    #pragma warning(disable : 4201)
    #pragma warning(disable : 4324)
    #define NDIS_SUPPORT_NDIS6 1
    #include <ntifs.h>
    #include <ntddk.h>
    #include <ndis.h>
    #include <fwpsk.h>
    #include <fwpmk.h>
    #include <wdm.h>
    #pragma warning(pop)
    #define INITGUID
    #include <guiddef.h>
    
    #define DEVICE_NAME L"\\Device\\GhostNet"
    #define DEVICE_DOSNAME L"\\DosDevices\\GhostNet"
    #define kmalloc(_s) ExAllocatePoolWithTag(NonPagedPool, _s, 'GSYS')
    #define kfree(_p) ExFreePool(_p)
    
    DEFINE_GUID
        (
            GUID_ALE_AUTH_CONNECT_CALLOUT_V4,
            0x6812fc83,
            0x7d3e,
            0x499a,
            0xb8, 0x59,
            0x55, 0xe0, 0xd8, 0x5f, 0x34, 0x8b);
    
    
    
    PDEVICE_OBJECT gDevObj;
    HANDLE gEngineHandle = 0;
    HANDLE gInjectHandle = 0;
    
    UINT32 gAleConnectCalloutId = 0;
    UINT64 gAleConnectFilterId = 0;
    
    NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING regPath);
    VOID DriverUnload(PDRIVER_OBJECT driver);
    
    //协议代码转为名称
    char *ProtocolIdToName(UINT16 id)
    {
        char *ProtocolName = (char *)kmalloc(16);
        switch (id)
        {
        case 1:
            strcpy_s(ProtocolName, 4 + 1, "ICMP");
            break;
        case 2:
            strcpy_s(ProtocolName, 4 + 1, "IGMP");
            break;
        case 6:
            strcpy_s(ProtocolName, 3 + 1, "TCP");
            break;
        case 17:
            strcpy_s(ProtocolName, 3 + 1, "UDP");
            break;
        case 27:
            strcpy_s(ProtocolName, 3 + 1, "RDP");
            break;
        default:
            strcpy_s(ProtocolName, 7 + 1, "UNKNOWN");
            break;
        }
        return ProtocolName;
    }
    
    NTSTATUS NTAPI WallNotifyFn(
        IN FWPS_CALLOUT_NOTIFY_TYPE notifyType,
        IN const GUID *filterKey,
        IN const FWPS_FILTER *filter)
    {
        return STATUS_SUCCESS;
    }
    
    VOID NTAPI WallFlowDeleteFn(
        IN UINT16 layerId,
        IN UINT32 calloutId,
        IN UINT64 flowContext)
    {
        return;
    }
    
    
    
    // 连接过滤
    void NTAPI ALEConnectClassify(
        IN const FWPS_INCOMING_VALUES0 *inFixedValues,
        IN const FWPS_INCOMING_METADATA_VALUES0 *inMetaValues,
        IN OUT void *layerData,
        IN const void *classifyContext,
        IN const FWPS_FILTER *filter,
        IN UINT64 flowContext,
        OUT FWPS_CLASSIFY_OUT *classifyOut)
    {
        char *ProtocolName = NULL;
        DWORD LocalIp, RemoteIP;
        LocalIp = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
        RemoteIP = inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_ADDRESS].value.uint32;
        ProtocolName = ProtocolIdToName(inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_PROTOCOL].value.uint16);
        DbgPrint("[WFP]IRQL=%d;PID=%ld;Path=%S;Local=%u.%u.%u.%u:%d;Remote=%u.%u.%u.%u:%d;Protocol=%s\n",
                 (USHORT)KeGetCurrentIrql(),
                 (DWORD)(inMetaValues->processId),
                 (PWCHAR)inMetaValues->processPath->data, //NULL,//
                 (LocalIp >> 24) & 0xFF, (LocalIp >> 16) & 0xFF, (LocalIp >> 8) & 0xFF, LocalIp & 0xFF,
                 inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16,
                 (RemoteIP >> 24) & 0xFF, (RemoteIP >> 16) & 0xFF, (RemoteIP >> 8) & 0xFF, RemoteIP & 0xFF,
                 inFixedValues->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_REMOTE_PORT].value.uint16,
                 ProtocolName);
        
        kfree(ProtocolName);
        classifyOut->actionType = FWP_ACTION_PERMIT; //允许连接
    
        //禁止IE联网(设置“行动类型”为FWP_ACTION_BLOCK)
        // if(wcsstr((PWCHAR)inMetaValues->processPath->data,L"iexplore.exe"))
        // {
        // classifyOut->actionType = FWP_ACTION_BLOCK;
        // classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
        // classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
        // }
        return;
    }
    
    
    /*
    * 注册过滤层回调函数
    */
    NTSTATUS RegisterCalloutForLayer(
        IN const GUID *layerKey,
        IN const GUID *calloutKey,
        IN FWPS_CALLOUT_CLASSIFY_FN classifyFn,
        IN FWPS_CALLOUT_NOTIFY_FN notifyFn,
        IN FWPS_CALLOUT_FLOW_DELETE_NOTIFY_FN flowDeleteNotifyFn,
        OUT UINT32 *calloutId,
        OUT UINT64 *filterId)
    {
        NTSTATUS status = STATUS_SUCCESS;
        FWPS_CALLOUT sCallout = {0};
        FWPM_FILTER mFilter = {0};
        FWPM_FILTER_CONDITION mFilter_condition[1] = {0};
        FWPM_CALLOUT mCallout = {0};
        FWPM_DISPLAY_DATA mDispData = {0};
        BOOLEAN bCalloutRegistered = FALSE;
        sCallout.calloutKey = *calloutKey;
        sCallout.classifyFn = classifyFn;
        sCallout.flowDeleteFn = flowDeleteNotifyFn;
        sCallout.notifyFn = notifyFn;
        status = FwpsCalloutRegister(gDevObj, &sCallout, calloutId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpsCalloutRegister failed.");
            goto exit;
        }
        bCalloutRegistered = TRUE;
        mDispData.name = L"WFP TEST";
        mDispData.description = L"TESLA.ANGELA's WFP TEST";
        mCallout.applicableLayer = *layerKey;
        mCallout.calloutKey = *calloutKey;
        mCallout.displayData = mDispData;
        status = FwpmCalloutAdd(gEngineHandle, &mCallout, NULL, NULL);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpmCalloutAdd falied");
            goto exit;
        }
        mFilter.action.calloutKey = *calloutKey;
        mFilter.action.type = FWP_ACTION_CALLOUT_TERMINATING;
        mFilter.displayData.name = L"WFP TEST";
        mFilter.displayData.description = L"TESLA.ANGELA's WFP TEST";
        mFilter.layerKey = *layerKey;
        mFilter.numFilterConditions = 0;
        mFilter.filterCondition = mFilter_condition;
        mFilter.subLayerKey = FWPM_SUBLAYER_UNIVERSAL;
        mFilter.weight.type = FWP_EMPTY;
        status = FwpmFilterAdd(gEngineHandle, &mFilter, NULL, filterId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("FwpmFilterAdd failed");
            goto exit;
        }
    exit:
        if (!NT_SUCCESS(status))
        {
            if (bCalloutRegistered)
            {
                FwpsCalloutUnregisterById(*calloutId);
            }
        }
        return status;
    }
    
    NTSTATUS WallRegisterCallouts()
    {
        NTSTATUS status = STATUS_SUCCESS;
        BOOLEAN bInTransaction = FALSE;
        BOOLEAN bEngineOpened = FALSE;
        FWPM_SESSION session = {0};
        session.flags = FWPM_SESSION_FLAG_DYNAMIC;
        status = FwpmEngineOpen(NULL,
                                RPC_C_AUTHN_WINNT,
                                NULL,
                                &session,
                                &gEngineHandle);
        if (!NT_SUCCESS(status))
            goto exit;
        bEngineOpened = TRUE;
        status = FwpmTransactionBegin(gEngineHandle, 0);
        if (!NT_SUCCESS(status))
            goto exit;
        bInTransaction = TRUE;
        // 注册Connect
        status = RegisterCalloutForLayer(
            &FWPM_LAYER_ALE_AUTH_CONNECT_V4,
            &GUID_ALE_AUTH_CONNECT_CALLOUT_V4,
            ALEConnectClassify,
            WallNotifyFn,
            WallFlowDeleteFn,
            &gAleConnectCalloutId,
            &gAleConnectFilterId);
        if (!NT_SUCCESS(status))
        {
            DbgPrint("RegisterCalloutForLayer-FWPM_LAYER_ALE_AUTH_CONNECT_V4 failed!\n");
            goto exit;
        }
    
        status = FwpmTransactionCommit(gEngineHandle);
        if (!NT_SUCCESS(status))
            goto exit;
        bInTransaction = FALSE;
    exit:
        if (!NT_SUCCESS(status))
        {
            if (bInTransaction)
            {
                FwpmTransactionAbort(gEngineHandle);
            }
            if (bEngineOpened)
            {
                FwpmEngineClose(gEngineHandle);
                gEngineHandle = 0;
            }
        }
        return status;
    }
    
    NTSTATUS WallUnRegisterCallouts()
    {
        if (gEngineHandle != 0)
        {
            // 删除FilterId
            FwpmFilterDeleteById(gEngineHandle, gAleConnectFilterId);
            // 删除CalloutId
            FwpmCalloutDeleteById(gEngineHandle, gAleConnectCalloutId);
            // 清空FilterId
            gAleConnectFilterId = 0;
            // 反注册CalloutId
            FwpsCalloutUnregisterById(gAleConnectCalloutId);
            // 清空CalloutId
            gAleConnectCalloutId = 0;
            // 关闭引擎
            FwpmEngineClose(gEngineHandle);
            gEngineHandle = 0;
        }
        return STATUS_SUCCESS;
    }
    
    // #pragma alloc_text(PAGE, DriverUnload)
    VOID DriverUnload(PDRIVER_OBJECT driver)
    {
        UNICODE_STRING DeviceDosName;
        WallUnRegisterCallouts();
        RtlInitUnicodeString(&DeviceDosName,DEVICE_DOSNAME);
        IoDeleteSymbolicLink(&DeviceDosName);
        IoDeleteDevice(driver->DeviceObject);
    }
    
    NTSTATUS DefIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS CreateIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    NTSTATUS CloseIRPHandler(IN PDEVICE_OBJECT devobj, IN PIRP Irp){
        Irp->IoStatus.Status = STATUS_SUCCESS;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return STATUS_SUCCESS;
    }
    
    // #pragma alloc_text(INIT, DriverEntry)
    NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING regPath)
    {
        // PAGED_CODE();
        NTSTATUS status;
        UNICODE_STRING DeviceName,DeviceDosName;
        RtlInitUnicodeString(&DeviceName,DEVICE_NAME);
        RtlInitUnicodeString(&DeviceDosName,DEVICE_DOSNAME);
        // 设置默认IRP派遣处理函数
        for(UINT i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){
            driver->MajorFunction[i] = DefIRPHandler;
        }
        //  IRP 打开关闭处理函数
        driver->MajorFunction[IRP_MJ_CREATE] = CreateIRPHandler;
        driver->MajorFunction[IRP_MJ_CLOSE] = CloseIRPHandler;
        driver->DriverUnload = DriverUnload;
        status = IoCreateDevice(driver,
                                0,
                                NULL,
                                FILE_DEVICE_UNKNOWN,
                                0, TRUE,
                                &gDevObj);
        if (!NT_SUCCESS(status))
            return status;
        if (!gDevObj)
            return STATUS_UNEXPECTED_IO_ERROR;
        status = WallRegisterCallouts();
        if (!NT_SUCCESS(status))
            return status;
        
    
        // 设置设备读写方式
        gDevObj->Flags |= DO_DIRECT_IO;
        // 创建符号链接
        status = IoCreateSymbolicLink(&DeviceDosName, &DeviceName);
        gDevObj->Flags &= ~ DO_DEVICE_INITIALIZING;
        return STATUS_SUCCESS;
    }
    

    network->CMakeLists.txt

    SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/./build)
    wdk_add_driver(network main.c)
    target_link_libraries(network ntoskrnl ndis fwpkclnt uuid)
    

    NetFilter->CMakeLists.txt
    其中需要自己设置一下WDK Library链接的路径

    cmake_minimum_required(VERSION 3.0)
    
    project(NetFilter)
    
    set_property(GLOBAL PROPERTY USE_FOLDERS ON)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W0 /WX")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /W0 /WX")
    
    list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/./cmake")
    find_package(WDK REQUIRED)
    
    # 设置WDK Library路径
    link_directories("C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17134.0\\km\\x86")
    add_subdirectory(comport)
    add_subdirectory(network)
    

    NetFilter->build.bat
    如果需要编译Release版本的请替换脚本中的Debug字符串

    cmake .
    devenv ./NetFilter.sln /Build "Debug"
    

    祝你成功编译出sys文件 😈
    0_1540261742778_WX20181023-102839@2x.png

    posted in GuaiK重灾区 read more
  • G
    guluting

    收费的,不过价格不贵。短信验证的签名不需要审核,你在brand中填什么它就给你显示什么,及时性还不错。

    posted in GuaiK实验室 read more