Haskell 中的 Pcap 文件解码

发布于 2024-12-09 23:47:30 字数 2609 浏览 1 评论 0原文

我正在尝试解码 pcap 文件 和除了几件事之外,它工作正常。

import Network.Pcap
import System.IO
import Control.Monad

callfun f = do
    ( p , q ) <- next f 
    print $ hdrSeconds p  
    print $ hdrCaptureLength p
    print $ hdrWireLength p
    print q 
    when ( hdrWireLength p /= 0 ) $ callfun f    

main = do
    f <- openOffline "udp_lite_full_coverage_0.pcap"
    callfun f 

我希望 hdrSeconds p [ 捕获的时间 ] 返回的时间与wireshark [ 日期 : 月 : 年 : 分钟 : 秒 ] 中的格式相同,并且通过变量 q 以 Ascii 格式返回数据。请告诉我如何做到这一点。
实际上,我试图解析 pcap 文件以与不带 libpcap 库的wireshark 几乎类似的方式显示其内容[纯粹在 haskell 中通过以二进制格式打开 pcap 文件并逐字节读取],但我无法进一步。请有人提供这个项目的指南,比如读什么,如何进行,任何你认为有帮助的东西。

编辑: 我开始编写这个应用程序,但缺少一些东西。我读了这个文件 http://www.viste.com/Linux/Server/WireShark /libpcapformat.pdf 它说前 24 个字节是全局标头,之后每个数据包都包含 pcap 本地标头。我想做的是,首先尝试通过读取第三个数据包来获取每个数据包中的数据字节 本地标头中的 incl_len 字段,但我的代码的行为并不像它想象的那样。我的测试 libcap 文件

--http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf  
import Data.List 
import qualified Data.ByteString.Lazy as BS 
import qualified Data.ByteString.Lazy.Char8 as B 
import Control.Monad 
import Text.Printf 
import Data.Word 
import Data.Char 
import System.Time 
import Numeric 
import System.Environment 
hexTodec :: BS.ByteString ->  Integer 
hexTodec lst = read $   "0x" ++  (  concatMap ( \x -> showHex x "" ) $ BS.unpack lst  ) 
parseFile :: BS.ByteString -> Bool -> IO [ BS.ByteString ] 
parseFile xs revflag 
  | BS.null xs = return [] 
  | otherwise =   do 
    let ind =if revflag then   hexTodec . BS.reverse . BS.take 4 . BS.drop 8 $ xs 
              else hexTodec  . BS.take 4 . BS.drop 8 $ xs 
    print ind 
    let ( x , ys ) = BS.splitAt  ( fromIntegral ind  )  xs 
    --BS.putStrLn $ x 
    tmp <- parseFile ys revflag 
    return $ x : tmp 
main = do 
    [ file ]  <- getArgs 
    contents  <- BS.readFile file 
    let ( a , rest ) =  BS.splitAt 24  contents  --strip global header 
    let revflag = case BS.unpack $ BS.take 4  a of 
                    [ 0xd4 , 0xc3 , 0xb2 , 0xa1 ] -> True 
                    _ -> False 
    p <-   parseFile  rest  revflag 
    print $ p !! 0 
    BS.putStr $  p !! 0 


问候
穆克什·蒂瓦里

I am trying to decode a pcap file and its working fine except couple of things.

import Network.Pcap
import System.IO
import Control.Monad

callfun f = do
    ( p , q ) <- next f 
    print $ hdrSeconds p  
    print $ hdrCaptureLength p
    print $ hdrWireLength p
    print q 
    when ( hdrWireLength p /= 0 ) $ callfun f    

main = do
    f <- openOffline "udp_lite_full_coverage_0.pcap"
    callfun f 

I want the time return by hdrSeconds p [ time to capture ] in same format as in wireshark [ Date : Month : Year Hour : Min : Sec ] and data return by variable q in Ascii format.Kindly tell me how to do this.

Actually i was trying to parse pcap file to display its content in almost similar manner to wireshark without libpcap library [ purely in haskell by opening the pcap file in binary format and read byte by byte ] but i could not get any further. Could some please put the guide map for this project like what to read , how to approach , any thing which you feel would be helpful .

Edit:
I started writing this application but there is some thing missing. I read this file http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf and it say that first 24 bytes are global headers , after that every packet contains pcap local header . What i am trying to do is , first trying to get the bytes of data in each packet by reading the third
field incl_len in local header but my code is not behaving as it suppose . My test libcap file.

--http://www.viste.com/Linux/Server/WireShark/libpcapformat.pdf  
import Data.List 
import qualified Data.ByteString.Lazy as BS 
import qualified Data.ByteString.Lazy.Char8 as B 
import Control.Monad 
import Text.Printf 
import Data.Word 
import Data.Char 
import System.Time 
import Numeric 
import System.Environment 
hexTodec :: BS.ByteString ->  Integer 
hexTodec lst = read $   "0x" ++  (  concatMap ( \x -> showHex x "" ) $ BS.unpack lst  ) 
parseFile :: BS.ByteString -> Bool -> IO [ BS.ByteString ] 
parseFile xs revflag 
  | BS.null xs = return [] 
  | otherwise =   do 
    let ind =if revflag then   hexTodec . BS.reverse . BS.take 4 . BS.drop 8 $ xs 
              else hexTodec  . BS.take 4 . BS.drop 8 $ xs 
    print ind 
    let ( x , ys ) = BS.splitAt  ( fromIntegral ind  )  xs 
    --BS.putStrLn $ x 
    tmp <- parseFile ys revflag 
    return $ x : tmp 
