Hi Lutz,
Do you know if its possible to execute from variable? Eighter in C or Newlisp.
example:
(setq a '(here is binary data stored ) )
I would love to be able to do an (exec a) but its not inside newlisp.
The concept is, reading a file into a newlisp list/variable to be able to
include the data inside the newlisp script source-code itself.
During execution of the newlisp script the data can be executed. (by calling
to its variable or memory address) To prevent all files on being seperate
files on disk and make 'linking newlisp more complete im thinking of this feature but i dont to have any solution yet...
Any hint is welcome..
Norman.
You could do it this way:
; call a function specified as binary data from newLISP
; ----- this is a wild unsupported hack!
; do not try this unless you know what you are doing!
; get a template cell for a library function
; from any library function
(set 'foo (import "libc.so" "kill"))
; get you binary data
; you could encode those with " 01 02" etc.
; specifying each byte as a 3-digit decimal
; or you could load it from a file
(set 'bindata "<you binary data goes here>")
; copy the address of the binary data into the contents
; field of the 'foo' function cell at offset 12
(cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4)
; foo is now ready to execute, if it is a function
; written to 'C' conventions (args are on the stack)
; arguments can be passed too.
;
; do not destroy 'bindata' or the data in it as it is
; referenced by foo
(foo)
Note, that the binary data would be the raw function binary data. You cannot just read an executable file and plug it into this. It's similar to the payload of a computer virus, just the raw code you start to execute.
You could use 'base64-enc' and 'base64-dec' to include the binary stuff in the newLISP source itself.
Instaed of loading a cell template from a library you could also get it from any built-in function, but if you want to pass parameters, is has to be from a library, or you take a built-in function template but hack the type value field to make it look like a library function. The type field is at offset 4 and has to be 264 instead of 263 for a built-in function.
Lutz
Thats a great Hack ;-) Thanks a lot Lutz, Im working on it!
Ill let you know the outcome..
Norman.
Hi Lutz,
Im trying my headoff ;-) but im only getting SegDumps...
Actualy it look slike its loading the file from the variable but then its
segdumping..mmmmm any idea?
..
.. falert.lsp is the file i want to include and execute...
.. im using the import function...
..
..
open("./imp64.lsp", O_RDONLY) = 3
read(3, "#!/usr/bin/newlispnn(setq jelly "..., 18432) = 665
stat64("falert.lsp", {st_mode=S_IFREG|0700, st_size=691, ...}) = 0
open("falert.lsp", O_RDONLY) = 4
read(4, "#!/usr/bin/newlispn;;n;; For the"..., 691) = 691
close(4) = 0
brk(0) = 0x8094000
brk(0x8098000) = 0x8098000
brk(0) = 0x8098000
brk(0x8099000) = 0x8099000
brk(0) = 0x8099000
brk(0x809a000) = 0x809a000
--- SIGSEGV (Segmentation fault) @ 0 (0) ---
+++ killed by SIGSEGV +++
Oke somethng is happening ;-)
this is my script -->
#!/usr/bin/newlisp
(setq foo (import "/lib/libc.so.6" "kill"))
(setq jelly (string (join (map (lambda (y) (string {}y)) (map (lambda (x) (format "%03d" x)) (map char (explode (read-file "falert.lsp"))))))))
;;(cpymem (pack "ld" (address jelly)) (+ (first (dump 'foo)) 12) 4)
(cpymem (pack "ld" (address jelly)) (pack "ld" (address foo)) 4)
(foo)
but the STRACE shows me an -->>>-1 ESRCH (No such process) <<<--
(I tried either of the obove cpymem both do the same..)
open("/usr/share/newlisp/init.lsp", O_RDONLY) = 3
brk(0) = 0x808b000
brk(0x808f000) = 0x808f000
read(3, ";; init.lsp - newLISP initializa"..., 18432) = 1355
brk(0) = 0x808f000
brk(0x8090000) = 0x8090000
open("/home/nodep/.init.lsp", O_RDONLY) = 4
brk(0) = 0x8090000
brk(0x8094000) = 0x8094000
read(4, ";; init.lsp - newLISP initializa"..., 18432) = 1343
close(4) = 0
close(3) = 0
open("./imp64.lsp", O_RDONLY) = 3
read(3, "#!/usr/bin/newlispnn(setq foo (i"..., 18432) = 352
stat64("falert.lsp", {st_mode=S_IFREG|0700, st_size=691, ...}) = 0
open("falert.lsp", O_RDONLY) = 4
read(4, "#!/usr/bin/newlispn;;n;; For the"..., 691) = 691
close(4) = 0
brk(0) = 0x8094000
brk(0x8098000) = 0x8098000
brk(0) = 0x8098000
brk(0x8099000) = 0x8099000
brk(0) = 0x8099000
brk(0x809a000) = 0x809a000
kill(134682816, 134676448) = -1 ESRCH (No such process) <<<--- HERE !!!!!!!!!!!
close(3) = 0
Hope you have a hint..?
Norman
It has to be the first of the 'cpymem' lines. You seem to do the right thing. The problem is perhaps what youn have in jelly? I would start with some assembly instructions, i.e. just moving some values into registers AX DX for a retun value and then a ret, to see if you get the return value.
Can you do a disassembly of jelly, to see whats really in it?
How did you produce your binary? It should not be just some compiled program, but the bytes from the beginning should be executable machine code, without headers etc.
Lutz
Hi Lutz,
In the problem above I used a newlisp script called falert.lsp to be executed.
(http://www.nodep.nl/downloads/newlisp/falert.lsp) And thats executing newlisp first...
And when I use a binary file then its a normal compiled C file, and ELF binary
and that thus had an ELF header..(I should strip it off?)
I can try and use a raw ASM file and see what it does...
Regards, Norman.
Hi Lutz,
I tried a simple ASM code without the ELF header but also thatone
does give me the same result as above.. (kill(....,......) = -1 ESRCH)
I like this hack very much so i hope i can get it running ;-)
If you have a hint..please let me know..
Regards, Norman.
The binary also has to be relocateble, no memory references outside the stack, just stripping of the header might not be enough, so your ASM code should work ... strange.
Lutz
Hi Lutz,
I used Fasm for this without ELF header creation...
(fasm infile outfile)
These are not doing anything special.. but did not work..
--- nop.asm
start:
push eax
xor eax,eax
pop eax
--- hello.asm
start:
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msize
int 0x80
mov eax,1
xor ebx,ebx
int 0x80
msg db 'Hello Newlisp',0xA
msize = $-msg
The code that executed the above is this ->
#!/usr/bin/newlisp
(setq foo (import "/lib/libc.so.6" "kill"))
(setq jelly (string (join (map (lambda (y) (string {}y)) (map (lambda (x) (format "%03d" x)) (map char (explode (read-file "nop"))))))))
(cpymem (pack "ld" (address jelly)) (+ (first (dump 'foo)) 12) 4)
(foo)
PS: !!! Must it be (dump 'foo) or (dump foo)? They both give a different
address range back... But im using (dump 'foo)
Perhpas its the "kill" function that causes the problem? Lets see what
I can test...
Regards, Norman.
It has to be (dump foo) not (dump 'foo). Do it exactly like shown in my earlier post. After this statement:
(cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4)
do:
(dump foo)
; and
(address bindata)
The last number in (dump foo) should be the same as (address bindata). What we are doing here is putting the address of the executable 'bindata' into the address, which normally points to a libray 'C' function.
I don't have a chance at the moment, but will try the stuff myself tomorrow and if possible post a working example.
Lutz
Here is a working example session:
newLISP v.8.5.10 on Win32 MinGW, execute 'newlisp -h' for more info.
> (set 'foo (import "cygwin1.dll" "kill"))
kill <610945DA>
> (set 'bindata (pack "ccccccccccc" 0x55 0x8B 0xEC 0x8B 0x45 0x08 0x03 0x45 0x0C 0x5D 0xC3))
"Uï∞ïE 08 03E 12]├"
> (cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4)
4
> (foo 3 4)
7
> (foo 123 456)
579
>
The assembly executed is the following:
55 push epb
8B EC mov ebp, esp
8B 45 08 mov eax, [ebp+08]
03 45 0C add eax, [ebp+0c]
5D pop ebp
C3 ret
This should work on Linux or any other Intel platform too. The coude has to be a callable function treating the stack and register variables as it is usual on that platform and OS.
Lutz
BTW instead of importing a library template you could use an internal function and patch the type int to library functions type:
; get a template cell from a built-in function
(set 'foo print)
; change the type to a library function
(cpymem (pack "ld" 265) (first (dump foo)) 4)
; see previous post
(set 'bindata (pack "ccccccccccc"
0x55 0x8B 0xEC 0x8B 0x45 0x08 0x03 0x45 0x0C 0x5D 0xC3))
(cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4)
(foo 3 4) => 7
This make the whole thing more usable because you can write code without dependence of libraries.
Lutz