遍历一个长字符串并上传到 SQL - Python
Looping through a long string and uploading to SQL - Python
大约 2 周以来,我一直在为这个问题绞尽脑汁,但似乎想不出一种方法来做到这一点。
我的任务是创建一个脚本,该脚本可以获取机器的缓存凭据并将该数据上传到 SQL 数据库。
我已经查看了所有主要工具、mimikatz 等。但目前,我只是使用基本的命令提示符命令,"cmdkey.exe /list"
此命令是使用 "subprocess" 模块调用的,我可以获得非常好的数据,但问题是输出 returns 是一个完整的字符串。
不提供返回的敏感数据,这是数据的结构:
目标:...
类型:...
用户:...
~注意事项~
我已经能够使用内置的 "split" 函数逐行遍历字符串。我创建了一个函数,根据它是否包含特定字符串,将行的值添加到不同的列表中,例如"Target: "。由于最后的注释,没有标题,这不能正常工作。
我遇到的另一个问题是有些条目有全部 4 个字段,而有些条目只有 2 个字段,所以我不能逐行循环并将每一行逐一添加到不同的列表。
我已经能够为每一行设置一个计数,例如
0 Target:
1 Type: Domain Extended Credentials
2 User:
3 Saved for this logon only
4
0 Target:
1 Type: Generic
2 Local machine persistence
3
如您所见,由于每个 "block" 显示的数据不同,行数不匹配。
困扰我的不是特定的代码,而是方法。
这就是我调用 "cmdkey.exe /list" 命令的方式。
command = ['cmdkey.exe', '/list']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
r = result.stdout
formatted = r.split("\n", 3)[-1]
基本上,我希望它逐行循环遍历一个字符串,并根据字段标题将该行添加到列表中。如果该标题没有,请添加一个空白值。
我知道这很模糊,但在寻找完成它的方法之后,我一直在努力寻找实现它的方法。在这一点上,我们也将不胜感激关于其他实现此目的的任何建议。
根据评论中的要求,添加我正在使用的数据,编辑以删除敏感数据:
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Domain Extended Credentials
User: username
Saved for this logon only
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Domain Password
User: domain\username
Local machine persistence
Target: LegacyGeneric:target=Slack/tokens
Type: Generic
User: tokens
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: domain\username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username token
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: domain\username
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: email address
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic Certificate
User: <Certificate>
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
您可以将数据读入字典,如本例所示:
def empty():
return {'Target': '', 'Type': '', 'User': '', 'Comment': ''}
def process(record):
item = empty()
for line in record:
line_items = line.split(':', 1)
if len(line_items) == 2:
item[line_items[0]] = line_items[1].strip()
if len(line_items) == 1:
item['Comment'] = line_items[0].strip()
print('here save into SQL:')
print(' Target:' + item['Target'])
print(' Type:' + item['Type'])
print(' User:' + item['User'])
print(' Comment:' + item['Comment'])
print('')
def main():
lines = r.split('\n')
record = []
for line in lines:
line = line.strip()
if line != '':
record.append(line)
else:
process(record)
record = []
process(record)
if __name__ == "__main__":
main()
结果为:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Domain Extended Credentials
User:username
Comment:Saved for this logon only
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Domain Password
User:domain\username
Comment:Local machine persistence
here save into SQL:
Target:LegacyGeneric:target=Slack/tokens
Type:Generic
User:tokens
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:domain\username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username token
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:domain\username
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:email address
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic Certificate
User:<Certificate>
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:
我将您的输入封装到一个名为 data
的变量中。
您遇到的问题是格式化数据,而不是插入 SQL。所以我现在把这个留给你了:)
# I see that my common characters to split my data is 2 following \n
groups = data.split('\n\n')
print(groups[0])
# Target: MicrosoftAccount:target=SSO_POP_Device
# Type: Domain Extended Credentials
# User: username
# Saved for this logon only
def format_group(group):
""" Takes a group as input, and returns a properly formatted dict for the group.
"""
resulting_dict = {}
for line in group.split('\n'):
split_pos = line.find(':')
if split_pos > -1: # ':' is found, meaning it is not a comment but actual data.
# The data I have contains extra spaces and tabs, so I strip it.
clean_key = line[:split_pos].strip()
clean_val = line[split_pos+1:].strip()
resulting_dict[clean_key] = clean_val
return resulting_dict
# Using my previously defined function for each group.
new_data = [format_group(group) for group in groups]
from pprint import pprint #Something to display nicely
pprint(new_data)
# [{'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Domain Extended Credentials',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Domain Password',
# 'User': 'domain\username'},
# {'Target': 'LegacyGeneric:target=Slack/tokens',
# 'Type': 'Generic',
# 'User': 'tokens'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'domain\username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username token'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'domain\username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'email address'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic Certificate',
# 'User': '<Certificate>'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'}]
大约 2 周以来,我一直在为这个问题绞尽脑汁,但似乎想不出一种方法来做到这一点。
我的任务是创建一个脚本,该脚本可以获取机器的缓存凭据并将该数据上传到 SQL 数据库。 我已经查看了所有主要工具、mimikatz 等。但目前,我只是使用基本的命令提示符命令,"cmdkey.exe /list" 此命令是使用 "subprocess" 模块调用的,我可以获得非常好的数据,但问题是输出 returns 是一个完整的字符串。
不提供返回的敏感数据,这是数据的结构:
目标:...
类型:...
用户:...
~注意事项~
我已经能够使用内置的 "split" 函数逐行遍历字符串。我创建了一个函数,根据它是否包含特定字符串,将行的值添加到不同的列表中,例如"Target: "。由于最后的注释,没有标题,这不能正常工作。
我遇到的另一个问题是有些条目有全部 4 个字段,而有些条目只有 2 个字段,所以我不能逐行循环并将每一行逐一添加到不同的列表。
我已经能够为每一行设置一个计数,例如
0 Target:
1 Type: Domain Extended Credentials
2 User:
3 Saved for this logon only
4
0 Target:
1 Type: Generic
2 Local machine persistence
3
如您所见,由于每个 "block" 显示的数据不同,行数不匹配。
困扰我的不是特定的代码,而是方法。
这就是我调用 "cmdkey.exe /list" 命令的方式。
command = ['cmdkey.exe', '/list']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
r = result.stdout
formatted = r.split("\n", 3)[-1]
基本上,我希望它逐行循环遍历一个字符串,并根据字段标题将该行添加到列表中。如果该标题没有,请添加一个空白值。
我知道这很模糊,但在寻找完成它的方法之后,我一直在努力寻找实现它的方法。在这一点上,我们也将不胜感激关于其他实现此目的的任何建议。
根据评论中的要求,添加我正在使用的数据,编辑以删除敏感数据:
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Domain Extended Credentials
User: username
Saved for this logon only
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Domain Password
User: domain\username
Local machine persistence
Target: LegacyGeneric:target=Slack/tokens
Type: Generic
User: tokens
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: domain\username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username token
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: username
Local machine persistence
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: domain\username
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
User: email address
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic Certificate
User: <Certificate>
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
Target: MicrosoftAccount:target=SSO_POP_Device
Type: Generic
您可以将数据读入字典,如本例所示:
def empty():
return {'Target': '', 'Type': '', 'User': '', 'Comment': ''}
def process(record):
item = empty()
for line in record:
line_items = line.split(':', 1)
if len(line_items) == 2:
item[line_items[0]] = line_items[1].strip()
if len(line_items) == 1:
item['Comment'] = line_items[0].strip()
print('here save into SQL:')
print(' Target:' + item['Target'])
print(' Type:' + item['Type'])
print(' User:' + item['User'])
print(' Comment:' + item['Comment'])
print('')
def main():
lines = r.split('\n')
record = []
for line in lines:
line = line.strip()
if line != '':
record.append(line)
else:
process(record)
record = []
process(record)
if __name__ == "__main__":
main()
结果为:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Domain Extended Credentials
User:username
Comment:Saved for this logon only
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Domain Password
User:domain\username
Comment:Local machine persistence
here save into SQL:
Target:LegacyGeneric:target=Slack/tokens
Type:Generic
User:tokens
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:domain\username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username token
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:username
Comment:Local machine persistence
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:domain\username
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:email address
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic Certificate
User:<Certificate>
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:
here save into SQL:
Target:MicrosoftAccount:target=SSO_POP_Device
Type:Generic
User:
Comment:
我将您的输入封装到一个名为 data
的变量中。
您遇到的问题是格式化数据,而不是插入 SQL。所以我现在把这个留给你了:)
# I see that my common characters to split my data is 2 following \n
groups = data.split('\n\n')
print(groups[0])
# Target: MicrosoftAccount:target=SSO_POP_Device
# Type: Domain Extended Credentials
# User: username
# Saved for this logon only
def format_group(group):
""" Takes a group as input, and returns a properly formatted dict for the group.
"""
resulting_dict = {}
for line in group.split('\n'):
split_pos = line.find(':')
if split_pos > -1: # ':' is found, meaning it is not a comment but actual data.
# The data I have contains extra spaces and tabs, so I strip it.
clean_key = line[:split_pos].strip()
clean_val = line[split_pos+1:].strip()
resulting_dict[clean_key] = clean_val
return resulting_dict
# Using my previously defined function for each group.
new_data = [format_group(group) for group in groups]
from pprint import pprint #Something to display nicely
pprint(new_data)
# [{'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Domain Extended Credentials',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Domain Password',
# 'User': 'domain\username'},
# {'Target': 'LegacyGeneric:target=Slack/tokens',
# 'Type': 'Generic',
# 'User': 'tokens'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'domain\username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username token'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'domain\username'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic',
# 'User': 'email address'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device',
# 'Type': 'Generic Certificate',
# 'User': '<Certificate>'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'},
# {'Target': 'MicrosoftAccount:target=SSO_POP_Device', 'Type': 'Generic'}]