main = do 
    [ file ]  <- getArgs 
    contents  <- BS.readFile file 
    let ( a , rest ) =  BS.splitAt 24  contents  --strip global header 
    let revflag = case BS.unpack $ BS.take 4  a of 
                    [ 0xd4 , 0xc3 , 0xb2 , 0xa1 ] -> True 
                    _ -> False 
    p <-   parseFile  rest  revflag 
    print $ p !! 0 
    BS.putStr $  p !! 0 

Regards

Mukesh Tiwari

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

_畞蕅 2024-12-16 23:47:31

我希望 hdrSeconds p [捕获时间]返回的时间与wireshark中的格式相同[日期:月份:年小时:分:秒]

您可以使用 time 包并将其转换为UTC 时间。这使得提取月、日、年等变得微不足道。查看 时间包 的黑线鳕更多。

let epoch = pcapEpochTimeThatYouFindInOnlineDocumentation
diff <- hdrDiffTime p
let date = addUTCTime (realToFrac diff) epoch

据我所知,Haskell 绑定不提供纪元,但一旦你发现这应该没问题。我会通过电子邮件将补丁发送给维护者,以将转换直接添加到 UTCTime。

并通过变量 q 以 Ascii 格式返回数据

q 只是一个积分,您可以使用 toEnumInt 中获取 Char

print (toEnum (fromIntegral q) :: Char)

那么 在纯 Haskell 中执行此操作,我认为您需要退后一步,了解有关 Haskell 作为一种语言的更多信息,也许可以从诸如 学习你哈斯克尔。如果您决心继续前进,请阅读邮件中提到的二进制包列为其非公共 pcap Haskell 库的首选库。

I want the time return by hdrSeconds p [ time to capture ] in same format as in wireshark [ Date : Month : Year Hour : Min : Sec ]

Well you can use the time package and convert this to a UTCTime. This makes it trivial to extract month, day, year, etc. Look at the time package's haddock for more.

let epoch = pcapEpochTimeThatYouFindInOnlineDocumentation
diff <- hdrDiffTime p
let date = addUTCTime (realToFrac diff) epoch

From what I can tell the Haskell bindings don't provide the epoch, but once you find that this should be fine. I'd e-mail in a patch to the maintainer to add a converstion directly to UTCTime.

and data return by variable q in Ascii format

Well q is just an intergral and you can get Chars from Ints using toEnum:

print (toEnum (fromIntegral q) :: Char)

As for doing this in pure Haskell, I think you need to step back a bit and learn more about Haskell as a language, perhaps from a tutuorial such as learnyouahaskell. If you are determined to forge ahead then read up on the binary package, which was mentioned on the mailing list as the library of choice for their non-public pcap Haskell library.

浪荡不羁 2024-12-16 23:47:31

您可以使用 Data.Time 模块将 hdrSeconds 返回的基于 UNIX 纪元的时间转换为 LocalTime 对象,然后将其格式化为带有 formatTime 的字符串。

import Data.Time.Clock.POSIX
import Data.Time.Format
import Data.Time.LocalTime
import System.Locale
import Data.Word (Word32)

data MockPCap = MockPCap { hdrSeconds :: Word32 }

toPosixTime :: Word32 -> POSIXTime
toPosixTime = fromIntegral

localHdrTime p = do tz <- getCurrentTimeZone
                    return $ utcToLocalTime tz $ posixSecondsToUTCTime $ toPosixTime $ hdrSeconds p

main = let p = MockPCap 1318464165  {-- Mock a PCap object --}
       in do hTime <- localHdrTime p
             print $ formatTime defaultTimeLocale "%c" hTime

You can use the Data.Time module to convert the UNIX epoch-based time returned by hdrSeconds to a LocalTime object that can then be formatted into a string with formatTime.

import Data.Time.Clock.POSIX
import Data.Time.Format
import Data.Time.LocalTime
import System.Locale
import Data.Word (Word32)

data MockPCap = MockPCap { hdrSeconds :: Word32 }

toPosixTime :: Word32 -> POSIXTime
toPosixTime = fromIntegral

localHdrTime p = do tz <- getCurrentTimeZone
                    return $ utcToLocalTime tz $ posixSecondsToUTCTime $ toPosixTime $ hdrSeconds p

main = let p = MockPCap 1318464165  {-- Mock a PCap object --}
       in do hTime <- localHdrTime p
             print $ formatTime defaultTimeLocale "%c" hTime
遮了一弯 2024-12-16 23:47:31

一个用于读取 pcap 文件的 Haskell 库,它负责解析文件头和数据包记录头的工作,因此您不必自己执行此操作。然而,您仍然需要自己解析数据包数据。

There's a Haskell library for reading pcap files, which does the work of parsing the file header and packet record headers, so you don't have to do that on your own. You're still on your own parsing the packet data, however.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文