博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Wireshark 解析 自定义 加密 协议
阅读量:4622 次
发布时间:2019-06-09

本文共 9478 字,大约阅读时间需要 31 分钟。

一、概述

网上撰文写wireshark使用lua脚本解析协议的文章比较多。

笔者最近也因工作需要使用wireshark解析协议。但因网络安全,协议的数据部分被加密了。无法简单的使用lua脚本进行解析。

考虑到加密算法和压缩算法的复杂性,采用调用lua C库的方法,完成解密(解压)。

下面与大家分享下大致思路。

二、目标及思路

协议的大致格式如下:

协议字段 命名
协议版本(1字节) protoVersion
协议命令类型(2字节) protoCmdType
协议加密类型(1字节) protoEncrytionType
协议压缩类型(1字节) protoCompressionType
协议数据长度(4字节) protoDataLength
协议数据(protoDataLength字节) protoData

 

:本文仅专注于解码,为简化复杂性,暂时不考虑一个UDP/TCP包出现多个自定义数据包的情况。

 

Lua脚本的伪代码:

local p_multi = Proto("multi","MultiProto");local f_protoVersion = ProtoField.uint8("multi.protoVersion","Version",base.DEC)local f_protoCmdType = ProtoField.uint16("multi.protoCmdType","CmdType",base.DEC,{        [1] = "CmdType_1",        [2] = "CmdType_2",        [3] = "CmdType_3",        })local f_protoEncrytionType = ProtoField.uint8(        "multi.protoEncrytionType","EncrytionType",base.DEC,{        [1] = "EncrytionType_1",        [2] = "EncrytionType_2",        [3] = "EncrytionType_3",        })local f_protoCompressionType = ProtoField.uint8(        "multi.protoCompressionType","CompressionType",base.DEC,{        [1] = "CompressionType_1",        [2] = "CompressionType_2",        [3] = "CompressionType_3",        })local f_protoDataLength = ProtoField.uint32("multi.protoDataLength","DataLength",base.DEC)p_multi.fields = { f_protoVersion, f_protoCmdType, f_protoEncrytionType,         f_protoCompressionType, f_protoDataLength }function DecodeBufferFunction(protoEncrytionType, protoCompressionType, buf, pos, buf_len)    local decodeBuf = buf    -- TODO: This artical job    return decodeBufendfunction p_multi.dissector(buf,pkt,root)    local pos = 0    local buf_len = buf:len()    local t = root:add(p_multi,buf(0,buf_len))    -- 协议版本(1字节)    t:add(f_protoVersion, buf(pos, 1))    pos = pos + 1    -- 协议命令类型(2字节)    t:add(f_protoCmdType, buf(pos, 2))    pos = pos + 2    -- 协议加密类型(1字节)    t:add(f_protoEncrytionType, buf(pos, 1))    local protoEncrytionType = buf(pos, 1):uint()    pos = pos + 1    -- 协议压缩类型(1字节)    t:add(f_protoCompressionType, buf(pos, 1))    local protoCompressionType = buf(pos, 1):uint()    pos = pos + 1    -- 协议数据长度(4字节)    t:add(f_protoDataLength, buf(pos, 1))    local protoDataLength = buf(pos, 4):uint()    pos = pos + 4    -- 协议数据(protoDataLength字节)    buf = DecodeBuffer(protoEncrytionType, protoCompressionType, buf, pos, buf_len)    new_buf_len = buf:len()    -- TODO: add your codeend

本文的主要任务是DecodeBufferFunction的实现。

目前的任务是把原始数据(buf)

 

变成(decodeBuf)

上图实际上就是原始buf和decodeBuf。这里buf、decodeBuf均为Tvb (). 另外,为操持两个buf在偏移上的一致,decodeBuf的头部也添加了“协议头”

因而DecodeBufferFunction的任务有3个:

1. 由buf转换成Lua c库的数据结构

2. Lua c库完成解码,并返回数据

3. 再由Lua c库的数据结构转换成decodeBuf.

当然,如果我们知道Tvb的数据结构格式,可以省去第1、3步。

 

三、Lua c库的编写

Lua c库的开发可以参考相关资料。本文的开发需要用到LuaBinaries. 可以在: 下载。

详细路径:。根据平台和lua版本,可以自选。

本文使用了lua-5.1.5_Win32_dll10_lib.zip

