DllCalls in a vbscript - vbscript

I would like to have a simple vbs script which runs on every Windows PC without additional apps and tools.
Below is a short script written in AHK:
A text string is extracted from a file and added as resource in an exe file by dllcalls.
Can this be reproduced in a simple way in vbs?
ExeFile = MyExe.exe
ScriptF = Script.txt
FileRead, Script, %ScriptF%
VarSetCapacity(Bin, BinScript_Len := StrPut(Script, "UTF-8") - 1)
StrPut(Script, &BinScript, "UTF-8")
Module := DllCall("BeginUpdateResource", "str", ExeFile, "uint", 0, "ptr")
DllCall("UpdateResource", "ptr", Module, "ptr", 10, "str", ">MY SCRIPT<"
, "ushort", 0x409, "ptr", &BinScript, "uint", BinScript_Len, "uint")
DllCall("EndUpdateResource", "ptr", Module, "uint", 0)

The short answer is No.
VBScript can only call DLLs that are exposed through COM (Component Object Model) and referenced in VBScript via the function CreateObject().
Here is an example of VBScript calling an external library;
Dim dll: Set dll = CreateObject("Scripting.FileSystemObject")
'Call the CreateFolder() method from FileSystemObject object in the Scripting Library.
dll.CreateFolder("C:\test")
Although this is technically a built-in component (part of the Scripting Runtime) it demonstrates the process and is housed in an external library (scrrun.dll).
In this case though as according to the documentation
From AutoHotKey Reference - DllCall()
DllFile may be omitted when calling a function that resides in User32.dll, Kernel32.dll, ComCtl32.dll, or Gdi32.dll. For example, "User32\IsWindowVisible" produces the same result as "IsWindowVisible".
the script is calling Windows System DLL function calls that are unlikely exposed to COM. The only option would be to write a COM DLL wrapper for the Windows System DLLs.

Related

How to break (set a breakpoint) on Console output on Windows?

