

---( interprocess communication by mort[MATRiX] )---------------------------

 This article is for educational purpose only and  I AM  NOT  responsibille
 for anything nor my english, nor myself,...anyway, enjoy it...


 .xxx
----------------------------------------------------------------------------
 Interprocess communication (IPC) is the way processes can communicate with
 each  other.  In window's enviroment  each process  has  its  own separate 
 address space, so no process can directly see the memory of other process.
 Win32 API provides  some features to IPC.  IPC could be  very helpfull for 
 virii (eg. the one i like the most used in Vulcano...hi Benny :)), so i'll
 describe some  ways despite im  not sure all could be effectivelly used in
 virii, anyway as i said somewhere, im lamer.

 IPC ways described in this article:
 
  - atoms
  - file mapping
  - anonymous pipes
  - mailslots


 I wrote two virusses to describe some IPC nore detailed. It's ls and aiD
 virus. There's describtion of behaviour u can check at both virii.
 
                    .------------.
                    | here we go |
                    '-----.------'
 .                        |
 |atoms                   |
-'------------------------'-------------------------------------------------
 Atoms are  very simple  and <>  ways of IPC. The point  is the process can
 place  string  into  atom's  table and  this string  is vissible for other
 processes.  When process place the string into atom's table it'll get back
 the 32bit value(atom), and this value is used to access the string. System
 doesn't difer the string by case, in other words it's not case sensitive.
 
 There're two types of atom tables - global (GAT) and the local one (LAT).
 

 .---<<<-
 |GAT is set up for 37 entries and is vissible for all process in system.
 |
 | functions
 |
 '----(adding string to GAT)------------------------------------------
 |
    push _address_of_string - NULL terminated string max size is 255B
    call GlobalAddAtom(A/W)
 .
 |  returns -  eax - atom
 |
 '----(delete atom from GAT)------------------------------------------
 |
    push _atom
    call GlobalDeleteAtom(A/W)
 .
 |  returns -  eax - 0 if succed
 |
 '----(find atom)-----------------------------------------------------
 |
    push _address_of_string - NULL terminated string max-size is 256B
    call GlobalFindAtom(A/W)
 .
 |  returns - eax - 0 if fail otherwise atom
 |
 '----(get atom string via atom)--------------------------------------.
 |                                                                    |
    push _size_of_buffer      - buffer length                         |\
    push _address_of_buffer   - buffer                                | |
    push _atom                - atom :)                                 |\
    call GlobalGetAtomName(A/W)                                         | |
                                                                          |
    returs - if succed the buffer will be filled by atom string           |
                                                                          |
 .------------------------------------------------------------------------'
 |LAT  uses the  same calls  for atoms work, but without the 'Global' word.
 |Anyway  LAT is vissible  for the  current process  and no for others. The 
 |values of entries  is set by default up to 37,  but it can  be changed by
 'the InitAtomTable API. The maximum it could be set is 3FFF. Huuuuum, this
  number is in MSDN but when i tried to get error-value of this call by the
 .to high value  of entries i didnt find it. Functions seems work  with any 
 |numbert of entries,...
 |
 '----(inicialize LAT)-------------.
 |                                 |
   push _LAT_size                  |
   call InitAtomTable              |
 .                                 |
 | returns - ...                   |
 '--------------------------------'|'--------------------------------------'
                            .------'-----------.
                            | All for atoms... |
                            '------------.-----'
 .                                       |
 |file mapping                           |