Lua c库的结构定义如下:

typedef struct MyByteArray {     int size;     unsigned char values[1];  /* variable part */ } MyByteArray;

wireshark中的Tvb、ByteArray都是以0为起始索引的方式。所以下面MyByteArray也以0为索引。这一点和lua语言提倡的方式不一致。

 

本文采用vs2010生成一个win32 dll的库,工程名称:decode. 工程向导设置如下:

删除decode.h和decode.cpp中的,示例代码。并在decode.h中,把导出定义改成:

#ifdef DECODE_EXPORTS #define DECODE_API extern "C" __declspec(dllexport) #else #define DECODE_API extern "C" __declspec(dllimport) #endif

并引入lua-5.1.5_Win32_dll10_lib的库到本工程。

本文使用了《Program in Lua》第28章的部分示例代码。关键源代码如下:

Stdafx.h

// stdafx.h : include file for standard system include files,// or project specific include files that are used frequently, but// are changed infrequently//#pragma once#include "targetver.h"#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers// Windows Header Files:#include 
// TODO: reference additional headers your program requires here#include "include/lua.hpp"#pragma comment(lib, "lib/lua51")

 

decode.h

#ifdef DECODE_EXPORTS#define DECODE_API extern "C" __declspec(dllexport)#else#define DECODE_API extern "C" __declspec(dllimport)#endiftypedef struct MyByteArray {     int size;     unsigned char values[1];  /* variable part */ } MyByteArray; enum EncryptionType{    EncryptionType_begin,    EncryptionType_1 = EncryptionType_begin,    EncryptionType_2,    EncryptionType_3,    // new ...    EncryptionType_end = EncryptionType_3,};enum CompressionType{    CompressionType_begin,    CompressionType_1 = CompressionType_begin,    CompressionType_2,    CompressionType_3,    // new ...    CompressionType_end = CompressionType_3,};DECODE_API int luaopen_decode (lua_State *L);static int newarray (lua_State *L);static int setarray (lua_State *L);static int getarray (lua_State *L);static int getsize (lua_State *L);static int decodearray (lua_State *L);static MyByteArray* decryptarray(unsigned char encryptionType, MyByteArray* myarray);static MyByteArray* decompressarray(unsigned char encryptionType, MyByteArray* myarray);

 

decode.cpp

#include "stdafx.h"#include "decode.h"static const struct luaL_reg decodeLib [] = {     {
"new", newarray}, {
"set", setarray}, {
"get", getarray}, {
"size", getsize}, {
"decode", decodearray}, {NULL, NULL} }; int luaopen_decode (lua_State *L) { luaL_openlib(L, "decode", decodeLib, 0); return 1; } static int newarray (lua_State *L) { int n = luaL_checkint(L, 1); size_t nbytes = sizeof(MyByteArray) + (n - 1)*sizeof(unsigned char); MyByteArray *a = (MyByteArray *)lua_newuserdata(L, nbytes); a->size = n; return 1; /* new userdatum is already on the stack */ }static int setarray (lua_State *L) { MyByteArray *a = (MyByteArray *)lua_touserdata(L, 1); int index = luaL_checkint(L, 2); unsigned char value = (unsigned char)luaL_checknumber(L, 3); luaL_argcheck(L, a != NULL, 1, "`array' expected"); luaL_argcheck(L, 0 <= index && index < a->size, 2, "index out of range"); a->values[index] = value; return 0; } static int getarray (lua_State *L) { MyByteArray *a = (MyByteArray *)lua_touserdata(L, 1); int index = luaL_checkint(L, 2); luaL_argcheck(L, a != NULL, 1, "'array' expected"); luaL_argcheck(L, 0 <= index && index < a->size, 2, "index out of range"); lua_pushnumber(L, a->values[index]); return 1; }static int getsize (lua_State *L) { MyByteArray *a = (MyByteArray *)lua_touserdata(L, 1); luaL_argcheck(L, a != NULL, 1, "`array' expected"); lua_pushnumber(L, a->size); return 1; } static int decodearray (lua_State *L) { unsigned char encryptionType = (unsigned char)lua_touserdata(L, 1); unsigned char compressionType = (unsigned char)lua_touserdata(L, 2); MyByteArray *a = (MyByteArray *)lua_touserdata(L, 3); luaL_argcheck(L, EncryptionType_begin<=encryptionType && encryptionType<=EncryptionType_end, 2, "undefine encryption type"); luaL_argcheck(L, CompressionType_begin<=compressionType && compressionType<=CompressionType_end, 2, "undefine compression type"); luaL_argcheck(L, a != NULL, 3, "`array' expected"); MyByteArray* a1 = NULL; MyByteArray* a2 = NULL; if (NULL != a) { a1 = decryptarray(encryptionType, a); if (NULL != a1) { a2 = decryptarray(compressionType, a1); } } if (NULL != a2) { lua_pushlightuserdata(L,a2); } else { lua_pushnil(L); } return 1; } //static MyByteArray* decryptarray(unsigned char encryptionType, MyByteArray* myarray) { MyByteArray* retarray = NULL; switch (encryptionType) { case EncryptionType_1: // TODO: break; case EncryptionType_2: // TODO: break; case EncryptionType_3: // TODO: break; default: break; } return retarray;}static MyByteArray* decompressarray(unsigned char encryptionType, MyByteArray* myarray) { MyByteArray* retarray = NULL; switch (encryptionType) { case CompressionType_1: // TODO: break; case CompressionType_2: // TODO: break; case CompressionType_3: // TODO: break; default: break; } return retarray;}

 

