pykd

Форк
0
/
nbl.py 
560 строк · 15.3 Кб
1
#
2
#
3
#
4

5
from optparse import OptionParser
6
from pykd import *
7

8
IPv4 = 0x0008
9
ARP = 0x0608
10
IPv6 = 0xdd86
11

12
ICMP_PROTO = 0x01
13
UDP_PROTO = 0x11
14
TCP_PROTO = 0x06
15

16

17
NET_BUFFER_LIST = None
18
MDL = None
19
NET_BUFFER = None
20

21
def getNdisTypesInfo():
22
    ndis = module("ndis")
23
    
24
    global NET_BUFFER_LIST
25
    global MDL
26
    global NET_BUFFER
27
    
28
    try:
29
        NET_BUFFER_LIST = ndis.type("_NET_BUFFER_LIST")
30
        MDL = ndis.type("_MDL")
31
        NET_BUFFER = ndis.type("_NET_BUFFER")
32
    except SymbolException:
33
        NET_BUFFER_LIST =typeInfo("_NET_BUFFER_LIST")
34
        MDL = typeInfo("_MDL")
35
        NET_BUFFER = typeInfo("_NET_BUFFER")  
36

37

38
def getHostWord( dataPos ):
39
    return ( dataPos.next() << 8 ) + dataPos.next()   
40

41

42
def getNetWord( dataPos ):
43
    return dataPos.next() + ( dataPos.next() << 8 )
44

45

46
def getHostDWord( dataPos ):
47
    return ( dataPos.next() << 24 ) + ( dataPos.next() << 16 ) + ( dataPos.next() << 8 ) + dataPos.next()
48

49

50
def getNetDWord( dataPos ):
51
    return dataPos.next() + ( dataPos.next() << 8 ) + ( dataPos.next() << 16 ) + ( dataPos.next() << 24 )
52

53
class UdpPacket:
54

55
    def __init__( self, dataPos ):
56

57
        self.parsed = False
58

59
        try:
60
            self.sourcePort = getHostWord( dataPos )
61
            self.destPort = getHostWord( dataPos )
62
            self.length = getHostWord( dataPos )
63
            self.checksum = getHostWord( dataPos )             
64
            self.parsed = True
65

66
        except StopIteration:
67
            pass                   
68

69
    def __str__( self ):
70
        s = "UDP header: "
71
        if self.parsed:
72
            s += "OK\n"
73
            s += "\tSrc port: %d\n" % self.sourcePort
74
            s += "\tDest port: %d\n" % self.destPort
75
            s += "\tLength: %d\n" % self.length
76
            s += "\tChecksum: %#x\n" % self.checksum
77
            s += "\n"
78
        else:
79
            s += "MALFORMED\n"
80

81
        return s
82

83

84
class TcpPacket:
85
    
86
    def __init__( self, dataPos ):
87

88
        self.parsed = False
89

90
        try:
91
            self.parsed = True
92
            self.sourcePort = getHostWord( dataPos )
93
            self.destPort = getHostWord( dataPos )
94
            self.SeqNumber = getHostDWord( dataPos )
95
            self.AckNumber = getHostDWord( dataPos )
96
            self.dataOffset = ( dataPos.next() >> 4 )
97
            self.flags = dataPos.next() & 0x3F
98
            self.window = getHostWord( dataPos )
99
            self.checksum = getHostWord( dataPos )              
100
            self.urgentPointer = getHostWord( dataPos )     
101

102

103
        except StopIteration:
104
            pass
105

106
    def __str__( self ):
107

108
        s = "TCP header: "
109
        fl = [ "FIN", "SYN","RST", "PSH", "ACK", "URG" ]
110

111
        if self.parsed:
112
            s += "OK\n"
113
            s += "\tSrc port: %d\n" % self.sourcePort
114
            s += "\tDest port: %d\n" % self.destPort
115
            s += "\tSEQ: %x\n" % self.SeqNumber
116
            s += "\tACK: %x\n" % self.AckNumber