-'---------------------------------------'----------------------------------
 I think file mapping is well known way of accessing files.  It's described
 in many articles  so i wont waste the time  with details. The  point is we
 can map file into memory. Then  with every change in  memory we change the
 file.  Due  to  IPC  we can  map the  same file  in several  processes and 
 communicate via it.

     functions
 ->>>-------------------------------------------------------.
    push template file handle           ;default - 0         \
    push flags and attributes           ;default - 0        ----.
    push create/open flags                                       \
    push security attributes            ;default - 0              |
    push share flags                    ;default - 1              |
    push object access                                            |
    push file name                               .----------------'
                                                 |
    call CreateFile(A/W)                         |
    \\\\\\\\\\\\\\\\\\\\                         |
                                  >>>>>-------------------->
    returns - file handle                        |
                                                 |
    create/open flags                            |
          CREATE_NEW          equ 1              |
          CREATE_ALWAYS       equ 2               \
          OPEN_EXISTING       equ 3                |
          OPEN_ALWAYS         equ 4                |
          TRUNCATE_EXISTING   equ 5                |
                                                   |
    object access                                  |
          GENERIC_READ        equ 080000000h       |
          GENERIC_WRITE       equ 040000000h       |
          GENERIC_EXECUTE     equ 020000000h       |
          GENERIC_ALL         equ 010000000h      /
                                                 |
    The right mapping starts here,...object to map needn't to be opened by
    CreateFile(A/W)  API.  If we use (-1)  value in  next API file  handle
    parameter,  we'll map part of shared-able memory with out conecting to
    file,...ideal for IPC.                       .
                                                 |
   .---------------------------------------------|---<><<
   |push name of file-mapping object       ;default - 0
   |push low-order 32 bits of object size  ;default - size
   |push high-order 32 bits of object size ;default - 0
  /|push protection                        ;default - 4
 |u|push security attributes               ;default - 0
 |n|push file handle                       ;default - HNDL from CreateFile
 |c|
 |l|call CreateFileMapping(A/W)
 |e|\\\\\\\\\\\\\\\\\\\\\\\\\\\
 | | returns - object handle
 |f|
 |u|this function create a map object and returns handle of it
 |c|>protection 
 |k|             PAGE_READONLY             equ 2
 |e|             PAGE_READWRITE            equ 4
 |r|             PAGE_WRITECOPY            equ 8
  \|
   |>security attributes - pointer can be set to NULL, anyway the struc:
   |             SECURITY_ATTRIBUTES struc
   |               _saSize               dd ? ;struc size
   |               _lpSecurityDescriptor dd ? ;pointer to sec. descriptor
   |               _bInheritHandle       dd ? ;bool val. True for inherit
   |             SECURITY_ATTRIBUTES ends
  / 
 |
 | .--------------------------------------------------------------<><<
 | |push name of mapping object
 |/|push inherit flag
 |w|push access mode   
 |h|
 |o|call OpenFileMapping(A/W)
 |o|\\\\\\\\\\\\\\\\\\\\\\\\\
 |o| return - object handle
 |o|
 |p|>access mode 
 |s|            FILE_MAP_WRITE   equ 2       ;R/W access  <--.
 |/|            FILE_MAP_READ    equ 4       ;R access   <---|     
 | |                                                         |
 | '--------.                                                |\
 |          |                                                |s|
 '--->-.-<--'                                                |a|
       | now we have map object                              |m|
   .---'                                                     |e|
   |push bytes to map     ;default - size                    |/
   |push file offset low  ;default - 0                       |
  /|push file offset high ;default - 0                       |
 |l|push access mode      ;----------------------------------'
 |a|push object handle    ;default - HNDL from Create(Open)FileMapping
 |m|
 |e|call MapViewOfFile
  \|\\\\\\\\\\\\\\\\\\
   | return - map address
   |
   '-->--.
         | now we have file mapped in memory
         | we can write part fo mapped file to the disk using:
         |
         |   push number of bytes to write
         |   push start address
         |   
         |   call FlushViewOfFile
         |   \\\\\\\\\\\\\\\\\\\\
   .--<--' 
   |push map address
  /|call UnmapViewOfFile   ;unmaps the view of file
 |e|\\\\\\\\\\\\\\\\\\\\\
 |n|
 |d|push object handle     ;closing mapped object 
  \|call CloseHandle
   |\\\\\\\\\\\\\\\\
   |
   |push file handle       ;closing file handle
   |call CloseHandle
   |\\\\\\\\\\\\\\\\
   '-----------------------------------------------.
                                                   |
                                   .---------------'---------.
                                   | All for file mapping,...|
                                   '---.---------------------'
 .                                     |
 |anonymous pipes                      |
-'-------------------------------------'------------------------------------
 |There two types of pipes. The anonymous and the named ones.  Named pipes
 |are a  'little' bit dificult to use  then anonymous so i'll discuss them
 'in some other article.
  Well, anonymous pipes are one-way, unnamed pipes. They can't be used for
  remote communication (despite the named pipes can). The point is that
  server create a pipe and receive read and write handle of pipe. Then it
  can send one of this handles to process to communicate to (we must send 
 .it via some other IPC method, i think the best will be Atoms IPC, anyway
 |there are next ways...).
  \
   |creating anonymous (unnamed) pipe
  / 
 |  push pipe size
 |  push protection
 |  push pointer to write pipe handle
    push pointer to read pipe handle

    call CreatePipe
    \\\\\\\\\\\\\\\

   >pipe size  - size of pipe buffer
                 if it's NULL system uses default size
   >protection - pointer to SECURITY_ATTRIBUTES
                 if it's NULL pipe cant be inherited
 |
 |  When pipe is  created we have  access to both ends.  To read and  write
 |  one.  Server is the one process which create pipe. After creating pipe,
 |  server have to send one handle to client process.
  \
   |read from pipe - this reading is synchronous one -> the func. wont end
   |                 until the read is done
  / 
 |  push pointer to struc for data
 |  push pointer to bytes read number
 |  push number of read bytes
    push pointer to read buffer 
    push handle of read pipe

    call ReadFile
    \\\\\\\\\\\\\

   >pointer to struc for data    - this struc is use for asynchronous input
 |                                 and output; so set to NULL
 | >pointer to bytes read number - pointer to dword which will contain 
 |                                 number of read bytes     
  \
   |write to pipe - this reading is synchronous one -> the func. wont end
   | until the read is done
  /
 |  push pointer to struc for data
 |  push pointer to bytes write number
 |  push number of write bytes
 |  push pointer to write buffer 
 |  push handle of write pipe
 |
 |  call WriteFile
 |  \\\\\\\\\\\\\\
 | 
 |  Anonymous  pipes  lives  until the  read and write handle  is open.  We
 |  can close it by using CloseHandle function.
 '-----------------------------------.--------------------------------------
                                     |  
                                   .-'--------------------------.
                                   | All for anonymous pipes,...|
                                   '---.------------------------'
                                       |
 .                                     |
 |mailslots                            |