四、调用lua c 库解码

Lua解析脚本的开头需要增加部分代码,以加载新开发的decode.dll库。

Path = "D:\\Documents\\Visual Studio 2010\\Projects\\decode\\Debug\\decode.dll"decodelib = package.loadlib(path, "luaopen_decode")if nil ~= decodelib then    decodelib()end

 

DecodeBufferFunction的实现如下:

function DecodeBufferFunction(protoEncrytionType, protoCompressionType, buf, pos, buf_len)    if nil ~= decode then        -- construct MyByteArray        local rawLen = buf_len - pos        array = decode.new(rawLen)        for i=0,rawLen-1,1 do            decode.set(array,i, buf(pos,1):uint())        end        -- decode        array = decode.decode(protoEncrytionType, protoCompressionType, array)        if nil ~= array then            -- construct decodeBuf tvb            local decodeLen = decode.size(array)            -- construct tvb throught wireshark ByteArray            local bArray = ByteArray.new(decodeLen + pos)            for i=0,pos-1,1 do                bArray.set_index(i, buf(i,1):uint())            end            for i=0,decodeLen-1,1 do                bArray.set_index(pos+i, decode.get(array,i))            end            -- reture decode buffer            return bArray.tvb("decodeBuf")        end    end    return nilend

 

五、总结

通过上面的介绍,提供了wireshark中解析自定义加密协议的思路和大致实现。

需要注意的是:

1. LuaBinarires的版本问题。Wireshark采用了lua5.1和lua5.2,因此需要使用对应的LuaBinarires版本进行开发;

2. 开发lua c库,需要使用LuaBinarires的动态库版本。尤其是lua5.2,如果使用静态库进行开发,wireshark在加载decode.dll时会报错:multi lua VMs detected。

转载于:https://www.cnblogs.com/iamkun2005/p/4353046.html

你可能感兴趣的文章
Go语言基础之12--Channel
查看>>
Codeforces Round #446 Div1 E
查看>>
Linux代码的重用与强行卸载Linux驱动
查看>>
Quartz.Net实现定时任务调度
查看>>
Java多线程系列---“JUC原子类”01之 原子类的实现(CAS算法)
查看>>
基于朴素贝叶斯的定位算法
查看>>
排序算法-----总结
查看>>
【前端安全】JavaScript防http劫持与XSS
查看>>
14:调整数组顺序使奇数位于偶数的前面
查看>>
Android 开发工具方法整理
查看>>
windows下配置tomcat的虚拟路径编译器为IDEA
查看>>
Docker 命令导图
查看>>
关于.Net WebAPI数据认证(包括登陆认证、模型认证)
查看>>
吉他消音小技巧
查看>>
升级log4j到log4j2报错:cannot access org.apache.http.annotation.NotThreadSafe
查看>>
ASP工作积累
查看>>
编写可维护的JavaScript----笔记(三)
查看>>
LuoguP2762 太空飞行计划问题(最大权闭合子图,最小割)
查看>>
到底谁霸占了A类的IP地址
查看>>
在Fedora 20 上安装Mysql并初始化root密码
查看>>