103 lines
3.2 KiB
Common Lisp
103 lines
3.2 KiB
Common Lisp
;;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
|
|
;;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)
|