Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

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

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

492

493

494

495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524

525

526

527

528

529

530

531

532

533

534

535

536

537

538

539

540

541

542

543

544

545

546

547

548

549

550

551

552

553

554

555

556

557

558

559

560

561

562

563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585

586

587

588

589

590

591

592

593

594

595

596

597

598

599

600

601

602

603

604

605

606

607

608

609

610

611

612

613

614

615

616

617

618

619

620

621

622

623

624

625

626

627

628

629

630

631

632

633

634

635

636

637

638

639

640

641

642

643

644

645

646

647

648

649

650

651

652

653

654

655

656

657

658

659

660

661

662

663

664

665

666

667

668

669

670

671

672

673

674

675

676

677

678

679

680

681

682

683

684

685

686

687

688

689

690

691

692

693

694

695

696

697

698

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

724

725

726

727

728

729

730

731

732

733

734

735

736

737

738

739

740

741

742

743

744

745

746

747

748

749

750

751

752

753

754

755

756

757

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773

774

775

776

777

778

779

780

781

782

783

784

785

786

787

788

789

790

791

792

793

794

795

796

797

798

799

800

801

802

803

804

805

806

807

808

809

810

811

812

813

814

815

816

817

818

819

820

821

822

823

824

825

826

827

828

829

830

831

832

833

834

835

836

837

838

839

840

841

842

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

859

860

861

862

863

864

865

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902

903

904

905

906

907

908

909

910

911

912

913

914

915

916

917

918

919

920

921

922

923

924

925

926

927

928

929

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950

951

952

953

954

955

956

957

958

959

960

961

962

963

964

965

966

967

968

969

970

971

972

973

974

975

976

977

# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved. 

# 

# This software is provided under under a slightly modified version 

# of the Apache Software License. See the accompanying LICENSE file 

# for more information. 

# 

from __future__ import division 

from __future__ import print_function 

import base64 

import struct 

import calendar 

import time 

import hashlib 

import random 

import string 

import binascii 

from six import b 

 

from impacket.structure import Structure 

from impacket import LOG 

 

 

# This is important. NTLMv2 is not negotiated by the client or server.  

# It is used if set locally on both sides. Change this item if you don't want to use  

# NTLMv2 by default and fall back to NTLMv1 (with EXTENDED_SESSION_SECURITY or not) 

# Check the following links: 

# https://davenport.sourceforge.io/ntlm.html 

# https://blogs.msdn.microsoft.com/openspecification/2010/04/19/ntlm-keys-and-sundry-stuff/ 

# https://social.msdn.microsoft.com/Forums/c8f488ed-1b96-4e06-bd65-390aa41138d1/msnlmp-msntht-determining-ntlm-v1-or-v2-in-http-authentication?forum=os_specifications 

# So I'm setting a global variable to control this, this can also be set programmatically 

 

USE_NTLMv2 = True # if false will fall back to NTLMv1 (or NTLMv1 with ESS a.k.a NTLM2) 

TEST_CASE = False # Only set to True when running Test Cases 

 

 

def computeResponse(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', 

use_ntlmv2=USE_NTLMv2): 

38 ↛ 42line 38 didn't jump to line 42, because the condition on line 38 was never false if use_ntlmv2: 

return computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password, 

lmhash, nthash, use_ntlmv2=use_ntlmv2) 

else: 

return computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, 

lmhash, nthash, use_ntlmv2=use_ntlmv2) 

try: 

from Cryptodome.Cipher import ARC4 

from Cryptodome.Cipher import DES 

from Cryptodome.Hash import MD4 

except Exception: 

LOG.critical("Warning: You don't have any crypto installed. You need pycryptodomex") 

LOG.critical("See https://pypi.org/project/pycryptodomex/") 

 

NTLM_AUTH_NONE = 1 

NTLM_AUTH_CONNECT = 2 

NTLM_AUTH_CALL = 3 

NTLM_AUTH_PKT = 4 

NTLM_AUTH_PKT_INTEGRITY = 5 

NTLM_AUTH_PKT_PRIVACY = 6 

 

# If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN 

# with NTLMSSP_NEGOTIATE_56 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to 

# the client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 

# are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be 

# returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is 

# supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56. 

NTLMSSP_NEGOTIATE_56 = 0x80000000 

 

# If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message 

# integrity or confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for 

# this field is NTLMSSP_NEGOTIATE_KEY_EXCH. 

NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000 

 

# If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128. 

# If the client sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return 

# NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or 

# NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are 

# requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be 

# returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if it 

# is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128 

NTLMSSP_NEGOTIATE_128 = 0x20000000 

 

NTLMSSP_RESERVED_1 = 0x10000000 

NTLMSSP_RESERVED_2 = 0x08000000 

NTLMSSP_RESERVED_3 = 0x04000000 

 

# If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field 

# of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field 

# is NTLMSSP_NEGOTIATE_VERSION 

NTLMSSP_NEGOTIATE_VERSION = 0x02000000 

NTLMSSP_RESERVED_4 = 0x01000000 

 

# If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated. 

# An alternate name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO. 

NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000 

 

# If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is 

# NTLMSSP_REQUEST_NON_NT_SESSION_KEY. 

NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000 

