Skip to content

Commit 3e8c562

Browse files
committed
Mass commit.
0 parents  commit 3e8c562

11 files changed

+555
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
based on https://github.com/k-stz/cl-ptrace

a.out

15.8 KB
Binary file not shown.

cl-ptrace.asd

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
;;;; This file contains the system definition for ASDF
2+
3+
(in-package :asdf-user)
4+
5+
(defsystem #:cl-ptrace
6+
:description "My own take at a lisp process hacking"
7+
:version "0.3.0"
8+
:author "liamm91"
9+
:licence "MIT"
10+
:depends-on ("cffi" "cl-ppcre")
11+
:serial t
12+
:components
13+
((:file "src/package")
14+
(:file "src/utils")
15+
(:file "src/memmappings")))

debug.asm

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
.file "prog.c"
2+
.text
3+
.globl flag
4+
.data
5+
.align 4
6+
.type flag, @object
7+
.size flag, 4
8+
flag:
9+
.long 43981
10+
.globl x
11+
.bss
12+
.align 8
13+
.type x, @object
14+
.size x, 8
15+
x:
16+
.zero 8
17+
.section .rodata
18+
.align 8
19+
.LC0:
20+
.string "Modified flag variable! Flag now: %x"
21+
.text
22+
.globl main
23+
.type main, @function
24+
main:
25+
.LFB0:
26+
.cfi_startproc
27+
pushq %rbp
28+
.cfi_def_cfa_offset 16
29+
.cfi_offset 6, -16
30+
movq %rsp, %rbp
31+
.cfi_def_cfa_register 6
32+
jmp .L2
33+
.L3:
34+
movq x(%rip), %rax
35+
addq $1, %rax
36+
movq %rax, x(%rip)
37+
.L2:
38+
movl flag(%rip), %eax
39+
cmpl $43981, %eax
40+
je .L3
41+
movl flag(%rip), %eax
42+
movl %eax, %esi
43+
leaq .LC0(%rip), %rdi
44+
movl $0, %eax
45+
call printf@PLT
46+
movl $0, %eax
47+
popq %rbp
48+
.cfi_def_cfa 7, 8
49+
ret
50+
.cfi_endproc
51+
.LFE0:
52+
.size main, .-main
53+
.ident "GCC: (GNU) 10.2.0"
54+
.section .note.GNU-stack,"",@progbits

makefile

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
SCRIPT_NAME := cl-ptrace.asd
2+
PACKAGE_NAME := :cl-ptrace
3+
4+
target:
5+
@echo "Run (load-short) to run load the package into the REPL, then (in-package ${PACKAGE_NAME})"
6+
@sbcl --load ${SCRIPT_NAME} --eval "(asdf:load-system ${PACKAGE_NAME})" --eval "(in-package ${PACKAGE_NAME})"
7+

prog.c

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#include <stdio.h>
2+
3+
int flag = 0xABCD;
4+
unsigned long long x = 0;
5+
6+
int main () {
7+
while (flag == 0xABCD) {
8+
++x;
9+
}
10+
printf("Modified flag variable! Flag now: %x", flag);
11+
return 0;
12+
}

source.c

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <sys/ptrace.h>
4+
#include <sys/reg.h>
5+
#include <sys/wait.h>
6+
#include <sys/types.h>
7+
#include <sys/user.h>
8+
#include <unistd.h>
9+
#include <errno.h>
10+
#include <string.h>
11+
12+
// literally just so I can look through all of the header files with
13+
// their definition so I can learn from it
14+
int main () {
15+
return 0;
16+
}

