Extract line that matches with my criteria in Python - python

I have a variable with this inside:
Device ID: second-02 Entry address(es): IP address: 7.7.7.7
Platform: cisco WS-8PC-S, Capabilities: Router Switch IGMP Interface:
GigabitEthernet0/20, Port ID (outgoing port): GigabitEthernet0/11
Holdtime : 100 sec
Power request id: 0, Power management id: 1, Power available: 0, Power management level: -1 Management address(es): IP address:
7.7.7.7
Device ID: first-01 Entry address(es): IP address: 8.8.8.8 Platform:
cisco ME--12CS-A, Capabilities: Router Switch IGMP Interface:
GigabitEthernet0/11, Port ID (outgoing port): GigabitEthernet0/12
Holdtime : 158 sec Power request id: 0, Power management id: 0, Power available: 0, Power management level: 0 Management address(es): IP address: 8.8.8.8
How can I extract each IP address with its respective Device ID and output something like
Device ID: second-02 = IP address: 7.7.7.7
Device ID: first-01 = IP address: 8.8.8.8
Please note that for each Device ID we have one unique IP address but each one appears two times inside the main variable
So far Ive been able to verify if there is an IP address inside the variable with ip = re.findall( r'[0-9]+(?:\.[0-9]+){3}', s ) but that wont do the trick as I need each Device ID to be paired (or matched?) against its IP address.

How about using this regular expression:
r'Device ID: ([^ ]*) Entry address\(es\): IP address: ([^ ]*)'
https://regex101.com/r/BsIRh1/2

Related

How to read iOS device serial number or IMEI via USB ? [Windows]

I tried pywinusb, wmic, msiout all are unable to read the device serial number.
msiout results
Name [00000014] Apple Mobile Device Ethernet
Adapter Type Ethernet 802.3
Product Type Apple Mobile Device Ethernet
Installed Yes
PNP Device ID USB\VID_05AC&PID_12AX&MI_02\6&30B6FDC3&1&XXXX
Last Reset 19-11-2020 07:21
Index 14
Service Name Netaapl
IP Address 172.XX.XX.X, fe80::f903:XXXX:XXXX:XXXX, 2401:4900:195b:XXXX:XXXX:XXXX:XXXX:XXXX, 2401:4900:195b:f4e4:f903:XXXX:XXXX:XXXX
IP Subnet 255.XXX.XXX.XXX, 64, 128, 64
Default IP Gateway 172.XX.XX.X, fe80::XX:d1e9:XXXX:XXXX
DHCP Enabled Yes
DHCP Server 172.XX.XX.X
DHCP Lease Expires 10-12-2020 07:54
DHCP Lease Obtained 09-12-2020 08:08
MAC Address ‪72:70:XX:XX:XX:XX
Driver C:\WINDOWS\SYSTEM32\DRIVERS\NETAAPL64.SYS (1.8.5.1, 22.50 KB (23,040 bytes), 06-05-2020 13:05)
How to extract this serial number?
Device Properties (sorry for not taking a screenshot)

Router not responding to spoofed DNS query

I'm writing a Python script with scapy to spoof the address of a DNS query. So far, the router is not replying to the spoofed queries.
I have set the IP and MAC addresses to match on the script and a non-spoofed DNS request works fine.
Here's the script.
from scapy.all import *
packet=sendp(Ether(src="B0:70:2D:CF:4D:8F")/IP(id=random.randint(0, 0xFFFF),dst="192.168.0.1",src="192.168.0.123")/UDP(dport=53,sport=11333)/DNS(id=random.randint(0, 0xFFFF),rd=1,qd=DNSQR(qname="www.duckduckgo.org")))
Here's the packet captures
Frame 323: 78 bytes on wire (624 bits), 78 bytes captured (624 bits) on interface wlp0s20f0u9, id 0
Ethernet II
Destination: <DNS Server>
Source: <Spoofed MAC Address>
Type: IPv4 (0x0800)
Internet Protocol Version 4, Src: 192.168.0.123, Dst: 192.168.0.1
0100 .... = Version: 4
.... 0101 = Header Length: 20 bytes (5)
Differentiated Services Field: 0x00 (DSCP: CS0, ECN: Not-ECT)
Total Length: 64
Identification: 0xfd74 (64884)
Flags: 0x0000
Fragment offset: 0
Time to live: 64
Protocol: UDP (17)
Header checksum: 0xfb6b [correct]
[Header checksum status: Good]
[Calculated Checksum: 0xfb6b]
Source: 192.168.0.123
Destination: 192.168.0.1
User Datagram Protocol, Src Port: 11333, Dst Port: 53
Source Port: 11333
Destination Port: 53
Length: 44
Checksum: 0x89a7 [correct]
[Checksum Status: Good]
[Stream index: 20]
[Timestamps]
Domain Name System (query)
Transaction ID: 0x404c
Flags: 0x0100 Standard query
Questions: 1
Answer RRs: 0
Authority RRs: 0
Additional RRs: 0
Queries
Destination: 192.168.0.1