117
            s += "\tFlags: %x ( %s )\n" % ( self.flags, " ".join( [ fl[i] for i in xrange( len(fl) ) if ( self.flags & ( 1 << i ) ) != 0 ] ) ) 
118
            s += "\tWindows: %x\n" % self.window 
119
            s += "\tChecksum: %x\n" % self.checksum
120

121
        else:
122
            s += "MALFORMED\n"
123

124
        return s            
125

126

127
class ArpPacket:
128

129
    def __init__( self, dataPos ):
130
        pass
131
    
132
    def __str__( self ):
133
        return ""
134

135

136
class IpAddress:
137

138
    def __init__( self, dataPos ):
139

140
        self.addr = [ dataPos.next() for i in xrange(4) ]
141

142
    def __str__( self ):
143
        
144
        return "%d.%d.%d.%d" % tuple( self.addr[0:4] ) 
145

146

147
class Ip6Address:
148
   
149
    def __init__( self, dataPos ):
150
        self.addr = [ getHostWord( dataPos ) for i in xrange(8) ] 
151

152
    def __str__( self ):
153
        return "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" % tuple( self.addr )
154

155

156
class IpProtocol:
157

158
    def __init__( self, dataPos ):
159
        self.typeVal = dataPos.next()
160

161
    def isICMP( self ):
162
        return self.typeVal==ICMP_PROTO
163

164
    def isUDP( self ):
165
        return self.typeVal==UDP_PROTO
166

167
    def isTCP( self ):
168
        return self.typeVal==TCP_PROTO
169

170
    def __str__( self ):
171
        return { ICMP_PROTO: "ICMP", UDP_PROTO: "UDP", TCP_PROTO: "TCP" }.get( self.typeVal, hex(self.typeVal) )
172

173

174
    def getNextLayerPacket( self, dataPos ):
175
        return { 
176
                ICMP_PROTO : lambda x : "",
177
                UDP_PROTO : lambda x : UdpPacket(x),
178
                TCP_PROTO : lambda x : TcpPacket(x)
179
            }.get( self.typeVal, lambda x : "Unknown protocol" )(dataPos)
180

181

182
class IpPacket:
183

184
    def __init__( self, dataPos ):
185

186
        self.parsed = False
187

188
        try:                                
189

190
            version = dataPos.next()
191
            self.ihl = version & 0xF
192
            self.version = version >> 4
193
            self.tos = dataPos.next()
194
            self.TotalLength = getHostWord( dataPos )
195
            self.ident = getHostWord( dataPos )
196
            frag = getHostWord( dataPos )
197
            self.offset = frag & 0x1FFF
198
            self.flags = frag >> 13
199
            self.ttl = dataPos.next()
200
            self.protocol = IpProtocol( dataPos )
201
            self.checlsum = getNetWord( dataPos )
202
            self.srcAddr = IpAddress( dataPos )
203
            self.destAddr = IpAddress( dataPos )
204
            
205
            if  self.offset == 0:
206
                self.nextLayerPckt = self.protocol.getNextLayerPacket( dataPos )
207
            else:
208
                self.nextLayerPckt = ""
209
                
210
            self.parsed = True
211

212
        except StopIteration:
213
             pass
214

215

216

217
    def __str__( self ):
218

219
        s = "IPv4 header: "
220

221
        if self.parsed:
222
            s += "OK\n" 
223
            s += "\tversion: %x\n" % self.version
224
            s += "\theader length: %d bytes\n" % ( self.ihl * 4 )
225
            s += "\ttotal length: %d bytes\n" % self.TotalLength
226
            s += "\tID: %x\n" % self.ident
227
            s += "\tflags: %x\n" % self.flags    
228
            s += "\toffset: %x" % ( self.offset * 8) 
229
            if ( self.offset == 0 ) and ( self.flags & 0x4 == 0 ):
230
                s += " (not fragmented)\n"
231
            elif  self.offset == 0 :
