In the case of .NET framework (at least as far as I know), the loader identifies a file as a .NET executable, reads in the meta header, and initializes the mscoree.dll appropriately. We will not go through all those complications and will use a regular PE file:
Customized PE file
PE Header - regular PE Header, no modification needed;
Code Section- simply invokes the core function of the framework:push pseudo_code_base_address call [core]
Import Section - regular import section that only imports one function from the framework.dll - framework.core(unsigned int);
Data Section - this section contains the actual compiled pseudo assembly code and whatever headers you may come up with, that may instruct the core() function to correctly initialize the application.
Example Executable Source Code
The following is the source code of the example executable. It may be compiled with FASM (Flat Assembler).
include 'win32a.asm' ;we need the 'import' macro include 'asm.asm' ;pseudo assembly commands and constants format PE console entrystart section '.text' readable executable start: push _base call [core_func]
section '.idata' dataimportwriteable library framework, 'framework.dll' import framework,\ core_func, 'Core' section '.data' readablewriteable _base: loadi A, _base loadi B, 0x31 _add A, B loadr B, A loadi A, _data.string loadi C, _data.string_len _call _func loadi A, 1 loadi B, _data.string loadi C, _data.str_len _int sys_write loadi A, 1 loadi B, _data.msg loadi C, _data.msg_len _int sys_write _int sys_exit
_func: ; A = string address ; B = key ; C = counter .decode: loadr D, A xorr D, B storr A, D loadi D, 4 _add A, D _loop .decode _ret
_data: .string db 'Hello, developer!', 10, 13 .str_len = $-.string db 0 .string_len = ($-.string)/4 .msg db 'The program will now exit.', 10, 13 .msg_len = $-.msg
;Encrypt one string load k dword from _base + 0x31 repeat 5 load a dword from _data.string+(% - 1)*4 a = a xor k store dword a at _data.string + (% - 1)*4 end repeat
The code above produces a tiny executable which invokes framework's core() function. Pseudo assembly code simply prints two messages (the first one is decoded prior to being printed). Full source code is available, see link at the end of the article.
The good thing is that you do not have to start the interpreter and load this executable (or specify it as a command line parameter) - you may simply run this executable, Windows loader will bind it with the framework.dll automatically.
The bad thing is that you would, most probably, have to write your own compiler, because writing assembly is fun, dealing with pseudo assembly is fun as well, BUT, only when done for fun. It is not as pleasant when dealing with production code.
Unless you are trying to create a framework that would improve on existing software frameworks, you could use such approach to increase the protection of your applications by, for example, virtualizing cryptography algorithms or any other part of your program which is not crucial in terms of execution speed, but represents a sensitive intellectual property.