ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COM.TXT]ÄÄÄ Author: Silent Supporter Contact: silentsupporter@poczta.onet.pl NOTE: Few weeks after I had finished this article, I have found on the Net a set of COM articles included in Masm32 Service Pack #1 and #2 written in 2000 by Ernest J. Murphy. I want to underline that my article was written totally from the scratch and it has nothing in common with that set - too bad for me that I had to dig into COM details on my own (damn it! =), not knowing somebody has already done that. I can only tell that my article is mostly focused on old-fashioned point of view and doesn't go into details about COM - it tells mostly "how to do that in a simply asm" and not "how does it work in C++". I suggest you download Ernest's articles - they're great - but be prepared - some knowledge about COM and C++ is a must there =). This article is my first one that is exclusively written for 29A magazine. To all those freaks who are curious about who am I and what do I do, I can answer shortly - I am Silent Supporter and I support silently :>. If you want to know more - you are just far too curious :). btw. I apologize for my bad english ... I am so so so sorry for that [not really ;-p] Back to the real topic now. "How to use COM (Component Object Model) in ass-embler :)" As most of you guys know, COM is a shortcut for Component Object Model - thing that is really interesting from the VX writer point of view. You may ask why - of course - curiosity is your right, but I am not going to tell you - you have to find the answer on your own. It starts when you are born, then it grows up with you and helps you understand the etehernity blah, blah, blah. Oops, sorry. That's not the real topic of that article, right? RIGHT! Let's break that fuck-king silence about COM! COM is Component Object Model. It means that you have an access to the functions of the object that is somewhere in memory and gives you some kind of flexibility in writing programs. To write it in english it means that when you are using COM, you have the access to the functions that are implemented in othe programs and it means you have to connect to them in some way. It finally means that you must use some kind of interface. A good example of using COM is an automation - the mechanism that made Love Letter Worm so popular. You create Outlook object, connect to it, then use some methods that let you create emails, add attachments and finally send them to all people found in the address books. Windows on its own relies on COM very much - all those funny features like Google toolbar in Internet Explorer, extended menus with WinAmp or WinZip work via COM. All COM servers are nothing special and you may find them in DLL libraries. All of them have some functions exported and you use object by calling those methods. If you still don't understand, don't worry - what follows is an example that should help you get the point. I have found that there's no informations at all about programming COM in pure assembler. It's a real surprise because using COM gives you a real power + access to all those objects that are easily accessed f.ex. via Visual Basic Script and it's Shell Object's. Are we asm coders worse than those script-kiddies? COM is the thing that I had to research on my own, when I faced a really trivial problem. I wanted my application to create shortcut to my program in some easily accessed places like: - Desktop - Start Menu - Quick Launch All of them have their own directories that can be read directly from the Registry or through the SHGetSpecialFolderPath API function (thx Benny for pointing out SHGetSpecialFolderPath API function). We meet the real problem when we want to create a shortcut and by this, I mean the file with the LNK extension that should point to our program [see? who's talking about viruses here :)?] In Visual Basic Script, it's easy as the example taken from "Microsoft Windows Script Host 2.0" help file shows: set WshShell = WScript.CreateObject("WScript.Shell") strDesktop = WshShell.SpecialFolders("Desktop") set ShellLink = WshShell.CreateShortcut(strDesktop & "\Shortcut Script.lnk") ShellLink.TargetPath = WScript.ScriptFullName ShellLink.WindowStyle = 1 ShellLink.Hotkey = "CTRL+SHIFT+F" ShellLink.IconLocation = "notepad.exe, 0" ShellLink.Description = "Shortcut Script" ShellLink.WorkingDirectory = strDesktop ShellLink.Save set UrlLink = WshShell.CreateShortcut(strDesktop & "\Microsoft Web Site.url") UrlLink.TargetPath = "http://www.microsoft.com" UrlLink.Save Hmmm I guess I went too far, before explaining a typical way of writing programs for Windows. Time for a rollback :-) My task was to create a shortcut to my program. What most people do when they want to write some code for win32? Yes, you guessed it right they open MSDN and try to find the answer. So did I. I have chosen "create shortcut" line and pressed RETURN [ did you see PI- the movie? not too many people use RETURN for ENTER nowadays - I am kind old-fashioned - you know :) ] MSDN is a great library. Unfortunately it's so good that it is incomplete. This time I was lucky. I have found 284 items. Let's see what is the first one - you know, trying "beginner's luck" rule. So, here we go: "How to Create a Shortcut on the Desktop", Article ID: Q140443. [...] This article describes how to create a new shortcut on the desktop in Windows 95. The following topics are discussed" Sounds great, right? Let's see what's next. "To create a shortcut on the desktop to a program or file, follow these steps: 1. Use the right mouse button to click an open area on the desktop, point to New on the menu that appears, and then click Shortcut. 2. Click Browse. 3. Locate the program or file to which you want to create a shortcut, click the program or file, click Open, and then click Next. 4. Type a name for the shortcut. If a Finish button appears at the bottom of the dialog box, click it. If a Next button appears at the bottom of the dialog box, click it, click the icon you want to use for the shortcut, and then click Finish." Whadda heck? MSDN is for _developers_ as the name states - and not for dumb users right? So what the hell that article is doing there? After reading some unuseful crap [like that one above], I have finally found the answer to my question. "Shell Links" is the article I am talking about and it states: "Applications can also create and use shell links and shortcuts. For example, a word processing application might create a shell link to implement a list of the most recently used documents. An application creates a shell link by using the IShellLink interface to create a shell link object. The application uses theIPersistFile orIPersistStream interface to store the object in a file or stream. This overview describes the IShellLink interface and explains how to use it to create and resolve shell links from within a Microsoft(R) Win32(R)-based application. Because the design of shell links is based on the OLE Component Object Model (COM), you should be familiar with the basic concepts of COM and OLE programming before reading this overview." Oops. That doesn't sound very good. Yup. It simply means that we are not lucky this time. OLE and COM are those things we hate so much :-) But are we unlucky, for sure? COM is a black-box, and not too many people understand it - even those MFC/VC++ lovers who cannot turn their head without using a wizard. But we are smart! We know that everything always goes under the hood and touches the heart of CPU. Yup. Ass-embler gives us a power and COM is something we are not scared of. Am I Right? Let's see how the example of CreateShortcut function, that MSDN gives us in that mentioned article, looks like: // CreateLink - uses the shell's IShellLink and IPersistFile interfaces // to create and store a shortcut to the specified object. // Returns the result of calling the member functions of the interfaces. // lpszPathObj - address of a buffer containing the path of the object. // lpszPathLink - address of a buffer containing the path where the // shell link is to be stored. // lpszDesc - address of a buffer containing the description of the // shell link. HRESULT CreateLink(LPCSTR lpszPathObj, LPSTR lpszPathLink, LPSTR lpszDesc) { HRESULT hres; IShellLink* psl; // Get a pointer to the IShellLink interface. hres = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl); if (SUCCEEDED(hres)) { IPersistFile* ppf; // Set the path to the shortcut target and add the // description. psl->lpVtbl->SetPath(psl, lpszPathObj); psl->lpVtbl->SetDescription(psl, lpszDesc); // Query IShellLink for the IPersistFile interface for saving the // shortcut in persistent storage. hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile, &ppf); if (SUCCEEDED(hres)) { WORD wsz[MAX_PATH]; // Ensure that the string is ANSI. MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH); // Save the link by calling IPersistFile::Save. hres = ppf->lpVtbl->Save(ppf, wsz, TRUE); ppf->lpVtbl->Release(ppf); } psl->lpVtbl->Release(psl); } return hres; } Okay. It doesn't seem to be a hard thing. Just few lines of code and it shouldn't be difficult to translate it into our favourite language. The problem is in pointers and interfaces. In COM - everything is based on pointers and interfaces. The reason for what COM is so hard to use in assembler is mostly based on the lack of documentation for its structures from the asmcoder point of view. The one and only way to find some info is to dig in include files of Visual C++. But we are going to c:\win :) this time. Let's see how to convert that code to meet our needs. VC++ and MSDN are higly recommended at this moment. Especially VC++ header files with all the definitons and the structures. NOTE: Before you use any COM function, you _must_ use CoInitialize API function and CoUninitialize at the end it should go like that: ... invoke CoInitialize,NULL ... ... ; <--- your COM code here ... invoke CoUninitialize ... You must use them cuz ... they say that in MSDN ;-p -------------------- API -------------------------------------------- HRESULT CoInitialize( LPVOID pvReserved //Reserved; must be NULL ); " Initializes the COM library on the current apartment and identifies the concurrency model as single-thread apartment (STA). Applications must initialize the COM library before they can call COM library functions other than CoGetMalloc and memory allocation functions " void CoUninitialize( ); " Closes the COM library on the current apartment, unloads all DLLs loaded by the apartment, frees any other resources that the apartment maintains, and forces all RPC connections on the apartment to close. " -------------------- API -------------------------------------------- Let's start ............................. CreateShortCut proc toFile:DWORD,lnkDesc:DWORD,lnkPath:DWORD ; ; I changed the name because it's _MY_ own :) ; ; The function CreateShortCut takes 3 parameters: ; ; - toFile = address to the filename of the executable ; f.ex.: ; CalcExe db 'c:\windows\calc.exe',NULL ; ; - lnkDesc = address to the description - f.ex. name visible ; below the icon on the Desktop or in the menu ; ; f.ex.: ; CalcDesc db 'Calculator',NULL ; ; - lnkPath = address to the LNK file name - so if you want ; to put a shortcut on the Desktop, you have to find ; a directory (using Registry or SHGetSpecialFolderPath API) ; and append a link name to it ; ; f.ex. (shortcut on drive C:): ; CalcLnkPath db 'c:\calc.lnk',NULL ;CODE --> HRESULT hres; ;-------------------------- ; HRESULT is a typical dword - but we don't need it - see? ; how easily it started? :) ;CODE --> IShellLink* psl; ;-------------------------- ; ; THAT'S THE BITCH!!! ; ; It took me a lot of time to find a real structure of it. ; The worst thing in COM is that descriptions of the structures ; are really painful :(. ; ; Here's the one from VC - I hope you don't mind ;-p ; ; [I found it in a file "shlobj.h" if you are curious :)] ; ; #ifdef UNICODE ; #define IShellLink IShellLinkW ; #define IShellLinkVtbl IShellLinkWVtbl ; #else ; #define IShellLink IShellLinkA ; #define IShellLinkVtbl IShellLinkAVtbl ; #endif ; ; We are focused on ANSI version so I take a look on IShellLinkA now ; ; #define INTERFACE IShellLinkA ; ; DECLARE_INTERFACE_(IShellLinkA, IUnknown) // sl ; { ; // *** IUnknown methods *** ; STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID * ppvObj) PURE; ; STDMETHOD_(ULONG,AddRef) (THIS) PURE; ; STDMETHOD_(ULONG,Release) (THIS) PURE; ; ; // *** IShellLink methods *** ; STDMETHOD(GetPath)(THIS_ LPSTR pszFile, int cchMaxPath, WIN32_FIND_DATAA *pfd, DWORD fFlags) PURE; ; ; STDMETHOD(GetIDList)(THIS_ LPITEMIDLIST * ppidl) PURE; ; STDMETHOD(SetIDList)(THIS_ LPCITEMIDLIST pidl) PURE; ; ; STDMETHOD(GetDescription)(THIS_ LPSTR pszName, int cchMaxName) PURE; ; STDMETHOD(SetDescription)(THIS_ LPCSTR pszName) PURE; ; ; STDMETHOD(GetWorkingDirectory)(THIS_ LPSTR pszDir, int cchMaxPath) PURE; ; STDMETHOD(SetWorkingDirectory)(THIS_ LPCSTR pszDir) PURE; ; ; STDMETHOD(GetArguments)(THIS_ LPSTR pszArgs, int cchMaxPath) PURE; ; STDMETHOD(SetArguments)(THIS_ LPCSTR pszArgs) PURE; ; ; STDMETHOD(GetHotkey)(THIS_ WORD *pwHotkey) PURE; ; STDMETHOD(SetHotkey)(THIS_ WORD wHotkey) PURE; ; ; STDMETHOD(GetShowCmd)(THIS_ int *piShowCmd) PURE; ; STDMETHOD(SetShowCmd)(THIS_ int iShowCmd) PURE; ; ; STDMETHOD(GetIconLocation)(THIS_ LPSTR pszIconPath, int cchIconPath, int *piIcon) PURE; ; STDMETHOD(SetIconLocation)(THIS_ LPCSTR pszIconPath, int iIcon) PURE; ; ; STDMETHOD(SetRelativePath)(THIS_ LPCSTR pszPathRel, DWORD dwReserved) PURE; ; ; STDMETHOD(Resolve)(THIS_ HWND hwnd, DWORD fFlags) PURE; ; ; STDMETHOD(SetPath)(THIS_ LPCSTR pszFile) PURE; ; }; ; ; Oops. Houston. We have the problem. Or to put it in a diff way ; we have the situation here as they say in US movies. ; ; What the heck that INTERFACE and DECLARE_INTERFACE_ mean? ; ; It eats a lot of time to find an answer. It's all about the ; dependencies and structures and it's just too much for a human being ; As I am not :) - I found the answer for ya :). ; The 1-st thing is to find INTERFACE definiton in other files. ; Some kind of explaination may be found in "objbase.h" file, but the ; biggest surprise is on your way... I did ther research for you and ... ; ; SURPRISE SURPRISE !!! ; ; INTERFACE is just a 32-bit pointer! ; ; Just like that and the structure of IShellLink is then as follows: ; IShellLink STRUC lpVtbl dd ? IShellLink ENDS ; ; Things cannot be easier now, as we are smart and see that ; Charles Symonyi (or Symonya?) gives us with his hungarian notation. ; ; - "lp" is a long pointer == OFFSET ; - "Vtbl" is a table with the addresses to Virtual Functions ; To put it simply way "lpVtbl" is a long pointer to that table. ; ; Before we talk about the table, let's see What MSDN says about IShelLink ; ; "The IShellLink interface allows shell links to be created, ; modified, and resolved. IShellLink Methods Description ; ; GetArguments Retrieves the command-line arguments associated ; with a shell link object. ; GetDescription Retrieves the description string for a shell ; link object. ; GetHotkey Retrieves the hot key for a shell link object. ; GetIconLocation Retrieves the location (path and index) of the icon ; for a shell link object. ; GetIDList Retrieves the list of item identifiers for a shell ; link object. ; GetPath Retrieves the path and file name of a shell link object. ; GetShowCmd Retrieves the show (SW_) command for a shell link object. ; GetWorkingDirectory Retrieves the name of the working directory ; for a shell link object. ; Resolve Resolves a shell link by searching for the shell ; link object and updating the shell link path and ; its list of identifiers (if necessary). ; SetArguments Sets the command-line arguments associated with a shell link object. ; SetDescription Sets the description string for a shell link object. ; SetHotkey Sets the hot key for a shell link object. ; SetIconLocation Sets the location (path and index) of the icon for a shell link object. ; SetIDList Sets the list of item identifiers for a shell link object. ; SetPath Sets the path and file name of a shell link object. ; SetRelativePath Sets the relative path for a shell link object. ; SetShowCmd Sets the show (SW_) command for a shell link object. ; SetWorkingDirectory Sets the name of the working directory for a shell link object. ; " ; ; What's next? ; As we have seen, there are some weird things called STDMETHOD in the ; declaration of IShellLinkA. And all the methods are declared like that. ; Apart from mentioned methods of IShellLinkA, we have to add 3 methods ; for IUnknown object (it's at the beginning of that VC declaration): ; ; QueryInterface Returns pointers to supported interfaces. ; AddRef Increments reference count. ; Release Decrements reference count. ; ; Those 3 methods are the heart of COM - all COM object have to ; implement them. ; Well, STDMETHOD is just another way how to make things look ; more difficult, but after a little research I have found that ; they're just ... dwords! ; ; As for now, we have "IShellLink" structure with the "lpVtbl" that points ; to the table with the unknown content. As STDMETHOD is for dword ; we may write something like that: ; IShellLinkVtbl STRUC QueryInterface dd ? AddRef dd ? Release dd ? GetPath dd ? GetIDList dd ? SetIDList dd ? GetDescription dd ? SetDescription dd ? GetWorkingDirectory dd ? SetWorkingDirectory dd ? GetArguments dd ? SetArguments dd ? GetHotkey dd ? SetHotkey dd ? GetShowCmd dd ? SetShowCmd dd ? GetIconLocation dd ? SetIconLocation dd ? SetRelativePath dd ? Resolve dd ? SetPath dd ? IShellLinkVtbl ENDS ; ; now we may use a local variable ; LOCAL psl : IShellLink ; ; et voila! ; ; That's all! Surprised? I was - I just couldn't imagine it was so simple! ; Time for the next step. ; ;CODE --> hres = CoCreateInstance(&CLSID_ShellLink, NULL, ; CLSCTX_INPROC_SERVER, &IID_IShellLink, &psl); ;-------------------------- ; ; CoCreateInstance is a typical API, so no need to explain anything ; but the params. ; ; OFS CLSID_ShellLink=OFFSET (i always use OFS for short :) ; to a GUID class. I know it sounds weird but it's easy. ; I guess you know those weird numbers in the Registry? ; ; All the interfaces and objects have their unique ID ; and you have to find the one you want to use. ; It's not an easy task for a beginner, but I have a hint :) ; just find files named "comdef.h" and "shlguid.h". ; There are all IDs we want to use here and most of the IDs ; you will need in the future. ; Here are those we will use in the shortcut example: ; ; CLSID_ShellLink 00021401-0000-0000-C000-000000000046 ; IID_IShellLink 000214EE-0000-0000-C000-000000000046 ; IID_IPersistFile 0000010b-0000-0000-C000-000000000046 ; ; I don't like masm's definition for GUID so I have written my own ; GUID2 STRUC dd1 dd ? dw1 dw ? dw2 dw ? db1 db ? db2 db ? db3 db ? db4 db ? db5 db ? db6 db ? db7 db ? db8 db ? GUID2 ENDS ; ; We define those IDs as: ; CLSID_ShellLink GUID2 <00021401h,0,0,0C0h,0,0,0,0,0,0,46h> IID_IShellLink GUID2 <000214EEh,0,0,0C0h,0,0,0,0,0,0,46h> IID_IPersistFile GUID2 <0000010Bh,0,0,0C0h,0,0,0,0,0,0,46h> ; ; I put IID_IPersistFile here cuz it will be needed later ; and now we may call the function ; ;CODE --> if (SUCCEEDED(hres)) { ;-------------------------- ; ; SUCCEEDED is a macro, it simply means that hres=eax>0 ; I use "if eax==S_OK" because MSDN says about CoCreateInstance ; that it gives S_OK if it's okay ; .if eax==S_OK ;CODE --> IPersistFile* ppf; ;-------------------------- ; ; It's just a time for another INTERFACE ; Not to mix the things too much - here's the answer ; It's the same as with IShellLink interface - ; all you need is to define pointer and the table ; Piece of cake now :-) ; IPersistFile STRUC lpVtbl dd ? IPersistFile ENDS IPersistFileVtbl STRUC QueryInterface dd ? AddRef dd ? Release dd ? GetClassID dd ? IsDirty dd ? Load dd ? Save dd ? SaveCompleted dd ? GetCurFile dd ? IPersistFileVtbl ENDS ;CODE --> psl->lpVtbl->SetPath(psl, lpszPathObj); ;-------------------------- ; ; here comes the typical hard-asm-working :-) push toFile ; we put "lpszPathObj" on the stack mov eax,psl.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IShellLinkVtbl.SetPath] ; eax=address of "SetPath" method push psl ; and the address to "psl" "object" call eax ; well done :-) we call "SetPath" method ;CODE --> psl->lpVtbl->SetDescription(psl, lpszDesc); ;-------------------------- ; ; and another one (similar situation here) ; push lnkDesc ; we put "lpszDesc" on the stack mov eax,psl.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IShellLinkVtbl.SetDescription] ; eax=addres of "SetDescription" method push psl ; the addres to "psl" "object" call eax ; we call "SetDescription" method ;CODE --> hres = psl->lpVtbl->QueryInterface(psl, &IID_IPersistFile,&ppf); ;-------------------------- ; ; and one more time :-) ; lea eax,ppf ; push eax ; we put address to "ppf" on the stack push OFS IID_IPersistFile ; we put offset to the ID mov eax,psl.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IShellLinkVtbl.QueryInterface] ; eax=addres of "QueryInterface" method push psl ; the addres to "psl" "object" call eax ; we call "QueryInterface" method ;CODE --> if (SUCCEEDED(hres)) { ;-------------------------- ; ; yet another piece of cake :-) ; .if eax==S_OK ;CODE --> WORD wsz[MAX_PATH]; ;-------------------------- ; ; too many pieces of cake :-) ; LOCAL wsz[256]: WORD ;CODE --> MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1,wsz, MAX_PATH); ;-------------------------- ; ; I am already bored, take a look into MSDN :-) ; invoke MultiByteToWideChar,CP_ACP,0,lnkPath,-1,ADDR wsz,SIZEOF wsz ;CODE --> hres = ppf->lpVtbl->Save(ppf, wsz, TRUE); ;-------------------------- ; ; do I need to say anything? :) ; mov eax,TRUE ; true, true, yeah :-) push eax ; lea eax,wsz ; we put address to "wsz" on the stack push eax ; mov eax,ppf.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IPersistFileVtbl.Save] ; eax=addres of "Save" method push ppf ; the addres to "ppf" "object" call eax ; we call "Save" method ;CODE --> ppf->lpVtbl->Release(ppf); ;-------------------------- ; ; blah, blah, blah ; if you want to know more, read about IShellLink object and it's ; methods in MSDN - all the informations about the parameters ; are taken from it. ; mov eax,ppf.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IPersistFileVtbl.Release] ; eax=addres of "Release" method push ppf ; the addres to "ppf" "object" call eax ; we call "Release" method ;CODE --> } ;-------------------------- ; ; really hard thing ;-p ; .endif ;CODE --> psl->lpVtbl->Release(psl); ;-------------------------- ; ; just freeing the resources ; mov eax,psl.lpVtbl ; eax=offset to pointer to table mov eax,[eax] ; eax=table mov eax,[eax.IShellLinkVtbl.Release] ; eax=addres of "Release" method push psl ; the addres to "psl" "object" call eax ; we call "Release" method ;CODE --> } ;-------------------------- ; ; I wonder if you guess :) ; .endif So, finally after ages of explainations here goes the whole function: (I make some includes - those that are typically needed :-) ;----------------------------------------------------------------------- ; ; ;---------------------------- CUT HERE --------------------------------- ; ; ;----------------------------------------------------------------------- ; ; Copyright Note: ; ; I (Silent Supporter) am the author of that code and article. ; It may be freely distributed ONLY as a part of 29A magazine. ; You cannot extract this code from the magazine, sell it, etc., ; without my permission. However If you want to use it in your ; application feel free - remember it _would_ be _NICE_ if you mention ; me in credits - I am just greedy for them :) ; I don't think that I need to explain more as all 29A readers have balls. ; include \MASM32\INCLUDE\windows.inc include \MASM32\INCLUDE\user32.inc includelib \MASM32\LIB\user32.lib include \MASM32\INCLUDE\kernel32.inc includelib \MASM32\LIB\kernel32.lib include \MASM32\INCLUDE\advapi32.inc includelib \MASM32\LIB\advapi32.lib include \MASM32\INCLUDE\shell32.inc includelib \MASM32\LIB\shell32.lib include \MASM32\INCLUDE\ole32.inc includelib \MASM32\LIB\ole32.lib OFS equ OFFSET IShellLink STRUC lpVtbl dd ? IShellLink ENDS IShellLinkVtbl STRUC QueryInterface dd ? AddRef dd ? Release dd ? GetPath dd ? GetIDList dd ? SetIDList dd ? GetDescription dd ? SetDescription dd ? GetWorkingDirectory dd ? SetWorkingDirectory dd ? GetArguments dd ? SetArguments dd ? GetHotkey dd ? SetHotkey dd ? GetShowCmd dd ? SetShowCmd dd ? GetIconLocation dd ? SetIconLocation dd ? SetRelativePath dd ? Resolve dd ? SetPath dd ? IShellLinkVtbl ENDS IPersistFile STRUC lpVtbl dd ? IPersistFile ENDS IPersistFileVtbl STRUC QueryInterface dd ? AddRef dd ? Release dd ? GetClassID dd ? IsDirty dd ? Load dd ? Save dd ? SaveCompleted dd ? GetCurFile dd ? IPersistFileVtbl ENDS GUID2 STRUC dd1 dd ? dw1 dw ? dw2 dw ? db1 db ? db2 db ? db3 db ? db4 db ? db5 db ? db6 db ? db7 db ? db8 db ? GUID2 ENDS ; CLSID_ShellLink '00021401-0000-0000-C000-000000000046' CLSID_ShellLink GUID2 <00021401h,0,0,0C0h,0,0,0,0,0,0,46h> ; IID_IShellLink db '000214EE-0000-0000-C000-000000000046',NULL IID_IShellLink GUID2 <000214EEh,0,0,0C0h,0,0,0,0,0,0,46h> ; IID_IPersistFile db '0000010b-0000-0000-C000-000000000046',NULL IID_IPersistFile GUID2 <0000010Bh,0,0,0C0h,0,0,0,0,0,0,46h> CreateShortCut proc toFile:DWORD,lnkDesc:DWORD,lnkPath:DWORD LOCAL psl : IShellLink LOCAL ppf : IPersistFile LOCAL wsz[256]: WORD invoke CoInitialize,NULL invoke CoCreateInstance,OFS CLSID_ShellLink,NULL,\ CLSCTX_INPROC_SERVER,OFS IID_IShellLink,ADDR psl .if eax==S_OK push toFile mov eax,psl.lpVtbl mov eax,[eax] mov eax,[eax.IShellLinkVtbl.SetPath] push psl call eax push lnkDesc mov eax,psl.lpVtbl mov eax,[eax] mov eax,[eax.IShellLinkVtbl.SetDescription] push psl call eax lea eax,ppf push eax push OFS IID_IPersistFile mov eax,psl.lpVtbl mov eax,[eax] mov eax,[eax.IShellLinkVtbl.QueryInterface] push psl call eax .if eax==S_OK invoke MultiByteToWideChar,CP_ACP,0,lnkPath,-1,ADDR wsz,SIZEOF wsz mov eax,TRUE push eax lea eax,wsz push eax mov eax,ppf.lpVtbl mov eax,[eax] mov eax,[eax.IPersistFileVtbl.Save] push ppf call eax mov eax,ppf.lpVtbl mov eax,[eax] mov eax,[eax.IPersistFileVtbl.Release] push ppf call eax .endif mov eax,psl.lpVtbl mov eax,[eax] mov eax,[eax.IShellLinkVtbl.Release] push psl call eax .endif invoke CoUninitialize ret CreateShortCut endp and calling: invoke CreateShortCut,OFS szFileName,OFS szDescription,ADDR szLnkFileName ;----------------------------------------------------------------------- ; ; ;---------------------------- CUT HERE --------------------------------- ; ; ;----------------------------------------------------------------------- Everything what's good has its end :-). The article is finished and I am going back to real life :-). Silent Supporter 11-08-01 23-09-01 [corrected] ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COM.TXT]ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COMPILERS.TXT]ÄÄÄ Author: Silent Supporter Contact: silentsupporter@poczta.onet.pl btw. I apologize for my bad english ... I am so so so sorry for that [not really ;-p] "Infecting Compilers" All of us know how to modify executables right? The bad thing is, that all of AVers know that too. Well, there's a chance to make their work incredibly hard. What I am talking of is to infect not executables, but sources. But not the old way, like most of source infectors do. It is too easy to append some code to the file that is on the hard disk. it is also too easy for a programmer [he's not dumb, right?] to notice that something is wrong with his files. No, No. This time we will talk about something more clever :) There's a lot of programs that compile programs to executables. Most of the old-fashioned compilers/linkers use files that are passed to them via command line or via "make" tool. In this way, infection would just need a virus to take an input file, append the virus source code in run-time [f.ex. by appending the virus to the copy of the source code file that would stay in a diff., temporary file] The executable would contain the virus in an unpredictable place + if the author of the program uses any executable packer wouldn't be easily able to be detected. Of course, there's still a chance to append the encrypted body of the virus - by using polymorphism f.ex. New compilers like the most known VC++ and Delphi need some special treatment. It is still possible to play with them, and it shouldn't be so hard - cuz it seems quite easy to infect their project files. Other possibilites are like adding new header files or even more clever, modyfying some standard header files to include our virus. Let's imagine that a virus stays in memory and tries to infect only when somebody uses F7 key in VC++ [Building EXE File] and only when somebody builds the Release version... Hmm guess what happens few months later =) A lot of the users use a new version of the product. They use newest AV programs and are proud of their safety and then one day something happens and the question appears where the hell that virus came to my machine from, huh? :> See? Midfile infectors may enter totally a new era. Not to mention those which are also polymorphic ones. Silent Supporter 23-09-01 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[COMPILERS.TXT]ÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MARKETING.TXT]ÄÄÄ Author: Silent Supporter Contact: silentsupporter@poczta.onet.pl btw. I apologize for my bad english ... I am so so so sorry for that [not really ;-p] "Marketing Virus The new age of malixious programs" Well, I don't know if anybody has ever written about such an idea, but let's start from the very beginning. New technologies created by virus writers are cool and powerful. Unfortunately AV community is more than just coders. They're damn smart and able to react to all the tricks very fast. So, what a poor VX-writer can do? Hmm I guess there're few ideas, right? Like f.ex. drinking a beer in a companion of a nude blonde :>> Okay, let's make things more serious. The past and reality shows that viruses which use all the tricks like slow multi-layered polymorphism, EPO, midfile infection and even metamorphism have their chances, but ... Yes, sadly to say, most of them are unable to survive in the new environments for a very long time. It is easy to detect them and even easier to protect against them. ISP install scanners on their servers, people use more and more sophisticated AV programs. Some friends of mine even use 2 AV programs at the same time. It makes longlasting infection hard, almost impossible. So, again, back to the question about ideas... What frustrated VX-writer may do in such situation? =D The idea I want to describe here is not a very new one. All of us know droppers, right? So, here starts the story. Imagine such a scenario: Starring: - Master Evil (how silly!): A sick, frustrated VX-writer who wants his/her virus to spread around the world and last [this is just a profile for people who will work later on that case from the psycho-something point of view =>]. - dumb-users World It is about all those people who love to download new software and install it on their lovely machines. By software I mean even all the crap like applications that change the background of the Desktop every 5 minutes, screen savers. This sort of people collects ShockWave Flash executables, stores thousands of JPEG, MPEG files on their hard disks, etc., etc. Hard to believe but the number of such stupid people increases rapidly as Internet grows up. And an important hint: some users will never learn! [I know what I am talking about - have been working in a company in which most of the users were just as those described above :>], Master Evil wants to shock the world. He does as follows: 1) writes a new program, fully working cool application there's thousands of ideas: -- peer to peer, client/server applications for sharing data (Napster, Gnutella, etc.) -- chat program - far better than ICQ, Yahoo Messenger etc. or even new IRC client -- powerful multimedia viewer (to kick Irfan off of the scene :>) -- whatever else, you know what I mean 2) program must be FREEWARE 3) buys the domain with a cool name Let's say "www.fufme.com" is a good example. [I wonder how many of you will visit mentioned page now :>] Few bucks for a domain is not a big deal today. 4) starts marketing action with -- ZDNET -- TUCOWS -- computer magazines [putting program on CDs] -- etc. 5) apart from the real application code, implements some "features". Those features we may call a bomb, payload, trojan horse, whatever. Let's say it is something that does a lot of funny things. As some people like to deassemble programs [me :>], the features may be implemented in version 3.0 of the application (no one will be interested anymore). 6) activation of that "something" goes on ... okay ... Friday, 13th - but not the next Friday, 13th. It should start to work year or two after the main application appears on the Net. After such a period of time, people will - recognize program as a product, - be waiting for a newer version, - discuss why it is a better program than others - TRUST IT [The most important thing!] Imagine hundred of thousands applications that try to connect to White House home page [Code Red's idea :)] on December, 31th, let's say year 2003. Impossible? Imagine AV community that wants to write a program to remove that "virus" from the computers [a lot of versions already exist]. Imagine such "features" of the program that on that Friday, 13th will 0) - infect compilers [read article "Infecting compilers" in that issue] 1) - take a data file of the program - extracts encrypted packers like old lzexe, pklite and newer like upx, aspack (who would believe that innocent file like prog.dat may contain any encrypted executables, right?) - use those packer/encryptors to change executable of the program on the disk and drop copies around 2) - make regular copies of the program by overwriting typical applications like "calc.exe" etc. or by modyfying them as viruses do 3) - spread as a typical worm/virus (using most known viruses/worms' methods) 4) - infect installation packages of Windows and other applications; most of ppl have them on their HD, you may find them using Registry check this one HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\SourcePath or those ones HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\OLSSrcPath HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Setup\CommandLine Guess what happens when the user reinstalls the system :) 5) - whatever else .... The thing is that, even the marketing virus strikes on that Friday, 13th even AV people will get the source, even people will know everything about it, it will be a very very hard task to clean the systems. Silent Supporter 2001-09-21 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ[MARKETING.TXT]ÄÄÄ