How to replace words/digits in a file

I'm trying to replace the global IP inside a file with a private one and create a mapping of them, so i can revert it back even if part of the new string is different.
I'm stuck at the point of replace the global IP with the bogus one and write it to a file.
Starting file example:
ip route 192.168.1.0 255.255.0.0 10.10.10.2
ip route 192.168.1.0 255.255.0.0 1.1.1.2
ip route 1.1.1.1 255.255.0.0 1.1.1.3
interface FastEthernet1
ip address 1.1.1.1
duplex auto
speed auto
Wanted end result, some wording may change before revert back:
ip route ipv4 192.168.1.0 255.255.0.0 10.10.10.2
ip route ipv4 192.168.1.0 255.255.0.0 10.1.1.11
ip route ipv4 10.1.1.10 255.255.0.0 10.1.1.12
interface FastEthernet1
ip address 10.1.1.10
duplex auto
speed auto
The mapping I though is a dictionary like this:
mapping = {
'1.1.1.2': "10.1.1.10",
'1.1.1.1': "10.1.1.10",
'1.1.1.3': "10.1.1.30
}
I came out with this script until now, but it not doing what I want:
import re
import ipaddress
def load_file(file) -> str:
with open(file, 'r') as f:
return f.read()
def find_ips(config) -> set:
ip_regex = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}'
match = set(re.findall(ip_regex, config))
return match
def mapping_ip(ips) -> dict:
counter = 0
ip_table = {}
for ip in ips:
ip4_type = ipaddress.IPv4Address(ip)
if ip4_type.is_global:
counter += 1
private = ipaddress.IPv4Address('10.1.1.10') + counter
ip_table.update({
ip: str(private),
})
return ip_table
def replace(mapping, s_file, d_file):
with open(s_file, 'r') as reader, open(d_file, 'w') as writer:
for line in reader:
for orig, temp in mapping.items():
if orig in line:
x = line.replace(orig, temp)
writer.write(x)
Any suggestion on how should I do the replace funcion?
Only the IP can be change, the rest of the string need to stay as it's(revert back process).
You can simply use string replace on the lines of your source file:
Create source file:
t = """ip route 192.168.1.0 255.255.0.0 10.10.10.2
ip route 192.168.1.0 255.255.0.0 1.1.1.2
ip route 1.1.1.1 255.255.0.0 1.1.1.3
interface FastEthernet1
ip address 1.1.1.1
duplex auto
speed auto"""
with open("t.txt","w") as f:
f.write(t)
Replace stuff and write to "mod.txt":
mapping = {
'1.1.1.2': "10.1.1.10",
'1.1.1.1': "10.1.1.10",
'1.1.1.3': "10.1.1.30"
}
with open("mod.txt","w") as m, open("t.txt") as data:
for line in data:
for key,replacewith in mapping.items():
line = line.replace(key,replacewith)
m.write(line)
with open("mod.txt") as f:
print(f.read())
Output:
ip route 192.168.1.0 255.255.0.0 10.10.10.2
ip route 192.168.1.0 255.255.0.0 10.1.1.10
ip route 10.1.1.10 255.255.0.0 10.1.1.30
interface FastEthernet1
ip address 10.1.1.10
duplex auto
speed auto
This will try to replace each line m times (m == len(mapping)) and is not very speedy due to creating lots of intermediate strings (if something got replaced) - it is more a hacky solution to your problem.
You could harness re.sub in this case, following way:
import re
txt = 'ip route 192.168.1.0 255.255.0.0 10.10.10.2\nip route 192.168.1.0 255.255.0.0 1.1.1.2\nip route 1.1.1.1 255.255.0.0 1.1.1.3\ninterface FastEthernet1\nip address 1.1.1.1\nduplex auto\nspeed auto'
out = re.sub(r'1\.1\.1\.([1-3])','10.1.1.\g<1>0',txt)
print(out)
Output:
ip route 192.168.1.0 255.255.0.0 10.10.10.2
ip route 192.168.1.0 255.255.0.0 10.1.1.20
ip route 10.1.1.10 255.255.0.0 10.1.1.30
interface FastEthernet1
ip address 10.1.1.10
duplex auto
speed auto
For simplicity I hardcoded txt, most important line is that of re.sub:
out = re.sub(r'1\.1\.1\.([1-3])','10.1.1.\g<1>0',txt)
It replaces substrings of txt which match first argument with second argument, first argument contain one group ([1-3]) which is later referenced in second argument (\g<1>) thus it in fact of executing following relacement:
1.1.1.1 to 10.1.1.10
1.1.1.2 to 10.1.1.20
1.1.1.3 to 10.1.1.30
However keep in mind that re.sub is working in single-pass fashion, unlike repeating usage of .replace method of str.