232
                s += " (first fragment)\n"
233
            elif not ( self.flags & 0x4 == 0 ):
234
                s += " (fragmented)\n"
235
            else:
236
                s += " (last fragment)\n"
237
            s += "\tprotocol: " + str( self.protocol ) + "\n"
238
            s += "\tTTL: %d\n" % self.ttl
239
            s += "\tSrc addr: " + str(self.srcAddr) + "\n"
240
            s += "\tDest addr: " + str(self.destAddr) + "\n"
241
            s += str( self.nextLayerPckt )
242

243
        else:
244
            s += "MALFORMED\n"
245

246
        return s
247

248

249
class Ip6Packet():
250

251
   def  __init__( self, dataPos ):
252
  
253
       self.parsed = False
254
        
255
       try:
256
           
257
           t = getHostDWord( dataPos )
258
           self.version = ( t >> 28 ) & 0xF
259
           self.trafficClass = ( t >> 20 ) & 0xFF
260
           self.flowLabel = t & 0xFFF
261
           self.payloadLength = getNetWord( dataPos )
262
           self.nextHeader = IpProtocol( dataPos )
263
           self.hopLimit = dataPos.next()
264
           self.srcAddr = Ip6Address( dataPos )
265
           self.destAddr = Ip6Address( dataPos ) 
266

267
           self.nextLayerPckt = self.nextHeader.getNextLayerPacket( dataPos )
268
           
269
           self.parsed = True     
270
        
271
       except StopIteration:
272
           pass
273
 
274
   def __str__( self ):
275

276
       s = "IPv6 header: "
277

278
       if self.parsed:
279
           s += "OK\n"
280
           s += "\tversion: %x\n" % self.version       
281
           s += "\ttraffic class %x\n" % self.trafficClass
282
           s += "\tflowLabel: %x\n" % self.flowLabel
283
           s += "\tpayloadLength: %x\n" % self.payloadLength
284
           s += "\tnextHeader: " + str( self.nextHeader ) + "\n"
285
           s += "\thopLimit: %d\n" % self.hopLimit
286
           s += "\tsrcAddr: " + str(self.srcAddr) + "\n"
287
           s += "\tdestAddr: " + str(self.destAddr) + "\n"
288
           s += str( self.nextLayerPckt )
289
       else:
290
           s += "MALFORMED\n"
291

292
       return s
293

294

295
class ARPPacket():
296

297
   def  __init__( self, dataPos ):
298
    
299
       self.parsed = False
300

301
       try:
302

303
           self.HWType = getNetWord( dataPos )
304
           self.PType = getNetWord( dataPos )
305
           self.HLen = dataPos.next()
306
           self.PLen = dataPos.next()
307
           self.oper = getNetWord( dataPos )
308
           self.senderHWAddr = EthernetAddress( dataPos )
309
           self.senderPAddr = IpAddress( dataPos )
310
           self.targetHWAddr = EthernetAddress( dataPos )
311
           self.targetPAddr = IpAddress( dataPos )
312

313
           self.parsed = True
314

315
       except StopIteration:
316
           pass
317

318
   def __str__( self ):
319
       s = "ARP Packet: "
320

321
       if self.parsed:
322
           s += "OK\n"
323
           s += { 0x100: "REQUEST", 0x200: "REPLAY" }.get(self.oper, hex(self.oper) ) + "\n"
324
           s += "HTYPE: " + { 0x100: "Ethernet", }.get( self.HWType, hex( self.HWType) ) + "  "
325
           s += "PTYPE: " + { IPv4: "IPv4", }.get( self.PType, hex( self.PType) ) + "  "
326
           s += "HLEN: %x  " % self.HLen
327
           s += "PLEN: %x  " % self.PLen
328
           s += "\nSender: " + str(self.senderHWAddr) + "  " + str( self.senderPAddr )
329
           s += "\nTarget: " + str(self.targetHWAddr) + "  " + str( self.targetPAddr ) + "\n"
330

