2024-10-16 18:07:41 -07:00
;;Update 2024: the previous code is likely not going to work on modern OS, because there is a need to allocate memory with the correct permissions (readable, writable, and executable). We will update with another machine code, equivalent to the function 'ash' in common lisp
89 f8 mov %edi,%eax
89 f1 mov %esi,%ecx
d3 e8 shr %cl,%eax
c3 ret
;;sbcl
( require :sb-posix )
( defconstant +PROT-READ+ 1 )
( defconstant +PROT-WRITE+ 2 )
( defconstant +PROT-EXEC+ 4 )
( defconstant +MAP-PRIVATE+ 2 )
( defconstant +MAP-ANONYMOUS+ #x20 )
( defun allocate-executable-memory ( size )
( sb-posix:mmap nil
size
( logior +PROT-READ+ +PROT-WRITE+ +PROT-EXEC+ )
( logior +MAP-PRIVATE+ +MAP-ANONYMOUS+ )
-1
0 ) )
;; Example usage:
( defparameter *shellcode* #( #x89 #xf8 #x89 #xf1 #xd3 #xe8 #xc3 ) )
( defparameter *mem-ptr* ( allocate-executable-memory ( length *shellcode* ) ) )
;; Copy shellcode to allocated memory
( loop for byte across *shellcode*
for i from 0
do ( setf ( sb-sys:sap-ref-8 *mem-ptr* i ) byte ) )
;; Create a callable function pointer
( defparameter *func* ( sb-alien:sap-alien *mem-ptr* ( sb-alien:function sb-alien:unsigned-int sb-alien:unsigned-int sb-alien:unsigned-int ) ) )
;; Call the function
( sb-alien:alien-funcall *func* 18 1 )
;; 9
;;(ash 18 -1) => 9
;; Don't forget to free the memory when done
;;(sb-posix:munmap *mem-ptr* (length *shellcode*))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;old contribution starts here
2023-07-01 11:58:00 -04:00
;;Note that by using the 'CFFI' library, one can apply this procedure portably in any lisp implementation;
;; in this code however I chose to demonstrate only the implementation-dependent programs.
;;CCL
;; Allocate a memory pointer and poke the opcode into it
( defparameter ptr ( ccl::malloc 9 ) )
( loop for i in ' ( 139 68 36 4 3 68 36 8 195 )
for j from 0 do
( setf ( ccl::%get-unsigned-byte ptr j ) i ) )
;; Execute with the required arguments and return the result as an unsigned-byte
( ccl::ff-call ptr :UNSIGNED-BYTE 7 :UNSIGNED-BYTE 12 :UNSIGNED-BYTE )
;; Output = 19
;; Free the pointer
( ccl::free ptr )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;SBCL
( defparameter mmap ( list 139 68 36 4 3 68 36 8 195 ) )
( defparameter pointer ( sb-alien:make-alien sb-alien:unsigned-char ( length mmap ) ) )
( defparameter callp ( loop for byte in mmap
for i from 0
do
( setf ( sb-alien:deref pointer i ) byte )
finally
( return ( sb-alien:cast pointer ( function integer integer integer ) ) ) ) )
( sb-alien:alien-funcall callp 7 12 )
( loop for i from 0 below 18 collect ( sb-alien:deref ptr i ) )
( sb-alien:free-alien pointer )
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;CLISP
( defparameter mmap ( list 139 68 36 4 3 68 36 8 195 ) )
( defparameter POINTER ( FFI:FOREIGN-ADDRESS ( FFI:FOREIGN-ALLOCATE 'FFI:UINT8 :COUNT 9 ) ) )
( loop for i in mmap
for j from 0 do
( FUNCALL #' ( SETF FFI:MEMORY-AS ) i POINTER 'FFI:INT j ) )
( FUNCALL
( FFI:FOREIGN-FUNCTION POINTER
( LOAD-TIME-VALUE
( FFI:PARSE-C-TYPE
' ( FFI:C-FUNCTION ( :ARGUMENTS 'FFI:INT 'FFI:INT ) ( :RETURN-TYPE FFI:INT ) ( :LANGUAGE :STDC ) ) ) ) )
7 12 )
( FFI:FOREIGN-FREE POINTER )