NTLMSSP_RESERVED_5 = 0x00200000 

 

# If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY 

NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000 

 

# If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not 

# NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and 

# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 

# and NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the 

# client. NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be 

# used, and extended session security signing and sealing requires support from the client and the server in order to 

# be used.<23> An alternate name for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 

NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000 

NTLMSSP_NEGOTIATE_NTLM2 = 0x00080000 

NTLMSSP_TARGET_TYPE_SHARE = 0x00040000 

 

# If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the 

# TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set. 

# This flag MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field 

# is NTLMSSP_TARGET_TYPE_SERVER 

NTLMSSP_TARGET_TYPE_SERVER = 0x00020000 

 

# If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the 

# TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST 

# be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is 

# NTLMSSP_TARGET_TYPE_DOMAIN. 

NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000 

 

# If set, requests the presence of a signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the 

# NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden 

# by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field is 

# NTLMSSP_NEGOTIATE_ALWAYS_SIGN. 

NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 # forces the other end to sign packets 

NTLMSSP_RESERVED_6 = 0x00004000 

 

# This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field MUST be 

# ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name is 

# nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED. 

NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000 

 

# If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is 

# NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 

NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000 

NTLMSSP_RESERVED_7 = 0x00000800 

 

 

# If set, LM authentication is not allowed and only NT authentication is used. 

NTLMSSP_NEGOTIATE_NT_ONLY = 0x00000400 

 

# If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the 

# NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is 

# NTLMSSP_NEGOTIATE_NTLM 

NTLMSSP_NEGOTIATE_NTLM = 0x00000200 

NTLMSSP_RESERVED_8 = 0x00000100 

 

# If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and 

# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and 

# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be 

# returned to the client. NTLM v2 authentication session key generation MUST be supported by both the client and the 

# DC in order to be used, and extended session security signing and sealing requires support from the client and the 

# server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY. 

NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080 

 

# If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH 

# MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate 

# name for this field is NTLMSSP_NEGOTIATE_DATAGRAM. 

NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040 

 

# If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL to 

# the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the 

# CHALLENGE_MESSAGE. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and 

# NTLMSSP_NEGOTIATE_128, if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL. 

NTLMSSP_NEGOTIATE_SEAL = 0x00000020 

 

# If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the 

# server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE. 

# An alternate name for this field is NTLMSSP_NEGOTIATE_SIGN. 

NTLMSSP_NEGOTIATE_SIGN = 0x00000010 # means packet is signed, if verifier is wrong it fails 

NTLMSSP_RESERVED_9 = 0x00000008 

 

# If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this 

# field is NTLMSSP_REQUEST_TARGET. 

NTLMSSP_REQUEST_TARGET = 0x00000004 

 

# If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for 

# details. 

NTLM_NEGOTIATE_OEM = 0x00000002 

 

# If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE. 

NTLMSSP_NEGOTIATE_UNICODE = 0x00000001 

 

# AV_PAIR constants 

NTLMSSP_AV_EOL = 0x00 

NTLMSSP_AV_HOSTNAME = 0x01 

NTLMSSP_AV_DOMAINNAME = 0x02 

NTLMSSP_AV_DNS_HOSTNAME = 0x03 

NTLMSSP_AV_DNS_DOMAINNAME = 0x04 

NTLMSSP_AV_DNS_TREENAME = 0x05 

NTLMSSP_AV_FLAGS = 0x06 

NTLMSSP_AV_TIME = 0x07 

NTLMSSP_AV_RESTRICTIONS = 0x08 

NTLMSSP_AV_TARGET_NAME = 0x09 

NTLMSSP_AV_CHANNEL_BINDINGS = 0x0a 

 

class AV_PAIRS: 

def __init__(self, data = None): 

self.fields = {} 

205 ↛ exitline 205 didn't return from function '__init__', because the condition on line 205 was never false if data is not None: 

self.fromString(data) 

 

def __setitem__(self,key,value): 

self.fields[key] = (len(value),value) 

 

def __getitem__(self, key): 

212 ↛ 214line 212 didn't jump to line 214, because the condition on line 212 was never false if key in self.fields: 

return self.fields[key] 

return None 

 

def __delitem__(self, key): 

del self.fields[key] 

 

def __len__(self): 

return len(self.getData()) 

 

def __str__(self): 

return len(self.getData()) 

 

def fromString(self, data): 

tInfo = data 

fType = 0xff 

while fType is not NTLMSSP_AV_EOL: 

fType = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0] 

tInfo = tInfo[struct.calcsize('<H'):] 

length = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0] 

tInfo = tInfo[struct.calcsize('<H'):] 

content = tInfo[:length] 

self.fields[fType]=(length,content) 

tInfo = tInfo[length:] 

 

def dump(self): 

for i in list(self.fields.keys()): 

print("%s: {%r}" % (i,self[i])) 

 

def getData(self): 

242 ↛ 244line 242 didn't jump to line 244, because the condition on line 242 was never false if NTLMSSP_AV_EOL in self.fields: 

del self.fields[NTLMSSP_AV_EOL] 

ans = b'' 

for i in list(self.fields.keys()): 

ans+= struct.pack('<HH', i, self[i][0]) 

ans+= self[i][1] 

 

