Valid HTML 4.01 Transitional Valid CSS Valid SVG 1.0

Me, myself & IT

Write, Read and Execute NTFS Alternate Data Streams

Purpose
Background Information
Demonstration

Purpose

Background Information

The MSKB article 105763 provides an introduction to NTFS alternate data streams.

Demonstration

Perform the following 18 simple steps to build a DLL and a Windows application solely within NTFS alternate data streams and execute them both.
  1. Start the command prompt of the Windows SDK in an arbitrary, preferable empty directory, then create an (empty) file or subdirectory, for example streams, there:

    COPY NUL: streams
            1 file(s) copied.
  2. Write the hexadecimal dump of a 16-bit DOS program that prints its copyright message on standard output to an alternate data stream, for example .txt, of the file or subdirectory created in step 1.:

    1>streams:.txt (
    ECHO 4d 5a 90 00 01 00 00 00 04 00 00 00 ff ff 00 00 e0 00 00 00 43 00 00 00
    ECHO 40 00 00 00 00 00 00 00 00 00 00 00 19 57 04 27 00 00 00 00 00 00 00 00
    ECHO 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 28 43 29 6f 70 79 72 69
    ECHO 67 68 74 20 32 30 30 34 2d 32 30 32 35 2c 20 53 74 65 66 61 6e 20 4b 61
    ECHO 6e 74 68 61 6b 20 3c 73 74 65 66 61 6e 2e 6b 61 6e 74 68 61 6b 40 6e 65
    ECHO 78 67 6f 2e 64 65 3e 0d 0a 07 24 0e 1f 33 d2 b4 09 cd 21 b8 01 4c cd 21)
    Note: the command lines can be copied and pasted as block into a Command Processor window.
  3. Decode the 16-bit DOS program to another alternate data stream, for example .dos, of the file or subdirectory created in step 1.:

    CERTUTIL.EXE /DecodeHex streams:.txt streams:.dos
    Input Length = 438
    Output Length = 144
    CertUtil: -decodehex command completed successfully.
  4. Execute the 16-bit DOS program created in step 3.:

    .\streams:.dos
    The syntax of the command is incorrect.
    Oops¹: except for input and output redirection the Command Processor Cmd.exe (and all its internal commands) fail to support alternate data streams!
  5. Write a JScript that prints its pathname on standard output to the alternate data stream .js of the file or subdirectory created in step 1. and execute it with the Windows Script Host console application:

    1>streams:.js ECHO WScript.Echo(WScript.ScriptFullName)
    CSCRIPT.EXE streams:.js
    Microsoft (R) Windows Script Host, Version 5.8
    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
    
    C:\Users\Stefan\Desktop\streams:.js
  6. Write a VBScript that executes the 16-bit DOS program created in step 3. and prints its exit code to the alternate data stream .vbs of the file or subdirectory created in step 1. and execute it with the Windows Script Host console application:

    1>streams:.vbs ECHO WScript.Echo WScript.CreateObject("WScript.Shell").Exec("%CD%\streams:.dos").ExitCode
    CSCRIPT.EXE streams:.vbs
    32-bit editions of Windows execute the 16-bit DOS program:
    Microsoft (R) Windows Script Host, Version 5.8
    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
    
    (C)opyright 2004-2025, Stefan Kanthak <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>
    
    0

    [Screen shot of message box from module loader on Windows 7] 64-bit editions of Windows don’t support 16-bit DOS programs and display the message box shown to the right:

    C:\Users\Stefan\Desktop\streams:.vbs(1, 1) WshShell.Exec: This version of C:\Users\Stefan\Desktop\streams:.dos is not compatible with the version of Windows you're running. Check your computer's system information to see whether you need an x86 (32-bit) or x64 (64-bit) version of the program, and then contact the software publisher.

  7. Write an ANSI C source code to another alternate data stream, for example .c, of the file or subdirectory created in step 1.:

    1>streams:.c ECHO unsigned _DllMainCRTStartup(void *module, unsigned reason, void *context) { return 0; }
  8. Compile and link the source code from the alternate data stream .c written in step 7.:

    SET CL=/Fa /Gz /LD /W4 /Zl
    SET LINK=/MANIFEST /MAP /NODEFAULTLIB /STUB:streams:.dos
    CL.EXE streams:.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    streams:.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /MANIFEST /MAP /NODEFAULTLIB /STUB:streams:.dos
    /out:streams:.dll
    /dll
    /implib:streams:.lib
    streams:.obj
    Note: the Visual C compiler writes its output to one or more alternate data streams of the file or subdirectory from which it reads the alternate data stream with the (first) source, then the linker reads object file and DOS stub from and writes its output to one or more alternate data streams of the same file or subdirectory.
  9. List the alternate data streams of the (still empty) file or subdirectory created in step 1.:

    DIR /R streams
     Volume in drive C has no label.
     Volume Serial Number is 1957-0427
    
     Directory of C:\Users\Stefan\Desktop
    
    04/27/2012  08:15 PM                 0 streams
                                       619 streams:.asm:$DATA
                                        89 streams:.c:$DATA
                                     1.024 streams:.dll:$DATA
                                       381 streams:.dll.manifest:$DATA
                                       144 streams:.dos:$DATA
                                        38 streams:.js:$DATA
                                       577 streams:.map:$DATA
                                       469 streams:.obj:$DATA
                                       438 streams:.txt:$DATA
                                       103 streams:.vbs:$DATA
                   1 File(s)              0 bytes
                   0 Dir(s)    9,876,543,210 bytes free
  10. Execute the DLL built in step 8. via the Windows host process (Rundll32) application:

    [Screen shot of error message box from 'RunDLL32.exe' on Windows 7]

    RUNDLL32.EXE "%CD%\streams:.dll",#0
    Note: the error message box is expected – the _DllMainCRTStartup() function intentionally returns 0 alias FALSE to let the Win32 functions LoadLibrary() and LoadLibraryEx() fail with Win32 error code 1114 alias ERROR_DLL_INIT_FAILED.
  11. Write another ANSI C source code to the alternate data stream .c of the file or subdirectory created in step 1.:

    1>streams:.c ECHO unsigned mainCRTStartup(void) { return 'NTFS'; }
  12. Compile and link the source code from the alternate data stream .c overwritten in step 11.:

    SET CL=/Gd /W4 /Zl
    SET LINK=/ENTRY:mainCRTStartup /FIXED /NODEFAULTLIB /STUB:streams:.dos /SUBSYSTEM:Console
    CL.EXE streams:.c
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    streams:.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /ENTRY:mainCRTStartup /FIXED /NODEFAULTLIB /STUB:streams:.dos /SUBSYSTEM:Console
    /out:streams:.exe
    streams:.obj
  13. Write a VBScript that executes the Win32 console application built in step 12. and prints its process identifier to the alternate data stream .vbs of the file or subdirectory created in step 1. and execute it with the Windows Script Host console application:

    1>streams:.vbs ECHO WScript.Echo WScript.CreateObject("WScript.Shell").Exec("%CD%\streams:.exe").ProcessID
    CSCRIPT.EXE streams:.vbs
    Microsoft (R) Windows Script Host, Version 5.8
    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
    
    1234
  14. Write an intentionally invalid external manifest for the Win32 console application built in step 12. to the alternate data stream .exe.manifest of the file or subdirectory created in step 1.:

    1>streams:.exe.manifest ECHO ^<?xml version='1.0' encoding='US-ASCII' standalone='yes' ?^>
  15. Execute the Win32 console application built in step 12. via the VBScript overwritten in step 13. again:

    CSCRIPT.EXE streams:.vbs
    Microsoft (R) Windows Script Host, Version 5.8
    Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
    
    C:\Users\Stefan\Desktop\streams:.vbs(1, 1) WshShell.Exec: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log or use the command-line sxstrace.exe tool for more detail.
    Oops²: Windows’ module loader honors external manifests for executable image files stored in alternate data streams!
  16. Write yet another ANSI C source code to the alternate data stream .c of the file or subdirectory created in step 1.:

    1>streams:.c ECHO void wWinMainCRTStartup(void) { ExitProcess(MessageBox(HWND_DESKTOP, GetCommandLine(), __LPREFIX(__FUNCTION__), MB_OK) ? ERROR_SUCCESS : GetLastError()); }
  17. Compile and link the source code from the alternate data stream .c overwritten in step 16.:

    SET CL=/DSTRICT /DUNICODE /DWIN32_LEAN_AND_MEAN /FIwindows.h /Gd /W4 /we4013 /Zl
    SET LINK=/ENTRY:wWinMainCRTStartup /FIXED /MANIFEST /NODEFAULTLIB /STUB:streams:.dos /SUBSYSTEM:Windows
    CL.EXE streams:.c kernel32.lib user32.lib
    Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 16.00.40219.01 for 80x86
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    streams:.c
    
    Microsoft (R) Incremental Linker Version 10.00.40219.386
    Copyright (C) Microsoft Corporation.  All rights reserved.
    
    /ENTRY:wWinMainCRTStartup /FIXED /MANIFEST /NODEFAULTLIB /STUB:streams:.dos /SUBSYSTEM:Windows
    /out:streams:.exe
    kernel32.lib
    user32.lib
    streams:.obj
  18. Execute the Windows application built in step 17. via the WMI Commandline Utility console application:

    [Screen shot of message box on Windows 7]

    WMIC.EXE PROCESS CALL CREATE "%CD%\streams:.exe"
    Executing (Win32_Process)->Create()
    Method execution successful.
    Out Parameters:
    instance of __PARAMETERS
    {
    	ProcessId = 9876;
    	ReturnValue = 0;
    };
