-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathldaputils.py
198 lines (159 loc) · 7.91 KB
/
ldaputils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
import os
# import ldap
import ldap3
from ldap3 import Server, Connection, NTLM, SIMPLE, ANONYMOUS, SASL, SUBTREE, LEVEL, ALL_ATTRIBUTES, ALL
import binascii
from time import sleep
# split file by word
def sortFile(filename="Computers", folder="out/", sortWord="operatingSystem"):
"""Мощьный инструмент для сортировки файлов на под файлы, по указаному слову
### Имя файла для сортировки
filename: Computers
### Папка с файлом
folder: out/
### Слово для сортировки
sortWord: operatingSystem"""
DN=""; PC=""
try:
with open(folder+filename, 'r') as file:
content = file.read()
# Split text to blocks
blocks = content.split('DN:')[1:]
# make dict for group items
grouped_blocks = {}
for block in blocks:
operating_system = next((line.split(':', 1)[1].strip() for line in block.split('\n') if line.startswith(sortWord+':')), None)
if operating_system not in grouped_blocks:
grouped_blocks[operating_system] = []
grouped_blocks[operating_system].append(block)
# Write blocks to files
for operating_system, blocks_in_group in grouped_blocks.items():
file_name = f"{folder}{operating_system}"
with open(file_name, 'w') as grouped_file:
grouped_file.write("DN:" + "".join(blocks_in_group))
except Exception as e:
print(f"Error: {e}\nMaybe file or folder not found")
def removeFiles(folder="out/"):
"""Удалиения файлов в указаной папке
### папка
folder: out/ """
try:
file_list = os.listdir(folder)
for file_name in file_list:
file_path = os.path.join(folder, file_name)
try:
if os.path.isfile(file_path):
os.remove(file_path)
except: pass
except: pass
return "cleared: "+folder
def toHex(obj):
hexx = binascii.hexlify(obj).decode('utf-8')
return hexx
class LDAP:
def __init__(self, ldapUri, ldapDomain, ldapUser, ldapPassword, ldapAuth) -> None:
"""Инициализация класса
### юри сервера
ldapUri="ldap://192.168.1.100"
### домен лдап
ldapDomain="dc=ldap,dc=domain,dc=local"
### пользователь с правами к лдап
ldapUser="Admin"
### пароль пользователя
ldapPassword='password123'"""
self.ldapUri = ldapUri
self.ldapDomain = ldapDomain
self.ldapUser = ldapUser if ldapUser else ""
self.ldapPassword = ldapPassword if ldapPassword else ""
self.ldapAuth = ldapAuth if ldapAuth else SIMPLE
# Список который содержыт символы которые нужено перевести в hex
self.hexlist = ['objectSid', 'objectGUID', 'dnsRecord', 'auditingPolicy', 'dSASignature'
'samDomainUpdates', 'msDFSR-ReplicationGroupGuid', 'ipsecData', 'samDomainUpdates'
'msDS-AdditionalDnsHostName', 'dSASignature', 'msDS-AdditionalDnsHostName', 'msDFSR-ContentSetGuid']
self.connect()
# default using to connect
def connect(self):
"""### Базовое подключение"""
try:
# old python-ldap
# self.conn = ldap.initialize(self.ldapUri)
# self.conn.simple_bind_s(self.ldapUser, self.ldapPassword)
server = Server(self.ldapUri, get_info=ALL)
if self.ldapAuth == NTLM:
print("Generating NTLM...")
else:
print("Loading...")
if self.ldapAuth == ANONYMOUS:
self.conn = Connection(server, user='', password=self.ldapPassword, authentication=self.ldapAuth)
else:
self.conn = Connection(server, user=f'{self.ldapDomain}\\{self.ldapUser}', password=self.ldapPassword, authentication=self.ldapAuth)
if not self.conn.bind():
print('Authenticated Failed')
exit(1);
print('Authentication Success')
except Exception as e:
print("Error connecting to LDAP:", e)
# default unbind/close connection
def unbind(self):
"""### Отключения и анбинд"""
self.conn.unbind()
return "Connection closed"
# default search method (generator) SCOPE_ONELEVEL , SCOPE_SUBTREE , SCOPE_BASE
def search(self, DN="", searchFilter="objectClass=*", scopeLevel=ldap3.SUBTREE, timeout=0):
""" Базовый поиск и система запросов
### ДН
DN: cn=Param ИЛИ cn=Param1,cn=Param2
### фильтр поиска
searchFilter: (objectClass=*)
### Таймаут запросов (в сек)
timeout: 0"""
components = self.ldapDomain.split('.')
dn_components = [f"dc={component}" for component in components]
formatted_dn = ','.join(dn_components)
baseDN = DN + "," + formatted_dn if DN != "" else formatted_dn
# Search in LDAP
try:
searchResult = self.conn.search(search_base=baseDN, search_scope=scopeLevel, search_filter="("+searchFilter+")", attributes=ALL_ATTRIBUTES)
sleep(timeout)
for entry in self.conn.entries:
yield "\nDN: " + str(entry.entry_dn)
for attribute in entry.entry_attributes:
yield attribute + ": " + str(entry[attribute])
except ValueError:
yield "Colected all"
except Exception as e:
yield "Yield error: " + str(e)
# writing to file
def toFile(self, folder="out/", timeout=1, yarafile=None, clear_old_files=True):
"""Функция для перенаправления ответов от AD сервера в файлы
### Папка для сохранения
folder: out/
### Таймаут запросов (в сек)
timeout: 1
### Файл с правилами yara
yara.txt
### Очистка старых файлов в папке
clear_old_files: True"""
if clear_old_files:
removeFiles()
if not os.path.exists(folder):
os.makedirs(folder)
if yarafile:
rules = [line.strip() for line in yarafile.readlines()]
yarafile.close()
for rule in rules:
for i in self.search(DN=rule, timeout=timeout):
with open(os.path.join(folder, rule.replace("CN=", "").replace(",", "-")), 'a') as file:
file.write(i+"\n")
sortFile()
else:
# по ONE_LEVEL создать файлы а по SUB_TREE заполнить файлы
for i in self.search(scopeLevel=ldap3.LEVEL, timeout=timeout): # default to all AD treas
main_cn = next((line.split(':', 1)[1].strip() for line in i.split('\n') if line.startswith("DN:")), None)
if main_cn != None:
main_cn = main_cn.split(",DC")[0]
# print("wewe: ", main_cn)
for sub in self.search(DN=main_cn, timeout=timeout):
with open(os.path.join(folder, main_cn.replace("CN=", "").replace(",", "-")), 'a') as file:
file.write(sub+"\n")
sortFile()