# end with a NTLMSSP_AV_EOL 

ans += struct.pack('<HH', NTLMSSP_AV_EOL, 0) 

 

return ans 

 

class NTLMAuthMixin: 

def get_os_version(self): 

if self['os_version'] == '': 

return None 

else: 

mayor_v = struct.unpack('B',self['os_version'][0])[0] 

minor_v = struct.unpack('B',self['os_version'][1])[0] 

build_v = struct.unpack('H',self['os_version'][2:4]) 

return mayor_v,minor_v,build_v 

 

class NTLMAuthNegotiate(Structure, NTLMAuthMixin): 

 

structure = ( 

('','"NTLMSSP\x00'), 

('message_type','<L=1'), 

('flags','<L'), 

('domain_len','<H-domain_name'), 

('domain_max_len','<H-domain_name'), 

('domain_offset','<L=0'), 

('host_len','<H-host_name'), 

('host_maxlen','<H-host_name'), 

('host_offset','<L=0'), 

('os_version',':'), 

('host_name',':'), 

('domain_name',':')) 

 

def __init__(self): 

Structure.__init__(self) 

self['flags']= ( 

NTLMSSP_NEGOTIATE_128 | 

NTLMSSP_NEGOTIATE_KEY_EXCH| 

# NTLMSSP_LM_KEY | 

NTLMSSP_NEGOTIATE_NTLM | 

NTLMSSP_NEGOTIATE_UNICODE | 

# NTLMSSP_ALWAYS_SIGN | 

NTLMSSP_NEGOTIATE_SIGN | 

NTLMSSP_NEGOTIATE_SEAL | 

# NTLMSSP_TARGET | 

0) 

self['host_name']='' 

self['domain_name']='' 

self['os_version']='' 

self._workstation = '' 

 

def setWorkstation(self, workstation): 

self._workstation = workstation 

 

def getWorkstation(self): 

return self._workstation 

 

def getData(self): 

305 ↛ 306line 305 didn't jump to line 306, because the condition on line 305 was never true if len(self.fields['host_name']) > 0: 

self['flags'] |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED 

307 ↛ 308line 307 didn't jump to line 308, because the condition on line 307 was never true if len(self.fields['domain_name']) > 0: 

self['flags'] |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED 

309 ↛ 310line 309 didn't jump to line 310, because the condition on line 309 was never true if len(self.fields['os_version']) > 0: 

self['flags'] |= NTLMSSP_NEGOTIATE_VERSION 

311 ↛ 312line 311 didn't jump to line 312, because the condition on line 311 was never true if (self['flags'] & NTLMSSP_NEGOTIATE_VERSION) == NTLMSSP_NEGOTIATE_VERSION: 

version_len = 8 

else: 

version_len = 0 

315 ↛ 316line 315 didn't jump to line 316, because the condition on line 315 was never true if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED: 

self['host_offset']=32 + version_len 

317 ↛ 318line 317 didn't jump to line 318, because the condition on line 317 was never true if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED: 

self['domain_offset']=32+len(self['host_name']) + version_len 

return Structure.getData(self) 

 

def fromString(self,data): 

Structure.fromString(self,data) 

 

domain_offset = self['domain_offset'] 

domain_end = self['domain_len'] + domain_offset 

self['domain_name'] = data[ domain_offset : domain_end ] 

 

host_offset = self['host_offset'] 

host_end = self['host_len'] + host_offset 

self['host_name'] = data[ host_offset : host_end ] 

 

hasOsInfo = self['flags'] & NTLMSSP_NEGOTIATE_VERSION 

if len(data) >= 36 and hasOsInfo: 

self['os_version'] = data[32:40] 

else: 

self['os_version'] = '' 

 

class NTLMAuthChallenge(Structure): 

 

structure = ( 

('','"NTLMSSP\x00'), 

('message_type','<L=2'), 

('domain_len','<H-domain_name'), 

('domain_max_len','<H-domain_name'), 

('domain_offset','<L=40'), 

('flags','<L=0'), 

('challenge','8s'), 

('reserved','8s=""'), 

('TargetInfoFields_len','<H-TargetInfoFields'), 

('TargetInfoFields_max_len','<H-TargetInfoFields'), 

('TargetInfoFields_offset','<L'), 

('VersionLen','_-Version','self.checkVersion(self["flags"])'), 

('Version',':'), 

('domain_name',':'), 

('TargetInfoFields',':')) 

 

@staticmethod 

def checkVersion(flags): 

359 ↛ 362line 359 didn't jump to line 362, because the condition on line 359 was never false if flags is not None: 

360 ↛ 361line 360 didn't jump to line 361, because the condition on line 360 was never true if flags & NTLMSSP_NEGOTIATE_VERSION == 0: 

return 0 

return 8 

 

def getData(self): 

if self['TargetInfoFields'] is not None and type(self['TargetInfoFields']) is not bytes: 

raw_av_fields = self['TargetInfoFields'].getData() 

self['TargetInfoFields'] = raw_av_fields 

return Structure.getData(self) 

 

def fromString(self,data): 

Structure.fromString(self,data) 

self['domain_name'] = data[self['domain_offset']:][:self['domain_len']] 

