From 779d1f7142cca250cea80fcf5c74c78382f76167 Mon Sep 17 00:00:00 2001 From: Christopher Shepherd Date: Sun, 24 May 2015 19:49:14 -0400 Subject: [PATCH] SMB_Setup_AndX logs in with old/insecure Lanman (DES) hashing (requires Tool129) --- README.md | 1 + latest_tcpdump.txt | 154 ++++++++++++++++++++++++ src/SMBDEMO.S | 287 ++++++++++++++++++++++++++++++++++++++++++--- src/smbdemo | Bin 37715 -> 38624 bytes 4 files changed, 425 insertions(+), 17 deletions(-) create mode 100644 latest_tcpdump.txt diff --git a/README.md b/README.md index 2bbc499..147a395 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ CIFS / SMB2 navel gazing, in 65816 assembly. 5/9/2015 - Current status: Connects on port 445, sends valid SMB Protocol Negotiation message, accepts and analyzes reply. Next step: Login, mount a share, read a file. +5/24/2015 - Current status: Connects on port 445, completes Protocol Negotiation, successfully sends login (on Setup_ANDX message), obsolete LM (DES) style password Build 'CMD.S' with Merlin32 and the included Library directory. diff --git a/latest_tcpdump.txt b/latest_tcpdump.txt new file mode 100644 index 0000000..2231da9 --- /dev/null +++ b/latest_tcpdump.txt @@ -0,0 +1,154 @@ +10.0.2.55 = Apple IIgs running Marinetti +10.0.2.1 = Raspberry Pi running A2SERVER, SMB credentials 'PI' / 'APPLE2' + +19:44:52.729775 IP (tos 0x0, ttl 60, id 437, offset 0, flags [none], proto TCP (6), length 91) + 10.0.2.55.1025 > 10.0.2.1.445: Flags [P.], cksum 0x9201 (correct), seq 1:52, ack 1, win 16384, length 51 +SMB PACKET: SMBnegprot (REQUEST) +SMB Command = 0x72 +Error class = 0x0 +Error code = 0 (0x0) +Flags1 = 0x8 +Flags2 = 0x1 +Tree ID = 0 (0x0) +Proc ID = 57005 (0xdead) +UID = 0 (0x0) +MID = 1 (0x1) +Word Count = 0 (0x0) +smb_bcc=12 +Dialect=NT LM 0.12 + + + 0x0000: 4500 005b 01b5 0000 3c06 64b1 0a00 0237 E..[....<.d....7 + 0x0010: 0a00 0201 0401 01bd 0b17 3b08 4197 ac10 ..........;.A... + 0x0020: 5018 4000 9201 0000 0000 002f ff53 4d42 P.@......../.SMB + 0x0030: 7200 0000 0008 0100 0000 0000 0000 0000 r............... + 0x0040: 0000 0000 0000 adde 0000 0100 000c 0002 ................ + 0x0050: 4e54 204c 4d20 302e 3132 00 NT.LM.0.12. + +19:44:52.730020 IP (tos 0x0, ttl 64, id 59985, offset 0, flags [DF], proto TCP (6), length 40) + 10.0.2.1.445 > 10.0.2.55.1025: Flags [.], cksum 0x1852 (incorrect -> 0x24dd), seq 1, ack 52, win 14600, length 0 + 0x0000: 4500 0028 ea51 4000 4006 3847 0a00 0201 E..(.Q@.@.8G.... + 0x0010: 0a00 0237 01bd 0401 4197 ac10 0b17 3b3b ...7....A.....;; + 0x0020: 5010 3908 1852 0000 P.9..R.. + +19:44:52.735280 IP (tos 0x0, ttl 64, id 59986, offset 0, flags [DF], proto TCP (6), length 141) + 10.0.2.1.445 > 10.0.2.55.1025: Flags [P.], cksum 0x975e (correct), seq 1:102, ack 52, win 14600, length 101 +SMB PACKET: SMBnegprot (REPLY) +SMB Command = 0x72 +Error class = 0x0 +Error code = 0 (0x0) +Flags1 = 0x88 +Flags2 = 0x3 +Tree ID = 0 (0x0) +Proc ID = 57005 (0xdead) +UID = 0 (0x0) +MID = 1 (0x1) +Word Count = 17 (0x11) +NT1 Protocol +DialectIndex=0 (0x0) +SecMode=0x3 +MaxMux=50 (0x32) +NumVcs=1 (0x1) +MaxBuffer=16644 (0x4104) +RawSize=65536 (0x10000) +SessionKey=0x76A1 +Capabilities=0x80F3FD +ServerTime=Sun May 24 19:44:54 2015 +TimeZone=240 (0xf0) +CryptKey=Data: (1 bytes) +[000] 08 \0x08 +smb_bcc=28 +[000] E1 F1 F5 61 E2 7C 34 34 57 00 4F 00 52 00 4B 00 \0xe1\0xf1\0xf5a\0xe2|44 W\0x00O\0x00R\0x00K\0x00 +[010] 47 00 52 00 4F 00 55 00 50 00 00 00 G\0x00R\0x00O\0x00U\0x00 P\0x00\0x00\0x00 + + + 0x0000: 4500 008d ea52 4000 4006 37e1 0a00 0201 E....R@.@.7..... + 0x0010: 0a00 0237 01bd 0401 4197 ac10 0b17 3b3b ...7....A.....;; + 0x0020: 5018 3908 975e 0000 0000 0061 ff53 4d42 P.9..^.....a.SMB + 0x0030: 7200 0000 0088 0340 0000 0000 0000 0000 r......@........ + 0x0040: 0000 0000 0000 adde 0000 0100 1100 0003 ................ + 0x0050: 3200 0100 0441 0000 0000 0100 a176 0000 2....A.......v.. + 0x0060: fdf3 8000 f7ae 6fa1 7b96 d001 f000 081c ......o.{....... + 0x0070: 00e1 f1f5 61e2 7c34 3457 004f 0052 004b ....a.|44W.O.R.K + 0x0080: 0047 0052 004f 0055 0050 0000 00 .G.R.O.U.P... + +19:44:52.789776 IP (tos 0x0, ttl 60, id 438, offset 0, flags [none], proto TCP (6), length 40) + 10.0.2.55.1025 > 10.0.2.1.445: Flags [.], cksum 0x1d80 (correct), seq 52, ack 102, win 16384, length 0 + 0x0000: 4500 0028 01b6 0000 3c06 64e3 0a00 0237 E..(....<.d....7 + 0x0010: 0a00 0201 0401 01bd 0b17 3b3b 4197 ac75 ..........;;A..u + 0x0020: 5010 4000 1d80 0000 0000 0000 0000 P.@........... + +19:44:53.037171 IP (tos 0x0, ttl 60, id 439, offset 0, flags [none], proto TCP (6), length 183) + 10.0.2.55.1025 > 10.0.2.1.445: Flags [P.], cksum 0xe588 (correct), seq 52:195, ack 102, win 16384, length 143 +SMB PACKET: SMBsesssetupX (REQUEST) +SMB Command = 0x73 +Error class = 0x0 +Error code = 0 (0x0) +Flags1 = 0x8 +Flags2 = 0x1 +Tree ID = 0 (0x0) +Proc ID = 57005 (0xdead) +UID = 0 (0x0) +MID = 1 (0x1) +Word Count = 13 (0xd) +Com2=0xFF +Res1=0x0 +Off2=0 (0x0) +MaxBuffer=16644 (0x4104) +MaxMpx=50 (0x32) +VcNumber=1 (0x1) +SessionKey=0x76A1 +CaseInsensitivePasswordLength=24 (0x18) +CaseSensitivePasswordLength=0 (0x0) +Res=0x0 +Capabilities=0x80F3FD +Pass1&Pass2&Account&Domain&OS&LanMan= +smb_bcc=78 +[000] F3 E1 2B C1 B9 1E F4 0B 7A E8 D5 93 F2 C6 56 11 \0xf3\0xe1+\0xc1\0xb9\0x1e\0xf4\0x0b z\0xe8\0xd5\0x93\0xf2\0xc6V\0x11 +[010] 2C 20 43 40 C5 58 11 C6 00 00 00 00 00 00 00 00 , C@\0xc5X\0x11\0xc6 \0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00 +[020] 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 \0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00 \0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00 +[030] 50 49 00 57 4F 52 4B 47 52 4F 55 50 00 47 53 2F PI\0x00WORKG ROUP\0x00GS/ +[040] 4F 53 00 41 70 70 6C 65 20 49 49 67 73 00 OS\0x00Apple IIgs\0x00 + + + 0x0000: 4500 00b7 01b7 0000 3c06 6453 0a00 0237 E.......<.dS...7 + 0x0010: 0a00 0201 0401 01bd 0b17 3b3b 4197 ac75 ..........;;A..u + 0x0020: 5018 4000 e588 0000 0000 008b ff53 4d42 P.@..........SMB + 0x0030: 7300 0000 0008 0100 0000 0000 0000 0000 s............... + 0x0040: 0000 0000 0000 adde 0000 0100 0dff 0000 ................ + 0x0050: 0004 4132 0001 00a1 7600 0018 0000 0000 ..A2....v....... + 0x0060: 0000 00fd f380 004e 00f3 e12b c1b9 1ef4 .......N...+.... + 0x0070: 0b7a e8d5 93f2 c656 112c 2043 40c5 5811 .z.....V.,.C@.X. + 0x0080: c600 0000 0000 0000 0000 0000 0000 0000 ................ + 0x0090: 0000 0000 0000 0000 0050 4900 574f 524b .........PI.WORK + 0x00a0: 4752 4f55 5000 4753 2f4f 5300 4170 706c GROUP.GS/OS.Appl + 0x00b0: 6520 4949 6773 00 e.IIgs. + +19:44:53.039043 IP (tos 0x0, ttl 64, id 59987, offset 0, flags [DF], proto TCP (6), length 112) + 10.0.2.1.445 > 10.0.2.55.1025: Flags [P.], cksum 0x0d0a (correct), seq 102:174, ack 195, win 15544, length 72 +SMB PACKET: SMBsesssetupX (REPLY) +SMB Command = 0x73 +Error class = 0x0 +Error code = 0 (0x0) +Flags1 = 0x88 +Flags2 = 0x3 +Tree ID = 0 (0x0) +Proc ID = 57005 (0xdead) +UID = 100 (0x64) +MID = 1 (0x1) +Word Count = 3 (0x3) +Com2=0xFF +Off2=0 (0x0) +Action=0x1 +smb_bcc=27 +[000] 55 6E 69 78 00 53 61 6D 62 61 20 33 2E 36 2E 36 Unix\0x00Sam ba 3.6.6 +[010] 00 57 4F 52 4B 47 52 4F 55 50 00 \0x00WORKGRO UP\0x00 + + + 0x0000: 4500 0070 ea53 4000 4006 37fd 0a00 0201 E..p.S@.@.7..... + 0x0010: 0a00 0237 01bd 0401 4197 ac75 0b17 3bca ...7....A..u..;. + 0x0020: 5018 3cb8 0d0a 0000 0000 0044 ff53 4d42 P.<........D.SMB + 0x0030: 7300 0000 0088 0340 0000 0000 0000 0000 s......@........ + 0x0040: 0000 0000 0000 adde 6400 0100 03ff 0000 ........d....... + 0x0050: 0001 001b 0055 6e69 7800 5361 6d62 6120 .....Unix.Samba. + 0x0060: 332e 362e 3600 574f 524b 4752 4f55 5000 3.6.6.WORKGROUP. diff --git a/src/SMBDEMO.S b/src/SMBDEMO.S index 9a6e16b..75b04a6 100644 --- a/src/SMBDEMO.S +++ b/src/SMBDEMO.S @@ -6,6 +6,7 @@ * Friday, May 1, 2015 - Ported more code to Merlin32, set up Merlin32 equates * Saturday, May 2, 2015 - Formatting fixes, refactoring, rewritten SMB Negotiation code * Saturday, May 9, 2015 - Receive and interpret NEG_PROT reply and start login +* Sunday, May 24, 2015 - Some bugfixes, Tool128 and Tool129 requirement for hashing and DES, LM password hashing support * * REFERENCES * smb.c / smb.h from libOGC @@ -91,7 +92,7 @@ StartUpTools _TLStartUp pha pha - PushLong #$800 ; 8 pages of DP space + PushLong #$900 ; 9 pages of DP space PushWord AppMMID PushWord #$C005 ; Fixed, Page-Aligned, Locked, Unpurgeable PushLong #$000000 ; in Bank $00, $0000 @@ -185,11 +186,21 @@ StartUpTools _TLStartUp clc adc #$100 pha + pha _SoundStartUp jsr CheckError _TCPIPStartUp jsr CheckError + + Tool $280 ; HashStartUp + jsr CheckError + + pla + clc + adc #$100 + pha + Tool $281 ; CryptoStartUp rts @@ -636,6 +647,13 @@ sendloop2 PushWord #0000 pla cmp #2 bne noevent3 + PushWord #0000 ; space for result + PushLong #00000000 ; nil filter procedure + _ModalDialog + pla + cmp #2 + bne noevent3 + jmp CTSClose3 noevent3 PushLong MySMBHandle jsr SMB_Negotiate_Poll @@ -647,7 +665,31 @@ login PushLong CTSWinPtr PushLong #CTSTextB _SetIText - jmp SMB_input_brk ; die so we can inspect things + PushLong MySMBHandle + jsr SMB_SetupAndX + +sendloop3 PushWord #0000 + PushWord #$0006 + PushLong #EventRec + _EventAvail + pla + beq noevent4 + PushWord #0000 + PushLong #00000000 + _ModalDialog + pla + cmp #2 + bne noevent4 + PushWord #0000 ; space for result + PushLong #00000000 ; nil filter procedure + _ModalDialog + pla + cmp #2 + bne noevent4 + jmp SMB_staging_brk + +noevent4 _TCPIPPoll + bra sendloop3 closed PushLong CTSWinPtr PushWord #1350 @@ -717,7 +759,7 @@ readbuf ds 4 ; rrBuffCount * * Tool List * -ToolList dw 13 ; Tool Count +ToolList dw 15 ; Tool Count dw 01,00 ; Tool Locator, any vers dw 02,00 ; Memory Manager, any vers dw 03,00 ; Misc Tools, any vers @@ -731,6 +773,8 @@ ToolList dw 13 ; Tool Count dw 20,00 ; Line Edit, any vers dw 21,00 ; Dialog Manager, any vers dw 54,00 ; Marinetti, any vers + dw 128,00 ; HashTool, any vers (MD2/MD4/MD5/SHA1 hashing for NTLMv2) + dw 129,00 ; Crypto tool, any vers (DES for NTLMv1) ToolListEnd * @@ -1083,6 +1127,11 @@ SMB_sess_domain ds 32 ; sloppy 32 byte buffer to hold SMB domain SMB_dialect asc 02'NT LM 0.12'00 ; the only dialect we're gonna speak SMB_os asc 'GS/OS'00 ; native Operating System SMB_lanman asc 'Apple IIgs'00 ; native LAN Manager +SMB_lm_username asc 'PI'00,00,00,00,00,00,00,00,00,00,00,00 ; lanman hash login username +SMB_lm_password asc 'APPLE2'00,00,00,00,00,00,00,00 ; lanman hash login password +SMB_lm_magic asc 'KGS!@#$%' ; lanman hash magic DES crypt string +SMB_lm_hash ds 21 ; LM Hash, actually 16 bytes but the extra zeroes make response easier to generate +SMB_lm_response ds 24 ; LM Response * SMB packet staging area * TODO these will probably be dynamically allocated too? @@ -1356,45 +1405,223 @@ SMB_SetupAndX plx ; return address ldy #SMB_sess_maxbuffer-SMB_sess_begin lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+3 ; max buffer size + sta SMB_staging+SMB_header_size+5 ; max buffer size ldy #SMB_sess_maxmpx-SMB_sess_begin lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+5 ; max MPX + sta SMB_staging+SMB_header_size+7 ; max MPX ldy #SMB_sess_maxvcs-SMB_sess_begin lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+7 ; max VCS + sta SMB_staging+SMB_header_size+9 ; max VCS ldy #SMB_sess_skey-SMB_sess_begin lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+9 ; session key + sta SMB_staging+SMB_header_size+11 ; session key lda #0 - sta SMB_staging+SMB_header_size+11 ; session key (upper, should always be zero?) + sta SMB_staging+SMB_header_size+13 ; session key (upper, should always be zero?) lda #24 - sta SMB_staging+SMB_header_size+13 ; password length (case insensitive) - - lda #24 - sta SMB_staging+SMB_header_size+15 ; password length (case sensitive) + sta SMB_staging+SMB_header_size+15 ; password length (case insensitive) + + lda #0 + sta SMB_staging+SMB_header_size+17 ; password length (case sensitive/NTLM) lda #0 - sta SMB_staging+SMB_header_size+17 ; reserved sta SMB_staging+SMB_header_size+19 ; reserved + sta SMB_staging+SMB_header_size+21 ; reserved ldy #SMB_sess_caps-SMB_sess_begin lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+21 + sta SMB_staging+SMB_header_size+23 iny iny lda [SMB_sessid],y - sta SMB_staging+SMB_header_size+23 ; session capabilities + sta SMB_staging+SMB_header_size+25 ; session capabilities + jsr SMB_LM_Hash ; generate NTLMv1 Hash + jsr SMB_LM_Response ; generate NTLMv1 Response + lda #0 + sta SMB_tmp5 ; initialize pointer -* TODO copy username, password, native os, native lanmanager, update byte count, send result + ; Case Insensitive Password (LM Response) + PushLong #SMB_lm_response ; source + pea #^SMB_staging + lda #SMB_staging+SMB_header_size+29 + clc + adc SMB_tmp5 + pha + ldx #24 + jsr _strncpy + lda #24 + clc + adc SMB_tmp5 + sta SMB_tmp5 + + ; Case Sensitive Password (NTLM Response) + clc + adc #24 + sta SMB_tmp5 ; skip it / zero it for now + + ; Account + PushLong #SMB_lm_username ; source + pea #^SMB_staging ; destination + lda #SMB_staging+SMB_header_size+29 + clc + adc SMB_tmp5 + pha + jsr _strcpy + tya + clc + adc SMB_tmp5 + sta SMB_tmp5 + + ; Domain + PushLong #SMB_sess_domain ; source + pea #^SMB_staging ; destination + lda #SMB_staging+SMB_header_size+29 + clc + adc SMB_tmp5 + pha + jsr _strcpy + tya + clc + adc SMB_tmp5 + sta SMB_tmp5 + + ; OS + PushLong #SMB_os ; source + pea #^SMB_staging ; destination + lda #SMB_staging+SMB_header_size+29 + clc + adc SMB_tmp5 + pha + jsr _strcpy + tya + clc + adc SMB_tmp5 + sta SMB_tmp5 + + ; LanMan + PushLong #SMB_lanman + pea #^SMB_staging ; destination + lda #SMB_staging+SMB_header_size+29 + clc + adc SMB_tmp5 + pha + jsr _strcpy + tya + clc + adc SMB_tmp5 + sta SMB_tmp5 + + sta SMB_staging+SMB_header_size+27 ; update byte count + + clc + adc #SMB_header_size+29 + pha ; 'length' parameter for _SMB_Send + dec + dec + dec + dec + xba + sta SMB_staging+SMB_offset_tcplength+1 ; save length for naked-TCP dgram - jsr _SMB_Send + jsr _SMB_Send ; send our reply! + clc + rts + +* SMB_LM_Hash - operate on the SMB_lm_username and SMB_lm_password values to produce +* SMB_lm_hash, using V1 DES-based operation. Requires TOOL129 (Crypto Tool) +* +* The password has been uppercased and chopped to 14 bytes, with 0x00 padding +* We take it in two 7-byte pieces, add parity, and use each piece to DES-encrypt the string +* 'KGS!@#$%'. The result is the LM hash. +SMB_LM_Hash PushLong #SMB_tmp1 ; SMB_tmp1 will have our parity-enhanced key + PushLong #SMB_lm_password ; key to add parity to + Tool $0A81 ; DESAddParity + + PushLong #SMB_lm_hash ; where DES-encrypted data will go + PushLong #SMB_tmp1 ; parity-enhanced key + PushLong #SMB_lm_magic ; the magic string we're encrypting + PushWord #0000 ; operation: encrypt + Tool $0981 ; DESCipher + + ; now do the same thing with the second 7 bytes of the password + + PushLong #SMB_tmp1 + PushLong #SMB_lm_password+7 + Tool $0A81 ; DesAddParity + + PushLong #SMB_lm_hash+8 + PushLong #SMB_tmp1 + PushLong #SMB_lm_magic + PushWord #0000 + Tool $0981 + + ; SMB_lm_hash should now contain the NTLMv1 hash of the password + clc + rts + +* SMB_LM_Response - operate on SMB_lm_hash and 8-byte challenge to produce +* SMB_lm_response, using V1 DES-based operation. Requires TOOL129 (Crypto Tool) +* +* LM Hash is padded out to 21 bytes, each of which gets parity added and is +* used to DES encrypt the session challenge. The result is the LM response. +SMB_LM_Response + PushLong #SMB_tmp1 ; SMB_tmp1 will have our parity-enhanced key + PushLong #SMB_lm_hash ; key to add parity to + Tool $0A81 ; DESAddParity + + PushLong #SMB_lm_response ; where the DES-encrypted data will go + PushLong #SMB_tmp1 ; parity-enhanced key + ldy #SMB_sess_challenge-SMB_sess_begin + lda [SMB_sessid],y ; PushLong [SMB_sessid],y + pha + iny + iny + lda [SMB_sessid],y + pha + PushWord #0000 ; operation: encrypt + Tool $0981 ; DESCipher + + ; second 7 bytes of hash + + PushLong #SMB_tmp1 + PushLong #SMB_lm_hash+7 + Tool $0A81 ; DESAddParity + + PushLong #SMB_lm_response+8 + PushLong #SMB_tmp1 + ldy #SMB_sess_challenge-SMB_sess_begin + lda [SMB_sessid],y ; PushLong [SMB_sessid],y + pha + iny + iny + lda [SMB_sessid],y + pha + PushWord #0000 + Tool $0981 ; DESCipher + + ; third 7 bytes of hash + + PushLong #SMB_tmp1 + PushLong #SMB_lm_hash+14 + Tool $0A81 ; DesAddParity + + PushLong #SMB_lm_response+16 + PushLong #SMB_tmp1 + ldy #SMB_sess_challenge-SMB_sess_begin + lda [SMB_sessid],y + pha + iny + iny + lda [SMB_sessid],y + pha + PushWord #0000 + Tool $0981 ; DESCipher + clc rts @@ -1762,8 +1989,34 @@ _sclp lda [SMB_tmp3],y bra _sclp _scrt rep #$30 mx %00 + iny rts +* _strncpy - Copy a string somewhere, only n bytes +* Arguments: +* Pointer to source (two words, on stack) +* Pointer to destination (two words, on stack) +* X = number of bytes to copy +_strncpy txy + plx + PullLong SMB_tmp1 ; Destination + PullLong SMB_tmp3 ; Source + phx + tyx + ldy #00 + sep #$30 + mx %11 +_snclp lda [SMB_tmp3],y + sta [SMB_tmp1],y + dex + cpx #00 + beq _sncrt + iny + bra _snclp +_sncrt rep #$30 + mx %00 + rts + * _SMB_Check - Check to see if TCP received data is SMB _SMB_Check lda SMB_input+SMB_offset_proto cmp #SMB_proto1 diff --git a/src/smbdemo b/src/smbdemo index 0004a9621517804157bcfdf3ad6072893acde3ee..9d5e88415a99911f853727a652c7d0c8f314356c 100644 GIT binary patch literal 38624 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