331
       else:
332
           s += "MALFORMED\n"
333

334
       return s
335

336

337
class EthernetType:
338

339
    def __init__( self, dataPos ):
340
        self.typeVal = getNetWord( dataPos )
341

342
    def isIPv4( self ):
343
        return self.typeVal == IPv4
344

345
    def isARP( self ):
346
        return self.typeVal == ARP
347

348
    def isIPv6( self ):
349
        return self.typeVal == IPv6
350

351
    def __str__( self ):
352
        return { IPv4 : "IPv4", ARP : "ARP", IPv6 : "IPv6" }.get( self.typeVal, str(self.typeVal) )    
353

354
    def getNextLayerPacket( self, dataPos ):
355
        return {  
356
            IPv4 : lambda x : IpPacket(x),
357
            ARP : lambda x : ARPPacket(x), 
358
            IPv6 : lambda x : Ip6Packet(x), 
359
        }.get( self.typeVal, lambda x : "" )( dataPos )
360

361

362
class EthernetAddress:
363

364
    def __init__( self, dataPos ):
365
        self.addr = [ dataPos.next() for i in range(0,6) ]
366

367
    def __str__( self ):      
368
        return "%02x-%02x-%02x-%02x-%02x-%02x" % tuple( self.addr[0:6] )       
369
    
370

371

372
class EthernetPacket:
373

374
    def __init__( self, dataPos ):
375

376
        self.parsed = False
377

378
        try:
379

380
            self.destAddress = EthernetAddress( dataPos)
381
            self.srcAddress = EthernetAddress( dataPos)
382
            self.frametype = EthernetType( dataPos )
383
            self.nextLayerPckt = self.frametype.getNextLayerPacket( dataPos )
384
            self.parsed = True
385

386
        except StopIteration:
387
            pass
388

389

390
    def __str__( self):
391
   
392
        s = "Ethernet header: "
393
         
394
        if self.parsed:
395
         
396
            s += "OK\n"
397
            s += "\tDest MAC: " + str(self.destAddress) + "\n"
398
            s += "\tSrc MAC: " + str(self.srcAddress) + "\n"
399
            s += "\tType: " + str( self.frametype) + "\n"
400
            s += str( self.nextLayerPckt )
401

402
        else:
403
            s += "FAILED\n"
404

405
        return s
406

407

408
class NetPacket:
409

410
    def __init__( self, rawData, startProtocol="eth", beginOffset=0 ):
411
        self.rawData = rawData
412
        dataPos = iter( self.rawData[ beginOffset : ] )        
413
        
414
        self.mediaParsed = {
415
            "eth" : lambda : EthernetPacket( dataPos ),
416
            "ip4" : lambda : IpPacket( dataPos ),
417
            "ip6" : lambda : Ip6Packet( dataPos ),
418
            "tcp" : lambda : TcpPacket( dataPos ),
419
            "udp" : lambda : UdpPacket( dataPos )            
420
        }[startProtocol]()
421

422
    def __str__( self ):
423
        s = "Length: %d bytes\n" % len(self.rawData) 
424
        s += str( self.mediaParsed )
425
        return s            
426

427

428
def getPacketFromNb( nb ):
429

430
    pcktBytes = list()
431

432
    mdl = typedVar( MDL, nb.CurrentMdl )
433
    dataLength = nb.DataLength
434
    dataOffset = nb.CurrentMdlOffset
435

436
    while dataLength > 0:
437
 
438
        copyData = mdl.ByteCount - dataOffset
439
        if copyData > dataLength: copyData = dataLength
440
             
441
        pcktBytes.extend( loadBytes( mdl.MappedSystemVa + dataOffset, copyData ) )
442

443
        dataLength -= copyData
444

445
        mdl = typedVar( MDL, mdl.Next )
446

447
    return pcktBytes
448
    
449

450

451
def getPacketsFromNbl( nblAddr ):
452

453
    try:
454
        
455
        getNdisTypesInfo()
456