Note: a repetition using a subdirectory instead of a file is left as an exercise to the reader.

Contact and Feedback

If you miss anything here, have additions, comments, corrections, criticism or questions, want to give feedback, hints or tipps, report broken links, bugs, deficiencies, errors, inaccuracies, misrepresentations, omissions, shortcomings, vulnerabilities or weaknesses, …: don’t hesitate to contact me and feel free to ask, comment, criticise, flame, notify or report!

Use the X.509 certificate to send S/MIME encrypted mail.

Note: email in weird format and without a proper sender name is likely to be discarded!

I dislike HTML (and even weirder formats too) in email, I prefer to receive plain text.
I also expect to see your full (real) name as sender, not your nickname.
I abhor top posts and expect inline quotes in replies.

Terms and Conditions

By using this site, you signify your agreement to these terms and conditions. If you do not agree to these terms and conditions, do not use this site!

Data Protection Declaration

This web page records no (personal) data and stores no cookies in the web browser.

The web service is operated and provided by

Telekom Deutschland GmbH
Business Center
D-64306 Darmstadt
Germany
<‍hosting‍@‍telekom‍.‍de‍>
+49 800 5252033

The web service provider stores a session cookie in the web browser and records every visit of this web site with the following data in an access log on their server(s):


Copyright © 1995–2025 • Stefan Kanthak • <‍stefan‍.‍kanthak‍@‍nexgo‍.‍de‍>