self['TargetInfoFields'] = data[self['TargetInfoFields_offset']:][:self['TargetInfoFields_len']] 

return self 

 

class NTLMAuthChallengeResponse(Structure, NTLMAuthMixin): 

 

structure = ( 

('','"NTLMSSP\x00'), 

('message_type','<L=3'), 

('lanman_len','<H-lanman'), 

('lanman_max_len','<H-lanman'), 

('lanman_offset','<L'), 

('ntlm_len','<H-ntlm'), 

('ntlm_max_len','<H-ntlm'), 

('ntlm_offset','<L'), 

('domain_len','<H-domain_name'), 

('domain_max_len','<H-domain_name'), 

('domain_offset','<L'), 

('user_len','<H-user_name'), 

('user_max_len','<H-user_name'), 

('user_offset','<L'), 

('host_len','<H-host_name'), 

('host_max_len','<H-host_name'), 

('host_offset','<L'), 

('session_key_len','<H-session_key'), 

('session_key_max_len','<H-session_key'), 

('session_key_offset','<L'), 

('flags','<L'), 

('VersionLen','_-Version','self.checkVersion(self["flags"])'), 

('Version',':=""'), 

('MICLen','_-MIC','self.checkMIC(self["flags"])'), 

('MIC',':=""'), 

('domain_name',':'), 

('user_name',':'), 

('host_name',':'), 

('lanman',':'), 

('ntlm',':'), 

('session_key',':')) 

 

def __init__(self, username = '', password = '', challenge = '', lmhash = '', nthash = '', flags = 0): 

Structure.__init__(self) 

self['session_key']='' 

self['user_name']=username.encode('utf-16le') 

self['domain_name']='' #"CLON".encode('utf-16le') 

self['host_name']='' #"BETS".encode('utf-16le') 

self['flags'] = ( #authResp['flags'] 

# we think (beto & gera) that his flags force a memory conten leakage when a windows 2000 answers using 

# uninitializaed verifiers 

NTLMSSP_NEGOTIATE_128 | 

NTLMSSP_NEGOTIATE_KEY_EXCH| 

# NTLMSSP_LM_KEY | 

NTLMSSP_NEGOTIATE_NTLM | 

NTLMSSP_NEGOTIATE_UNICODE | 

# NTLMSSP_ALWAYS_SIGN | 

NTLMSSP_NEGOTIATE_SIGN | 

NTLMSSP_NEGOTIATE_SEAL | 

# NTLMSSP_TARGET | 

0) 

# Here we do the stuff 

431 ↛ 432line 431 didn't jump to line 432, because the condition on line 431 was never true if username and ( lmhash != '' or nthash != ''): 

self['lanman'] = get_ntlmv1_response(lmhash, challenge) 

self['ntlm'] = get_ntlmv1_response(nthash, challenge) 

elif username and password: 

lmhash = compute_lmhash(password) 

nthash = compute_nthash(password) 

self['lanman']=get_ntlmv1_response(lmhash, challenge) 

self['ntlm']=get_ntlmv1_response(nthash, challenge) # This is not used for LM_KEY nor NTLM_KEY 

else: 

self['lanman'] = '' 

self['ntlm'] = '' 

442 ↛ exitline 442 didn't return from function '__init__', because the condition on line 442 was never false if not self['host_name']: 

self['host_name'] = 'NULL'.encode('utf-16le') # for NULL session there must be a hostname 

 

@staticmethod 

def checkVersion(flags): 

447 ↛ 450line 447 didn't jump to line 450, because the condition on line 447 was never false if flags is not None: 

448 ↛ 450line 448 didn't jump to line 450, because the condition on line 448 was never false if flags & NTLMSSP_NEGOTIATE_VERSION == 0: 

return 0 

return 8 

 

@staticmethod 

def checkMIC(flags): 

# TODO: Find a proper way to check the MIC is in there 

455 ↛ 458line 455 didn't jump to line 458, because the condition on line 455 was never false if flags is not None: 

456 ↛ 458line 456 didn't jump to line 458, because the condition on line 456 was never false if flags & NTLMSSP_NEGOTIATE_VERSION == 0: 

return 0 

return 16 

 

def getData(self): 