-'-------------------------------------'------------------------------------
 | Mailslots  are next  simple way of IPC  between processes.  The point is
 | one  process(server) create  a mailslot,  and this one process has right
 | to read  messages from it.  Other  processes (clients)  can  connect  to
 | mailslot and  send  there message. The  different  from pipes is obvious,
 | anyway, there's  one more.  Maislots use datagrams for communication and
 | named pipes not(for remote communication). Uhghhh,...
 '-------------->>>-------------------------.
                                            |
  push protection                           |
  push time(ms) before read time-out        |
  push maximum message size                 |
  push mailslot name                        |
                                            |
  call CreateMailslot(A/W)                  |
                                            |
  returns : mailslot handle                 |
 .--------<<<-------------------------------'
 |mailslot name - name has following form:
 |                db "\\.\mailslot\[path]name",0
 |              - name must be unique, and there can be some 
 |                pseudodirectories (the [path]), and as ussual in this 
 |                article, it's not case-sensitive
 |
 |maximum message size - we can specify the maximum lenght of written
 |                message to mailslot, anyway if this field is NULL
 |                the message can be of any size
 |
 |time(ms) before read time-out - this is time, that will be the ReadFile
 |                function wait if there's no message in mailslot yet.
 |                There some special numbers:
 |
 |                0  - if no message in mailslot, func. wont wait :)
 |                -1 - this spec. will wait until there'll be message
 |                     in mailslot -> (MAILSLOT_WAIT_FOREVER)
 '
  Well, we created a mailslot and have handle of it. We can close it
  using CloseHandle,...

 .Now, mailslot is created and accessable by name.  The clients can connect
 |to it via  the CreateFile(A/W)  API,  using the mailslot name in filename
 |fields.  After connecting,  client receive handle to mailslot and is able
 |to write messages  to  mailslot.  This is  done by  WriteFile API. Server
 |is  reading  from mailslot  using  the  ReadFile  API.  All,  CreateFile,
 |ReadFile and WriteFile,  are explained somewhere here in text,  so i wont
 |waste  the space to explained  it  oncemore. Anyway,  there're some other
 |functions for mailslots. Here we go,...
 '
  mailslot server funcs:
 .
 |push pointer of read time-out
 |push pointer of number of messages
 |push pointer of size of next message
 |push pointer of maximum message size
 |push mailslot handle        ;returned by the CreateMailslot(A/W) API
 |
 |call GetMailslotInfo
 '                  
  returns - TRUE(1) if succeds

 .pointer of size of next message - this parameter could be NULL, anyway if
 |        not,  we'll  received  size of next  message in mailslot.  We can
 |        received MAILSLOT_NO_MESSAGE(-1) -> no next messsage in mailslot.
 |
 |pointer of number of messages -  this parameter could be NULL,  anyway if
 |        not, we'll receive total number of messages waiting to be read.
 |
 |
 'To set mailslot time-out for read operation we can use:
 .
 |push read time-out
 |push mailslot handle
 |
 |call SetMailslotInfo
 '
 .When we have mailslot handle we can use standart functions to get handle
 |informations about it. We can use:
 |
 |   DuplicateHandle 
 |   GetFileTime 
 |   SetFileTime 
 |   GetHandleInformation
 |   SetHandleInformation 
 |
-'-------------------------------------------------------------.------------
 |                                                             |
 '                                                 .-----------'----.
                                                   |  Thats all,... |
                                                   '----------------'

 greet(s):
    Benny,...IPC forever
   
   .
   |\
   | |.--.   -|-.
   | ||  |.--|| |
   |  \  m o r|t .
 .-'-----'\._''--'-.
 '--[MATRiX]-------'
 [mort@matrixvx.org]
  \\\\\\\\\\\\\\\\\\
