 NtUnload.asm contains new-style remote code. The only differences
between old and new style remote codes are:
 1) At code end is REMOTE_CODE_END structure (5 DWORDs) instead
    of OLD_REMOTE_CODE_END structure (3 DWORDs).
 2) New remote should compare DWORD in REMOTE_CODE_END.WhatReturn
    with 0. If it is not 0 this DWORD should be returned to
    REMOTE_CODE_END.WhereReturn. Only NtProtectVirtualMemory must
    be used to change page protection (don't care about Win9x).
 Both built-in remote codes (ApiWorks and ModuleWorks) are new-style.
Use of new-style remote code is important when new threads are executed
during remote code execution.
 Old-style remote code can be still used without problems (and new
threads).

 NtUnload.asm's remote code tries to unload given module from
process where is it executed. The only difference between NtUnload
and ApiHooks -u is that ApiHooks can't operate with NT processes where
KERNEL32.dll is not present (usually native processes: smss.exe,
os2ss.exe) while NtUnload uses only NTDLL APIs to unload module
(doesn't require KERNEL32.dll, is universal). Note don't try to preload
KERNEL32.dll to native processes (its initialization will not succeed).
 It is a chance that NtUnload.asm's remote code uses native APIs only,
it could use Win32 APIs normally (but + NtProtectVirtualMemory).

 Remote code must be written in assembly language. Program which calls
remote code can be written in any supported language, e.g. VB.

 NtUnload.exe tries to unload given module from given process It expects
2 parameters:
 1st - the name of process (can contain PathTo)
 2nd - the name of the module to unload (can contain PathTo)
Of course statically loaded modules can't be unloaded.

 In Win2K try: ntunload.exe smss.exe sfcfiles.dll >result.txt