self['domain_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"]) 

self['user_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])+len(self['domain_name']) 

self['host_offset']=self['user_offset']+len(self['user_name']) 

self['lanman_offset']=self['host_offset']+len(self['host_name']) 

self['ntlm_offset']=self['lanman_offset']+len(self['lanman']) 

self['session_key_offset']=self['ntlm_offset']+len(self['ntlm']) 

return Structure.getData(self) 

 

def fromString(self,data): 

Structure.fromString(self,data) 

# [MS-NLMP] page 27 

# Payload data can be present in any order within the Payload field,  

# with variable-length padding before or after the data 

 

domain_offset = self['domain_offset'] 

domain_end = self['domain_len'] + domain_offset 

self['domain_name'] = data[ domain_offset : domain_end ] 

 

host_offset = self['host_offset'] 

host_end = self['host_len'] + host_offset 

self['host_name'] = data[ host_offset: host_end ] 

 

user_offset = self['user_offset'] 

user_end = self['user_len'] + user_offset 

self['user_name'] = data[ user_offset: user_end ] 

 

ntlm_offset = self['ntlm_offset'] 

ntlm_end = self['ntlm_len'] + ntlm_offset 

self['ntlm'] = data[ ntlm_offset : ntlm_end ] 

 

lanman_offset = self['lanman_offset'] 

lanman_end = self['lanman_len'] + lanman_offset 

self['lanman'] = data[ lanman_offset : lanman_end] 

 

#if len(data) >= 36:  

# self['os_version'] = data[32:36] 

#else: 

# self['os_version'] = '' 

 

class ImpacketStructure(Structure): 

def set_parent(self, other): 

self.parent = other 

 

def get_packet(self): 

return str(self) 

 

def get_size(self): 

return len(self) 

 

class ExtendedOrNotMessageSignature(Structure): 

def __init__(self, flags = 0, **kargs): 

512 ↛ 515line 512 didn't jump to line 515, because the condition on line 512 was never false if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

self.structure = self.extendedMessageSignature 

else: 

self.structure = self.MessageSignature 

return Structure.__init__(self, **kargs) 

 

class NTLMMessageSignature(ExtendedOrNotMessageSignature): 

extendedMessageSignature = ( 

('Version','<L=1'), 

('Checksum','<q'), 

('SeqNum','<I'), 

) 

 

MessageSignature = ( 

('Version','<L=1'), 

('RandomPad','<I=0'), 

('Checksum','<I'), 

('SeqNum','<I'), 

) 

 

KNOWN_DES_INPUT = b"KGS!@#$%" 

 

def __expand_DES_key(key): 

# Expand the key from a 7-byte password key into a 8-byte DES key 

536 ↛ 537line 536 didn't jump to line 537, because the condition on line 536 was never true if not isinstance(key, bytes): 

key = bytes(key) 

key = bytearray(key[:7]).ljust(7, b'\x00') 

s = bytearray() 

s.append(((key[0] >> 1) & 0x7f) << 1) 

s.append(((key[0] & 0x01) << 6 | ((key[1] >> 2) & 0x3f)) << 1) 

s.append(((key[1] & 0x03) << 5 | ((key[2] >> 3) & 0x1f)) << 1) 

s.append(((key[2] & 0x07) << 4 | ((key[3] >> 4) & 0x0f)) << 1) 

s.append(((key[3] & 0x0f) << 3 | ((key[4] >> 5) & 0x07)) << 1) 

s.append(((key[4] & 0x1f) << 2 | ((key[5] >> 6) & 0x03)) << 1) 

s.append(((key[5] & 0x3f) << 1 | ((key[6] >> 7) & 0x01)) << 1) 

s.append((key[6] & 0x7f) << 1) 

return bytes(s) 

 

def __DES_block(key, msg): 

cipher = DES.new(__expand_DES_key(key),DES.MODE_ECB) 

return cipher.encrypt(msg) 

 

def ntlmssp_DES_encrypt(key, challenge): 

answer = __DES_block(key[:7], challenge) 

answer += __DES_block(key[7:14], challenge) 

answer += __DES_block(key[14:], challenge) 

return answer 

 

# High level functions to use NTLMSSP 

 

def getNTLMSSPType1(workstation='', domain='', signingRequired = False, use_ntlmv2 = USE_NTLMv2): 

# Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with 

# international characters. 

import sys 

encoding = sys.getfilesystemencoding() 

567 ↛ 578line 567 didn't jump to line 578, because the condition on line 567 was never false if encoding is not None: 

try: 

workstation.encode('utf-16le') 

except: 

workstation = workstation.decode(encoding) 

try: 

domain.encode('utf-16le') 

except: 

domain = domain.decode(encoding) 

 

# Let's prepare a Type 1 NTLMSSP Message 

auth = NTLMAuthNegotiate() 

auth['flags']=0 

if signingRequired: 

auth['flags'] = NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | \ 

NTLMSSP_NEGOTIATE_SEAL 

583 ↛ 585line 583 didn't jump to line 585, because the condition on line 583 was never false if use_ntlmv2: 

auth['flags'] |= NTLMSSP_NEGOTIATE_TARGET_INFO 

auth['flags'] |= NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_NEGOTIATE_UNICODE | \ 

NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56 

 

# We're not adding workstation / domain fields this time. Normally Windows clients don't add such information but, 

# we will save the workstation name to be used later. 

auth.setWorkstation(workstation) 

 

return auth 

 

def getNTLMSSPType3(type1, type2, user, password, domain, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2): 

 

# Safety check in case somebody sent password = None.. That's not allowed. Setting it to '' and hope for the best. 

597 ↛ 598line 597 didn't jump to line 598, because the condition on line 597 was never true if password is None: 

password = '' 

 

# Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with 

# international characters. 

import sys 

encoding = sys.getfilesystemencoding() 

604 ↛ 618line 604 didn't jump to line 618, because the condition on line 604 was never false if encoding is not None: 

try: 

user.encode('utf-16le') 

except: 

user = user.decode(encoding) 

try: 

password.encode('utf-16le') 

except: 

password = password.decode(encoding) 

try: 

domain.encode('utf-16le') 

except: 

domain = user.decode(encoding) 

 

ntlmChallenge = NTLMAuthChallenge(type2) 

 

# Let's start with the original flags sent in the type1 message 

responseFlags = type1['flags'] 

 

# Token received and parsed. Depending on the authentication  

# method we will create a valid ChallengeResponse 

ntlmChallengeResponse = NTLMAuthChallengeResponse(user, password, ntlmChallenge['challenge']) 

 

clientChallenge = b("".join([random.choice(string.digits+string.ascii_letters) for _ in range(8)])) 

 

serverName = ntlmChallenge['TargetInfoFields'] 

 

ntResponse, lmResponse, sessionBaseKey = computeResponse(ntlmChallenge['flags'], ntlmChallenge['challenge'], 

clientChallenge, serverName, domain, user, password, 

lmhash, nthash, use_ntlmv2) 

 

# Let's check the return flags 

636 ↛ 638line 636 didn't jump to line 638, because the condition on line 636 was never true if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) == 0: 

# No extended session security, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY 

639 ↛ 641line 639 didn't jump to line 641, because the condition on line 639 was never true if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_128 ) == 0: 

# No support for 128 key len, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_128 

if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH) == 0: 

# No key exchange supported, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_KEY_EXCH 

if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SEAL) == 0: 

