├── Main.hs ├── Morphism.hs ├── ParseTrace.hs ├── README.md ├── parse.cc ├── parse_syscall.cc ├── rp_syscall.cpp ├── strace_windows.cc ├── syscall.cc ├── syscall.h └── syscall_capture.cc /Main.hs: -------------------------------------------------------------------------------- 1 | module Main where 2 | 3 | import qualified System.Environment as E 4 | --import qualified Control.Monad as M 5 | --import qualified Data.List as L 6 | import ParseTrace 7 | --import qualified Text.ParserCombinators.Parsec as Parsec 8 | 9 | main :: IO () 10 | main = do 11 | args <- E.getArgs 12 | case args of 13 | (fileName : _) -> searchForLinearExtensionFromFile fileName 14 | --printGraphSelectedTraceFile fileName 15 | 16 | _ -> putStrLn "Please run as: this_program tracefile" 17 | 18 | {-main :: IO () 19 | main = do 20 | let rawLine = "1\ttest\targs\t" 21 | putStrLn $ show (parseRawLine rawLine)-} 22 | 23 | {-parseLine :: String -> IO () 24 | parseLine aLine = do 25 | case Parsec.parse lineParser "error" aLine of 26 | Left error -> putStrLn "Parsing error" 27 | Right fields -> M.mapM_ putStrLn fields 28 | 29 | lineParser :: Parsec.GenParser Char state [String] 30 | lineParser = do 31 | field1 <- fieldParser 32 | Parsec.char ',' 33 | field2 <- fieldParser 34 | return [field1,field2] 35 | 36 | fieldParser :: Parsec.GenParser Char state String 37 | fieldParser = Parsec.many (Parsec.noneOf ",")-} -------------------------------------------------------------------------------- /Morphism.hs: -------------------------------------------------------------------------------- 1 | module Morphism where 2 | 3 | import qualified Text.Printf as P 4 | import qualified Data.Graph.Inductive as G 5 | 6 | type Object = String 7 | 8 | data Morphism = Morphism { 9 | source :: Object, 10 | target :: Object, 11 | name :: String 12 | } 13 | 14 | {-type Path = [Morphism]-} 15 | 16 | instance Show Morphism where 17 | show morphism = P.printf "%-15s : %-10s -> %-10s" 18 | (name morphism) (source morphism) (target morphism) 19 | 20 | type ActiveObjects = [Object] 21 | 22 | {-G.Gr a b (a: label of node, b label of edge-} 23 | type OpenGraph = G.Gr String Object 24 | type TransOpenGraph = G.Gr String () 25 | 26 | data ActiveOpenGraph = ActiveOpenGraph { 27 | graph :: OpenGraph, 28 | input :: G.Node, 29 | output :: G.Node 30 | } 31 | -------------------------------------------------------------------------------- /ParseTrace.hs: -------------------------------------------------------------------------------- 1 | module ParseTrace where 2 | 3 | import qualified System.IO as I 4 | import qualified Data.List as L 5 | --import qualified System.Environment 6 | import qualified Text.ParserCombinators.Parsec as Parsec 7 | import qualified Control.Monad as M 8 | import qualified Control.Monad.State as M 9 | import qualified Control.Monad.Loops as M 10 | --import qualified Control.Monad.LoopWhile as M 11 | import qualified Text.Printf as P 12 | import qualified Data.Graph.Inductive.Graph as G 13 | import qualified Data.Graph.Inductive.Query.TransClos as G 14 | import qualified Data.Graph.Inductive.Graphviz as G 15 | import qualified Data.Random as R 16 | import qualified Data.Random.Source.DevRandom as R 17 | import qualified Data.Random.Extras as R 18 | 19 | import Morphism 20 | 21 | data RawSyscall = RawSyscall { 22 | sindex :: String, 23 | sname :: String, 24 | sarguments :: String 25 | } 26 | 27 | instance Show RawSyscall where 28 | show rawSyscall = P.printf "%s %s %s" (sindex rawSyscall) (sname rawSyscall) (sarguments rawSyscall) 29 | 30 | countLineTraceFile :: String -> IO Int 31 | countLineTraceFile fileName = do 32 | fileContent <- I.readFile fileName 33 | let fileLines = L.lines fileContent 34 | return $ L.length fileLines 35 | 36 | printTraceFile :: String -> IO () 37 | printTraceFile fileName = do 38 | fileContent <- I.readFile fileName 39 | let fileLines = L.lines fileContent 40 | M.mapM_ putStrLn fileLines 41 | 42 | printParsedTraceFile :: String -> IO () 43 | printParsedTraceFile fileName = do 44 | fileContent <- I.readFile fileName 45 | let fileLines = L.lines fileContent 46 | rawSyscalls = map parseRawLine fileLines 47 | rawSyscallStrings = map show rawSyscalls 48 | M.mapM_ putStrLn rawSyscallStrings 49 | 50 | parseRawLine :: String -> RawSyscall 51 | parseRawLine rawLine = 52 | case Parsec.parse rawLineParser "parsing error" rawLine of 53 | Left _ -> RawSyscall { sindex = [], sname = [], sarguments = [] } 54 | Right fields -> fields 55 | 56 | rawLineParser :: Parsec.GenParser Char status RawSyscall 57 | rawLineParser = do 58 | syscallIndex <- Parsec.many (Parsec.noneOf "\t") 59 | _ <- Parsec.char '\t' 60 | syscallName <- Parsec.many (Parsec.noneOf "\t") 61 | _ <- Parsec.char '\t' 62 | syscallArguments <- Parsec.many (Parsec.noneOf "\t") 63 | return RawSyscall { sindex = syscallIndex, sname = syscallName, sarguments = syscallArguments } 64 | 65 | parseSyscall :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 66 | parseSyscall rawSyscall = 67 | case sname rawSyscall of 68 | "NtCreateKey" -> parseNtCreateKey rawSyscall 69 | "NtSetValueKey" -> parseNtSetValueKey rawSyscall 70 | "NtQueryValueKey" -> parseNtQueryValueKey rawSyscall 71 | "NtOpenKey" -> parseNtOpenKey rawSyscall 72 | "NtClose" -> parseNtClose rawSyscall 73 | _ -> return Nothing 74 | 75 | filterRawSyscalls :: [RawSyscall] -> M.State ActiveObjects [Morphism] 76 | filterRawSyscalls rawSyscalls = 77 | case rawSyscalls of 78 | (rawSyscall : otherRawSyscalls) -> do 79 | newMorphism <- parseSyscall rawSyscall 80 | case newMorphism of 81 | Just morphism -> do 82 | otherMorphisms <- filterRawSyscalls otherRawSyscalls 83 | return $ morphism : otherMorphisms 84 | Nothing -> filterRawSyscalls otherRawSyscalls 85 | _ -> return [] 86 | 87 | printSelectedTraceFile :: String -> IO () 88 | printSelectedTraceFile fileName = do 89 | fileContent <- I.readFile fileName 90 | let rawLines = L.lines fileContent 91 | rawSyscalls = map parseRawLine rawLines 92 | selectedMorphisms = M.evalState (filterRawSyscalls rawSyscalls) [] 93 | selectedMorphismStrings = map show selectedMorphisms 94 | M.mapM_ putStrLn selectedMorphismStrings 95 | 96 | parseGraphSyscall :: RawSyscall -> M.State ActiveOpenGraph () 97 | parseGraphSyscall rawSyscall = 98 | case sname rawSyscall of 99 | "NtCreateKey" -> parseGraphNtCreateKey rawSyscall 100 | "NtSetValueKey" -> parseGraphNtSetValueKey rawSyscall 101 | "NtQueryValueKey" -> parseGraphNtQueryValueKey rawSyscall 102 | "NtOpenKey" -> parseGraphNtOpenKey rawSyscall 103 | "NtClose" -> parseGraphNtClose rawSyscall 104 | _ -> return () 105 | 106 | parseGraphSyscall' ::RawSyscall -> M.State ActiveOpenGraph () 107 | parseGraphSyscall' rawSyscall = 108 | case sname rawSyscall of 109 | "NtCreateKey" -> parseGraphDataGenerator fNtCreateKeyParser rawSyscall 110 | "NtOpenKey" -> parseGraphDataGenerator fNtCreateKeyParser rawSyscall 111 | "NtCreateFile" -> parseGraphDataGenerator fNtCreateFileParser rawSyscall 112 | "NtOpenFile" -> parseGraphDataGenerator fNtCreateFileParser rawSyscall 113 | 114 | "NtSetValueKey" -> parseGraphDataModifier fNtSetValueKeyParser rawSyscall 115 | "NtQueryValueKey" -> parseGraphDataModifier fNtSetValueKeyParser rawSyscall 116 | "NtWriteFile" -> parseGraphDataModifier fNtWriteFileParser rawSyscall 117 | "NtReadFile" -> parseGraphDataModifier fNtWriteFileParser rawSyscall 118 | 119 | "NtClose" -> parseGraphDataAnnihilator fNtCloseParser rawSyscall 120 | 121 | _ -> return () 122 | 123 | filterGraphRawSyscalls :: [RawSyscall] -> M.State ActiveOpenGraph () 124 | filterGraphRawSyscalls = M.mapM_ parseGraphSyscall' 125 | 126 | printGraphSelectedTraceFile :: String -> IO () 127 | printGraphSelectedTraceFile fileName = do 128 | --fileContent <- I.readFile fileName 129 | --let rawLines = L.lines fileContent 130 | -- rawSyscalls = map parseRawLine rawLines 131 | -- inputNode = (0, "Input") 132 | -- outputNode = (1, "Output") 133 | -- initActiveOpenGraph = ActiveOpenGraph { graph = G.insNodes [inputNode,outputNode] G.empty, 134 | -- input = fst inputNode, output = fst outputNode } 135 | -- finalActiveOpenGraph = M.execState (filterGraphRawSyscalls rawSyscalls) initActiveOpenGraph 136 | --putStrLn $ G.graphviz' (graph finalActiveOpenGraph) 137 | finalActiveOpenGraph <- constructGraph fileName 138 | putStrLn $ G.graphviz (graph finalActiveOpenGraph) "TraceOpenGraph" (8.3,11.7) (0,0) G.Portrait 139 | 140 | 141 | {---------------------------------------------------------------------------------------------------------------------} 142 | {- generate random linear extensions -} 143 | {---------------------------------------------------------------------------------------------------------------------} 144 | isConnected :: G.Node -> G.Node -> TransOpenGraph -> Bool 145 | isConnected headNode tailNode transGraph = tailNode `L.elem` G.suc transGraph headNode 146 | 147 | swapAt :: Int -> [G.Node] -> [G.Node] 148 | swapAt index nodes = L.take index nodes ++ [nodes !! index + 1,nodes !! index] ++ L.drop (index + 1) nodes 149 | 150 | randomLinearExtension :: TransOpenGraph -> [G.Node] -> IO [G.Node] 151 | randomLinearExtension transGraph currentLE = do 152 | let upperIndex = L.length currentLE - 2 153 | randomIndex <- R.runRVar (R.choice [0..upperIndex]) R.DevRandom 154 | return $ 155 | if isConnected (currentLE !! randomIndex) (currentLE !! (randomIndex + 1)) transGraph 156 | then [] 157 | else swapAt randomIndex currentLE 158 | 159 | constructGraph :: String -> IO ActiveOpenGraph 160 | constructGraph fileName = do 161 | fileContent <- I.readFile fileName 162 | let rawLines = L.lines fileContent 163 | rawSyscalls = map parseRawLine rawLines 164 | inputNode = (0, "Input") 165 | outputNode = (1, "Output") 166 | initActiveOpenGraph = ActiveOpenGraph { graph = G.insNodes [inputNode,outputNode] G.empty, 167 | input = fst inputNode, output = fst outputNode } 168 | finalActiveOpenGraph = M.execState (filterGraphRawSyscalls rawSyscalls) initActiveOpenGraph 169 | return finalActiveOpenGraph 170 | 171 | searchForLinearExtensionFromFile :: String -> IO () 172 | searchForLinearExtensionFromFile fileName = do 173 | finalActiveOpenGraph <- constructGraph fileName 174 | let standardGraph = G.delNodes [0,1] (graph finalActiveOpenGraph) 175 | print (G.nodes standardGraph) 176 | let transGraph = G.trc standardGraph 177 | newLinExt <- M.iterateUntil (not . null) (randomLinearExtension transGraph (G.nodes standardGraph)) 178 | --newLinExt <- randomLinearExtension transGraph (G.nodes standardGraph) 179 | print newLinExt 180 | 181 | 182 | {---------------------------------------------------------------------------------------------------------------------} 183 | {- parsing functions -} 184 | {---------------------------------------------------------------------------------------------------------------------} 185 | {-error parsing morphism-} 186 | errorMorphism :: String -> Morphism 187 | errorMorphism syscallName = 188 | Morphism { name = syscallName, source = "unknown", target = "unknown" } 189 | 190 | {-parse NtCreateFile-} 191 | fNtCreateFileParser :: Parsec.GenParser Char status String 192 | fNtCreateFileParser = do 193 | _ <- Parsec.string "(FileHdl=>" 194 | Parsec.many (Parsec.noneOf ",") 195 | 196 | parseNtCreateFile :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 197 | parseNtCreateFile rawSyscall = 198 | case Parsec.parse fNtCreateFileParser "parsing error" (sarguments rawSyscall) of 199 | Left _ -> return Nothing 200 | Right object -> 201 | if object == "0x00000000" 202 | then return Nothing 203 | else do 204 | currentActiveObjects <- M.get 205 | M.put $ object : currentActiveObjects 206 | return $ Just Morphism { name = sname rawSyscall, source = "e", target = object } 207 | 208 | parseGraphNtCreateFile :: RawSyscall -> M.State ActiveOpenGraph () 209 | parseGraphNtCreateFile rawSyscall = 210 | case Parsec.parse fNtCreateFileParser "parsing error" (sarguments rawSyscall) of 211 | Left _ -> return () 212 | Right object -> 213 | M.unless (object == "0x00000000") $ do 214 | currentActiveOpenGraph <- M.get 215 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 216 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 217 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 218 | newEdge1 = (newId, output currentActiveOpenGraph, object) 219 | newOpenGraph2 = G.insEdge newEdge1 newOpenGraph1 220 | newEdge2 = (input currentActiveOpenGraph, newId, "0x00000000") 221 | newOpenGraph3 = G.insEdge newEdge2 newOpenGraph2 222 | M.put ActiveOpenGraph { graph = newOpenGraph3, 223 | input = input currentActiveOpenGraph, 224 | output = output currentActiveOpenGraph } 225 | return () 226 | 227 | {-parse NtOpenFile-} 228 | parseNtOpenFile :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 229 | parseNtOpenFile = parseNtCreateFile 230 | 231 | {-parse NtWriteFile-} 232 | fNtWriteFileParser :: Parsec.GenParser Char status String 233 | fNtWriteFileParser = do 234 | _ <- Parsec.string "(FileHdl<=" 235 | Parsec.many (Parsec.noneOf ",") 236 | 237 | parseNtWriteFile :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 238 | parseNtWriteFile rawSyscall = 239 | case Parsec.parse fNtWriteFileParser "parsing error" (sarguments rawSyscall) of 240 | Left _ -> return Nothing 241 | Right object -> do 242 | currentActiveObjects <- M.get 243 | return $ 244 | if object `L.elem` currentActiveObjects 245 | then Just Morphism { name = sname rawSyscall, source = object, target = object } 246 | else Nothing 247 | 248 | parseGraphNtWriteFile :: RawSyscall -> M.State ActiveOpenGraph () 249 | parseGraphNtWriteFile = parseGraphNtSetValueKey 250 | 251 | {-parse NtReadFile-} 252 | parseNtReadFile :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 253 | parseNtReadFile = parseNtWriteFile 254 | 255 | parseGraphNtReadFile :: RawSyscall -> M.State ActiveOpenGraph () 256 | parseGraphNtReadFile = parseGraphNtWriteFile 257 | 258 | {-parse NtClose-} 259 | fNtCloseParser :: Parsec.GenParser Char status String 260 | fNtCloseParser = do 261 | _ <- Parsec.string "(Hdl<=" 262 | Parsec.many (Parsec.noneOf ",)") 263 | 264 | {-linear parsing-} 265 | parseNtClose :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 266 | parseNtClose rawSyscall = 267 | case Parsec.parse fNtCloseParser "parsing error" (sarguments rawSyscall) of 268 | Left _ -> return Nothing 269 | Right object -> do 270 | currentActiveObjects <- M.get 271 | if object `L.elem` currentActiveObjects 272 | then do 273 | let newActiveObjects = L.filter ( /= object) currentActiveObjects 274 | M.put newActiveObjects 275 | return $ Just Morphism { name = sname rawSyscall, source = object, target = "e" } 276 | else return Nothing 277 | 278 | {-graphical parsing-} 279 | parseGraphNtClose :: RawSyscall -> M.State ActiveOpenGraph () 280 | parseGraphNtClose rawSyscall = 281 | case Parsec.parse fNtCloseParser "parsing error" (sarguments rawSyscall) of 282 | Left _ -> return () 283 | Right object -> do 284 | currentActiveOpenGraph <- M.get 285 | let openLEdges = G.inn (graph currentActiveOpenGraph) (output currentActiveOpenGraph) 286 | case L.find (\(_,_,x) -> x == object) openLEdges of 287 | Nothing -> return () 288 | Just (pre, _, _) -> do 289 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 290 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 291 | newEdge1 = (pre, newId, object) 292 | newEdge2 = (newId, output currentActiveOpenGraph, "0x00000000") 293 | exisingEdge = (pre, output currentActiveOpenGraph, object) 294 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 295 | newOpenGraph2 = G.insEdges [newEdge1,newEdge2] newOpenGraph1 296 | newOpenGraph3 = G.delLEdge exisingEdge newOpenGraph2 297 | M.put ActiveOpenGraph { graph = newOpenGraph3, 298 | input = input currentActiveOpenGraph, 299 | output = output currentActiveOpenGraph } 300 | return () 301 | 302 | {-parse NtCreateKey-} 303 | fNtCreateKeyParser :: Parsec.GenParser Char status String 304 | fNtCreateKeyParser = do 305 | _ <- Parsec.string "(KeyHdl=>" 306 | Parsec.many (Parsec.noneOf ",") 307 | 308 | parseNtCreateKey :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 309 | parseNtCreateKey rawSyscall = 310 | case Parsec.parse fNtCreateKeyParser "parsing error" (sarguments rawSyscall) of 311 | Left _ -> return Nothing 312 | Right object -> 313 | if object == "0x00000000" 314 | then return Nothing 315 | else do 316 | currentActiveObjects <- M.get 317 | M.put $ object : currentActiveObjects 318 | return $ Just Morphism { name = sname rawSyscall, source = "e", target = object } 319 | 320 | {-parse NtCreateKey-} 321 | parseGraphNtCreateKey :: RawSyscall -> M.State ActiveOpenGraph () 322 | parseGraphNtCreateKey rawSyscall = 323 | case Parsec.parse fNtCreateKeyParser "parsing error" (sarguments rawSyscall) of 324 | Left _ -> return () 325 | Right object -> M.unless (object == "0x00000000") $ do 326 | currentActiveOpenGraph <- M.get 327 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 328 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 329 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 330 | newEdge1 = (newId, output currentActiveOpenGraph, object) 331 | newOpenGraph2 = G.insEdge newEdge1 newOpenGraph1 332 | newEdge2 = (input currentActiveOpenGraph, newId, "0x00000000") 333 | newOpenGraph3 = G.insEdge newEdge2 newOpenGraph2 334 | M.put ActiveOpenGraph { graph = newOpenGraph3, 335 | input = input currentActiveOpenGraph, 336 | output = output currentActiveOpenGraph } 337 | return () 338 | 339 | parseNtOpenKey :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 340 | parseNtOpenKey = parseNtCreateKey 341 | 342 | {-parse NtOpenKey-} 343 | parseGraphNtOpenKey :: RawSyscall -> M.State ActiveOpenGraph () 344 | parseGraphNtOpenKey = parseGraphNtCreateKey 345 | 346 | {-parse NtSetValueKey-} 347 | fNtSetValueKeyParser :: Parsec.GenParser Char status String 348 | fNtSetValueKeyParser = do 349 | _ <- Parsec.string "(KeyHdl<=" 350 | Parsec.many (Parsec.noneOf ",") 351 | 352 | parseNtSetValueKey :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 353 | parseNtSetValueKey rawSyscall = 354 | case Parsec.parse fNtSetValueKeyParser "parsing error" (sarguments rawSyscall) of 355 | Left _ -> return Nothing 356 | Right object -> do 357 | currentActiveObjects <- M.get 358 | return $ 359 | if object `L.elem` currentActiveObjects 360 | then Just Morphism { name = sname rawSyscall, source = object, target = object } 361 | else Nothing 362 | 363 | parseGraphNtSetValueKey :: RawSyscall -> M.State ActiveOpenGraph () 364 | parseGraphNtSetValueKey rawSyscall = 365 | case Parsec.parse fNtSetValueKeyParser "parsing error" (sarguments rawSyscall) of 366 | Left _ -> return () 367 | Right object -> do 368 | currentActiveOpenGraph <- M.get 369 | let openLEdges = G.inn (graph currentActiveOpenGraph) (output currentActiveOpenGraph) 370 | case L.find (\(_,_,x) -> x == object) openLEdges of 371 | Nothing -> return () 372 | Just (pre, _, _) -> do 373 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 374 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 375 | newEdge1 = (pre, newId, object) 376 | newEdge2 = (newId, output currentActiveOpenGraph, object) 377 | exisingEdge = (pre, output currentActiveOpenGraph, object) 378 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 379 | newOpenGraph2 = G.insEdges [newEdge1,newEdge2] newOpenGraph1 380 | newOpenGraph3 = G.delLEdge exisingEdge newOpenGraph2 381 | M.put ActiveOpenGraph { graph = newOpenGraph3, 382 | input = input currentActiveOpenGraph, 383 | output = output currentActiveOpenGraph } 384 | return () 385 | 386 | 387 | parseNtQueryValueKey :: RawSyscall -> M.State ActiveObjects (Maybe Morphism) 388 | parseNtQueryValueKey = parseNtSetValueKey 389 | 390 | parseGraphNtQueryValueKey :: RawSyscall -> M.State ActiveOpenGraph () 391 | parseGraphNtQueryValueKey = parseGraphNtSetValueKey 392 | 393 | parseGraphDataModifier :: Parsec.Parser String -> RawSyscall -> M.State ActiveOpenGraph () 394 | parseGraphDataModifier syscallParser rawSyscall = 395 | case Parsec.parse syscallParser "parsing error" (sarguments rawSyscall) of 396 | Left _ -> return () 397 | Right object -> do 398 | currentActiveOpenGraph <- M.get 399 | let openLEdges = G.inn (graph currentActiveOpenGraph) (output currentActiveOpenGraph) 400 | case L.find (\(_,_,x) -> x == object) openLEdges of 401 | Nothing -> return () 402 | Just (pre, _, _) -> do 403 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 404 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 405 | newEdge1 = (pre, newId, object) 406 | newEdge2 = (newId, output currentActiveOpenGraph, object) 407 | exisingEdge = (pre, output currentActiveOpenGraph, object) 408 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 409 | newOpenGraph2 = G.insEdges [newEdge1,newEdge2] newOpenGraph1 410 | newOpenGraph3 = G.delLEdge exisingEdge newOpenGraph2 411 | M.put ActiveOpenGraph { graph = newOpenGraph3, 412 | input = input currentActiveOpenGraph, 413 | output = output currentActiveOpenGraph } 414 | return () 415 | 416 | 417 | parseGraphDataGenerator :: Parsec.Parser String -> RawSyscall -> M.State ActiveOpenGraph () 418 | parseGraphDataGenerator syscallParser rawSyscall = 419 | case Parsec.parse syscallParser "parsing error" (sarguments rawSyscall) of 420 | Left _ -> return () 421 | Right object -> M.unless (object == "0x00000000") $ do 422 | currentActiveOpenGraph <- M.get 423 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 424 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 425 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 426 | newEdge1 = (newId, output currentActiveOpenGraph, object) 427 | newOpenGraph2 = G.insEdge newEdge1 newOpenGraph1 428 | newEdge2 = (input currentActiveOpenGraph, newId, "0x00000000") 429 | newOpenGraph3 = G.insEdge newEdge2 newOpenGraph2 430 | M.put ActiveOpenGraph { graph = newOpenGraph3, 431 | input = input currentActiveOpenGraph, 432 | output = output currentActiveOpenGraph } 433 | return () 434 | 435 | parseGraphDataAnnihilator :: Parsec.Parser String -> RawSyscall -> M.State ActiveOpenGraph () 436 | parseGraphDataAnnihilator syscallParser rawSyscall = 437 | case Parsec.parse syscallParser "parsing error" (sarguments rawSyscall) of 438 | Left _ -> return () 439 | Right object -> do 440 | currentActiveOpenGraph <- M.get 441 | let openLEdges = G.inn (graph currentActiveOpenGraph) (output currentActiveOpenGraph) 442 | case L.find (\(_,_,x) -> x == object) openLEdges of 443 | Nothing -> return () 444 | Just (pre, _, _) -> do 445 | let newId = L.length $ G.nodes (graph currentActiveOpenGraph) 446 | newNode = (newId, sname rawSyscall ++ "\n(" ++ show (newId - 1) ++ ")") 447 | newEdge1 = (pre, newId, object) 448 | newEdge2 = (newId, output currentActiveOpenGraph, "0x00000000") 449 | exisingEdge = (pre, output currentActiveOpenGraph, object) 450 | newOpenGraph1 = G.insNode newNode (graph currentActiveOpenGraph) 451 | newOpenGraph2 = G.insEdges [newEdge1,newEdge2] newOpenGraph1 452 | newOpenGraph3 = G.delLEdge exisingEdge newOpenGraph2 453 | M.put ActiveOpenGraph { graph = newOpenGraph3, 454 | input = input currentActiveOpenGraph, 455 | output = output currentActiveOpenGraph } 456 | return () -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #### SyscallTrace: a tool for tracing and obfuscating system calls -------------------------------------------------------------------------------- /parse.cc: -------------------------------------------------------------------------------- 1 | /* parse.cc */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "syscall.h" 12 | 13 | /* exported functions */ 14 | std::vector< std::shared_ptr > load_syscall_table(const std::string&); 15 | std::string lookup_syscall_name(std::vector< std::shared_ptr >&, int); 16 | int lookup_syscall_number(std::vector< std::shared_ptr > &syscall_table, 17 | std::string &syscall_name); 18 | 19 | /* ============================================================================ 20 | * parse a syscall table. 21 | * some codes are copied from: 22 | * http://stackoverflow.com/questions/7868936/c-read-file-line-by-line 23 | * ========================================================================== */ 24 | std::vector< std::shared_ptr > load_syscall_table(const std::string &syscall_table_file_name) 25 | { 26 | // initialize a vector of syscall's smart pointers 27 | std::vector< std::shared_ptr > syscall_table; 28 | 29 | // open file the syscall table file 30 | std::ifstream syscall_table_file(syscall_table_file_name); 31 | if (syscall_table_file.is_open()) { 32 | std::string current_line; 33 | 34 | // read it line by line 35 | while (std::getline(syscall_table_file, current_line)) { 36 | std::istringstream iss(current_line); 37 | std::string name = ""; int number = 0; 38 | 39 | // parse the current line 40 | iss >> name >> std::hex >> number; 41 | 42 | // create a smart pointer from parsed data and push it into the vector 43 | std::shared_ptr p_syscall(new syscall(number, name)); 44 | syscall_table.push_back(p_syscall); 45 | } 46 | 47 | // remember to close file 48 | syscall_table_file.close(); 49 | } 50 | else std::cerr << "Open syscall table error, continue running without translator." 51 | << std::endl; 52 | 53 | return syscall_table; 54 | } 55 | 56 | /* ============================================================================ 57 | * lookup the syscall name given its number 58 | * ========================================================================== */ 59 | std::string lookup_syscall_name(std::vector< std::shared_ptr > &syscall_table, 60 | int syscall_number) 61 | { 62 | std::vector< std::shared_ptr >::iterator iter_syscall = syscall_table.begin(); 63 | do { 64 | if ((*iter_syscall)->number == syscall_number) break; 65 | else iter_syscall++; 66 | } 67 | while (iter_syscall != syscall_table.end()); 68 | 69 | if (iter_syscall != syscall_table.end()) return (*iter_syscall)->name; 70 | else return "Unknow"; 71 | } 72 | 73 | /* ============================================================================ 74 | * lookup the syscall number given its name 75 | * ========================================================================== */ 76 | int lookup_syscall_number(std::vector< std::shared_ptr > &syscall_table, 77 | std::string &syscall_name) 78 | { 79 | std::vector< std::shared_ptr >::iterator iter_syscall = syscall_table.begin(); 80 | do { 81 | if ((*iter_syscall)->name == syscall_name) break; 82 | else iter_syscall++; 83 | } 84 | while (iter_syscall != syscall_table.end()); 85 | 86 | if (iter_syscall != syscall_table.end()) return (*iter_syscall)->number; 87 | else return -1; 88 | } 89 | -------------------------------------------------------------------------------- /parse_syscall.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* exported functions */ 18 | std::string process_dependent_trace_name(unsigned int pid); 19 | 20 | void parse_generic_syscall(std::wofstream &trace, std::string &syscall_name, 21 | unsigned int args[], unsigned int return_code); 22 | 23 | void parse_interesting_syscall(std::wofstream &trace, std::string &syscall_name, 24 | unsigned int args[], unsigned int return_code); 25 | 26 | bool is_verbose(std::string &syscall_name); 27 | 28 | bool is_intersting(std::string &syscall_name); 29 | 30 | /* local functions */ 31 | static std::wstring wbuffer_to_wstring(wchar_t *buffer, unsigned int length); 32 | 33 | static std::wstring cbuffer_to_wstring(char *buffer, unsigned int length); 34 | 35 | /* local variables */ 36 | static std::array verbose_syscalls = 37 | { 38 | "NtFlushInstructionCache", "NtRequestWaitReplyPort", "NtQueryPerformanceCounter", 39 | "NtTestAlert", "NtContinue", "NtQueryDebugFilterState", "NtConnectPort" 40 | "NtQueryDefaultLocale", "NtDelayExecution", "NtWaitForMultipleObjects32", 41 | "NtAccessCheckAndAuditAlarm", "NtReplyWaitReceivePortEx", "NtQueryDefaultUILanguage", 42 | "NtQueryInstallUILanguage", "NtQueryDefaultLocale", "Unknow" 43 | }; 44 | 45 | static std::array interesting_syscalls = 46 | { 47 | "NtReadFile", "NtWriteFile", "NtCreateFile", "NtOpenFile", "NtClose", 48 | "NtCreateSection", "NtMapViewOfSection", "NtUnmapViewOfSection", "NtOpenSection", 49 | "NtOpenKey", "NtCreateKey", "NtSetValueKey", "NtQueryKey", "NtQueryValueKey", 50 | "NtAllocateVirtualMemory", "NtFreeVirtualMemory", "NtDeviceIoControlFile", 51 | "NtCreateEvent", "NtWaitForSingleObject", "NtFlushBuffersFile", "NtQueryInformationFile", 52 | "NtQueryVolumeInformationFile", "NtSetInformationFile", "NtQueryDirectoryFile", 53 | "NtEnumerateKey", "NtOpenProcess", "NtCreateProcessEx", "NtReadVirtualMemory", 54 | "NtWriteVirtualMemory", "NtCreateThread", "NtResumeThread", "NtQueryInformationProcess", 55 | "NtQuerySection", "NtQueryInformationToken", "NtSetInformationProcess", 56 | "NtQueryAttributesFile", "NtSetEvent", "NtQueryEvent", "NtOpenEvent", 57 | "NtOpenThreadToken", "NtOpenThreadTokenEx", "NtSetInformationObject", "NtQueryVirtualMemory", 58 | "NtQueryInformationThread", "NtTerminateThread", "NtSetInformationThread" 59 | "NtCreateSemaphore", "NtReleaseSemaphore", "NtProtectVirtualMemory", 60 | "NtOpenProcessToken", "NtAdjustPrivilegesToken", "NtFsControlFile", 61 | "NtDuplicateToken", "NtOpenProcessTokenEx", "NtDuplicateObject", 62 | "NtQuerySystemInformation" 63 | }; 64 | 65 | /* ============================================================================ 66 | * generate a trace file name depending on process id 67 | * ========================================================================== */ 68 | std::string process_dependent_trace_name(unsigned int pid) 69 | { 70 | std::stringstream ss; 71 | ss << std::dec << pid; 72 | 73 | std::string trace_name("strace_windows."); 74 | trace_name += ss.str(); trace_name += ".txt"; 75 | return trace_name; 76 | } 77 | 78 | /* ============================================================================ 79 | * filter some verbose syscalls 80 | * ========================================================================== */ 81 | bool is_verbose(std::string &syscall_name) 82 | { 83 | if (std::find(verbose_syscalls.begin(), verbose_syscalls.end(), syscall_name) 84 | != verbose_syscalls.end()) return true; 85 | else return false; 86 | } 87 | 88 | /* ============================================================================ 89 | * filter some interesting syscalls 90 | * ========================================================================== */ 91 | bool is_intersting(std::string &syscall_name) 92 | { 93 | if (std::find(interesting_syscalls.begin(), interesting_syscalls.end(), syscall_name) 94 | != interesting_syscalls.end()) return true; 95 | else return false; 96 | } 97 | 98 | /* ============================================================================ 99 | * convert wchar_t* buffer to std::wstring 100 | * ========================================================================== */ 101 | std::wstring wbuffer_to_wstring(wchar_t *buffer, unsigned int length) 102 | { 103 | wchar_t *w_buffer = new wchar_t[length + 1](); 104 | ::wcsncpy(w_buffer, buffer, length); 105 | std::wstring result(w_buffer); 106 | 107 | delete[] w_buffer; 108 | return result; 109 | } 110 | 111 | /* ============================================================================ 112 | * convert char* buffer to std::wstring 113 | * ========================================================================== */ 114 | std::wstring cbuffer_to_wstring(char *buffer, unsigned int length) 115 | { 116 | char *c_buffer = new char[length + 1](); 117 | ::strncpy(c_buffer, buffer, length); 118 | std::string c_result(c_buffer); 119 | std::wstring result(c_result.begin(), c_result.end()); 120 | 121 | delete[] c_buffer; 122 | return result; 123 | } 124 | 125 | 126 | /* ============================================================================ 127 | * parse the NtCreateFile syscall 128 | * ========================================================================== */ 129 | void parse_args_NtCreateFile(std::wofstream &trace, unsigned int args[]) 130 | { 131 | // trace << L"NtCreateFile\t("; 132 | 133 | // get the output file handle 134 | PHANDLE hFileHandle = PHANDLE (args[0]); 135 | trace << L"FileHdl=>0x" << *hFileHandle; 136 | 137 | // get the input file path 138 | POBJECT_ATTRIBUTES pObjAttrs = POBJECT_ATTRIBUTES (args[2]); 139 | trace << L", RootHdl<=0x" << pObjAttrs->RootDirectory; 140 | std::wstring file_path = wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 141 | pObjAttrs->ObjectName->Length); 142 | trace << L", File<=" << file_path; 143 | 144 | // trace << L")\tRet=>" << return_code << std::endl; 145 | } 146 | 147 | /* ============================================================================ 148 | * parse the NtOpenFile syscall 149 | * ========================================================================= */ 150 | void parse_args_NtOpenFile(std::wofstream &trace, unsigned int args[]) 151 | { 152 | // trace << L"NtOpenFile\t("; 153 | 154 | // get the output file handle 155 | PHANDLE hFileHandle = reinterpret_cast(args[0]); 156 | trace << L"FileHdl=>0x" << *hFileHandle; 157 | 158 | // get the input file path 159 | POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 160 | trace << L", RootHdl<=0x" << pObjAttrs->RootDirectory; 161 | std::wstring file_path = wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 162 | pObjAttrs->ObjectName->Length); 163 | trace << L", File<=" << file_path; 164 | 165 | // trace << L")\tRet=>" << return_code << std::endl; 166 | } 167 | 168 | /* ============================================================================ 169 | * parse the NtCreateSection syscall 170 | * ========================================================================= */ 171 | void parse_args_NtCreateSection(std::wofstream &trace, unsigned int args[]) 172 | { 173 | // trace << L"NtCreateSection\t("; 174 | 175 | // get the output section handle 176 | PHANDLE pSectionHandle = reinterpret_cast(args[0]); 177 | trace << L"SecHdl=>0x" << *pSectionHandle; 178 | 179 | // get the input desired access 180 | /*trace << L", DesiredAccess<="; 181 | ACCESS_MASK desiredAccess = static_cast(args[1]); 182 | switch (desiredAccess) { 183 | case SECTION_EXTEND_SIZE: trace << L"SECTION_EXTEND_SIZE"; break; 184 | case SECTION_MAP_EXECUTE: trace << L"SECTION_MAP_EXECUTE"; break; 185 | case SECTION_MAP_READ: trace << L"SECTION_MAP_READ"; break; 186 | case SECTION_MAP_WRITE: trace << L"SECTION_MAP_WRITE"; break; 187 | case SECTION_QUERY: trace << L"SECTION_QUERY"; break; 188 | case SECTION_ALL_ACCESS: trace << L"SECTION_ALL_ACCESS"; break; 189 | case GENERIC_READ: trace << L"GENERIC_READ"; break; 190 | case GENERIC_WRITE: trace << L"GENERIC_WRITE"; break; 191 | case GENERIC_EXECUTE: trace << L"GENERIC_EXECUTE"; break; 192 | case GENERIC_ALL: trace << L"GENERIC_ALL"; break; 193 | case READ_CONTROL: trace << L"STANDARD_RIGHTS_(READ,WRITE,EXECUTE)"; break; 194 | case STANDARD_RIGHTS_REQUIRED: trace << L"STANDARD_RIGHTS_REQUIRED"; break; 195 | case STANDARD_RIGHTS_ALL: trace << L"STANDARD_RIGHTS_ALL"; break; 196 | default: trace << L"Unknow access code: " << desiredAccess; break; 197 | }*/ 198 | 199 | // get the input allocation attributes 200 | trace << L", AllocAttrs<="; 201 | ULONG allocAttrs = static_cast(args[5]); 202 | switch (allocAttrs) { 203 | case SEC_IMAGE: trace << L"SEC_IMAGE"; break; 204 | case SEC_FILE: trace << L"SEC_FILE"; break; 205 | case SEC_RESERVE: trace << L"SEC_RESERVE"; break; 206 | case SEC_COMMIT: trace << L"SEC_COMMIT"; break; 207 | case SEC_NOCACHE: trace << L"SEC_NOCACHE"; break; 208 | default: trace << "Unknow attributes code: " << allocAttrs; break; 209 | } 210 | 211 | // get the input mapped file handle 212 | HANDLE hFileHandle = reinterpret_cast(args[6]); 213 | trace << L", FileHdl<=0x" << hFileHandle; 214 | 215 | // trace << L")\tRet=>" << return_code << std::endl; 216 | } 217 | 218 | /* ============================================================================ 219 | * parse the NtOpenSection syscall 220 | * ========================================================================= */ 221 | void parse_args_NtOpenSection(std::wofstream &trace, unsigned int args[]) 222 | { 223 | // parse the output section handle 224 | PHANDLE pSectionHandle = reinterpret_cast(args[0]); 225 | trace << L"SecHdl=>0x" << *pSectionHandle; 226 | 227 | // parse the input file path 228 | POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 229 | trace << L", RootHdl<=0x" << pObjAttrs->RootDirectory; 230 | std::wstring file_path = wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 231 | pObjAttrs->ObjectName->Length); 232 | trace << L", File<=" << file_path; 233 | } 234 | 235 | 236 | /* ============================================================================ 237 | * parse the NtMapViewOfSection 238 | * ========================================================================== */ 239 | void parse_args_NtMapViewOfSection(std::wofstream &trace, unsigned int args[]) 240 | { 241 | // get the input section handle 242 | HANDLE hSectionHandle = reinterpret_cast(args[0]); 243 | trace << L"SecHdl<=0x" << hSectionHandle; 244 | 245 | // get the input process handle 246 | HANDLE hProcessHandle = reinterpret_cast(args[1]); 247 | trace << L", ProcHdl<=0x" << hProcessHandle; 248 | 249 | // get the output base address 250 | PVOID *pBaseAddress = reinterpret_cast(args[2]); 251 | trace << L", BaseAddr<=0x" << *pBaseAddress; 252 | 253 | //// get the input commit size 254 | //SIZE_T lCommitSize = static_cast(arg_4); 255 | //trace << L"CommitSize<=0x" << lCommitSize; 256 | 257 | //// get the output section offset 258 | //HANDLE pSectionOffset = reinterpret_cast(arg_5); 259 | //trace << L"SectionOffset=>0x" << *(reinterpret_cast(pSectionOffset)); 260 | 261 | // trace << L")\tRet=>" << return_code << std::endl; 262 | } 263 | 264 | /* ============================================================================ 265 | * parse the NtUnMapViewOfSection 266 | * ========================================================================= */ 267 | void parse_args_NtUnmapViewOfSection(std::wofstream &trace, unsigned int args[]) 268 | { 269 | HANDLE hProcessHandle = reinterpret_cast(args[0]); 270 | trace << L"ProcHdl<=0x" << hProcessHandle; 271 | 272 | PVOID pBaseAddress = reinterpret_cast(args[1]); 273 | trace << L", BaseAddr<=0x" << pBaseAddress; 274 | } 275 | 276 | /* ============================================================================ 277 | * parse the NtClose syscall 278 | * ========================================================================= */ 279 | void parse_args_NtClose(std::wofstream &trace, unsigned int args[]) 280 | { 281 | // get the input file handle 282 | HANDLE hHandle = HANDLE (args[0]); 283 | trace << L"Hdl<=0x" << hHandle; 284 | } 285 | 286 | /* ============================================================================ 287 | * parse the NtWriteFile syscall 288 | * ========================================================================= */ 289 | void parse_args_NtWriteFile(std::wofstream &trace, unsigned int args[]) 290 | { 291 | // get the input file handle 292 | HANDLE hFileHandle = reinterpret_cast(args[0]); 293 | trace << L"FileHdl<=0x" << hFileHandle ; 294 | 295 | // get the input buffer address and length 296 | PVOID pBuffer = reinterpret_cast(args[5]); 297 | ULONG uLength = static_cast(args[6]); 298 | trace << L", BuffAddr<=0x" << pBuffer << L", ByteNum<=" << uLength; 299 | } 300 | 301 | /* ============================================================================ 302 | * parse the NtReadFile syscall 303 | * ========================================================================= */ 304 | void parse_args_NtReadFile(std::wofstream &trace, unsigned int args[]) 305 | { 306 | // get the input file handle 307 | HANDLE hFileHandle = reinterpret_cast(args[0]); 308 | trace << L"FileHdl<=0x" << hFileHandle; 309 | 310 | // get the output buffer address and length 311 | PVOID pBuffer = reinterpret_cast(args[5]); 312 | ULONG uLength = static_cast(args[6]); 313 | trace << L", BuffAddr<=0x" << pBuffer << L", ByteNum<=" << uLength; 314 | } 315 | 316 | /* ============================================================================ 317 | * parse the NtOpenKey 318 | * ========================================================================== */ 319 | void parse_args_NtOpenKey(std::wofstream &trace, unsigned int args[]) 320 | { 321 | // parse the output key handle 322 | PHANDLE pKeyHandle = reinterpret_cast(args[0]); 323 | trace << L"KeyHdl=>0x" << *pKeyHandle; 324 | 325 | // parse the input key 326 | POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 327 | trace << L", RootHdl<=0x" << pObjAttrs->RootDirectory; 328 | std::wstring key = wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 329 | pObjAttrs->ObjectName->Length); 330 | trace << L", Key<=" << key; 331 | } 332 | 333 | /* ============================================================================ 334 | * parse the NtCreateKey 335 | * ========================================================================== */ 336 | void parse_args_NtCreateKey(std::wofstream &trace, unsigned int args[]) 337 | { 338 | // parse the output key handle 339 | PHANDLE pKeyHandle = reinterpret_cast(args[0]); 340 | trace << L"KeyHdl=>0x" << *pKeyHandle; 341 | 342 | // parse the input key 343 | POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 344 | trace << L", RootHdl<=0x" << pObjAttrs->RootDirectory; 345 | 346 | std::wstring key = wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 347 | pObjAttrs->ObjectName->Length); 348 | trace << L", Key<=" << key; 349 | } 350 | 351 | /* ============================================================================ 352 | * parse the NtSetValueKey 353 | * ========================================================================== */ 354 | void parse_args_NtSetValueKey(std::wofstream &trace, unsigned int args[]) 355 | { 356 | // parse the input key handle 357 | HANDLE hKeyHdl = reinterpret_cast(args[0]); 358 | trace << L"KeyHdl<=0x" << hKeyHdl; 359 | 360 | // parse the value name 361 | PUNICODE_STRING pUniStr = reinterpret_cast(args[1]); 362 | std::wstring value_name = wbuffer_to_wstring(pUniStr->Buffer, pUniStr->Length); 363 | trace << L", ValName<=" << value_name; 364 | 365 | // parse the value type 366 | trace << L", ValType<="; 367 | ULONG ulType = static_cast(args[3]); 368 | switch (ulType) { 369 | case REG_BINARY: trace << L"REG_BINARY"; break; 370 | case REG_DWORD: trace << L"REG_DWORD"; break; 371 | // case REG_DWORD_LITTLE_ENDIAN: trace << L"REG_DWORD_LITTLE_ENDIAN"; break; 372 | case REG_DWORD_BIG_ENDIAN: trace << L"REG_DWORD_BIG_ENDIAN"; break; 373 | case REG_EXPAND_SZ: trace << L"REG_EXPAND_SZ"; break; 374 | case REG_LINK: trace << L"REG_LINK"; break; 375 | case REG_MULTI_SZ: trace << L"REG_MULTI_SZ"; break; 376 | case REG_NONE: trace << L"REG_NONE"; break; 377 | case REG_SZ: trace << L"REG_SZ"; break; 378 | case REG_RESOURCE_LIST: trace << L"REG_RESOURCE_LIST"; break; 379 | case REG_RESOURCE_REQUIREMENTS_LIST: trace << L"REG_RESOURCE_REQUIREMENTS_LIST"; break; 380 | case REG_FULL_RESOURCE_DESCRIPTOR: trace << L"REG_FULL_RESOURCE_DESCRIPTOR"; break; 381 | } 382 | 383 | // parse the value entry data 384 | trace << L", ValEntry<="; 385 | PVOID pvEntryData = reinterpret_cast(args[4]); 386 | ULONG ulDataSize = static_cast(args[5]); 387 | if (ulType == REG_SZ) trace << wbuffer_to_wstring(reinterpret_cast(pvEntryData), ulDataSize); 388 | else trace << L"Not a string"; 389 | } 390 | 391 | 392 | /* ============================================================================ 393 | * parse the NtQueryKey 394 | * ========================================================================== */ 395 | void parse_args_NtQueryKey(std::wofstream &trace, unsigned int args[]) 396 | { 397 | // parse the input key handle 398 | HANDLE hKeyHandle = reinterpret_cast(args[0]); 399 | trace << L"KeyHdl<=0x" << hKeyHandle; 400 | } 401 | 402 | /* ============================================================================ 403 | * parse the NtQueryValueKey 404 | * ========================================================================== */ 405 | void parse_args_NtQueryValueKey(std::wofstream &trace, unsigned int args[]) 406 | { 407 | // parse the input key handle 408 | HANDLE hKeyHandle = reinterpret_cast(args[0]); 409 | trace << L"KeyHdl<=0x" << hKeyHandle; 410 | 411 | // parse the input key 412 | PUNICODE_STRING pUniStr = reinterpret_cast(args[1]); 413 | std::wstring key = wbuffer_to_wstring(pUniStr->Buffer, pUniStr->Length); 414 | trace << L", Key<=" << key; 415 | } 416 | 417 | /* ============================================================================ 418 | * parse the NtAllocateVirtualMemory 419 | * ========================================================================== */ 420 | void parse_args_NtAllocateVirtualMemory(std::wofstream &trace, unsigned int args[]) 421 | { 422 | // parse the input process handle 423 | HANDLE hProcHandle = reinterpret_cast(args[0]); 424 | trace << L"ProcHdl<=0x" << hProcHandle; 425 | 426 | // parse the output base address 427 | PVOID *pBaseAddr = reinterpret_cast(args[1]); 428 | trace << L", BaseAddr=>0x" << *pBaseAddr; 429 | 430 | // parse the output region size 431 | PSIZE_T pRegSize = reinterpret_cast(args[3]); 432 | trace << L", RegSize=>" << *pRegSize; 433 | } 434 | 435 | /* ============================================================================ 436 | * parse the NtFreeVirtualMemory 437 | * ========================================================================== */ 438 | void parse_args_NtFreeVirtualMemory(std::wofstream &trace, unsigned int args[]) 439 | { 440 | // parse the input process handle 441 | HANDLE hProcHandle = reinterpret_cast(args[0]); 442 | trace << L"ProcHdl<=0x" << hProcHandle; 443 | 444 | // parse the output base address 445 | PVOID *pBaseAddr = reinterpret_cast(args[1]); 446 | trace << L", BaseAddr=>0x" << *pBaseAddr; 447 | } 448 | 449 | /* ============================================================================ 450 | * parse the NtDuplicateObject 451 | * ========================================================================== */ 452 | void parse_args_NtDuplicateObject(std::wofstream &trace, unsigned int args[]) 453 | { 454 | // parse the source process handle 455 | HANDLE hSrcProcHdl = reinterpret_cast(args[0]); 456 | trace << L"SrcProcHdl<=0x" << hSrcProcHdl; 457 | 458 | // parse the source handle 459 | HANDLE hSrcHdl = reinterpret_cast(args[1]); 460 | trace << L", SrcHdl<=0x" << hSrcHdl; 461 | 462 | // parse the target process handle 463 | HANDLE hTarProcHdl = reinterpret_cast(args[2]); 464 | trace << L", TarProcHdl<=0x" << hTarProcHdl; 465 | 466 | // parse the target handle 467 | PHANDLE pTarHdl = reinterpret_cast(args[3]); 468 | trace << L", TarHdl=>0x" << *pTarHdl; 469 | } 470 | 471 | /* ============================================================================ 472 | * parse the NtDeviceIoControlFile 473 | * ========================================================================== */ 474 | void parse_args_NtDeviceIoControlFile(std::wofstream &trace, unsigned int args[]) 475 | { 476 | // parse the file handle 477 | HANDLE hFileHdl = reinterpret_cast(args[0]); 478 | trace << L"FileHdl<=0x" << hFileHdl; 479 | 480 | // parse the event handle 481 | HANDLE hEventHdl = reinterpret_cast(args[1]); 482 | trace << L", EventHdl<=0x" << hEventHdl; 483 | 484 | // parse the control code 485 | ULONG uCtlCode = static_cast(args[5]); 486 | trace << L", CtlCode<=" << uCtlCode; 487 | } 488 | 489 | /* ============================================================================ 490 | * parse the NtCreateEvent 491 | * ========================================================================== */ 492 | void parse_args_NtCreateEvent(std::wofstream &trace, unsigned int args[]) 493 | { 494 | // parse the event handle 495 | PHANDLE pEventHdl = reinterpret_cast(args[0]); 496 | trace << L"EventHdl=>0x" << *pEventHdl; 497 | 498 | // parse the desired access 499 | /*ACCESS_MASK accessMask = static_cast(arg_1); 500 | trace << L"DesiredAccess=>" << accessMask;*/ 501 | 502 | // parse the event name 503 | /*POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 504 | std::wstring eventName = buffer_to_wstring(pObjAttrs->ObjectName); 505 | trace << L", EventName=>" << eventName;*/ 506 | } 507 | 508 | /* ============================================================================ 509 | * parse the NtOpenThreadToken 510 | * ========================================================================== */ 511 | void parse_args_NtOpenThreadToken(std::wofstream &trace, unsigned int args[]) 512 | { 513 | // parse the thread handle 514 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 515 | trace << L"ThreadHdl<=0x" << hThreadHdl; 516 | 517 | // parse the OpenAsSelf 518 | trace << L", OpenAsSelf<="; 519 | BOOLEAN bOpenAsSelf = static_cast(args[2]); 520 | if (bOpenAsSelf != 0) trace << L"True"; 521 | else trace << L"False"; 522 | } 523 | 524 | /* ============================================================================ 525 | * parse the NtOpenThreadTokenEx 526 | * ========================================================================== */ 527 | void parse_args_NtOpenThreadTokenEx(std::wofstream &trace, unsigned int args[]) 528 | { 529 | // parse the thread handle 530 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 531 | trace << L"ThreadHdl<=0x" << hThreadHdl; 532 | 533 | // parse the OpenAsSelf 534 | trace << L", OpenAsSelf<="; 535 | BOOLEAN bOpenAsSelf = static_cast(args[2]); 536 | if (bOpenAsSelf != 0) trace << L"True"; 537 | else trace << L"False"; 538 | } 539 | 540 | /* ============================================================================ 541 | * parse the NtWaitForSingleObject 542 | * ========================================================================== */ 543 | void parse_args_NtWaitForSingleObject(std::wostream &trace, unsigned int args[]) 544 | { 545 | // parse the object handle 546 | HANDLE hObjHdl = reinterpret_cast(args[0]); 547 | trace << L"ObjHdl<=0x" << hObjHdl; 548 | } 549 | 550 | /* ============================================================================ 551 | * parse the NtFlushBuffersFile 552 | * ========================================================================== */ 553 | void parse_args_NtFlushBuffersFile(std::wofstream &trace, unsigned int args[]) 554 | { 555 | // parse the object handle 556 | HANDLE hObjHdl = reinterpret_cast(args[0]); 557 | trace << L"FileHdl<=0x" << hObjHdl; 558 | } 559 | 560 | /* ============================================================================ 561 | * parse the NtQueryInformationFile 562 | * ========================================================================== */ 563 | void parse_args_NtQueryInformationFile(std::wofstream &trace, unsigned int args[]) 564 | { 565 | // parse the file handle 566 | HANDLE hFileHdl = reinterpret_cast(args[0]); 567 | trace << L"FileHdl<=0x" << hFileHdl; 568 | 569 | // parse the input file information class 570 | /*FILE_INFORMATION_CLASS eFileInfoClass = static_cast(args[4]); 571 | trace << L", FileInfoClass<=" << eFileInfoClass;*/ 572 | } 573 | 574 | /* ============================================================================ 575 | * parse the NtSetInformationFile 576 | * ========================================================================== */ 577 | void parse_args_NtSetInformationFile(std::wofstream &trace, unsigned int args[]) 578 | { 579 | // parse the input file handle 580 | HANDLE hFileHdl = reinterpret_cast(args[0]); 581 | trace << L"FileHdl<=0x" << hFileHdl; 582 | 583 | // parse the input file information class 584 | /*FILE_INFORMATION_CLASS eFileInfoClass = static_cast(args[4]); 585 | trace << L", FileInfoClass<=" << eFileInfoClass;*/ 586 | } 587 | 588 | /* ============================================================================ 589 | * parse the NtQueryVolumeInformationFile 590 | * ========================================================================== */ 591 | void parse_args_NtQueryVolumeInformationFile(std::wofstream &trace, unsigned int args[]) 592 | { 593 | // parse the input file handle 594 | HANDLE hFileHdl = reinterpret_cast(args[0]); 595 | trace << L"FileHdl<=0x" << hFileHdl; 596 | } 597 | 598 | /* ============================================================================ 599 | * parse the NtQueryDirectoryFile 600 | * ========================================================================== */ 601 | void parse_args_NtQueryDirectoryFile(std::wofstream &trace, unsigned int args[]) 602 | { 603 | // parse the input file handle 604 | HANDLE hFileHdl = reinterpret_cast(args[0]); 605 | trace << L"FileHdl<=0x" << hFileHdl; 606 | } 607 | 608 | /* ============================================================================ 609 | * parse the NtEnumerateKey 610 | * ========================================================================== */ 611 | void parse_args_NtEnumerateKey(std::wofstream &trace, unsigned int args[]) 612 | { 613 | // parse the input key handle 614 | HANDLE hKeyHdl = reinterpret_cast(args[0]); 615 | trace << L"KeyHdl<=0x" << hKeyHdl; 616 | 617 | // parse the input subkey index 618 | ULONG ulKeyIndex = static_cast(args[1]); 619 | trace << L", KeyIndex<=" << ulKeyIndex; 620 | } 621 | 622 | /* ============================================================================ 623 | * parse the NtOpenProcess 624 | * ========================================================================== */ 625 | void parse_args_NtOpenProcess(std::wofstream &trace, unsigned int args[]) 626 | { 627 | // parse the output process handle 628 | PHANDLE pProcHandle = reinterpret_cast(args[0]); 629 | trace << L"ProcHdl=>0x" << *pProcHandle; 630 | 631 | // parse the access mask 632 | trace << L", DesiredAccess<="; 633 | ACCESS_MASK eAccessMask = static_cast(args[1]); 634 | switch (eAccessMask) { 635 | case PROCESS_ALL_ACCESS: trace << L"PROCESS_ALL_ACCESS"; break; 636 | case PROCESS_CREATE_PROCESS: trace << L"PROCESS_CREATE_ACCESS"; break; 637 | case PROCESS_CREATE_THREAD: trace << L"PROCESS_CREATE_THREAD"; break; 638 | default: trace << "Unknow access code: " << eAccessMask; break; 639 | } 640 | 641 | // parse the cliend id 642 | trace << L", ProcId<=0x"; 643 | PHANDLE pClientId = reinterpret_cast(args[3]); 644 | HANDLE hProcId = pClientId[0]; 645 | trace << hProcId; 646 | 647 | // parse the object atrributes 648 | // POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 649 | // trace << L", ObjName<=" << wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 650 | // pObjAttrs->ObjectName->Length); 651 | } 652 | 653 | /* ============================================================================ 654 | * parse the NtCreateProcessEx 655 | * ========================================================================== */ 656 | void parse_args_NtCreateProcessEx(std::wofstream &trace, unsigned int args[]) 657 | { 658 | // parse the output process handle 659 | PHANDLE pProcHandle = reinterpret_cast(args[0]); 660 | trace << L"ProcHdl=>0x" << *pProcHandle; 661 | } 662 | 663 | /* ============================================================================ 664 | * parse the NtReadVirtualMemory 665 | * ========================================================================== */ 666 | void parse_args_NtReadVirtualMemory(std::wofstream &trace, unsigned int args[]) 667 | { 668 | // parse the input process handle 669 | HANDLE hProcHandle = reinterpret_cast(args[0]); 670 | trace << L"ProcHdl<=0x" << hProcHandle; 671 | 672 | // parse the base address 673 | PVOID pBaseAddr = reinterpret_cast(args[1]); 674 | trace << L", BaseAddr<=0x" << pBaseAddr; 675 | 676 | // parse the buffer address 677 | PVOID pBuffAddr = reinterpret_cast(args[2]); 678 | trace << L", BuffAddr<=0x" << pBuffAddr; 679 | 680 | // parse the requested byte 681 | ULONG ulByteNum = static_cast(args[3]); 682 | trace << L", ByteNum<=" << ulByteNum; 683 | } 684 | 685 | /* ============================================================================ 686 | * parse the NtWriteVirtualMemory 687 | * ========================================================================== */ 688 | void parse_args_NtWriteVirtualMemory(std::wofstream &trace, unsigned int args[]) 689 | { 690 | // parse the input process handle 691 | HANDLE hProcHandle = reinterpret_cast(args[0]); 692 | trace << L"ProcHdl<=0x" << hProcHandle; 693 | 694 | // parse the base address 695 | PVOID pBaseAddr = reinterpret_cast(args[1]); 696 | trace << L", BaseAddr<=0x" << pBaseAddr; 697 | 698 | // parse the buffer address 699 | PVOID pBuffAddr = reinterpret_cast(args[2]); 700 | trace << L", BuffAddr<=0x" << pBuffAddr; 701 | 702 | // parse the requested byte 703 | ULONG ulByteNum = static_cast(args[3]); 704 | trace << L", ByteNum<=" << ulByteNum; 705 | } 706 | 707 | /* ============================================================================ 708 | * parse the NtCreateThread 709 | * ========================================================================== */ 710 | void parse_args_NtCreateThread(std::wofstream &trace, unsigned int args[]) 711 | { 712 | // parse the output thread handle 713 | PHANDLE pThreadHdl = reinterpret_cast(args[0]); 714 | trace << L"ThreadHdl=>0x" << *pThreadHdl; 715 | 716 | // parse the input process handle 717 | HANDLE hProcHdl = reinterpret_cast(args[3]); 718 | trace << L", ProcHdl<=0x" << hProcHdl; 719 | } 720 | 721 | /* ============================================================================ 722 | * parse the NtResumeThread 723 | * ========================================================================== */ 724 | void parse_args_NtResumeThread(std::wofstream &trace, unsigned int args[]) 725 | { 726 | // parse the input thread handle 727 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 728 | trace << L"ThreadHdl<=0x" << hThreadHdl; 729 | } 730 | 731 | /* ============================================================================ 732 | * parse the NtQueryInformationProcess 733 | * ========================================================================== */ 734 | void parse_args_NtQueryInformationProcess(std::wofstream &trace, unsigned int args[]) 735 | { 736 | // parse the input process handle 737 | HANDLE hProcHdl = reinterpret_cast(args[0]); 738 | trace << L"ProcHdl<=0x" << hProcHdl; 739 | 740 | // parse the input process info class 741 | trace << L", InfoClass<="; 742 | PROCESSINFOCLASS eProcInfoClass = static_cast(args[1]); 743 | switch (eProcInfoClass) { 744 | case ProcessBasicInformation: trace << L"ProcessBasicInformation"; break; 745 | default: trace << L"Unknow class code: " << eProcInfoClass; break; 746 | } 747 | } 748 | 749 | /* ============================================================================ 750 | * parse the NtSetInformationProcess 751 | * ========================================================================== */ 752 | void parse_args_NtSetInformationProcess(std::wofstream &trace, unsigned int args[]) 753 | { 754 | // parse the input process handle 755 | HANDLE hProcHdl = reinterpret_cast(args[0]); 756 | trace << L"ProcHdl<=0x" << hProcHdl; 757 | 758 | // parse the input process info class 759 | trace << L", InfoClass<="; 760 | PROCESSINFOCLASS eProcInfoClass = static_cast(args[1]); 761 | switch (eProcInfoClass) { 762 | case ProcessBasicInformation: trace << L"ProcessBasicInformation"; break; 763 | default: trace << L"Unknow class code: " << eProcInfoClass; break; 764 | } 765 | } 766 | 767 | /* ============================================================================ 768 | * parse the NtQueryAttributesFile 769 | * ========================================================================== */ 770 | void parse_args_NtQueryAttributesFile(std::wofstream &trace, unsigned int args[]) 771 | { 772 | // parse the file name 773 | POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[0]); 774 | trace << L"File<=" << wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 775 | pObjAttrs->ObjectName->Length); 776 | } 777 | 778 | /* ============================================================================ 779 | * parse the NtQuerySection 780 | * ========================================================================== */ 781 | void parse_args_NtQuerySection(std::wofstream &trace, unsigned int args[]) 782 | { 783 | // parse the input section handle 784 | HANDLE hSecHdl = reinterpret_cast(args[0]); 785 | trace << L"SecHdl<=0x" << hSecHdl; 786 | 787 | // parse the input section information class 788 | trace << L", InfoClass<="; 789 | switch (args[1]) { 790 | case 0: trace << L"SectionBasicInformation"; break; 791 | case 1: trace << L"SectionImageInformation"; break; 792 | default: trace<< L"Unknow class code: " << args[1]; break; 793 | } 794 | } 795 | 796 | /* ============================================================================ 797 | * parse the NtQueryInformationToken 798 | * ========================================================================== */ 799 | void parse_args_NtQueryInformationToken(std::wofstream &trace, unsigned int args[]) 800 | { 801 | // parse the input token handle 802 | HANDLE hTokenHdl = reinterpret_cast(args[0]); 803 | trace << L"TokenHdl<=0x" << hTokenHdl; 804 | 805 | // parse the input info class 806 | trace << L", InfoClass<="; 807 | TOKEN_INFORMATION_CLASS eTokenInfoClass = static_cast(args[1]); 808 | switch (eTokenInfoClass) { 809 | case TokenDefaultDacl: trace << L"TokenDefaultDacl"; break; 810 | case TokenGroups: trace << L"TokenGroups"; break; 811 | case TokenImpersonationLevel: trace << L"TokenImpersonationLevel"; break; 812 | case TokenOwner: trace << L"TokenOwner"; break; 813 | case TokenPrimaryGroup: trace << L"TokenPrimaryGroup"; break; 814 | case TokenPrivileges: trace << L"TokenPrivileges"; break; 815 | case TokenSessionId: trace << L"TokenSessionId"; break; 816 | case TokenSource: trace << L"TokenSource"; break; 817 | case TokenStatistics: trace << L"TokenStatistics"; break; 818 | case TokenType: trace << L"TokenType"; break; 819 | case TokenUser: trace << L"TokenUser"; break; 820 | default: trace << L"Unknow class code: " << eTokenInfoClass; break; 821 | } 822 | } 823 | 824 | /* ============================================================================ 825 | * parse the NtSetEvent 826 | * ========================================================================== */ 827 | void parse_args_NtSetEvent(std::wofstream &trace, unsigned int args[]) 828 | { 829 | // parse the input event handle 830 | HANDLE hEventHdl = reinterpret_cast(args[0]); 831 | trace << L"EventHdl<=0x" << hEventHdl; 832 | } 833 | 834 | /* ============================================================================ 835 | * parse the NtQueryEvent 836 | * ========================================================================== */ 837 | void parse_args_NtQueryEvent(std::wofstream &trace, unsigned int args[]) 838 | { 839 | // parse the input event handle 840 | HANDLE hEventHdl = reinterpret_cast(args[0]); 841 | trace << L"EventHdl<=0x" << hEventHdl; 842 | } 843 | 844 | /* ============================================================================ 845 | * parse the NtOpenEvent 846 | * ========================================================================== */ 847 | void parse_args_NtOpenEvent(std::wofstream &trace, unsigned int args[]) 848 | { 849 | // parse the output event handle 850 | PHANDLE phEventHdl = reinterpret_cast(args[0]); 851 | trace << L"EventHdl=>0x" << *phEventHdl; 852 | 853 | // parse the desired access 854 | trace << L", DesiredAccess<="; 855 | ACCESS_MASK eDesiredAccess = static_cast(args[1]); 856 | switch (eDesiredAccess) { 857 | // case EVENT_QUERY_STATE: trace << L"EVENT_QUERY_STATE"; break; 858 | case EVENT_MODIFY_STATE: trace << L"EVENT_MODIFY_STATE"; break; 859 | case EVENT_ALL_ACCESS: trace << L"EVENT_ALL_ACCESS"; break; 860 | default: trace << L"Unknow access code: " << eDesiredAccess; break; 861 | } 862 | 863 | // trace << L"DesiredAccess<=0x" << eDesiredAccess; 864 | } 865 | 866 | /* ============================================================================ 867 | * parse the NtCreateSemaphore 868 | * ========================================================================== */ 869 | void parse_args_NtCreateSemaphore(std::wostream &trace, unsigned int args[]) 870 | { 871 | // parse the output semaphore handle 872 | PHANDLE phSemaphoreHdl = reinterpret_cast(args[0]); 873 | trace << L"SemHdl=>0x" << phSemaphoreHdl; 874 | 875 | // parse the input desired access 876 | trace << L", DesiredAccess<="; 877 | ACCESS_MASK eDesiredAccess = static_cast(args[1]); 878 | switch (eDesiredAccess) { 879 | case SEMAPHORE_ALL_ACCESS: trace << L"SEMAPHORE_ALL_ACCESS"; break; 880 | case SEMAPHORE_MODIFY_STATE: trace << L"SEMAPHORE_MODIFY_STATE"; break; 881 | default: trace << L"Unknow access code: " << eDesiredAccess; break; 882 | } 883 | 884 | // parse the input semaphore name 885 | // POBJECT_ATTRIBUTES pObjAttrs = reinterpret_cast(args[2]); 886 | // trace << L", Name<=" << wbuffer_to_wstring(pObjAttrs->ObjectName->Buffer, 887 | // pObjAttrs->ObjectName->Length); 888 | } 889 | 890 | /* ============================================================================ 891 | * parse the NtReleaseSemaphore 892 | * ========================================================================== */ 893 | void parse_args_NtReleaseSemaphore(std::wostream &trace, unsigned int args[]) 894 | { 895 | // parse the input semaphore handle 896 | HANDLE hSemHdl = reinterpret_cast(args[0]); 897 | trace << L"SemHdl<=0x" << hSemHdl; 898 | 899 | // parse the count 900 | ULONG uReleaseCount = static_cast(args[1]); 901 | trace << L", Count<=" << uReleaseCount; 902 | } 903 | 904 | /* ============================================================================ 905 | * parse the NtSetInformationObject 906 | * ========================================================================== */ 907 | void parse_args_NtSetInformationObject(std::wofstream &trace, unsigned int args[]) 908 | { 909 | // parse the input object handle 910 | HANDLE hObjHdl = reinterpret_cast(args[0]); 911 | trace << L"ObjectHdl<=0x" << hObjHdl; 912 | } 913 | 914 | /* ============================================================================ 915 | * parse the NtQueryVirtualMemory 916 | * ========================================================================== */ 917 | void parse_args_NtQueryVirtualMemory(std::wofstream &trace, unsigned int args[]) 918 | { 919 | // parse the input process handle 920 | HANDLE hProcHdl = reinterpret_cast(args[0]); 921 | trace << L"ProcHdl<=0x" << hProcHdl; 922 | 923 | // parse the input base address 924 | PVOID hBaseAddr = reinterpret_cast(args[0]); 925 | trace << L", BaseAddr<=0x" << hBaseAddr; 926 | } 927 | 928 | /* ============================================================================ 929 | * parse the NtQueryInformationThread 930 | * ========================================================================== */ 931 | void parse_args_NtQueryInformationThread(std::wofstream &trace, unsigned int args[]) 932 | { 933 | // parse the input thread handle 934 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 935 | trace << L"ThreadHdl<=0x" << hThreadHdl; 936 | 937 | // parse the thread info class 938 | trace << L", InfoClass<="; 939 | THREADINFOCLASS eThreadInfoClass = static_cast(args[1]); 940 | switch (eThreadInfoClass) { 941 | case ThreadIsIoPending: trace << L"ThreadIsIoPending"; break; 942 | default: trace << L"Unknow class code: " << eThreadInfoClass; break; 943 | } 944 | } 945 | 946 | /* ============================================================================ 947 | * parse the NtTerminateThread 948 | * ========================================================================== */ 949 | void parse_args_NtTerminateThread(std::wofstream &trace, unsigned int args[]) 950 | { 951 | // parse the input thread handle 952 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 953 | trace << L"ThreadHdl<=0x" << hThreadHdl; 954 | } 955 | 956 | /* ============================================================================ 957 | * parse the NtSetInformationThread 958 | * ========================================================================== */ 959 | void parse_args_NtSetInformationThread(std::wofstream &trace, unsigned int args[]) 960 | { 961 | // parse the input thread handle 962 | HANDLE hThreadHdl = reinterpret_cast(args[0]); 963 | trace << L"ThreadHdl<=0x" << hThreadHdl; 964 | } 965 | 966 | 967 | /* ============================================================================ 968 | * parse the NtProtectVirtualMemory 969 | * ========================================================================== */ 970 | void parse_args_NtProtectVirtualMemory(std::wofstream &trace, unsigned int args[]) 971 | { 972 | // parse the input process handle 973 | HANDLE hProcHdl = reinterpret_cast(args[0]); 974 | trace << L"ProcHdl<=0x" << hProcHdl; 975 | 976 | // parse the output base address 977 | PVOID *pBaseAddr = reinterpret_cast(args[1]); 978 | trace << L", BaseAddr=>0x" << *pBaseAddr; 979 | } 980 | 981 | /* ============================================================================ 982 | * parse the NtOpenProcessToken 983 | * ========================================================================== */ 984 | void parse_args_NtOpenProcessToken(std::wofstream &trace, unsigned int args[]) 985 | { 986 | // parse the input process handle 987 | HANDLE hProcHdl = reinterpret_cast(args[0]); 988 | trace << L"ProcHdl<=0x" << hProcHdl; 989 | 990 | // parse the output token handle 991 | PHANDLE pTokeHdl = reinterpret_cast(args[2]); 992 | trace << L", TokenHdl=>0x" << *pTokeHdl; 993 | } 994 | 995 | /* ============================================================================ 996 | * parse the NtAdjustPrivilegesToken 997 | * ========================================================================== */ 998 | void parse_args_NtAdjustPrivilegesToken(std::wofstream &trace, unsigned int args[]) 999 | { 1000 | // parse the input token handle 1001 | HANDLE hTokenHdl = reinterpret_cast(args[0]); 1002 | trace << L"TokenHdl<=0x" << hTokenHdl; 1003 | } 1004 | 1005 | /* ============================================================================ 1006 | * parse the NtFsControlFile 1007 | * ========================================================================== */ 1008 | void parse_args_NtFsControlFile(std::wofstream &trace, unsigned int args[]) 1009 | { 1010 | // parse the input file handle 1011 | HANDLE hFileHdl = reinterpret_cast(args[0]); 1012 | trace << L"FileHdl<=0x" << hFileHdl; 1013 | 1014 | // parse the input event handle 1015 | HANDLE hEventHdl = reinterpret_cast(args[1]); 1016 | trace << L", EventHdl<=0x" << hEventHdl; 1017 | } 1018 | 1019 | /* ============================================================================ 1020 | * parse the NtDuplicateToken 1021 | * ========================================================================== */ 1022 | void parse_args_NtDuplicateToken(std::wofstream &trace, unsigned int args[]) 1023 | { 1024 | // parse the input token handle 1025 | HANDLE hTokenHdl = reinterpret_cast(args[0]); 1026 | trace << L"TokenHdl<=0x" << hTokenHdl; 1027 | 1028 | // parse the output token handle 1029 | PHANDLE pNewTokenHdl = reinterpret_cast(args[5]); 1030 | trace << L", NewTokenHdl=>0x" << *pNewTokenHdl; 1031 | } 1032 | 1033 | /* ============================================================================ 1034 | * parse the NtQuerySystemInformation 1035 | * ========================================================================== */ 1036 | void parse_args_NtQuerySystemInformation(std::wofstream &trace, unsigned int args[]) 1037 | { 1038 | // parse the input system info class 1039 | trace << "SysInfoClass<="; 1040 | SYSTEM_INFORMATION_CLASS eSysInfoClass = static_cast(args[0]); 1041 | switch (eSysInfoClass) { 1042 | case SystemBasicInformation: trace << L"SystemBasicInformation"; break; 1043 | case SystemProcessInformation: trace << L"SystemProcessInformation"; break; 1044 | case SystemPerformanceInformation: trace << L"SystemPerformanceInformation"; break; 1045 | case SystemTimeOfDayInformation: trace << L"SystemTimeOfDayInformation"; break; 1046 | case SystemProcessorPerformanceInformation: trace << L"SystemProcessorPerformanceInformation"; break; 1047 | case SystemInterruptInformation: trace << L"SystemInterruptInformation"; break; 1048 | case SystemExceptionInformation: trace << L"SystemExceptionInformation"; break; 1049 | case SystemRegistryQuotaInformation: trace << L"SystemRegistryQuotaInformation"; break; 1050 | case SystemLookasideInformation: trace << L"SystemLookasideInformation"; break; 1051 | default: trace << "Unknow class code: " << eSysInfoClass; break; 1052 | } 1053 | } 1054 | 1055 | 1056 | /* ============================================================================ 1057 | * parse the NtOpenProcessTokenEx 1058 | * ========================================================================== */ 1059 | void parse_args_NtOpenProcessTokenEx(std::wofstream &trace, unsigned int args[]) 1060 | { 1061 | // parse the input process handle 1062 | HANDLE hProcHdl = reinterpret_cast(args[0]); 1063 | trace << L"ProcHdl<=0x" << hProcHdl; 1064 | 1065 | // parse the output token handle 1066 | PHANDLE pTokenHdl = reinterpret_cast(args[3]); 1067 | trace << L", TokenHdl=>0x" << *pTokenHdl; 1068 | } 1069 | 1070 | /* ============================================================================ 1071 | * parse general syscalls 1072 | * ========================================================================= */ 1073 | void parse_generic_syscall(std::wofstream &trace, std::string &syscall_name, 1074 | unsigned int args[], unsigned int return_code) 1075 | { 1076 | std::wstring syscall_wname(syscall_name.begin(), syscall_name.end()); 1077 | trace << syscall_wname << L"\t(" << "0x" << reinterpret_cast(args[0]) 1078 | << L", 0x" << reinterpret_cast(args[1]) 1079 | << L", 0x" << reinterpret_cast(args[2]) 1080 | << L", 0x" << reinterpret_cast(args[3]) 1081 | << L", 0x" << reinterpret_cast(args[4]) 1082 | << L", 0x" << reinterpret_cast(args[5]) 1083 | << L")\tRet " << return_code << std::endl; 1084 | } 1085 | 1086 | /* ============================================================================ 1087 | * parse interesting syscalls 1088 | * ========================================================================== */ 1089 | void parse_interesting_syscall(std::wofstream &trace, std::string& syscall_name, 1090 | unsigned int args[], unsigned int return_code) 1091 | { 1092 | std::wstring syscall_wname(syscall_name.begin(), syscall_name.end()); 1093 | trace << syscall_wname << L"\t("; 1094 | 1095 | if (syscall_name == "NtReadFile") // 1 1096 | parse_args_NtReadFile(trace, args); 1097 | else if (syscall_name == "NtWriteFile") // 2 1098 | parse_args_NtWriteFile(trace, args); 1099 | else if (syscall_name == "NtCreateFile") // 3 1100 | parse_args_NtCreateFile(trace, args); 1101 | else if (syscall_name == "NtOpenFile") // 4 1102 | parse_args_NtOpenFile(trace, args); 1103 | else if (syscall_name == "NtFlushBuffersFile") // 5 1104 | parse_args_NtFlushBuffersFile(trace, args); 1105 | else if (syscall_name == "NtClose") // 6 1106 | parse_args_NtClose(trace, args); 1107 | else if (syscall_name == "NtCreateSection") // 7 1108 | parse_args_NtCreateSection(trace, args); 1109 | else if (syscall_name == "NtMapViewOfSection") // 8 1110 | parse_args_NtMapViewOfSection(trace, args); 1111 | else if (syscall_name == "NtUnmapViewOfSection") // 9 1112 | parse_args_NtUnmapViewOfSection(trace, args); 1113 | else if (syscall_name == "NtOpenSection") // 10 1114 | parse_args_NtOpenSection(trace, args); 1115 | else if (syscall_name == "NtOpenKey") // 11 1116 | parse_args_NtOpenKey(trace, args); 1117 | else if (syscall_name == "NtCreateKey") // 12 1118 | parse_args_NtCreateKey(trace, args); 1119 | else if (syscall_name == "NtSetValueKey") // 13 1120 | parse_args_NtSetValueKey(trace, args); 1121 | else if (syscall_name == "NtQueryKey") // 14 1122 | parse_args_NtQueryKey(trace, args); 1123 | else if (syscall_name == "NtQueryValueKey") // 15 1124 | parse_args_NtQueryValueKey(trace, args); 1125 | else if (syscall_name == "NtAllocateVirtualMemory") // 16 1126 | parse_args_NtAllocateVirtualMemory(trace, args); 1127 | else if (syscall_name == "NtFreeVirtualMemory") // 17 1128 | parse_args_NtFreeVirtualMemory(trace, args); 1129 | else if (syscall_name == "NtDeviceIoControlFile") // 18 1130 | parse_args_NtDeviceIoControlFile(trace, args); 1131 | else if (syscall_name == "NtCreateEvent") // 19 1132 | parse_args_NtCreateEvent(trace, args); 1133 | else if (syscall_name == "NtWaitForSingleObject") // 20 1134 | parse_args_NtWaitForSingleObject(trace, args); 1135 | else if (syscall_name == "NtQueryInformationFile") // 21 1136 | parse_args_NtQueryInformationFile(trace, args); 1137 | else if (syscall_name == "NtQueryVolumeInformationFile") // 22 1138 | parse_args_NtQueryVolumeInformationFile(trace, args); 1139 | else if (syscall_name == "NtSetInformationFile") // 23 1140 | parse_args_NtSetInformationFile(trace, args); 1141 | else if (syscall_name == "NtQueryDirectoryFile") // 24 1142 | parse_args_NtQueryDirectoryFile(trace, args); 1143 | else if (syscall_name == "NtEnumerateKey") // 25 1144 | parse_args_NtEnumerateKey(trace, args); 1145 | else if (syscall_name == "NtOpenProcess") // 26 1146 | parse_args_NtOpenProcess(trace, args); 1147 | else if (syscall_name == "NtCreateProcessEx") // 27 1148 | parse_args_NtCreateProcessEx(trace, args); 1149 | else if (syscall_name == "NtReadVirtualMemory") // 28 1150 | parse_args_NtReadVirtualMemory(trace, args); 1151 | else if (syscall_name == "NtWriteVirtualMemory") // 29 1152 | parse_args_NtWriteVirtualMemory(trace, args); 1153 | else if (syscall_name == "NtCreateThread") // 30 1154 | parse_args_NtCreateThread(trace, args); 1155 | else if (syscall_name == "NtResumeThread") // 31 1156 | parse_args_NtResumeThread(trace, args); 1157 | else if (syscall_name == "NtQueryInformationProcess") // 32 1158 | parse_args_NtQueryInformationProcess(trace, args); 1159 | else if (syscall_name == "NtQuerySection") // 33 1160 | parse_args_NtQuerySection(trace, args); 1161 | else if (syscall_name == "NtQueryInformationToken") // 34 1162 | parse_args_NtQueryInformationToken(trace, args); 1163 | else if (syscall_name == "NtSetInformationProcess") // 35 1164 | parse_args_NtSetInformationProcess(trace, args); 1165 | else if (syscall_name == "NtQueryAttributesFile") // 36 1166 | parse_args_NtQueryAttributesFile(trace, args); 1167 | else if (syscall_name == "NtSetEvent") // 37 1168 | parse_args_NtSetEvent(trace, args); 1169 | else if (syscall_name == "NtQueryEvent") // 38 1170 | parse_args_NtQueryEvent(trace, args); 1171 | else if (syscall_name == "NtOpenEvent") // 39 1172 | parse_args_NtOpenEvent(trace, args); 1173 | else if (syscall_name == "NtOpenThreadToken") // 40 1174 | parse_args_NtOpenThreadToken(trace, args); 1175 | else if (syscall_name == "NtSetInformationObject") // 41 1176 | parse_args_NtSetInformationObject(trace, args); 1177 | else if (syscall_name == "NtQueryVirtualMemory") // 42 1178 | parse_args_NtQueryVirtualMemory(trace, args); 1179 | else if (syscall_name == "NtQueryInformationThread") // 43 1180 | parse_args_NtQueryInformationThread(trace, args); 1181 | else if (syscall_name == "NtTerminateThread") // 44 1182 | parse_args_NtTerminateThread(trace, args); 1183 | else if (syscall_name == "NtCreateSemaphore") // 45 1184 | parse_args_NtCreateSemaphore(trace, args); 1185 | else if (syscall_name == "NtReleaseSemaphore") // 46 1186 | parse_args_NtReleaseSemaphore(trace, args); 1187 | else if (syscall_name == "NtOpenThreadTokenEx") // 47 1188 | parse_args_NtOpenThreadTokenEx(trace, args); 1189 | else if (syscall_name == "NtProtectVirtualMemory") // 48 1190 | parse_args_NtProtectVirtualMemory(trace, args); 1191 | else if (syscall_name == "NtOpenProcessToken") // 49 1192 | parse_args_NtOpenProcessToken(trace, args); 1193 | else if (syscall_name == "NtAdjustPrivilegesToken") // 50 1194 | parse_args_NtAdjustPrivilegesToken(trace, args); 1195 | else if (syscall_name == "NtFsControlFile") // 51 1196 | parse_args_NtFsControlFile(trace, args); 1197 | else if (syscall_name == "NtDuplicateToken") // 52 1198 | parse_args_NtDuplicateToken(trace, args); 1199 | else if (syscall_name == "NtSetInformationThread") // 53 1200 | parse_args_NtSetInformationThread(trace, args); 1201 | else if (syscall_name == "NtOpenProcessTokenEx") // 54 1202 | parse_args_NtOpenProcessTokenEx(trace, args); 1203 | else if (syscall_name == "NtDuplicateObject") // 55 1204 | parse_args_NtDuplicateObject(trace, args); 1205 | else if (syscall_name == "NtQuerySystemInformation") // 56 1206 | parse_args_NtQuerySystemInformation(trace, args); 1207 | 1208 | trace << L")\tRet=>" << return_code << std::endl; 1209 | } 1210 | -------------------------------------------------------------------------------- /rp_syscall.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 5 | { 6 | printf("system-call: 0x%08x, arguments:", PIN_GetSyscallNumber(ctx, std)); 7 | for (int i = 0; i < 4; ++i) { 8 | ADDRINT value = PIN_GetSyscallArgument(ctx, std, i); 9 | printf(" %d 0x%08x", value, value); 10 | } 11 | } 12 | 13 | void syscall_exit(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 14 | { 15 | ADDRINT return_value = PIN_GetSyscallReturn(ctx, std); 16 | printf(", return-value: %d 0x%08x\n", return_value, return_value); 17 | } 18 | 19 | int main(int argc, char *argv[]) 20 | { 21 | if (PIN_Init(argc, argv)) { 22 | printf("Usage: %s [arguments]\n"); 23 | return 0; 24 | } 25 | 26 | PIN_AddSyscallEntryFunction(&syscall_entry, NULL); 27 | PIN_AddSyscallExitFunction(&syscall_exit, NULL); 28 | 29 | PIN_StartProgram(); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /strace_windows.cc: -------------------------------------------------------------------------------- 1 | /*BEGIN_LEGAL 2 | Intel Open Source License 3 | 4 | Copyright (c) 2002-2012 Intel Corporation. All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. Redistributions 12 | in binary form must reproduce the above copyright notice, this list of 13 | conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. Neither the name of 15 | the Intel Corporation nor the names of its contributors may be used to 16 | endorse or promote products derived from this software without 17 | specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR 23 | ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | END_LEGAL */ 31 | 32 | /* a lot of modification */ 33 | 34 | /* strace_windows.cc */ 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include 41 | 42 | #include "syscall.h" 43 | 44 | #pragma comment(lib, "MSVCRT.lib") 45 | 46 | /* imported functions */ 47 | extern std::string process_dependent_trace_name(unsigned int pid); 48 | 49 | extern std::vector< std::shared_ptr > load_syscall_table(const std::string&); // load the syscall table 50 | 51 | extern std::string lookup_syscall_name(std::vector< std::shared_ptr >&, int); 52 | extern int lookup_syscall_number(std::vector< std::shared_ptr > &syscall_table, 53 | std::string &syscall_name); 54 | 55 | void parse_generic_syscall(std::wofstream &trace, std::string &syscall_name, 56 | unsigned int args[], unsigned int return_code); 57 | 58 | void parse_interesting_syscall(std::wofstream &trace, std::string &syscall_name, 59 | unsigned int args[], unsigned int return_code); 60 | 61 | bool is_verbose(std::string &syscall_name); 62 | 63 | bool is_intersting(std::string &syscall_name); 64 | 65 | /* global variables */ 66 | //std::ofstream trace; // global trace file 67 | std::wofstream wtrace; // global trace file (unicode version) 68 | //std::ofstream io_trace; // file io trace file 69 | std::wofstream wio_trace; // file io trace file (unicode version) 70 | 71 | ADDRINT syscall_number; // syscall number 72 | std::string syscall_name; // syscall name 73 | ADDRINT args[9]; // syscall arguments 74 | ADDRINT return_code; // syscall return code 75 | 76 | unsigned int syscall_count; // count the order of the invoked syscall 77 | 78 | /* private variables */ 79 | static std::vector< std::shared_ptr > syscall_table; // loaded syscall table 80 | 81 | /* ============================================================================ 82 | * print the syscall number and the arguments. 83 | * ========================================================================= */ 84 | VOID sys_before() 85 | { 86 | syscall_name = lookup_syscall_name(syscall_table, syscall_number); 87 | } 88 | 89 | /* ============================================================================ 90 | * print the return value of the syscall 91 | * ========================================================================= */ 92 | VOID sys_after() 93 | { 94 | if (!is_verbose(syscall_name)) { 95 | syscall_count++; 96 | 97 | // wtrace << std::setw(7) << syscall_count << L"\t"; 98 | // parse_generic_syscall(wtrace, syscall_name, args, return_code); 99 | 100 | if (is_intersting(syscall_name)) { 101 | wtrace << std::setw(7) << syscall_count << L"\t"; 102 | parse_interesting_syscall(wtrace, syscall_name, args, return_code); 103 | } 104 | else { 105 | wtrace << std::setw(7) << syscall_count << L"\t"; 106 | parse_generic_syscall(wtrace, syscall_name, args, return_code); 107 | } 108 | } 109 | } 110 | 111 | /* ============================================================================ 112 | * log the syscall number and the arguments. 113 | * execute just before the syscall is invoked 114 | * ========================================================================== */ 115 | VOID syscall_enter(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) 116 | { 117 | syscall_number = PIN_GetSyscallNumber(ctxt, std); 118 | 119 | // basic arguments 120 | args[0] = PIN_GetSyscallArgument(ctxt, std, 0); args[1] = PIN_GetSyscallArgument(ctxt, std, 1); 121 | args[2] = PIN_GetSyscallArgument(ctxt, std, 2); args[3] = PIN_GetSyscallArgument(ctxt, std, 3); 122 | args[4] = PIN_GetSyscallArgument(ctxt, std, 4); args[5] = PIN_GetSyscallArgument(ctxt, std, 5); 123 | 124 | // additional arguments 125 | args[6] = PIN_GetSyscallArgument(ctxt, std, 6); args[7] = PIN_GetSyscallArgument(ctxt, std, 6); 126 | args[8] = PIN_GetSyscallArgument(ctxt, std, 7); 127 | 128 | sys_before(); 129 | } 130 | 131 | /* ============================================================================ 132 | * log the return value of the syscall 133 | * execute just after the syscall returns 134 | * ========================================================================== */ 135 | VOID syscall_exit(THREADID threadIndex, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) 136 | { 137 | return_code = PIN_GetSyscallErrno(ctxt, std); 138 | sys_after(); 139 | } 140 | 141 | /* =========================================================================== 142 | * log the loaded image. 143 | * called just before the image is loaded 144 | * ========================================================================== */ 145 | VOID image_load(IMG img, VOID *v) 146 | { 147 | //trace << "Load module: " << IMG_Name(img) << IMG_Id(img) << std::endl; 148 | } 149 | 150 | /* ============================================================================ 151 | * log the unloaded image 152 | * called somewhere... 153 | * ========================================================================== */ 154 | VOID image_unload(IMG img, VOID *v) 155 | { 156 | //trace << "Unload module: " << IMG_Name(img) << std::endl; 157 | } 158 | 159 | /* ============================================================================ 160 | * log the newly created process 161 | * called just before a new child process is created 162 | * ========================================================================== */ 163 | BOOL before_creating_process(CHILD_PROCESS child_process, VOID *data) 164 | { 165 | wtrace << L"New process is going to be created with id " 166 | << CHILD_PROCESS_GetId(child_process) << std::endl; 167 | return TRUE; 168 | } 169 | 170 | /* ============================================================================ 171 | * commence function 172 | * ========================================================================== */ 173 | VOID start_tracing(VOID *data) 174 | { 175 | std::string trace_name, io_trace_name; 176 | 177 | trace_name = process_dependent_trace_name(PIN_GetPid()); 178 | wtrace.open(trace_name); //wio_trace.open(io_trace_name); 179 | 180 | // load syscall table 181 | syscall_table = load_syscall_table("syscall_table.txt"); 182 | 183 | syscall_count = 0; 184 | } 185 | 186 | /* ============================================================================ 187 | * fini function 188 | * ========================================================================== */ 189 | VOID fini(INT32 code, VOID *v) 190 | { 191 | wtrace << "#eof" << std::endl; 192 | // wio_trace << "#eof" << std::endl; 193 | wtrace.close(); 194 | // wio_trace.close(); 195 | } 196 | 197 | /* ============================================================================ 198 | * main 199 | * ========================================================================== */ 200 | int main(int argc, char *argv[]) 201 | { 202 | PIN_Init(argc, argv); 203 | 204 | PIN_AddApplicationStartFunction(start_tracing, 0); 205 | 206 | // add instrumental functions 207 | PIN_AddSyscallEntryFunction(syscall_enter, 0); 208 | PIN_AddSyscallExitFunction(syscall_exit, 0); 209 | /*IMG_AddInstrumentFunction(image_load, 0); 210 | IMG_AddUnloadFunction(image_unload, 0);*/ 211 | PIN_AddFollowChildProcessFunction(before_creating_process, 0); 212 | 213 | PIN_AddFiniFunction(fini, 0); 214 | 215 | // now the control is passed to Pin 216 | PIN_StartProgram(); 217 | 218 | // so the program never returns 219 | return 0; 220 | } 221 | -------------------------------------------------------------------------------- /syscall.cc: -------------------------------------------------------------------------------- 1 | #include "syscall.h" 2 | 3 | syscall::syscall(int i_number, const std::string& i_name) 4 | { 5 | this->number = i_number; 6 | this->name = i_name; 7 | } 8 | 9 | syscall::~syscall(void) 10 | { 11 | } 12 | 13 | bool operator ==(syscall& lhs, syscall& rhs) 14 | { 15 | if (lhs.number == rhs.number) return true; 16 | else return false; 17 | } -------------------------------------------------------------------------------- /syscall.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class syscall 7 | { 8 | public: 9 | int number; 10 | std::string name; 11 | std::vector input_handles; 12 | std::vector output_handles; 13 | 14 | public: 15 | syscall(int i_number, const std::string& i_name); 16 | ~syscall(void); 17 | }; 18 | 19 | bool operator ==(syscall& lhs, syscall& rhs); 20 | -------------------------------------------------------------------------------- /syscall_capture.cc: -------------------------------------------------------------------------------- 1 | /* syscall_capture.cc */ 2 | 3 | /* ============================================================================ 4 | * Capture invoked system calls of running process. 5 | * Reuse some codes of Jurriaan Bremer @skier_t at 6 | * http://jbremer.org/malware-unpacking-level-pintool 7 | * ========================================================================= */ 8 | 9 | #include 10 | namespace WINDOWS 11 | { 12 | #include 13 | } 14 | #include 15 | #include 16 | #include 17 | 18 | /* ============================================================================ 19 | * command line switches 20 | * ========================================================================= */ 21 | KNOB KnotOutputFile(KNOB_MODE_WRITEONCE, "pintool", "o", 22 | "syscall_capture.out", "specify trace file name"); 23 | 24 | /* ============================================================================ 25 | * help message 26 | * ========================================================================= */ 27 | INT32 Usage() 28 | { 29 | std::cerr << "The Pin tool prints out the invoked system calls of running process"; 30 | std::cerr << std::endl << std::endl; 31 | std::cerr << KNOB_BASE::StringKnobSummary(); 32 | std::cerr << std::endl; 33 | return -1; 34 | } 35 | 36 | /* ============================================================================ 37 | * Get invoked syscall name and arguments 38 | * ========================================================================= */ 39 | void syscall_entry(THREADID thread_id, CONTEXT *ctx, SYSCALL_STANDARD std, void *v) 40 | { 41 | std::cout.setf(std::ios::right); 42 | std::cout << "0x" << std::setw(8) << std::setfill('0') << std::hex 43 | << PIN_GetSyscallNumber(ctx, std) << std::endl; 44 | } 45 | 46 | int main(int argc, char* argv[]) 47 | { 48 | if (PIN_Init(argc, argv)) { 49 | return Usage(); 50 | } 51 | else { 52 | PIN_AddSyscallEntryFunction(&syscall_entry, NULL); 53 | PIN_StartProgram(); 54 | return 0; 55 | } 56 | } --------------------------------------------------------------------------------