Python - Read Specific Lines of Text

I'm trying to search files for specific text. Then print the line immediately prior to the line, and all subsequent lines that start with a specific character, particularly a 'space.'
Here's a sample of the file I'm trying to read:
interface vlan 22
ip address 10.10.2.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface vlan 23
ip address 10.10.23.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
When I see 'IP address' I want to print the line immediately prior, and then all the configuration items under that interface.
Currently, I'm reading from a directory of files and outputting specific information from the files. Here's the code:
for file in glob.glob('*.log'):
with open(file) as search:
with open(queryoutput,"a") as foutput:
for line in search:
line = line.rstrip()
if hostcheck in line:
hostentry = line.split("hostname ")[1]
foutput.write("Subnet information below is from " + hostentry + "\n")
elif ipaddress in line:
foutput.write("Local Device: " + hostentry + "\n")
foutput.write("Remote " + line + "\n")
Not all network devices will state "interface" in the VLAN line, so that's why I don't want to search for that text, and there's not a guarantee an exclamation would be the last item, though it's highly probable. That's why I'm looking for a way to read the lines based on 'IP address' and spaces.
I'm still new to Python, and programming in general, but it looks like something like this might help. I'm just not fully understanding how that would work.
Any thoughts on how I can accomplish this? Also, I'm trying to use Python 3.x.
It would probably be easier to utilize a Cisco config-parsing library rather than start from first principles.
For example, the ciscoconfparse module makes your problem as easy as the following, creating a dict with each interface mapped to a list of its configuration items. Searching for other object types would just be a matter of changing the argument to find_objects.
Assuming we're dealing with a file named test-config:
import pprint
from ciscoconfparse import CiscoConfParse
parse = CiscoConfParse("test-config", syntax="ios")
pprint.pprint({
obj.text: [child.text.strip() for child in obj.children]
for obj in parse.find_objects(r"interface")
})
Result:
{'interface vlan 22': ['ip address 10.10.2.1 255.255.255.0',
'ip helper-address 10.10.44.1',
'ip helper-address 10.10.44.2'],
'interface vlan 23': ['ip address 10.10.23.1 255.255.255.0',
'ip helper-address 10.10.44.1',
'ip helper-address 10.10.44.2']}
Edit: Regarding your additional question, it would probably be wise to read the documentation and tutorial for the module which contains, among other things, examples of how to search for entries with specific children. To achieve what you're asking for, you could modify the above to use the find_objects_w_child() function:
pprint.pprint({
obj.text: [child.text.strip() for child in obj.children]
for obj in parse.find_objects_w_child(
parentspec=r"^interf", childspec=r"ip .*address"
)
})
Here's a sample from the ciscoconfparse recommended above. This actually is really useful. Just wondering if I can somehow exclude all the switch interfaces for devices.
'interface FastEthernet0/7': ['spanning-tree portfast'],
'interface FastEthernet0/8': ['switchport access vlan 300',
'switchport mode access',
'authentication event fail action next-method',
'authentication event server dead action reinitialize vlan 999',
'authentication host-mode multi-auth',
'authentication order dot1x mab',
'authentication priority dot1x mab',
'authentication port-control auto',
'mab eap',
'dot1x pae authenticator',
'spanning-tree portfast'],
'interface FastEthernet0/9': ['switchport access vlan 300',
'switchport mode access',
'authentication event fail action next-method',
'authentication event server dead action reinitialize vlan 999',
'authentication host-mode multi-auth',
'authentication order dot1x mab',
'authentication priority dot1x mab',
'authentication port-control auto',
'mab eap',
'dot1x pae authenticator',
'spanning-tree portfast'],
'interface GigabitEthernet0/1': [],
'interface GigabitEthernet0/2': [],
'interface Vlan1': ['no ip address', 'shutdown'],
'interface Vlan300': ['ip address 172.22.0.1 255.255.255.0',
'ip helper-address 10.208.111.196',
'ip helper-address 10.208.111.195'],
'interface Vlan310': ['ip address 172.31.200.1 255.255.255.0',
'ip access-group guest-restrictions in',
'ip helper-address 10.208.111.195',
'ip helper-address 10.208.111.196'],
'interface Vlan500': ['ip address 172.19.0.2 255.255.255.248'],
You can use TTP to parse above text, here is the code:
from ttp import ttp
data = """
interface vlan 22
ip address 10.10.2.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface vlan 23
ip address 10.10.23.1 255.255.255.0
ip helper-address 10.10.44.1
ip helper-address 10.10.44.2
!
interface Fast0/31
switchport
!
interface vlan 77
description Not In Use
!
"""
template = """
<group contains="ip">
interface {{ interface | ORPHRASE }}
ip address {{ ip }} {{ mask }}
ip helper-address {{ dhcp | to_list | joinmatches }}
</group>
"""
parser = ttp(data, template)
parser.parse()
print(parser.result(format="json")[0])
will print:
[
[
{
"dhcp": [
"10.10.44.1",
"10.10.44.2"
],
"interface": "vlan 22",
"ip": "10.10.2.1",
"mask": "255.255.255.0"
},
{
"dhcp": [
"10.10.44.1",
"10.10.44.2"
],
"interface": "vlan 23",
"ip": "10.10.23.1",
"mask": "255.255.255.0"
}
]
]
TTP allows to filter results based on matches produced, in this particular case group "contains" function invalidates results for interfaces that does not have matches for "ip"