457
        pcktList = list()
458

459
        nbl = typedVar( NET_BUFFER_LIST, nblAddr )
460

461
        while True:
462
    
463
            nb = typedVar( NET_BUFFER, nbl.FirstNetBuffer )
464
      
465
            while True:
466

467
                pcktList.append( getPacketFromNb( nb ) )
468

469
                if nb.Next == 0:
470
                    break
471

472
                nb = typedVar( NET_BUFFER, nb.Next )
473

474
            if nbl.Next == 0:
475
                break
476

477
            nbl = typedVar( NET_BUFFER_LIST, nbl.Next )
478

479
        return pcktList 
480
        
481
    except TypeException:      
482

483
        dprintln( "the symbols are wrong" )  
484

485
def printNblStruct( nblAddr, showNdisStruct = False, beginProtocol="eth", beginOffset=0 ):
486

487
    try:
488
    
489
        getNdisTypesInfo()    
490

491
        while nblAddr:
492
                     
493
            if showNdisStruct: 
494
                dprintln( "NET_BUFFER_LIST %#x" % nblAddr )
495

496
            nbl = typedVar( NET_BUFFER_LIST, nblAddr )
497

498
            nbAddr = nbl.FirstNetBuffer
499

500
            while nbAddr:
501
               
502
                nb = typedVar( NET_BUFFER, nbAddr )
503
               
504
                if showNdisStruct: 
505
                    dprint( "\tNET_BUFFER %#x" % nbAddr )
506
                    dprintln( "  data length = %d, data offset = %#x " % ( nb.DataLength, nb.DataOffset ) )
507

508
                mdlAddr = nb.CurrentMdl
509

510
                while mdlAddr:
511
               
512
                    mdl = typedVar( MDL, mdlAddr )
513

514
                    if showNdisStruct:
515
                        dprint( "\t\tMDL %#x" % mdlAddr )
516
                        dprintln( "  byte count = %d, byte offset = %#x, mapped addr = %#x" % ( mdl.ByteCount, mdl.ByteOffset, mdl.MappedSystemVa ) )
517

518
                    mdlAddr = mdl.Next
519

520
                dprintln( str( NetPacket( getPacketFromNb( nb ), beginProtocol, beginOffset ) ) )
521

522
                nbAddr = nb.Next  
523

524
            nblAddr = nbl.Next
525

526
    except TypeException:      
527

528
        dprintln( "the symbols are wrong" )
529

530
def main():
531

532
    if not isKernelDebugging():
533
        dprintln( "This script is for kernel debugging only" )
534
        return
535
        
536
    parser = OptionParser(usage="usage: !py nbl [options] address")
537
    parser.add_option("-s", "--struct", action="store_true",  dest="showNdisStruct", default=False, help="Show NDIS structures" )  
538
    parser.add_option("-p", "--proto", action="store", type="string", dest="startProtocol", default="eth", help="Packet protocol. Can be eth, ip4, ip6, tcp, udp. By default - eth." )
539
    parser.add_option("-o", "--offset", action="store", type="long", dest="beginOffset", default=0, help="Bytes offset from packet beginning" )
540
    parser.add_option("-r", "--raw", action="store_true", dest="rawBuffer", default=False, help="Show raw buffer")
541
   
542
    (options, args) = parser.parse_args()
543

544
    if len(args) < 1:
545
        parser.error("you should note address of network packet")
546

547
    if options.rawBuffer:
548

549
        if len(args) < 2:
550
            parser.error("you should note buffer length")
551
            return
552

553
        dprintln( str( NetPacket( rawData = loadBytes(expr(args[0]),expr(args[1])), startProtocol=options.startProtocol, beginOffset=options.beginOffset ) ) )
554

555
    else:
556
        printNblStruct( expr(args[0]), showNdisStruct = options.showNdisStruct, beginProtocol=options.startProtocol, beginOffset=options.beginOffset )
557
   
558

559
if __name__ == "__main__":
560
    main()

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.