Changeset 2505 for neercs/trunk
- Timestamp:
- Jul 1, 2008, 1:26:30 AM (13 years ago)
- Location:
- neercs/trunk/src
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
neercs/trunk/src/grab.c
r2504 r2505 23 23 #include <unistd.h> 24 24 25 #include "config.h"26 27 25 #if defined USE_GRAB 28 26 # include <sys/ioctl.h> … … 39 37 #include "neercs.h" 40 38 39 #define X(x) #x 40 #define STRINGIFY(x) X(x) 41 41 42 #if defined __x86_64__ 42 43 # define RAX rax … … 46 47 # define RSP rsp 47 48 # define RIP rip 49 # define RDI rdi 50 # define RSI rsi 51 # define SYSCALL 0x050fL /* 0F 05 = syscall */ 52 # define FMT "%016lx" 48 53 #else 49 54 # define RAX eax … … 53 58 # define RSP esp 54 59 # define RIP eip 60 # define RDI edi 61 # define RSI esi 62 # define SYSCALL 0x80cd /* CD 80 = int $0x80 */ 63 # define FMT "%08lx" 55 64 #endif 56 65 57 66 #if defined USE_GRAB 58 static int memcpy_from_target(pid_t pid, void* dest, void* src, size_t n) 59 { 67 /* For debugging purposes only. Prints register and stack information. */ 68 static void print_registers(pid_t pid) 69 { 70 union { long int l; unsigned char data[sizeof(long int)]; } inst; 71 struct user_regs_struct regs; 72 int i; 73 74 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 75 { 76 perror("ptrace_getregs"); 77 exit(errno); 78 } 79 80 fprintf(stderr, " / %s: "FMT" ", STRINGIFY(RAX), regs.RAX); 81 fprintf(stderr, "%s: "FMT"\n", STRINGIFY(RBX), regs.RBX); 82 fprintf(stderr, " | %s: "FMT" ", STRINGIFY(RCX), regs.RCX); 83 fprintf(stderr, "%s: "FMT"\n", STRINGIFY(RDX), regs.RDX); 84 fprintf(stderr, " | %s: "FMT" ", STRINGIFY(RDI), regs.RDI); 85 fprintf(stderr, "%s: "FMT"\n", STRINGIFY(RSI), regs.RSI); 86 fprintf(stderr, " | %s: "FMT" ", STRINGIFY(RSP), regs.RSP); 87 fprintf(stderr, "%s: "FMT"\n", STRINGIFY(RIP), regs.RIP); 88 89 inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP - 4, 0); 90 fprintf(stderr, " \\ code: ... %02x %02x %02x %02x <---> ", 91 inst.data[0], inst.data[1], inst.data[2], inst.data[3]); 92 inst.l = ptrace(PTRACE_PEEKTEXT, pid, regs.RIP, 0); 93 fprintf(stderr, "%02x %02x %02x %02x ...\n", 94 inst.data[0], inst.data[1], inst.data[2], inst.data[3]); 95 96 fprintf(stderr, " \\ stack: ... "); 97 for(i = -16; i < 24; i += sizeof(long)) 98 { 99 inst.l = ptrace(PTRACE_PEEKDATA, pid, regs.RSP + i, 0); 100 #if defined __x86_64__ 101 fprintf(stderr, "%02x %02x %02x %02x %02x %02x %02x %02x ", 102 inst.data[0], inst.data[1], inst.data[2], inst.data[3], 103 inst.data[4], inst.data[5], inst.data[6], inst.data[7]); 104 #else 105 fprintf(stderr, "%02x %02x %02x %02x ", 106 inst.data[0], inst.data[1], inst.data[2], inst.data[3]); 107 #endif 108 if(i == 0) 109 fprintf(stderr, "[%s] ", STRINGIFY(RSP)); 110 } 111 fprintf(stderr, "...\n"); 112 } 113 114 /* FIXME: this function and the following have alignment issues */ 115 static int memcpy_from_target(pid_t pid, void* dest, long src, size_t n) 116 { 117 long *d = (long*)dest; 60 118 unsigned int i; 61 long *d, *s; 62 d = (long*) dest; 63 s = (long*) src; 64 n /= sizeof(long); 65 for(i = 0; i < n; i++) 66 { 67 d[i] = ptrace(PTRACE_PEEKTEXT, pid, s + i, 0); 119 120 for(i = 0; i < n / sizeof(long); i++) 121 { 122 d[i] = ptrace(PTRACE_PEEKTEXT, pid, src + i * sizeof(long), 0); 68 123 if(errno) 69 124 { 70 perror("ptrace (PTRACE_PEEKTEXT)");125 perror("ptrace_peektext"); 71 126 return -1; 72 127 } … … 75 130 } 76 131 77 static int memcpy_into_target(pid_t pid, void* dest, void* src, size_t n) 78 { 132 static int memcpy_into_target(pid_t pid, long dest, void* src, size_t n) 133 { 134 long *s = (long*) src; 79 135 unsigned int i; 80 long *d, *s; 81 d = (long*) dest; 82 s = (long*) src; 136 83 137 for(i = 0; i < n / sizeof(long); i++) 84 138 { 85 if(ptrace(PTRACE_POKETEXT, pid, d + i, s[i]) == -1)86 { 87 perror("ptrace (PTRACE_POKETEXT)");139 if(ptrace(PTRACE_POKETEXT, pid, dest + i * sizeof(long), s[i]) == -1) 140 { 141 perror("ptrace_poketext"); 88 142 return -1; 89 143 } … … 92 146 } 93 147 94 static int do_syscall(pid_t pid, struct user_regs_struct *regs)148 static long do_syscall(pid_t pid, long call, long arg1, long arg2, long arg3) 95 149 { 96 150 /* Method for remote syscall: 97 * - store current register status into oregs 98 * - move stack pointer to the next empty element 99 * - store current read stack contents into oinst 100 * - put CD 80 (int 0x80) into the stack 101 * - set instruction pointer to the current stack address 102 * - single step: execute instruction (int 0x80) 103 * - get new register values 104 * - restore old register values from oregs 105 * - restore old stack contents from oinst */ 106 struct user_regs_struct oregs; 151 * - wait until the traced application exits from a syscall 152 * - save registers 153 * - rewind eip/rip to point on the syscall instruction 154 * - single step: execute syscall instruction 155 * - restore registers */ 156 struct user_regs_struct regs, oldregs; 107 157 long oinst; 108 158 109 if(ptrace(PTRACE_GETREGS, pid, NULL, &oregs) < 0) 159 for(;;) 160 { 161 if(ptrace(PTRACE_GETREGS, pid, NULL, &oldregs) < 0) 162 { 163 fprintf(stderr, "PTRACE_GETREGS failed\n"); 164 return -1; 165 } 166 167 oinst = ptrace(PTRACE_PEEKTEXT, pid, oldregs.RIP - 2, 0) & 0xffff; 168 169 if(oinst == SYSCALL) 170 break; 171 172 if(ptrace(PTRACE_SYSCALL, pid, NULL, 0) < 0) 173 { 174 perror("ptrace_syscall (1)"); 175 return -1; 176 } 177 waitpid(pid, NULL, 0); 178 179 if(ptrace(PTRACE_SYSCALL, pid, NULL, 0) < 0) 180 { 181 perror("ptrace_syscall (2)"); 182 return -1; 183 } 184 waitpid(pid, NULL, 0); 185 } 186 187 regs = oldregs; 188 regs.RIP = regs.RIP - 2; 189 regs.RAX = call; 190 #if defined __x86_64__ 191 regs.RDI = arg1; 192 regs.RSI = arg2; 193 regs.RDX = arg3; 194 #else 195 regs.RBX = arg1; 196 regs.RCX = arg2; 197 regs.RDX = arg3; 198 #endif 199 200 if(ptrace(PTRACE_SETREGS, pid, NULL, ®s) < 0) 201 { 202 fprintf(stderr, "PTRACE_SETREGS failed\n"); 203 return -1; 204 } 205 206 if(ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) 207 { 208 fprintf(stderr, "PTRACE_SINGLESTEP failed\n"); 209 return -1; 210 } 211 waitpid(pid, NULL, 0); 212 213 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 214 { 215 fprintf(stderr, "PTRACE_GETREGS failed\n"); 216 return -1; 217 } 218 219 if(ptrace(PTRACE_SETREGS, pid, NULL, &oldregs) < 0) 220 { 221 fprintf(stderr, "PTRACE_SETREGS failed\n"); 222 return -1; 223 } 224 225 debug("syscall %ld returned %ld", call, regs.RAX); 226 227 if((long)regs.RAX < 0) 228 { 229 errno = -(long)regs.RAX; 230 perror("syscall"); 231 return -1; 232 } 233 234 return regs.RAX; 235 } 236 237 static int do_close(pid_t pid, int fd) 238 { 239 return do_syscall(pid, SYS_close, fd, 0, 0); 240 } 241 242 static int do_dup2(pid_t pid, int oldfd, int newfd) 243 { 244 return do_syscall(pid, SYS_dup2, oldfd, newfd, 0); 245 } 246 247 static int do_open(pid_t pid, char *path, int mode) 248 { 249 char path_data[4096], backup_data[4096]; 250 struct user_regs_struct regs; 251 long target_data; 252 size_t size = (strlen(path) + sizeof(long)) & ~(sizeof(long) - 1L); 253 int ret; 254 255 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 110 256 { 111 257 fprintf(stderr, "PTRACE_GETREGS failed\n"); … … 113 259 } 114 260 115 regs->RSP = oregs.RSP - sizeof(long); 116 117 oinst = ptrace(PTRACE_PEEKTEXT, pid, regs->RSP, 0); 118 if(errno) 119 { 120 fprintf(stderr, "PTRACE_PEEKTEXT failed\n"); 121 return errno; 122 } 123 124 if(ptrace(PTRACE_POKETEXT, pid, regs->RSP, (long)0x80cd) < 0) /* int 0x80 */ 125 { 126 fprintf(stderr, "PTRACE_POKETEXT failed\n"); 127 return errno; 128 } 129 130 regs->RIP = regs->RSP; 131 132 if(ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) 133 { 134 fprintf(stderr, "PTRACE_SETREGS failed\n"); 135 return errno; 136 } 137 138 if(ptrace(PTRACE_SINGLESTEP, pid, NULL, NULL) < 0) 139 { 140 fprintf(stderr, "PTRACE_SINGLESTEP failed\n"); 141 return errno; 142 } 143 waitpid(pid, NULL, 0); 144 145 if(ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) 146 { 147 fprintf(stderr, "PTRACE_GETREGS failed\n"); 148 return errno; 149 } 150 151 if(ptrace(PTRACE_SETREGS, pid, NULL, &oregs) < 0) 152 { 153 fprintf(stderr, "PTRACE_SETREGS failed\n"); 154 return errno; 155 } 156 157 if(ptrace(PTRACE_POKETEXT, pid, oregs.RSP - sizeof(long), oinst) < 0) 158 { 159 fprintf(stderr, "PTRACE_POKETEXT failed\n"); 160 return errno; 161 } 162 163 return 0; 164 } 165 166 static int do_close(pid_t pid, int fd) 167 { 168 struct user_regs_struct regs; 169 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 170 { 171 fprintf(stderr, "PTRACE_GETREGS failed\n"); 172 return errno; 173 } 174 175 regs.RAX = SYS_close; 176 regs.RBX = fd; 177 178 return do_syscall(pid, ®s); 179 } 180 181 static int do_dup2(pid_t pid, int oldfd, int newfd) 182 { 183 struct user_regs_struct regs; 184 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 185 { 186 fprintf(stderr, "PTRACE_GETREGS failed\n"); 187 return errno; 188 } 189 190 regs.RAX = SYS_dup2; 191 regs.RBX = oldfd; 192 regs.RCX = newfd; 193 194 return do_syscall(pid, ®s); 195 } 196 197 static int do_open(pid_t pid, char *path, int mode, int *fd) 198 { 199 struct user_regs_struct regs; 200 void *backup_page; 201 void *target_page = (void*)(0x08048000); 202 size_t size = (1 << 12); /* 4K */ 203 int ret; 204 205 /* Backup the page that we will use */ 206 backup_page = malloc(size); 207 if(memcpy_from_target(pid, backup_page, target_page, size) < 0) 208 return -1; 209 210 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 211 { 212 fprintf(stderr, "PTRACE_GETREGS failed\n"); 213 return errno; 214 } 261 target_data = (regs.RSP - size) & ~(sizeof(long) - 1L); 262 263 /* Backup the data that we will use */ 264 if(memcpy_from_target(pid, backup_data, target_data, size) < 0) 265 return -1; 215 266 216 267 /* +4 (or 8) because it's truncated on a multiple of 4 (or 8) 217 268 * and we need 1 */ 218 memcpy_into_target(pid, target_page, path, strlen(path) + sizeof(long)); 219 220 regs.RAX = SYS_open; 221 regs.RBX = (long)target_page; 222 regs.RCX = O_RDWR; 223 regs.RDX = 0755; 224 225 if((ret = do_syscall(pid, ®s)) != 0) 226 { 227 return ret; 228 } 229 230 /* Restore the pages */ 231 memcpy_into_target(pid, target_page, backup_page, size); 232 233 *fd = regs.RAX; 234 235 return 0; 269 sprintf(path_data, "%s", path); 270 memcpy_into_target(pid, target_data, path_data, size); 271 272 ret = do_syscall(pid, SYS_open, target_data, O_RDWR, 0755); 273 274 /* Restore the datas */ 275 memcpy_into_target(pid, target_data, backup_data, size); 276 277 if(ret < 0) 278 { 279 errno = ret; 280 return -1; 281 } 282 283 return ret; 236 284 } 237 285 238 286 static int do_setsid(pid_t pid) 239 287 { 240 struct user_regs_struct regs; 241 int ret; 242 243 if(ptrace(PTRACE_GETREGS, pid, NULL, ®s) < 0) 244 { 245 fprintf(stderr, "PTRACE_GETREGS failed\n"); 246 return errno; 247 } 288 long ret; 248 289 249 290 debug("Running setsid on process %d (sid=%d)", pid, getsid(pid)); 250 291 251 regs.RAX = SYS_setpgid; 252 regs.RBX = 0; 253 regs.RCX = getsid(pid); 254 255 if((ret = do_syscall(pid, ®s)) != 0) 292 ret = do_syscall(pid, SYS_setpgid, 0, getsid(pid), 0); 293 if(ret < 0) 256 294 { 257 295 fprintf(stderr, "syscall setpgid failed\n"); … … 259 297 } 260 298 261 if(regs.RAX != 0) 262 { 263 fprintf(stderr, "setpgid returned %ld\n", (long)regs.RAX); 264 return -regs.RAX; 265 } 266 267 regs.RAX = SYS_setsid; 268 269 if((ret = do_syscall(pid, ®s)) != 0) 299 if(ret != 0) 300 { 301 fprintf(stderr, "setpgid returned %ld\n", ret); 302 return -ret; 303 } 304 305 ret = do_syscall(pid, SYS_setsid, 0, 0, 0); 306 if(ret < 0) 270 307 { 271 308 fprintf(stderr, "syscall setsid failed\n"); … … 275 312 debug("pid %d has now sid %d", pid, getsid(pid)); 276 313 277 if((long int)regs.RAX == -1L)278 {279 fprintf(stderr, "getsid failed\n");280 return -regs.RAX;281 }282 283 314 return 0; 284 315 } 285 316 #endif 286 317 287 int grab_process( pid_tpid, char *ptyname, int ptyfd)318 int grab_process(long pid, char *ptyname, int ptyfd) 288 319 { 289 320 #if defined USE_GRAB … … 295 326 debug("pty is %s", ptyname); 296 327 297 kill(pid, SIGSTOP);298 328 if(ptrace(PTRACE_ATTACH, pid, 0, 0) < 0) 299 329 { 300 fprintf(stderr, "Cannot access process % d\n", pid);330 fprintf(stderr, "Cannot access process %ld\n", pid); 301 331 return errno; 302 332 } 303 kill(pid, SIGCONT);304 333 waitpid(pid, NULL, 0); 305 334 306 335 for(i = 0; i <= 2; i++) 307 336 { 308 snprintf(fdstr, sizeof(fdstr), "/proc/% d/fd/%d", pid, i);309 to_open[i] =0;337 snprintf(fdstr, sizeof(fdstr), "/proc/%ld/fd/%d", pid, i); 338 to_open[i] = 0; 310 339 lstat(fdstr, &stat_buf); 311 340 if((stat_buf.st_mode & S_IRUSR) && (stat_buf.st_mode & S_IWUSR)) … … 319 348 continue; 320 349 321 if(!S_ISCHR(stat_buf.st_mode) || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR) 350 if(!S_ISCHR(stat_buf.st_mode) 351 || MAJOR(stat_buf.st_rdev) != UNIX98_PTY_SLAVE_MAJOR) 322 352 continue; 323 353 324 debug("fd %d is a pty", i); 354 debug("found pty %d", i); 355 325 356 if((ret = do_close(pid, i))) 326 357 { 327 358 fprintf(stderr, "do_close %s\n", strerror(ret)); 328 359 } 329 to_open[i] =1;360 to_open[i] = 1; 330 361 } 331 362 … … 339 370 if(!to_open[i]) 340 371 continue; 341 if((ret = do_open(pid, ptyname, mode, &fd))) 342 { 343 fprintf(stderr, "do_open %s\n", strerror(ret)); 344 } 345 if((ret = do_dup2(pid, fd, i))) 346 { 347 fprintf(stderr, "do_dup2 %s\n", strerror(ret)); 372 fd = do_open(pid, ptyname, mode); 373 if(fd < 0) 374 { 375 perror("do_open"); 376 } 377 ret = do_dup2(pid, fd, i); 378 if(ret < 0) 379 { 380 perror("do_dup2"); 348 381 } 349 382 } -
neercs/trunk/src/neercs.h
r2500 r2505 15 15 16 16 #include <stdint.h> 17 17 18 #include <caca.h> 18 19 … … 132 133 133 134 int create_pty(char *cmd, unsigned int w, unsigned int h, int *cpid); 134 int create_pty_grab( pid_tpid, unsigned int w, unsigned int h);135 int grab_process( pid_tpid, char *ptyname, int ptyfd);135 int create_pty_grab(long pid, unsigned int w, unsigned int h); 136 int grab_process(long pid, char *ptyname, int ptyfd); 136 137 137 138 long int import_term(struct screen_list *screen_list, struct screen *sc, void const *data, unsigned int size); … … 206 207 int fill_config(struct screen_list *screen_list); 207 208 208 #if 0209 #if 1 209 210 # define debug(f, z...) fprintf(stderr, f "\n", z) 210 211 #else -
neercs/trunk/src/term.c
r2479 r2505 582 582 } 583 583 584 int create_pty_grab( pid_tpid, unsigned int w, unsigned int h)584 int create_pty_grab(long pid, unsigned int w, unsigned int h) 585 585 { 586 586 int fdm, fds;
Note: See TracChangeset
for help on using the changeset viewer.