# No sign available, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SEAL 

if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SIGN) == 0: 

# No sign available, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SIGN 

if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) == 0: 

# No sign available, taking it out 

responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_ALWAYS_SIGN 

 

keyExchangeKey = KXKEY(ntlmChallenge['flags'], sessionBaseKey, lmResponse, ntlmChallenge['challenge'], password, 

lmhash, nthash, use_ntlmv2) 

 

# Special case for anonymous login 

if user == '' and password == '' and lmhash == '' and nthash == '': 

keyExchangeKey = b'\x00'*16 

 

# If we set up key exchange, let's fill the right variables 

if ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH: 

# not exactly what I call random tho :\ 

# exportedSessionKey = this is the key we should use to sign 

exportedSessionKey = b("".join([random.choice(string.digits+string.ascii_letters) for _ in range(16)])) 

#exportedSessionKey = "A"*16 

#print "keyExchangeKey %r" % keyExchangeKey 

# Let's generate the right session key based on the challenge flags 

#if responseFlags & NTLMSSP_NTLM2_KEY: 

# Extended session security enabled 

# if responseFlags & NTLMSSP_KEY_128: 

# Full key 

# exportedSessionKey = exportedSessionKey 

# elif responseFlags & NTLMSSP_KEY_56: 

# Only 56-bit key 

# exportedSessionKey = exportedSessionKey[:7] 

# else: 

# exportedSessionKey = exportedSessionKey[:5] 

#elif responseFlags & NTLMSSP_KEY_56: 

# No extended session security, just 56 bits key 

# exportedSessionKey = exportedSessionKey[:7] + '\xa0' 

#else: 

# exportedSessionKey = exportedSessionKey[:5] + '\xe5\x38\xb0' 

 

encryptedRandomSessionKey = generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey) 

else: 

encryptedRandomSessionKey = None 

# [MS-NLMP] page 46 

exportedSessionKey = keyExchangeKey 

 

ntlmChallengeResponse['flags'] = responseFlags 

ntlmChallengeResponse['domain_name'] = domain.encode('utf-16le') 

ntlmChallengeResponse['host_name'] = type1.getWorkstation().encode('utf-16le') 

if lmResponse == '': 

ntlmChallengeResponse['lanman'] = b'\x00' 

else: 

ntlmChallengeResponse['lanman'] = lmResponse 

ntlmChallengeResponse['ntlm'] = ntResponse 

if encryptedRandomSessionKey is not None: 

ntlmChallengeResponse['session_key'] = encryptedRandomSessionKey 

 

return ntlmChallengeResponse, exportedSessionKey 

 

 

# NTLMv1 Algorithm 

 

def generateSessionKeyV1(password, lmhash, nthash): 

hash = MD4.new() 

hash.update(NTOWFv1(password, lmhash, nthash)) 

return hash.digest() 

 

 

def computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', 

nthash='', use_ntlmv2=USE_NTLMv2): 

if user == '' and password == '': 

# Special case for anonymous authentication 

lmResponse = '' 

ntResponse = '' 

else: 

lmhash = LMOWFv1(password, lmhash, nthash) 

nthash = NTOWFv1(password, lmhash, nthash) 

if flags & NTLMSSP_NEGOTIATE_LM_KEY: 

ntResponse = '' 

lmResponse = get_ntlmv1_response(lmhash, serverChallenge) 

elif flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

md5 = hashlib.new('md5') 

chall = (serverChallenge + clientChallenge) 

md5.update(chall) 

ntResponse = ntlmssp_DES_encrypt(nthash, md5.digest()[:8]) 

lmResponse = clientChallenge + b'\x00'*16 

else: 

ntResponse = get_ntlmv1_response(nthash,serverChallenge) 

lmResponse = get_ntlmv1_response(lmhash, serverChallenge) 

 

sessionBaseKey = generateSessionKeyV1(password, lmhash, nthash) 

return ntResponse, lmResponse, sessionBaseKey 

 

def compute_lmhash(password): 

# This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html) 

password = password.upper() 

lmhash = __DES_block(b(password[:7]), KNOWN_DES_INPUT) 

lmhash += __DES_block(b(password[7:14]), KNOWN_DES_INPUT) 

return lmhash 

 

def NTOWFv1(password, lmhash = '', nthash=''): 

747 ↛ 748line 747 didn't jump to line 748, because the condition on line 747 was never true if nthash != '': 

return nthash 

return compute_nthash(password) 

 

def LMOWFv1(password, lmhash = '', nthash=''): 

752 ↛ 753line 752 didn't jump to line 753, because the condition on line 752 was never true if lmhash != '': 

return lmhash 

return compute_lmhash(password) 

 

def compute_nthash(password): 

# This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html) 

try: 

password = str(password).encode('utf_16le') 

except UnicodeDecodeError: 

import sys 

password = password.decode(sys.getfilesystemencoding()).encode('utf_16le') 

 

hash = MD4.new() 

hash.update(password) 

return hash.digest() 

 

def get_ntlmv1_response(key, challenge): 

return ntlmssp_DES_encrypt(key, challenge) 

 

# NTLMv2 Algorithm - as described in MS-NLMP Section 3.3.2 

 

# Crypto Stuff 

 

def MAC(flags, handle, signingKey, seqNum, message): 

# [MS-NLMP] Section 3.4.4 

# Returns the right messageSignature depending on the flags 

messageSignature = NTLMMessageSignature(flags) 

779 ↛ 792line 779 didn't jump to line 792, because the condition on line 779 was never false if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

780 ↛ 787line 780 didn't jump to line 787, because the condition on line 780 was never false if flags & NTLMSSP_NEGOTIATE_KEY_EXCH: 

messageSignature['Version'] = 1 

messageSignature['Checksum'] = \ 

struct.unpack('<q', handle(hmac_md5(signingKey, struct.pack('<i', seqNum) + message)[:8]))[0] 

messageSignature['SeqNum'] = seqNum 

seqNum += 1 

else: 

messageSignature['Version'] = 1 

messageSignature['Checksum'] = struct.unpack('<q',hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8])[0] 

messageSignature['SeqNum'] = seqNum 

seqNum += 1 

else: 

messageSignature['Version'] = 1 

messageSignature['Checksum'] = struct.pack('<I',binascii.crc32(message)& 0xFFFFFFFF) 

messageSignature['RandomPad'] = 0 

messageSignature['RandomPad'] = handle(struct.pack('<I',messageSignature['RandomPad'])) 

messageSignature['Checksum'] = struct.unpack('<I',handle(messageSignature['Checksum']))[0] 

messageSignature['SeqNum'] = handle(b'\x00\x00\x00\x00') 

messageSignature['SeqNum'] = struct.unpack('<I',messageSignature['SeqNum'])[0] ^ seqNum 

messageSignature['RandomPad'] = 0 

 

return messageSignature 

 

def SEAL(flags, signingKey, sealingKey, messageToSign, messageToEncrypt, seqNum, handle): 

sealedMessage = handle(messageToEncrypt) 

signature = MAC(flags, handle, signingKey, seqNum, messageToSign) 

return sealedMessage, signature 

 

def SIGN(flags, signingKey, message, seqNum, handle): 

return MAC(flags, handle, signingKey, seqNum, message) 

 

def SIGNKEY(flags, randomSessionKey, mode = 'Client'): 

812 ↛ 822line 812 didn't jump to line 822, because the condition on line 812 was never false if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

if mode == 'Client': 

md5 = hashlib.new('md5') 

md5.update(randomSessionKey + b"session key to client-to-server signing key magic constant\x00") 

signKey = md5.digest() 

else: 

md5 = hashlib.new('md5') 

md5.update(randomSessionKey + b"session key to server-to-client signing key magic constant\x00") 

signKey = md5.digest() 

else: 

signKey = None 

return signKey 

 

def SEALKEY(flags, randomSessionKey, mode = 'Client'): 

826 ↛ 843line 826 didn't jump to line 843, because the condition on line 826 was never false if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

827 ↛ 829line 827 didn't jump to line 829, because the condition on line 827 was never false if flags & NTLMSSP_NEGOTIATE_128: 

sealKey = randomSessionKey 

elif flags & NTLMSSP_NEGOTIATE_56: 

sealKey = randomSessionKey[:7] 

else: 

sealKey = randomSessionKey[:5] 

 

if mode == 'Client': 

md5 = hashlib.new('md5') 

md5.update(sealKey + b'session key to client-to-server sealing key magic constant\x00') 

sealKey = md5.digest() 

else: 

md5 = hashlib.new('md5') 

md5.update(sealKey + b'session key to server-to-client sealing key magic constant\x00') 

sealKey = md5.digest() 

 

elif flags & NTLMSSP_NEGOTIATE_56: 

sealKey = randomSessionKey[:7] + b'\xa0' 

else: 

sealKey = randomSessionKey[:5] + b'\xe5\x38\xb0' 

 

return sealKey 

 

 

def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey): 

cipher = ARC4.new(keyExchangeKey) 

cipher_encrypt = cipher.encrypt 

 

sessionKey = cipher_encrypt(exportedSessionKey) 

return sessionKey 

 

