executing from variable

For the Compleat Fan
Locked
newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

executing from variable

Post by newdep »

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.
-- (define? (Cornflakes))

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

You could do it this way:

Code: Select all

; 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 "\001\002" 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

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

Thats a great Hack ;-) Thanks a lot Lutz, Im working on it!
Ill let you know the outcome..

Norman.
-- (define? (Cornflakes))

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

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/newlisp\n\n(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/newlisp\n;;\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 +++
-- (define? (Cornflakes))

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

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/newlisp\n\n(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/newlisp\n;;\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
-- (define? (Cornflakes))

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

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.
-- (define? (Cornflakes))

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

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.
-- (define? (Cornflakes))

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

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

newdep
Posts: 2038
Joined: Mon Feb 23, 2004 7:40 pm
Location: Netherlands

Post by newdep »

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.
-- (define? (Cornflakes))

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

It has to be (dump foo) not (dump 'foo). Do it exactly like shown in my earlier post. After this statement:

Code: Select all

(cpymem (pack "ld" (address bindata)) (+ (first (dump foo)) 12) 4) 
do:

Code: Select all

(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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Here is a working example session:

Code: Select all

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\008\003E\012]├"
> (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:

Code: Select all

 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

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

BTW instead of importing a library template you could use an internal function and patch the type int to library functions type:

Code: Select all

; 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

Locked