src/memmappings.lisp

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
;;;; This file is to organize all the functions which access the memory mappings of the current process
2+
3+
;; Make a standardized format to remember functions by:
4+
;; -- a range of addresses is called a region. e.g., (- 111222333 777888999) is a region
5+
;; -- search functions will return a list of addresses (1111 2222 3333 4444 5555 6666)
6+
;; -- get functions return region(s)
7+
;; -- snapshot macros return an address value pair
8+
9+
;; [X] removed comparison and parsing function from get-memory-regions function
10+
;; [X] made a macro to specifically target the heap from a process
11+
;; [X] make a function to search memory regions for a specific value
12+
;; [ ] make a function to COMPLETELY stop multi-threaded processes
13+
14+
;; -- Aside/Rants --
15+
16+
;; I was erroring because my guess is that I was reading too small of address ranges
17+
;; and when the REPL was trying to convert it to an unsigned bytes it was crashing. Why? great question.
18+
;; The fix was fixing the value of +CHAR+ from 4 bits to 8 bits. Which it what it was supposed to be but
19+
;; I can't understand how many bits are in a byte.
20+
21+
;; -- Future --
22+
23+
;; Actually use this library on a simple program like an emulator
24+
25+
;; Make a function to calculate the displacement of a certain address from the start of the program
26+
;; and save it to a file
27+
;; e.g., calculate the displacement for a health variable
28+
29+
(in-package :cl-ptrace)
30+
31+
;; We are counting in bits, not bytes
32+
(defconstant +CHAR+ (* 8 1)) ; 1 byte
33+
(defconstant +SHORT+ (* 8 2)) ; 2 bytes
34+
(defconstant +INTEGER+ (* 8 4)) ; 4 bytes
35+
(defconstant +LONG+ (* 8 8)) ; 8 bytes
36+
37+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
38+
;; Snapshot Functions
39+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
40+
41+
(defmacro heap-snapshot (&optional (pid *pid*) (read-size +CHAR+))
42+
"This function is a short-hand to read and take the snapshot of the heap."
43+
`(let ((heap-range (get-heap-region ,pid)))
44+
(if (null heap-range)
45+
nil
46+
(collect-address-value-pairs heap-range ,read-size ,pid))))
47+
48+
(defmacro memory-snapshot (&optional (pid *pid*) (read-size +CHAR+))
49+
"This function takes a list of address ranges and then calls collect-address-value-pairs on them."
50+
`(apply #'append (loop for region in (get-memory-regions ,pid)
51+
collect (collect-address-value-pairs region ,pid ,read-size))))
52+
53+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
54+
;; Get Functions
55+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
56+
57+
(defmacro get-heap-region (&optional (pid *pid*))
58+
"Parses the memory regions of the process and returns the memory region of the heap"
59+
`(car (get-memory-regions ,pid #'parse-memory-regions "(heap)")))
60+
61+
(defun get-memory-regions (&optional (pid *pid*) (parser #'parse-memory-regions) (match-query "([r\-][w\-][x\-]p)"))
62+
"Reads the /proc/id/maps file and returns all the memory addresses associated with the process"
63+
(with-open-file (stream (concatenate 'string "/proc/" (write-to-string pid) "/maps"))
64+
(loop for line = (read-line stream nil)
65+
while line
66+
if (cl-ppcre:scan match-query line) ; this is to make sure I'm reading the memory regions that are private and not shared
67+
collect (funcall parser line))))
68+
69+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
70+
;; Search Functions
71+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
72+
73+
(defmacro search-all-regions (target-value &optional (pid *pid*) (read-size +CHAR+))
74+
"This macro is a short-hands to search every memory region for the target-value"
75+
`(apply #'append (loop for range in (get-memory-regions ,pid)
76+
collect (search-region ,target-value range ,pid ,read-size))))
77+
78+
(defun search-region (target-value region &optional (pid *pid*) (read-size +CHAR+))
79+
"This function searches for the target-value in a region of memory addresses and returns a list of addresses who's value matches the target-value."
80+
(loop for n from 0 to (/ (- (cadr region) (car region)) read-size)
81+
for mem-value = (peekdata (+ (car region) (* n read-size)) pid nil nil)
82+
if (= target-value mem-value)
83+
collect (+ (car region) (* n read-size))))
84+
85+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
86+
;; Miscellaneous Functions
87+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
88+
89+
(defun collect-address-value-pairs (region &optional (pid *pid*) (read-size +CHAR+))
90+
"This function searches each memory address and returns it and its corresponding value."
91+
(loop for n from 0 to (/ (- (cadr region) (car region)) read-size)
92+
collect (list (+ (car region) (* n read-size)) (peekdata (+ (car region) (* n read-size)) pid nil nil))))
93+
94+
(defmacro print-memory-regions (&optional (pid *pid*) (read-size +CHAR+))
95+
"This function prints the number of addresses in each address range: [a, b]. Including a proper (- a b) form"
96+
`(let ((list-regions (get-memory-regions ,pid)))
97+
(format t "Read size: ~D bits~%" ,read-size)
98+
(loop for region in list-regions
99+
do (format t "(- ~D ~D) >> ~D Addrs~%" (car region) (cadr region) (/ (- (cadr region) (car region)) ,read-size)))
100+
t))
101+
102+
(defun num-addresses (&optional (pid *pid*) (read-size +CHAR+))
103+
"Sums the amount of addresses used by the process"
104+
(let ((mappings (get-memory-regions pid)))
105+
(apply #'+ (loop for region in mappings
106+
collect (/ (- (cadr region) (car region)) read-size)))))
107+
108+
(defun parse-memory-regions (string)
109+
"Function built to parse the /proc/id/maps file"
110+
(mapcar #'(lambda (x) (parse-integer x :radix 16)) (cl-ppcre:split "\-" (car (cl-ppcre:split "\\s+" string)))))

src/memmappings.lisp~

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
;;;; This file is to organize all the functions which access the memory mappings of the current process
2+
3+
;; [X] removed comparison and parsing function from get-memory-regions function
4+
;; --- made a macro to specifically target the heap from a process
5+
6+
;; Make function to iterate over each address and scan for a target value,
7+
;; any result will be a signed
8+
9+
;; Make a function to calculate the displacement of a certain address from the start of the program
10+
;; and save it to a file
11+
;; e.g., calculate the displacement for a health variable
12+
13+
(in-package :cl-ptrace)
14+
15+
(defun num-addresses (&optional (pid *pid*))
16+
"Sums the amount of addresses used by the process"
17+
(let ((mappings (get-memory-regions pid)))
18+
(apply #'+ (loop for range in mappings
19+
collect (- (second range) (first range))))))
20+
21+
(defmacro get-heap-region (&optional (pid *pid*))
22+
"Parses the memory regions of the process and returns the memory region of the heap"
23+
`(car (get-memory-regions ,pid #'parse-memory-regions "(heap)")))
24+
25+
(defun parse-memory-regions (string)
26+
"Parses the memory regions from the /proc/id/maps file"
27+
(mapcar #'(lambda (x) (parse-integer x :radix 16)) (cl-ppcre:split "\-" (car (cl-ppcre:split "\\s+" string)))))
28+
29+
(defun get-memory-regions (&optional (pid *pid*) (parser #'parse-memory-regions) (read-if "([r\-][w\-][x\-]p)"))
30+
"Reads the /proc/id/maps file and returns all the memory addresses associated with the process"
31+
(with-open-file (stream (concatenate 'string "/proc/" (write-to-string pid) "/maps"))
32+
(loop for line = (read-line stream nil)
33+
while line
34+
if (cl-ppcre:scan read-if line) ; this is to make sure I'm reading the memory regions that are private and not shared
35+
collect (funcall parser line))))
36+

src/package.lisp

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
;;;; This file is to setup the package for the lisp system
2+
3+
(in-package "COMMON-LISP-USER")
4+
5+
(defpackage :cl-ptrace
6+
(:use :common-lisp :sb-ext :cffi))

0 commit comments

Comments
 (0)