Background:
I'm running a large nUnit test suite on my developer PC (via nunit-console) and I'm seeing some garbage output in the console window.
The units under test do involve .NET code as well as underlying C++ and C libraries and I haven't yet found out who is producing the garbage output.
Question:
Is there a single Windows API function where all Console output goes through? (regardless where it comes from.)
I have tried setting a breakpoint inside WriteConsole but that doesn't even catch printf output from the CRT. Is there any "central" location to set a breakpoint to catch all console output in a Windows application? (Some Nt... function?)
Console I/O makes calls to ReadFile and WriteFile on Windows. WriteFile is the routine for console output. It would be best to hook or breakpoint WriteFile and filter the handle specified to it. Don't mistake actual File I/O for operations on a console handle.
To acquire the correct handle used for console output on a Windows process:
GetStdHandle(STD_OUTPUT_HANDLE);
Alternatively, opening the console output handle using CreateFile and specifying CONOUT$ works and is also recommended:
HANDLE console_output = CreateFileA("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
This will return the handle you need to watch for in WriteFile calls. Just like with a hook though, you can specify the conditions for your breakpoint and check for the correct console handle in the call.
There is more about operations on console handles using ReadFile/WriteFile in the Microsoft documentation

Stop looking for the entry point at runtime in a DLL

I have an application which runs on windows 2003, window 2008 and windows small business server.
There is a windows call that I make to reboot the system.All the calls mentioned below come from advapi32.dll
InitiateSystemshutdown - This is fine in windows 2003 and windows 2008 but for some reason not working in Windows aurora
InitiateShutdown - since the above call is not working in windows aurora we used this call and minimum supported OS for this call is windows 2008
Now my application fails to run in windows 2003 since the InitiateShutDown is not present in the advapi32.dll on Windows 2003
I get a failed to find procedure entry point for Initiateshutdown in advapi32.dll
I have already put a condition also so that the proper function calls are called with respect to the windows version.
Is there way to stop looking for the entry point in the dll when the application launches.The condition will make sure that the proper function call are called?
OR
I should be asking Microsoft why the old call InitiateSystemshutdown is not working properly ?
You have to use GetProcAddress and set your preprocessor variables for the earlier version of Windows. See http://msdn.microsoft.com/en-us/library/aa383745(VS.85).aspx#setting_winver_or__win32_winnt
Basically, you should:
Set WINVER to the earliest version of Windows you must support so you don't accidentally use something newer.
Some API calls and definitions won't work anymore (like InitiateShutdown in your case) in your code, because they aren't included by header files. For these, you must use them dynamically. Typically you use the GetProcAddress API and use a "typedef" to define the function's signature (since it isn't in the header files you're including anymore). An example is here: http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx. In your case you would use the InitiateShutdown API instead of the given GetNativeSystemInfo. If the call to GetProcAddress fails then you can assume that the API is not supported on that version of Windows.
Rather that explicitly calling that function in your code (such that your app will fail to load if the function can't be loaded from the expected DLL), call it implicitly via LoadLibrary and GetProcAddress.
Do a "LoadLibrary" on advapi32.dll. And then call GetProcAddress for "InitiateShutdown". Fail gracefully if the function doesn't exist, otherwise cast it to an appropriate function pointer and
invoke it.
typedef DWORD (WINAPI *InitiateSystemShutdownTypeA) (char*, char*, DWORD, DWORD, DWORD);
typedef DWORD (WINAPI *InitiateSystemShutdownTypeW) (wchar_t*, wchar_t*, DWORD, DWORD, DWORD);
InitiateShutdownTypeA func = NULL;
HMODULE hMod = LoadLibrary("advapi32.dll");
if (hMod)
func = (InitiateShutdownTypeA)GetProcAddress("InitiateShutdownW");
if (func)
func(pwszMachineName, pwszMessage, dwGracePeriod, dwFlags, dwReason);

dynamically running a DLL at a remote Windows box?

Is there a way of dynamically running a DLL at a remote Windows box?
Say a user wants to send a his own DLL file to a remote server and run a function in that DLL at the remote site. The user may be able to provide function entry points as well as required parameters, but no more. (e.g. no header file)
I am thinking of setting up an agent executable at the remote site that can (1) dynamically load and bind a unknown DLL and (2) run a function with parameters. Is this a good a approach, or is such an executable possible?
You can use a technique of Dynamically loading your DLL's.
Normally you use a DLL by statically linking a .LIB into your project and compiling it. To load a DLL dynamically at runtime you use the following WIN32 API functions and a few other tricks.
LoadLibaray();
LoadLibarayEx();
GetProcAddress();
FreeLibrary();
There are some other tricks involved
You need to declare the dll functions as export'ed.
In c++ you need to use extern "C" to prevent name mangling of your functions.
FARPROC ... with GetProcAddress
It is all explained in the following wiki article - http://en.wikipedia.org/wiki/Dynamic-link_library
Your idea of installing an executable on the remote machine is a good one. So long as you agree on the function names and parameters with the user. If the dll complies with this then the dll can be changed at any time without requiring you EXE to be changed. Once set up and working it is simple to add extra functions.
Yes you could write small program that runs the DLL function using this information and call it remotely using the something like PSEXEC from sysinternals.
PsExec is a light-weight
telnet-replacement that lets you
execute processes on other systems,
complete with full interactivity for
console applications, without having
to manually install client softwareto manually install client software
Andrew Cash's reply is sound for unmanaged code. The technique he describes around GetProcAddress is essentially what RunDll32.exe does. RunDll32.exe is part of Windows and specializes at loading arbitrary DLLs and executing their code. You can run it like this:
RUNDLL32.EXE [dllfile],[entrypoint] [optional arguments]
When you do this, RunDll32 will call LoadLibrary on the DLL and then GetProcAddress on the entrypoint name you give it. If all that goes well then it calls the entry point function.
For this to actually work the entrypoint function needs to be exported. It must also be declared like this:
void CALLBACK MyEntryPoint(
HWND hwnd,
HINSTANCE hinst,
LPSTR lpszCmdLine,
int nCmdShow);

Some APIs that support the NT namespace absolute path of the format "\Device\Xxx"

In this document,
http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#paths
To make these device objects accessible by Windows applications, the device drivers create a symbolic link (symlink) in the Win32 namespace, "Global??", to their respective device objects. For example, COM0 and COM1 under the "Global??" subdirectory are simply symlinks to Serial0 and Serial1, "C:" is a symlink to HarddiskVolume1, "Physicaldrive0" is a symlink to DR0, and so on. Without a symlink, a specified device "Xxx" will not be available to any Windows application using Win32 namespace conventions as described previously. However, a handle could be opened to that device using any APIs that support the NT namespace absolute path of the format "\Device\Xxx".
What are the APIs? Let me know some such functions please.
For example, we can have a device sitting in the GLOBAL?? namespace:
GLOBAL??\
COM227
This device we can successfully open using CreateFile:
//Note: we have to prefix it with \\.\ in order to tell CreateFile that
//we want to open something from the Global device namespace.
//Otherwise it will try to open a file
HANDLE hdev = CreateFile("\\.\COM227", GENERIC_READ, 0, null, OPEN_EXISTING, 0, 0);
if (hdev == INVALID_HANDLE_VALUE)
raise new EWin32Exception(GetLastError);
This device (along with every other device in the Win32 Global?? namespace), actually a symbolic link to the "real" device:
GLOBAL??\
COM227 (SymbolicLink) ==> \Device\VCP0
Device\
VCP0 (Device)
So we try to open this real device:
HANDLE hdev = CreateFile("\\.\Device\VCP0", GENERIC_READ, 0, null, OPEN_EXISTING, 0, 0);
if (hdev == INVALID_HANDLE_VALUE)
raise new EWin32Exception(GetLastError);
But it fails with error code 3 (The system cannot find the specified file).
Short:
Works: COM227 (which is an alias of \Device\VCP0)
Fails: \Device\VCP0
The problem is that
#paulsm4 says that CreateFile should work
#larryostermm agrees, and even gives the device path syntax (e.g. \Device\Xxx)
except that it doesn't work
Which means that CreateFile is not one of the "APIs that support the NT namespace absolute path format of \Device\Xxx".
However, a handle could be opened to that device using any APIs that support the NT namespace absolute path of the format "\Device\Xxx".
What are the APIs?
The answers provided so far are misleading at best. They do not answer your question or cover the important distinction between the NT namespace and the other namespaces.
When accessing the NT namespace you need to use the API calls that start with Nt, such as NtOpenFile, if you want to access devices that are only found in the NT namespace of the kernel. For example, a device in \Devices with no symbolic link in \GLOBAL??.
The other calls mentioned above work fine if you are accessing the Win32 device namespace but these require the driver to create a symbolic link in that namespace.
If you want to access a device that is only found in the NT namespace then use NtOpenFile. This is really a very old API call and has drifted in and out of the userpace header files. It is available again and works just fine.
Benjamin -
The simple fact is that you CAN open a "special device file" in Windows, very much as you do in *nix. This is what I tried to say in my original reply. I stand by everything I said in my first post. And I believe the MSDN link I referred to there does a very good job of explaining this, too.
The syntax for a *nix device file is "/dev/SOME_DEVICE". Multiple devices are (by convention, not necessity) distinguished as "/dev/SOME_DEVICE0", "/dev/SOME_DEVICE1", etc. Device files can also be "aliased" using *nix "symbolic links".
The syntax for a Windows device file is a UNC name.
I'm sure you're familiar with UNC shares (for example, "\\myserver\c$").
In all the examples we've discussed above, the server happens to be the local host. Hence "\\.\SOME_RESOURCE_NAME".
It's really as simple as that.
And it DOES work.
Please let me know if you have any further questions.
Thank you in advance .. PSM
The concept of treating a "device" as a "file" is common in *nix (Unix, Linux, Mac OS, etc).
Basically, the MSDN article means that any Win32 API that opens a "file" (either a local disk file, or a UNC resource) could just as easily open a "special device".
A couple of examples:
http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx
CreateFile
WriteFile
ReadFile
CloseHandle

Unloading DLL from all processes after unhooking global CBT hook

How do you properly unload a DLL from all processes when the system-wide hook that loaded them gets unloaded?
From MSDN:
You can release a global hook
procedure by using
UnhookWindowsHookEx, but this function
does not free the DLL containing the
hook procedure. This is because global
hook procedures are called in the
process context of every application
in the desktop, causing an implicit
call to the LoadLibrary function for
all of those processes. Because a call
to the FreeLibrary function cannot be
made for another process, there is
then no way to free the DLL. The
system eventually frees the DLL after
all processes explicitly linked to the
DLL have either terminated or called
FreeLibrary and all processes that
called the hook procedure have resumed
processing outside the DLL.
So what I am looking for, is a method to detect when the hook is unhooked, and then call FreeLibrary from all the processes that were hooked. Are there any other ways to cause instant unloading of a DLL when the hook is unloaded?
Hook dll are unloaded in their message loop. Forcing them to pass in the message loop help to unload them.
Add this after your UnhookWindowsHookEx to force all message loops to wake up :
DWORD dwResult;
SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult);
However I still have the issue from time to time. I don't know where it's coming from. I suppose a locked process could prevent the dll to unload, but I have no proof of that.
In general you should use global windows hooking if FreeLibrary is not a required be called. If you do want to do this you can use DLL injection (see for example http://www.codeproject.com/KB/threads/winspy.aspx and http://www.codeproject.com/KB/system/hooksys.aspx) with respect of CreateRemoteThread and LoadLibrary technique. In the case you can do what you want in the remote process. You can combine both techniques.
If you want call FreeLibrary only to do an update of the DLL you can do this in another way. Every DLL which is loaded could be renamed (in cmd.exe for example) to a temporary name and you can call MoveFileEx with MOVEFILE_DELAY_UNTIL_REBOOT flag. Then you can already copy and use new version of the DLL. The old one DLL will be deleted at the next reboot of computer.

Resources