發一個自己寫的抓包軟體,支援外掛化指令碼分析
市場上的抓包工具已經足夠多,輕量級的,重量級的都有,典型的wireshark,smartsniff等,
各有優缺點,PowerSniff是為程式設計師準備的一款抓包工具,目標是使協議解析外掛編寫更簡單。檔案格式完全相容wiareshark和tcpdump。
原理:捕獲到資料就呼叫預設定的指令碼,將資料的指標和長度傳遞給指令碼分析,在指令碼中也支援呼叫註冊函式。
無需編譯,支援即寫即用,目前支援c語言和lua兩種程式語言作為指令碼,安裝檔案自帶一些例子,歡迎測試並提供意見。
一、典型場景
抓包軟體執行時(或事後分析),希望對每個資料包使用外掛分析,smartsniff直接不支援,而wireshark編寫外掛成本太大,
需要安裝visual studio和相關sdk,不論是外掛本身的開發還是除錯,都不是一件簡單的事。
一些廠商對常見的協議(如rtsp),做了wireshark的外掛,但是如果是自己的協議,只能手工分析。
PowerSniff是為快速解決資料分析而來,(即便不考慮資料分析,介面和可操作性也比wireshark, smartsniff更友好),
對捕獲的網路資料包,即時指令碼編寫(語法高亮,即時編譯,即時執行,也可以直接用編寫好的指令碼),
目前指令碼支援lua和c語言,實測在i7上單核處理簡單指令碼外掛呼叫,lua每秒1萬次,c語言更快。
示例:QQ使用UDP協議,伺服器埠8000,登入包的第49位元組到53位元組是qq號,解析並顯示這個qq號
int handle_data(const char *protocol, unsigned char *data, int total_len, int data_len) { unsigned int qq_number = data[49] * 256 * 256 * 256 + data[50] * 256 * 256 + data[51] * 256 + data[52]; plugin_summary("debug-%d, qq_number is: %d", __LINE__, qq_number); return 0; }
將上面程式碼儲存為test1.c,然後再選單的外掛列表裡面啟用它即可。程式碼不需要編譯
等價於將c語言作為指令碼,由於程式碼只在load時編譯,所以外掛執行速度非常快。(除了c語言支援,另外還支援lua指令碼)
二、相關介面截圖
(1)選單
(2)設定
(3)lua編輯器
(4)c語言編輯器
(5)hex顯示介面
(6)安裝檔案列表
(7)第三方外掛xtrace
這個軟體預計下週單獨釋出,目前PowerSniff已經整合c++的sdk。
xtrace程式提供了sdk函式xtrace(),可以看成一個printf函式(支援本機和網路),只是它的輸出不是stdout,而是xtrace軟體。
c++的版本只需要包含一個20k自己的標頭檔案即可,不需要包含lib。另外也支援lua,python,javascript,c#,delphi等語言。
除了printf ,還支援xcounter功能,方便程式效能分析或計數用。(支援本機和網路)
c++最簡用法:
#include "xtrace.h"
xtrace(_T("hello, %s, %d\n"), _T("world"), 99999999);
不需要其它任何改動,直接替換vc裡面的TRACE巨集,或者printf函式。開啟xtrace主程式,即可看到相關輸出。
三、外掛編寫說明(檔案編碼必須使用utf8)
程式需要呼叫的lua介面,參考plugin/demo_lua.lua(1)init: 外掛初始化(2)handle_data: 當收到一個數據包時呼叫這個函式,函式return "delete"也可以起到過濾作用(3)handle_click:當單擊列表資料時呼叫這個函式(4)handle_double: 當雙擊列表資料時呼叫這個函式
lua中增加的可以回撥的程式介面:plugin_output_clear: 清空plugin output視窗plugin_output: 輸出到plugin output視窗plugin_summary: 輸出到listview最右邊的Plugin Summary項trace: 輸出到三方工具xtracetrace_raw: 輸出到三方工具xtrace
dbgview:輸出到三方工具dbgview.exe
------------------------------------------------------------
c語言自定義函式參考:bin\3rd\libtcc\include\powersniff.h
#ifndef __POWERSNIFF_DEFINE_H_ #define __POWERSNIFF_DEFINE_H_ int trace(const char *format, ...); int TRACE(const char *format, ...); int xtrace(const char *format, ...); int XTRACE(const char *format, ...); int trace_raw(int color, const char *format, ...); int TRACE_RAW(int color, const char *format, ...); int xtrace_raw(int color, const char *format, ...); int XTRACE_RAW(int color, const char *format, ...); int dbgview(const char *format, ...); int DBGView(const char *format, ...); int plugin_output(const char *format, ...); int PLUGIN_OUTPUT(const char *format, ...); int plugin_output_clear(); int PLUGIN_OUTPUT_CLEAR(); int plugin_summary(const char *format, ...); int PLUGIN_SUMMARY(const char *format, ...); #endif
解析qq號的lua指令碼:
-- file encode must be UTF8 -- qq號碼登入監視指令碼(不支援手機號碼登入,不支援webqq,只在pc上用qq2015測試通過) -- 2015.9.14 require "base64" require "tcp_ip" function init() trace("plugin init: ".._VERSION.."\n") trace("package path: "..package.path.."\n") trace("package path: "..package.cpath.."\n") --for k,v in pairs(_G) do -- trace(string.format("%s,%s\n", k, v)) --end end -- protocol: 字串如tcp,udp,icmp -- data: 二進位制資料 -- len_total: 總共資料長度 -- len_data: 有效資料長度(去除各種頭之後的資料) function handle_data(protocol,data,len_total,len_data) if 54 == len_total then return "delete" -- remove handshake end src_port = tcp_ip_get_src_port(data) dst_port = tcp_ip_get_dst_port(data) -- if 8000 != src_port && 8000 != dst_port then if (8000 ~= dst_port) or (len_data < 100) then return "delete" end if 2 ~= data:byte(43) then -- 0x2是qq udp協議magic number return "delete" end if 8 ~= data:byte(46) then -- 8和37是 0x8和0x25是協議型別,表示登入 return "delete" end if 37 ~= data:byte(47) then return "delete" end -- 50, 51, 52, 53位元組是qq號(lua index從1開始而不是0) qq_number = data:byte(50) * 256 * 256 * 256 + data:byte(51) * 256 * 256 + data:byte(52) * 256 + data:byte(53) plugin_summary("qq_number is: " .. qq_number) end function handle_click(protocol,data,len_total,len_data) if 54 == len_total then return end src_port = tcp_ip_get_src_port(data) dst_port = tcp_ip_get_dst_port(data) -- if 8000 != src_port && 8000 != dst_port then if (8000 ~= dst_port) or (len_data < 100) then return end if 2 ~= data:byte(43) then -- 0x2是qq udp協議magic number return end if 8 ~= data:byte(46) then -- 8和37是 0x8和0x25是協議型別,表示登入 return end if 37 ~= data:byte(47) then return end -- 50, 51, 52, 53位元組是qq號(lua index從1開始而不是0) qq_number = data:byte(50) * 256 * 256 * 256 + data:byte(51) * 256 * 256 + data:byte(52) * 256 + data:byte(53) plugin_output_clear() plugin_output("qq_number is: " .. qq_number.."\n") end function handle_double(protocol,data,len_total,len_data) handle_data(protocol,data,len_total,len_data) end
解析qq號的c指令碼:
// file encode must be UTF8 // sdk function: // init() // handle_data() // handle_click() // handle_double() // all data lock at background, you can use pointer any case, but need ATTENTION also. // out of memory or invalid pointer may crash the full virutal machine, or cause application fetal error. // the follow thread .h file should include! #include <winapi\windows.h> #include <winapi\wingdi.h> #include <powersniff.h> void init() { trace_raw(RGB(255, 0, 0), "do init here\n"); } // if return -1, the packet will be deleted! int handle_data(const char *protocol, unsigned char *data, int total_len, int data_len) { if(0 != strcmp("udp", protocol)) { return -1; // filter } if(data_len < 100) { return -1; // filter } short src_port = data[34] * 256 + data[35]; short dst_port = data[36] * 256 + data[37]; if(8000 != dst_port) return -1; if(2 != data[42]) // 0x2是qq udp協議magic number return -1; if(8 != data[45]) // 8和37是 0x8和0x25是協議型別,表示登入 return -1; if(37 != data[46]) return -1; unsigned int qq_number = data[49] * 256 * 256 * 256 + data[50] * 256 * 256 + data[51] * 256 + data[52]; plugin_summary("debug-%d, qq_number is: %d", __LINE__, qq_number); plugin_output_clear(); plugin_output("debug-%d, qq_number is: %d\n", __LINE__, qq_number); trace("debug-%d, qq_number is: %d\n", __LINE__, qq_number); return 0; } // fixed return 0 int handle_click(const char *protocol, unsigned char *data, int total_len, int data_len) { trace_raw(RGB(0, 0, 255), "blue output\n"); return 0; } // fixed return 0 int handle_double(const char *protocol, unsigned char *data, int total_len, int data_len) { trace("default color output\n"); trace_raw(RGB(0, 0, 255), "blue output\n"); dbgview("output to debugview.exe\n"); plugin_summary("hello1: %d", 123); plugin_output_clear(); plugin_output("hello2: %d", 123); plugin_output_clear(); plugin_output("hello3: %d\n", 456); plugin_output("hello4: %d\n", 789); return 0; } void *my_memcpy(void * to, const void * from, int n) { int d0, d1, d2; __asm__ __volatile__( "rep ; movsl\n\t" "testb $2,%b4\n\t" "je 1f\n\t" "movsw\n" "1:\ttestb $1,%b4\n\t" "je 2f\n\t" "movsb\n" "2:" : "=&c" (d0), "=&D" (d1), "=&S" (d2) :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from) : "memory"); return (to); }
四、其它抓包工具
重量級抓包工具:wireshark(推薦);科來網路分析軟體;ominipeek;etherpeek;Charles;(經過各種測試,還是wireshark最好用)
輕量級抓包工具:smartsniff:只有230KB(推薦);minisniff:只有45KB(2006年停止維護);powersniff:2.3M(包含若干個第三方外掛)
五、閉源。非商業使用無限制。收到BUG會解決(反饋qq群466507719)。無其它技術支援。
付費封閉協議分析及定製指令碼。目前只支援ipv4(tcp,udp,icmp),已對pcap數十個樣本測試,如需要其它協議可以定製。
六、借地找個工作,地點武漢光谷~~~
目標嵌入式,c++,伺服器端開發,移動端或web開發等軟體工作;也可以偏管理;
對web開發較有興趣,熟練的同學可以技能交換
(只收3year+的同學,不閒聊,武漢光谷有定期線下交流,最好能提供一份帶詳細專案經驗的簡歷,qq:80101277)
擁劍,中南民族大學附近2018.10.12