Regex Match on IP Address Before Known String

I'm using nmap to search for hostnames and related IPs on my local (home) network. I can pull a string that looks something like this:
Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-15 22:20 PST
Nmap scan report for 192.168.1.1
Host is up (0.00025s latency).
MAC Address: ZZ:ZZ:11:ZZ:ZZ:ZZ (Cisco-Linksys)
Nmap scan report for 192.168.1.2
Host is up (0.0084s latency).
MAC Address: ZZ:ZZ:A1:2E:ZZ:ZZ (Apple)
Nmap scan report for 192.168.1.9
Host is up (0.012s latency).
MAC Address: A4:ZZ:57:17:ZZ:ZZ (Seiko Epson)
Nmap scan report for 192.168.1.103
Host is up (0.036s latency).
MAC Address: ZZ:ZZ:6D:05:ZZ:ZZ (Apple)
I know that I can put together a regular expression to give me the IP address directly above the "Seiko Epson" line, but I cannot figure out how to do it.
I'm specifically looking for a way to find the IP address of the host that I'm searching for, I'm currently using:
(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)
to find IP addresses, but I do not know how to augment this to find the IP address above a given string.
If you get the whole input as a single string, then
You firstly search for a fixed string Nmap scan report for,
nextly remember a sequence 0-9 or . (which should be there) as the output IP address,
then skip until the MAC addr part (containing :),
skip until the next opening paren,
and finally check if the string inside parens is Seiko Epson.
Example:
>>> inp='''Starting Nmap 6.40 ( http://nmap.org ) at 2014-02-15 22:20 PST
... Nmap scan report for 192.168.1.1
... Host is up (0.00025s latency).
... MAC Address: ZZ:ZZ:11:ZZ:ZZ:ZZ (Cisco-Linksys)
... Nmap scan report for 192.168.1.2
... Host is up (0.0084s latency).
... MAC Address: ZZ:ZZ:A1:2E:ZZ:ZZ (Apple)
... Nmap scan report for 192.168.1.9
... Host is up (0.012s latency).
... MAC Address: A4:ZZ:57:17:ZZ:ZZ (Seiko Epson)
... Nmap scan report for 192.168.1.103
... Host is up (0.036s latency).
... MAC Address: ZZ:ZZ:6D:05:ZZ:ZZ (Apple)'''
>>> import re
>>> r1 = re.compile(r'Nmap scan report for ([0-9.]*)[^:]*[^(]*\(Seiko Epson\)')
>>> r1.search(inp).group(1)
'192.168.1.9'
The idea behind [^...]'s is finite state machine.

Categories