def KXKEY(flags, sessionBaseKey, lmChallengeResponse, serverChallenge, password, lmhash, nthash, use_ntlmv2 = USE_NTLMv2): 

859 ↛ 862line 859 didn't jump to line 862, because the condition on line 859 was never false if use_ntlmv2: 

return sessionBaseKey 

 

if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY: 

if flags & NTLMSSP_NEGOTIATE_NTLM: 

keyExchangeKey = hmac_md5(sessionBaseKey, serverChallenge + lmChallengeResponse[:8]) 

else: 

keyExchangeKey = sessionBaseKey 

elif flags & NTLMSSP_NEGOTIATE_NTLM: 

if flags & NTLMSSP_NEGOTIATE_LM_KEY: 

keyExchangeKey = __DES_block(LMOWFv1(password, lmhash)[:7], lmChallengeResponse[:8]) + __DES_block( 

LMOWFv1(password, lmhash)[7] + b'\xBD\xBD\xBD\xBD\xBD\xBD', lmChallengeResponse[:8]) 

elif flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY: 

keyExchangeKey = LMOWFv1(password,lmhash)[:8] + b'\x00'*8 

else: 

keyExchangeKey = sessionBaseKey 

else: 

raise Exception("Can't create a valid KXKEY!") 

 

return keyExchangeKey 

 

def hmac_md5(key, data): 

import hmac 

h = hmac.new(key) 

h.update(data) 

return h.digest() 

 

def NTOWFv2( user, password, domain, hash = ''): 

if hash != '': 

theHash = hash 

else: 

theHash = compute_nthash(password) 

return hmac_md5(theHash, user.upper().encode('utf-16le') + domain.encode('utf-16le')) 

 

def LMOWFv2( user, password, domain, lmhash = ''): 

return NTOWFv2( user, password, domain, lmhash) 

 

 

def computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', 

nthash='', use_ntlmv2=USE_NTLMv2): 

 

responseServerVersion = b'\x01' 

hiResponseServerVersion = b'\x01' 

responseKeyNT = NTOWFv2(user, password, domain, nthash) 

 

av_pairs = AV_PAIRS(serverName) 

# In order to support SPN target name validation, we have to add this to the serverName av_pairs. Otherwise we will 

# get access denied 

# This is set at Local Security Policy -> Local Policies -> Security Options -> Server SPN target name validation 

# level 

909 ↛ 918line 909 didn't jump to line 918, because the condition on line 909 was never false if TEST_CASE is False: 

av_pairs[NTLMSSP_AV_TARGET_NAME] = 'cifs/'.encode('utf-16le') + av_pairs[NTLMSSP_AV_HOSTNAME][1] 

911 ↛ 914line 911 didn't jump to line 914, because the condition on line 911 was never false if av_pairs[NTLMSSP_AV_TIME] is not None: 

aTime = av_pairs[NTLMSSP_AV_TIME][1] 

else: 

aTime = struct.pack('<q', (116444736000000000 + calendar.timegm(time.gmtime()) * 10000000) ) 

av_pairs[NTLMSSP_AV_TIME] = aTime 

serverName = av_pairs.getData() 

else: 

aTime = b'\x00'*8 

 

temp = responseServerVersion + hiResponseServerVersion + b'\x00' * 6 + aTime + clientChallenge + b'\x00' * 4 + \ 

serverName + b'\x00' * 4 

 

ntProofStr = hmac_md5(responseKeyNT, serverChallenge + temp) 

 

ntChallengeResponse = ntProofStr + temp 

lmChallengeResponse = hmac_md5(responseKeyNT, serverChallenge + clientChallenge) + clientChallenge 

sessionBaseKey = hmac_md5(responseKeyNT, ntProofStr) 

 

if user == '' and password == '': 

# Special case for anonymous authentication 

ntChallengeResponse = '' 

lmChallengeResponse = '' 

 

return ntChallengeResponse, lmChallengeResponse, sessionBaseKey 

 

class NTLM_HTTP(object): 

# Parent class for NTLM HTTP classes. 

MSG_TYPE = None 

 

@classmethod 

def get_instace(cls,msg_64): 

msg = None 

msg_type = 0 

if msg_64 != '': 

msg = base64.b64decode(msg_64[5:]) # Remove the 'NTLM ' 

msg_type = ord(msg[8]) 

 

for _cls in NTLM_HTTP.__subclasses__(): 

if msg_type == _cls.MSG_TYPE: 

instance = _cls() 

instance.fromString(msg) 

return instance 

 

 

class NTLM_HTTP_AuthRequired(NTLM_HTTP): 

commonHdr = () 

# Message 0 means the first HTTP request e.g. 'GET /bla.png' 

MSG_TYPE = 0 

 

def fromString(self,data): 

pass 

 

 

class NTLM_HTTP_AuthNegotiate(NTLM_HTTP, NTLMAuthNegotiate): 

commonHdr = () 

MSG_TYPE = 1 

 

def __init__(self): 

NTLMAuthNegotiate.__init__(self) 

 

 

class NTLM_HTTP_AuthChallengeResponse(NTLM_HTTP, NTLMAuthChallengeResponse): 

commonHdr = () 

MSG_TYPE = 3 

 

def __init__(self): 

NTLMAuthChallengeResponse.__init__(self)