Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- .ELF file runner (v-1.-1.-1)
- -- (c) ProgramCrafter
- local function ByteStream()
- local t = {}
- local cidx = 0
- local bitstream = {
- extend = function(len, value)
- for i = 1, len do
- t[cidx + i] = value or 0
- end
- cidx = cidx + len
- end,
- put = function(...)
- for i = 1, table.pack(...).n do
- t[cidx + 1] = select(i, ...) or 0
- cidx = cidx + 1
- end
- end,
- puts = function(s)
- for i = 1, #s do
- t[cidx + i] = s:byte(i)
- end
- cidx = cidx + #s
- end,
- read = function(len)
- cidx = cidx + len
- return table.unpack(t, cidx - len + 1, cidx)
- end,
- seek = function(new_idx)
- if not new_idx then return cidx end
- cidx = new_idx
- end,
- len = function()
- return #t
- end,
- __raw = t
- }
- return bitstream
- end
- local function is_like(t1, t2)
- if #t1 ~= #t2 then return false end
- for i = 1, #t1 do
- if t1[i] ~= t2[i] and t2[i] then return false end
- end
- return true
- end
- local function assert_like(msg, t, pattern)
- local a = is_like(t, pattern) and '\27[32mOK: ' or '\27[33mFAIL: '
- print(a .. msg .. '\27[37m')
- if a:find('FAIL') then
- print('Found', table.unpack(t))
- print('Needs', table.unpack(pattern))
- error('Assertion failure')
- end
- end
- local function lton(t)
- local n = 0
- for i = #t, 1, -1 do
- n = n * 256 + t[i]
- end
- return n
- end
- local F = false
- local elf_code = '\x7F\x45\x4C\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x10\x02\x00\x03\x00\x01\x00\x00\x00\x80\x80\x04\x08\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x34\x00\x20\x00\x02\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x80\x00\x00\x00\x80\x80\x04\x08\x00\x00\x00\x00\x24\x00\x00\x00\x24\x00\x00\x00\x05\x00\x00\x00\x00\x10\x00\x00\x01\x00\x00\x00\xA4\x00\x00\x00\xA4\x80\x04\x08\x00\x00\x00\x00\x20\x00\x00\x00\x20\x00\x00\x00\x07\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xBB\x01\x00\x00\x00\xB8\x04\x00\x00\x00\xB9\xA4\x80\x04\x08\xBA\x0D\x00\x00\x00\xCD\x80\xB8\x01\x00\x00\x00\xBB\x5D\x00\x00\x00\xCD\x80\x00\x00\x48\x65\x6C\x6C\x6F\x20\x57\x6F\x72\x6C\x64\x21\x0A'
- local elf_stream = ByteStream()
- elf_stream.puts(elf_code)
- elf_stream.seek(0)
- assert_like('E_IDENT', {elf_stream.read(16)}, {0x7F,0x45,0x4C,0x46, 1,1,1, F,F,F,F,F,F,F,F, 16})
- assert_like('E_TYPE', {elf_stream.read(2)}, {0x02,0x00})
- assert_like('E_MACHINE', {elf_stream.read(2)}, {0x03,0x00})
- assert_like('E_VERSION', {elf_stream.read(4)}, {0x01,0x00,0x00,0x00})
- local e_entry = lton {elf_stream.read(4)}
- local e_phoff = lton {elf_stream.read(4)}
- local e_shoff = lton {elf_stream.read(4)}
- local e_flags = lton {elf_stream.read(4)}
- assert_like('E_EHSIZE', {elf_stream.read(2)}, {0x34,0x00})
- assert_like('E_PHENTSIZE',{elf_stream.read(2)}, {0x20,0x00})
- local e_phnum = lton {elf_stream.read(2)}
- assert_like('E_SH...', {elf_stream.read(6)}, {0,0,0,0,0,0})
- local appmem = ByteStream()
- local segments = {}
- elf_stream.seek(e_phoff)
- for i = 1, e_phnum do
- print('---- Segment #' .. tostring(i) .. ' ----')
- assert_like('P_TYPE', {elf_stream.read(4)}, {1,0,0,0})
- local p_offset = lton {elf_stream.read(4)}
- local p_vaddr = lton {elf_stream.read(4)}
- assert_like('P_PADDR',{elf_stream.read(4)}, {0,0,0,0})
- local p_filesz = lton {elf_stream.read(4)}
- local p_memsz = lton {elf_stream.read(4)}
- local p_flags = lton {elf_stream.read(4)}
- assert_like('P_ALIGN',{elf_stream.read(4)}, {0,0x10,0,0})
- segments[i] = {r_offset = p_offset, w_offset = p_vaddr, r_len = p_filesz, w_len = p_memsz}
- end
- for i = 1, e_phnum do
- local cs = segments[i]
- elf_stream.seek(cs.r_offset)
- appmem.seek(cs.w_offset)
- appmem.put(elf_stream.read(cs.r_len))
- appmem.extend(cs.w_len - cs.r_len)
- print('---- Segment #' .. tostring(i) .. ' loaded into VM ----')
- end
- local bit32 = require 'bit32'
- local band, bor, bxor, brs = bit32.band, bit32.bor, bit32.bxor, bit32.rshift
- appmem.seek(e_entry)
- local registers = {EAX = 0, EBX = 0, ECX = 0, EDX = 0}
- local ridxs = {[0] = 'EAX', [3] = 'EBX', [1] = 'ECX', [2] = 'EDX'}
- while true do
- local command = appmem.read(1)
- print('Command:', command)
- local opcode = band(command, 248)
- if opcode == 0xB8 then
- local target = ridxs[band(command, 7)]
- local value = lton {appmem.read(4)}
- print('Opcode: MOV ' .. tostring(value) .. ' ' .. target)
- registers[target] = value
- elseif command == 0xCD then
- local itype = appmem.read(1)
- if itype == 0x80 then
- print('Requested system call', registers.EAX)
- if registers.EAX == 1 then
- print('\27[32mExit code: ' .. tostring(registers.EBX) .. '\27[37m')
- return
- elseif registers.EAX == 4 then
- local cp = appmem.seek()
- appmem.seek(registers.ECX)
- local data = {appmem.read(registers.EDX)}
- print('Memory data:', table.unpack(data))
- print('\27[33m' .. string.char(table.unpack(data)) .. '\27[37m')
- appmem.seek(cp)
- end
- else
- print('Requested interrupt', registers.EAX)
- end
- else
- error('Unknown opcode')
- end
- os.sleep(0)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement