| /* |
| genlib - Create a COFF short import lib from a list of exported symbols. |
| Copyright (c) 2015 Martell Malone |
| |
| This program is free software: you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation, either version 3 of the License, or |
| (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with this program. If not, see <http://www.gnu.org/licenses/>. |
| */ |
| |
| /* |
| About: |
| |
| 1. does not need an assembler (its standalone) |
| 2. just needs to have a def file and arch you want to create the lib |
| |
| ALPHA VERSION |
| |
| This code has been matched to the coding styles of gendef which is why fprintf is used (a lot). |
| We should replace this with structs and allocations in memory before writing to disk for |
| cleaner code, better performance and ease of use. (Will do this at some point :) |
| |
| There is some very hacky code here btw :) |
| |
| HISTORY: |
| |
| version 1.0: initial support for PECOFF short import libs |
| version 1.1: added support for long names members (i.e dll's longer then 15 characters) |
| |
| IN PROGRESS: Alias support |
| |
| TODO: DATA type support in .def |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| #ifdef HAVE_INTTYPES_H |
| #include <inttypes.h> |
| #endif |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <memory.h> |
| #include <math.h> |
| #include <string.h> |
| #include <time.h> |
| #include "genlib.h" |
| #include "deflex.h" |
| #ifdef HAVE_LIBMANGLE |
| #include <libmangle.h> |
| #endif |
| |
| extern char *def_file; |
| extern char *dll_name; |
| |
| char *base_name; |
| uint16_t machine_type; |
| time_t time_now; |
| |
| /* Must unify into 1 header */ |
| typedef struct export |
| { |
| const char *name; |
| const char *internal_name; |
| const char *import_name; |
| const char *its_name; |
| int ordinal; |
| int constant; |
| int noname; /* Don't put name in image file. */ |
| int private; /* Don't put reference in import lib. */ |
| uint32_t data; |
| uint32_t hint; |
| int forward; /* Number of forward label, 0 means no forward. */ |
| struct export *next; |
| }export_type; |
| |
| extern int d_nfuncs; |
| extern export_type *d_exports; |
| |
| static int load_def (char *); |
| static int dump_def (void); |
| static void dump_lib (char *); |
| |
| static void dump_ialnm (FILE *fp); |
| static void dump_iamh (FILE *fp, uint32_t size, char *name); |
| static void dump_ialm1 (FILE *fp, uint32_t id, uint32_t nid, uint32_t ntd); |
| static void dump_ialm2 (FILE *fp, uint32_t id, uint32_t nid, uint32_t ntd); |
| static void dump_slif (FILE *fp, export_type *exp, uint16_t count); |
| static void dump_ifh (FILE *fp, uint16_t nsects, uint32_t nsymbols, uint32_t offset); |
| |
| static void dump_ish2 (FILE *fp, uint32_t offset, uint32_t reloc); |
| static void dump_ish3 (FILE *fp, uint32_t offset); |
| static void dump_ish4 (FILE *fp, uint32_t offset); |
| static void dump_ish5 (FILE *fp, uint32_t offset); |
| static void dump_ish6 (FILE *fp, uint32_t offset, uint32_t reloc); |
| |
| #include <getopt.h> |
| #include <time.h> |
| #include <string.h> |
| |
| // string.h |
| char * |
| xstrdup (const char *string) |
| { |
| return strcpy (malloc (strlen (string) + 1), string); |
| } |
| |
| static const char usage_string[] = |
| "Usage: genlib [options...] infile.def\n" |
| " or: genlib [options...] infile.def liboutfile.a\n" |
| " -a arch Set the target architecture\n" |
| " -o output Set the output library name\n" |
| " -d dllname Set the input dll name\n" |
| " -V Print version and exit\n" |
| "Usage example:\n" |
| " By default, the output file is named after the DLL counterpart\n" |
| " genlib mydef.def Produces libmydll.a\n" |
| "\nBuilt on " __DATE__ "\n" |
| "\nReport bugs to <martellmalone@gmail.com>\n" |
| ; |
| |
| static const char version_string[] = |
| "Short Import Library Compiler version " PACKAGE_VERSION "\n" |
| "Copyright 2015 Martell Malone\n"; |
| |
| static const struct option long_options[] = { |
| { "arch", required_argument, NULL, 'a' }, |
| { "output", required_argument, NULL, 'o' }, |
| { "dllname", required_argument, NULL, 'd' }, |
| { "version", no_argument, NULL, 'v' }, |
| { NULL, 0, NULL, 0 } |
| }; |
| |
| static int set_machine(const char *target) |
| { |
| static const struct |
| { |
| const char *name; |
| uint16_t type; |
| } machine_names[] = |
| { |
| { "x86", 0x014C }, |
| { "x86_64", 0x8664 }, |
| { "arm", 0x01C4 }, |
| { "aarch64", 0xAA64 } |
| }; |
| |
| unsigned int i; |
| char *spec = xstrdup(target); |
| |
| for (i = 0; i < sizeof(machine_names)/sizeof(machine_names[0]); i++) |
| { |
| if (!strcmp(machine_names[i].name, spec)) |
| { |
| machine_type = machine_names[i].type; |
| free(spec); |
| return 0; |
| } |
| } |
| return -1; |
| } |
| |
| int main(int argc, char *argv[]) |
| { |
| |
| int optc; |
| int opti = 0; |
| char *arch_name = NULL; |
| char *output_name = NULL; |
| |
| time_now = time(NULL); |
| |
| while((optc = getopt_long_only(argc, argv, ":a:o:V", long_options, &opti)) != EOF) { |
| switch(optc) { |
| case 'a': |
| arch_name = xstrdup(optarg); |
| break; |
| case 'o': |
| output_name = xstrdup(optarg); |
| break; |
| case 'd': |
| dll_name = xstrdup(optarg); |
| break; |
| case 'V': |
| printf("%s", version_string); |
| return 0; |
| default: |
| fprintf(stderr, "%s", usage_string); |
| return 1; |
| } |
| } |
| |
| if (optind >= argc) { |
| fprintf(stderr, "%s", usage_string); |
| return 1; |
| } |
| |
| if(arch_name == NULL) { |
| printf("Please set the Arch"); |
| return 1; |
| } |
| |
| if(set_machine(arch_name) < 0) { |
| printf("Invalid Machine Name"); |
| return 1; |
| } |
| |
| if (load_def(argv[optind])) { |
| dump_def (); |
| dump_lib (output_name); |
| return 0; |
| } |
| return -1; |
| } |
| |
| static int |
| load_def (char *fninput) |
| { |
| FILE *fp = fopen (fninput, "r"); |
| |
| if (!fp) |
| { |
| fprintf (stderr, "*** [%s] failed to open()\n", fninput); |
| return 0; |
| } |
| |
| yyin = fp; |
| |
| PRDEBUG("Parsing def file: %s\n", fninput); |
| def_file = fninput; |
| yyparse (); |
| PRDEBUG("Parsed def file\n"); |
| return 1; |
| } |
| |
| static int |
| dump_def (void) |
| { |
| export_type *exp; |
| PRDEBUG("Number of funcs: %d\n", d_nfuncs); |
| PRDEBUG("dll name: %s\n", dll_name); |
| |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| PRDEBUG("Weak name: %s\n", exp->name); |
| //PRDEBUG("Internal name: %s\n", exp->internal_name); |
| //PRDEBUG("Import name: %s\n", exp->import_name); |
| if (exp->its_name) |
| PRDEBUG("Real name: %s\n", exp->its_name); |
| |
| PRDEBUG("ordinal: %d\n", exp->ordinal); |
| PRDEBUG("constant: %d\n", exp->constant); |
| PRDEBUG("noname: %d\n", exp->noname); |
| PRDEBUG("private: %d\n", exp->private); |
| PRDEBUG("data: %d\n", exp->data); |
| PRDEBUG("hint: %d\n", exp->hint); |
| PRDEBUG("forward: %d\n", exp->forward); |
| } |
| return 0; |
| } |
| |
| # define BYTESWAP32(x) ((((x)&0xFF)<<24) \ |
| |(((x)>>24)&0xFF) \ |
| |(((x)&0x0000FF00)<<8) \ |
| |(((x)&0x00FF0000)>>8) ) |
| |
| // 4-> numofsymb |
| // dnfunc -> x2 *4 |
| // 12-> null thunk |
| #define OFFSETTABLE1(x) (4+(((x)*2)*4)+12) |
| // same as offset1 but without __imp_ doubles |
| #define OFFSETTABLE2(x) (4+((x)*4)+12) |
| |
| // 4-> numofsymb |
| // dnfunc -> x2 *2 |
| // 6-> null thunk |
| #define INDEXTABLE2(x) (4+((x)*2*2)+6) |
| |
| static inline uint32_t SYMBOLTABLE(export_type *exp) |
| { |
| uint32_t stsize = 0; |
| export_type *lexp = 0; |
| //MessageBoxA. +1 |
| //__imp_MessageBoxA. + 7 |
| // TODO: account for alias later |
| for(lexp=exp;lexp;lexp=lexp->next) |
| stsize += (strlen(lexp->name)*2) + 8; |
| //__IMPORT_DESCRIPTOR_user32. +21 |
| //__NULL_IMPORT_DESCRIPTOR. +25 |
| //Xuser32_NULL_THUNK_DATA. +17 +1 at start for \x7f |
| stsize += (strlen(base_name)*2) + 21 + 25 + 17 + 1; |
| return stsize; |
| } |
| |
| #define ARCHIVESYMBOLCOUNT(x) (((x)*2)+4) |
| |
| static void |
| dump_lib (char *fnoutput) |
| { |
| export_type *exp; |
| base_name = (char *) malloc (strlen (dll_name) - 4); |
| strncpy (base_name,dll_name, strlen(dll_name) - 4); |
| |
| PRDEBUG("basename: %s\n", base_name); |
| |
| if(!fnoutput) |
| { |
| fnoutput = (char *) malloc (strlen (dll_name) + 1); |
| strcpy (fnoutput,"lib"); |
| strcat (fnoutput,base_name); |
| strcat (fnoutput,".a"); |
| } |
| |
| FILE *fp = fopen(fnoutput,"wb"); |
| |
| if(!fp) |
| { |
| fprintf(stderr," * failed to create %s ...\n",fnoutput); |
| return; |
| } |
| |
| // if the weak symbol is the only on set the real name to that |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| if (!exp->its_name) |
| exp->its_name=exp->name; |
| } |
| |
| uint32_t sizemagic = 8; |
| /* MAGIC */ |
| fprintf (fp,"!<arch>\x0A"); // 21 3C 61 72 63 68 3E 0A |
| |
| uint32_t sizelm1; |
| sizelm1 = OFFSETTABLE1(d_nfuncs); |
| sizelm1 += SYMBOLTABLE(d_exports); |
| |
| uint32_t sizelm2; |
| sizelm2 = OFFSETTABLE2(d_nfuncs); |
| sizelm2 += INDEXTABLE2(d_nfuncs); |
| sizelm2 += SYMBOLTABLE(d_exports); |
| |
| // TODO: a #define for this |
| uint32_t sizelm3; |
| sizelm3 = strlen(dll_name) + 1; |
| // dont forget to handle odd obj |
| if (sizelm3 % 2 != 0) |
| sizelm3++; |
| |
| // ARCHIVE MEMBER 1 SIZE |
| //IFH = 20; |
| //ISH = 40*2; |
| // OFFSET => 100 |
| //SID2 = 20; |
| // RELOC => 120 |
| //IMGREL = 30 |
| // OFFSET => 150 |
| //SID6 = dllname + 1 (+ 1 if odd); |
| //OFFSET => 150 + dllname + 1 (+ 1 if odd); |
| //SYMT = 18*8 |
| //SIZE = 4 |
| //SYMST = NULL STUFF 76 |
| |
| uint32_t nidaddr = 4 + 21 + strlen(base_name); |
| uint32_t ntdaddr = nidaddr + 25; |
| uint32_t idaddr = ntdaddr + 18 + strlen(base_name); |
| |
| uint32_t size1even = 0; |
| uint32_t sizeam1 = 20 + (40*2) + 20 + 30 + strlen(dll_name) + (18*8) + idaddr; |
| |
| // dont forget to handle odd obj |
| if (strlen(dll_name) % 2 == 0) |
| size1even++; |
| sizeam1 +=size1even; |
| |
| // ARCHIVE MEMBER 2 SIZE |
| //IFH = 20; |
| //ISH = 40; |
| // OFFSET => 60 |
| //SID3 = 20; |
| // OFFSET => 80 |
| //SYMT = 18*2 |
| //SIZE = 4 |
| //SYMST = __NULL_IMPORT_DESCRIPTOR. |
| // was 25 but that is odd |
| uint32_t sizeam2 = 20 + 40 + 20 + (18*2) + 4 + 26; |
| |
| // ARCHIVE MEMBER 3 SIZE |
| //IFH = 20; |
| //ISH = 40*2; |
| // OFFSET => 100 |
| //SID5 = 8; |
| //SID4 = 8; |
| // OFFSET => 116 |
| //SYMT = 18*2 |
| //SIZE = 4 |
| //SYMST = \x7f%s_NULL_THUNK_DATA. base_name + 18 |
| |
| uint32_t size3even = 0; |
| uint32_t sizeam3 = 20 + 40*2 + 16 + (18*2) + 4 + strlen(base_name) + 18; |
| |
| // dont forget to handle odd obj |
| if (sizeam3 % 2 != 0) |
| size3even++; |
| sizeam3 +=size3even; |
| |
| //TODO: CHECK IF I NEED to add sizelm3 here |
| |
| uint32_t id = sizemagic+sizelm1+sizelm2+120; |
| uint32_t nid = sizemagic+sizelm1+sizelm2+sizeam1+181; |
| uint32_t ntd = sizemagic+sizelm1+sizelm2+sizeam1+sizeam2+241; |
| |
| uint32_t prevhint = sizemagic+sizelm1+sizelm2+sizeam1+sizeam2+sizeam3+301; |
| uint32_t prevhelp=0; |
| |
| /* SHORT IMPORT LIBRARY ARCHIVE MEMBERS */ |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| prevhint += prevhelp; |
| exp->hint = BYTESWAP32(prevhint); |
| exp->data = prevhint; |
| prevhelp = 60 + 20 + strlen(exp->name) + strlen(dll_name) + 2; |
| uint32_t d_imp_size = strlen(exp->name) + strlen(dll_name) + 2; |
| if (d_imp_size % 2 != 0) |
| { |
| prevhelp++; |
| } |
| } |
| |
| |
| /* LINKER MEMBER 1 */ |
| dump_iamh(fp, sizelm1, NULL); |
| dump_ialm1(fp, BYTESWAP32(id), BYTESWAP32(nid), BYTESWAP32(ntd)); |
| |
| /* LINKER MEMBER 2 */ |
| dump_iamh(fp, sizelm2, NULL); |
| dump_ialm2(fp, id, nid, ntd); |
| |
| //TODO: if dllname is 16 chars+ then add IMAGE_ARCHIVES_LONGNAMES_MEMBER |
| if(strlen(dll_name) > 15) |
| { |
| dump_iamh(fp, sizelm3, "//"); |
| dump_ialnm(fp); |
| } |
| |
| |
| uint32_t i; |
| |
| // ARCHIVE MEMBER 1 (.idata2 + .idata6) |
| dump_iamh(fp, sizeam1, dll_name); |
| dump_ifh (fp, 2, 8, 150 + strlen(dll_name) + 1 +size1even); |
| dump_ish2(fp, 100, 120); |
| dump_ish6(fp, 150, 120); |
| |
| // .idata2 is blank |
| for (i = 0;i < 20; i++) |
| { |
| fprintf (fp,"%c",'\x00'); |
| } |
| |
| // IMGREL |
| fprintf (fp,"%c%c%c%c",'\x0c','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x03','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x04','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| fprintf (fp,"%c%c%c%c",'\x10','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x05','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| //fprintf (fp,"%s", dll_name); |
| //uint32_t j; |
| |
| //TODO: fix dllname size in idata6 must do size in header also |
| |
| fprintf (fp,"%s%c", dll_name, '\x00'); |
| |
| // If dllname+1 is an odd number append 00 to close (not 0a here for some reason) |
| if (strlen(dll_name) % 2 == 0) |
| fprintf (fp,"%c", '\x00'); |
| |
| //for (j=0;j < 12-strlen(dll_name); j++) |
| // fprintf (fp,"%c",'\x00'); |
| |
| |
| |
| fprintf (fp,"@comp.id"); |
| //TODO: CHECK WHAT THIS MEANS ??? WHICH ONE ?? |
| //fprintf (fp,"%c%c%c%c",'\x7d','\x79','\xdd','\x00'); // CHECK LATER |
| fprintf (fp,"%c%c%c%c",'\xb4','\x9c','\xef','\x00'); // CHECK LATER |
| fprintf (fp,"%c%c%c%c",'\xff','\xff','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| // __IMPORT_DESCRIPTOR_%s |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x04','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x02','\x00'); |
| |
| fprintf (fp,".idata$2"); |
| fprintf (fp,"%c%c%c%c",'\x40','\x00','\x00','\xc0'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x68','\x00'); |
| |
| fprintf (fp,".idata$6"); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x03','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| fprintf (fp,".idata$4"); |
| fprintf (fp,"%c%c%c%c",'\x40','\x00','\x00','\xc0'); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x68','\x00'); |
| |
| fprintf (fp,".idata$5"); |
| fprintf (fp,"%c%c%c%c",'\x40','\x00','\x00','\xc0'); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x68','\x00'); |
| |
| //__NULL_IMPORT_DESCRIPTOR |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| |
| fwrite (&nidaddr, sizeof(uint32_t), 1, fp); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| |
| //X%s_NULL_THUNK_DATA |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| |
| fwrite (&ntdaddr, sizeof(uint32_t), 1, fp); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| |
| fwrite (&idaddr, sizeof(uint32_t), 1, fp); |
| fprintf (fp,"__IMPORT_DESCRIPTOR_%s%c", base_name, '\x00'); |
| fprintf (fp,"__NULL_IMPORT_DESCRIPTOR%c", '\x00'); |
| fprintf (fp,"\x7f%s_NULL_THUNK_DATA%c", base_name, '\x00'); |
| |
| // ARCHIVE MEMBER 2 (.idata3) |
| dump_iamh(fp, sizeam2, dll_name); |
| dump_ifh (fp, 1, 2, 80); |
| dump_ish3(fp, 60); |
| // Section .idata$3 |
| |
| for (i = 0;i < 20; i++) |
| { |
| fprintf (fp,"%c",'\x00'); |
| } |
| |
| fprintf (fp,"@comp.id"); |
| //TODO: CHECK WHAT THIS MEANS ??? |
| fprintf (fp,"%c%c%c%c",'\xb4','\x9c','\xef','\x00'); // CHECK LATER |
| fprintf (fp,"%c%c%c%c",'\xff','\xff','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| // __NULL_IMPORT_DESCRIPTOR |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x04','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x02','\x00'); |
| |
| |
| fprintf (fp,"%c%c%c%c",'\x1d','\x00','\x00','\x00'); |
| fprintf (fp,"__NULL_IMPORT_DESCRIPTOR%c", '\x00'); |
| |
| // THIS THING CARRIES |
| fprintf (fp,"%c",'\x0A'); |
| |
| // ARCHIVE MEMBER 3 (.idata5 .idata4) |
| dump_iamh(fp, sizeam3, dll_name); |
| dump_ifh (fp, 2, 2, 116); |
| dump_ish5(fp, 100); |
| dump_ish4(fp, 100); |
| |
| // idata4 and idata5 |
| for (i = 0;i < 2*8; i++) |
| { |
| fprintf (fp,"%c",'\x00'); |
| } |
| |
| fprintf (fp,"@comp.id"); |
| //TODO: CHECK WHAT THIS MEANS ??? |
| fprintf (fp,"%c%c%c%c",'\xb4','\x9c','\xef','\x00'); // CHECK LATER |
| fprintf (fp,"%c%c%c%c",'\xff','\xff','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x03','\x00'); |
| |
| //X%s_NULL_THUNK_DATA |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x04','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x00','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c%c%c",'\x02','\x00','\x00','\x00'); |
| fprintf (fp,"%c%c",'\x02','\x00'); |
| |
| fprintf (fp,"%c%c%c%c",'\x1c','\x00','\x00','\x00'); |
| fprintf (fp,"\x7f%s_NULL_THUNK_DATA%c", base_name, '\x00'); |
| |
| if(size3even) |
| fprintf (fp,"%c",'\x0A'); |
| |
| /* SHORT IMPORT LIBRARY ARCHIVE MEMBERS */ |
| i = 0; |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| dump_slif (fp,exp, i++); |
| } |
| |
| } |
| |
| /* dump image archive long name member */ |
| static void |
| dump_ialnm (FILE *fp) |
| { |
| fprintf (fp,"%s%c", dll_name, '\x00'); |
| |
| // If dllname+1 is an odd number append 0A to close |
| if (strlen(dll_name) % 2 == 0) |
| fprintf (fp,"\x0A"); |
| |
| } |
| |
| /* dump image file header */ |
| static void |
| dump_ifh (FILE *fp, uint16_t nsects, uint32_t nsymbols, uint32_t offset) |
| { |
| /* Machine */ |
| fprintf (fp,"\x64\x86"); |
| /* Num Sections */ |
| fwrite (&nsects, sizeof(uint16_t), 1, fp); |
| //TODO: SET DUMMY DATE |
| fwrite (&time_now, sizeof(uint32_t), 1, fp); |
| /* Pointer To Symbol Table */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Num Symbols */ |
| fwrite (&nsymbols, sizeof(uint32_t), 1, fp); |
| /* Size Of Optional Headers */ |
| fprintf (fp,"%c%c",'\x00', '\x00'); |
| /* Characteristics */ |
| fprintf (fp,"%c%c",'\x00', '\x00'); |
| } |
| |
| |
| /* dump image section header for .idata$2 */ |
| static void |
| dump_ish2 (FILE *fp, uint32_t offset, uint32_t reloc) |
| { |
| uint32_t dummy = 0x00000000; |
| uint32_t sizerd = 0x14; |
| uint32_t flags = 0xC0300040; |
| |
| /* NAME */ |
| fprintf (fp,".idata$2"); |
| /* Virtual Size */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* RVA */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Size of RAW Data */ |
| fwrite (&sizerd, sizeof(uint32_t), 1, fp); |
| /* Pointer To RAW Data */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Pointer To Relocations */ |
| fwrite (&reloc, sizeof(uint32_t), 1, fp); |
| /* Pointer To Lin Number */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| // Numer of Relocations |
| fprintf (fp,"\x03%c",'\x00'); |
| // Num of Lines |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| /* Characteristics */ |
| fwrite (&flags, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* dump image section header for .idata$3 */ |
| static void |
| dump_ish3 (FILE *fp , uint32_t offset) |
| { |
| uint32_t dummy = 0x00000000; |
| uint32_t sizerd = 0x14; |
| uint32_t flags = 0xC0300040; |
| |
| /* NAME */ |
| fprintf (fp,".idata$3"); |
| /* Virtual Size */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* RVA */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Size of RAW Data */ |
| fwrite (&sizerd, sizeof(uint32_t), 1, fp); |
| /* Pointer To RAW Data */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Pointer To Relocations */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Pointer To Lin Number */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| // Numer of Relocations |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| // Num of Lines |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| /* Characteristics */ |
| fwrite (&flags, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* dump image section header for .idata$3 */ |
| static void |
| dump_ish4 (FILE *fp , uint32_t offset) |
| { |
| uint32_t dummy = 0x00000000; |
| uint32_t sizerd = 0x8; |
| uint32_t flags = 0xC0400040; |
| |
| /* NAME */ |
| fprintf (fp,".idata$4"); |
| /* Virtual Size */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* RVA */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Size of RAW Data */ |
| fwrite (&sizerd, sizeof(uint32_t), 1, fp); |
| /* Pointer To RAW Data */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Pointer To Relocations */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Pointer To Lin Number */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| // Numer of Relocations |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| // Num of Lines |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| /* Characteristics */ |
| fwrite (&flags, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* dump image section header for .idata$3 */ |
| static void |
| dump_ish5 (FILE *fp , uint32_t offset) |
| { |
| uint32_t dummy = 0x00000000; |
| uint32_t sizerd = 0x8; |
| uint32_t flags = 0xC0400040; |
| |
| /* NAME */ |
| fprintf (fp,".idata$5"); |
| /* Virtual Size */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* RVA */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Size of RAW Data */ |
| fwrite (&sizerd, sizeof(uint32_t), 1, fp); |
| /* Pointer To RAW Data */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Pointer To Relocations */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Pointer To Lin Number */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| // Numer of Relocations |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| // Num of Lines |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| /* Characteristics */ |
| fwrite (&flags, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* dump image section header for .idata$6 */ |
| static void |
| dump_ish6 (FILE *fp, uint32_t offset, uint32_t reloc) |
| { |
| uint32_t dummy = 0x00000000; |
| //TODO: base on dllname |
| uint32_t sizerd = strlen(dll_name) + 1; |
| if (strlen(dll_name) % 2 == 0) |
| sizerd++; |
| uint32_t flags = 0xC0200040; |
| |
| /* NAME */ |
| fprintf (fp,".idata$6"); |
| /* Virtual Size */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* RVA */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| /* Size of RAW Data */ |
| fwrite (&sizerd, sizeof(uint32_t), 1, fp); |
| /* Pointer To RAW Data */ |
| fwrite (&offset, sizeof(uint32_t), 1, fp); |
| /* Pointer To Relocations */ |
| fwrite (&reloc, sizeof(uint32_t), 1, fp); |
| /* Pointer To Lin Number */ |
| fwrite (&dummy, sizeof(uint32_t), 1, fp); |
| // Numer of Relocations |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| // Num of Lines |
| fprintf (fp,"%c%c",'\x00','\x00'); |
| /* Characteristics */ |
| fwrite (&flags, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* dump image archive member header */ |
| static void |
| dump_iamh (FILE *fp, uint32_t size, char *name) |
| { |
| |
| // 4 cases |
| // name valid or invalid |
| // name shorter then 15 chars or not |
| |
| /* IMAGE_ARCHIVE_MEMBER_HEADER */ |
| /* NAME */ |
| // 15 char limit on dll name ?? |
| // 11 char limit on base name |
| |
| if(!name) |
| { |
| fprintf (fp,"/ "); // 2F 20++ |
| } |
| else |
| { |
| if(name[1] == '/') |
| { |
| fprintf (fp,"// "); // 2F 2F 20++ |
| } |
| else if(strlen(dll_name) > 15) |
| { |
| fprintf (fp,"/0 "); // 2F 30 20++ |
| } |
| else |
| { |
| fprintf (fp,"%s/", dll_name); |
| uint32_t j; |
| for (j=0;j < 15-strlen(dll_name); j++) |
| fprintf (fp," "); |
| } |
| } |
| |
| /* DATE */ |
| fprintf (fp,"\x31\x34\x33\x39\x32\x30\x34\x39\x32\x36 "); |
| //fprintf (fp,"0000000000 "); // CHECK LATER |
| /* USERID GROUPID */ |
| fprintf (fp," "); // 20++ |
| /* MODE */ |
| fprintf (fp,"\x30 "); // 30 20 20 20 20 20 20 20 |
| /* SIZE */ |
| fprintf (fp,"%d",size); |
| uint32_t i; |
| for (i = floor(log10(abs(size))) + 1;i < 10; i++) |
| { |
| fprintf (fp," "); |
| } |
| fprintf (fp,"\x60\x0A"); |
| /* END */ |
| } |
| |
| /* dump image archive linker member 1 */ |
| static void |
| dump_ialm1 (FILE *fp, uint32_t id, uint32_t nid, uint32_t ntd) |
| { |
| export_type *exp; |
| uint32_t d_nsymbols = (d_nfuncs*2) + 3; |
| |
| /* OFFSET TABLE */ |
| uint32_t swap_nsymbols = BYTESWAP32(d_nsymbols); |
| fwrite (&swap_nsymbols, sizeof(uint32_t), 1, fp); |
| |
| fwrite (&id, sizeof(uint32_t), 1, fp); |
| fwrite (&nid, sizeof(uint32_t), 1, fp); |
| fwrite (&ntd, sizeof(uint32_t), 1, fp); |
| |
| //TODO: stop hijacking hint |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| fwrite (&exp->hint, sizeof(uint32_t), 1, fp); |
| fwrite (&exp->hint, sizeof(uint32_t), 1, fp); |
| } |
| |
| fprintf (fp,"__IMPORT_DESCRIPTOR_%s%c", base_name, '\x00'); |
| fprintf (fp,"__NULL_IMPORT_DESCRIPTOR%c", '\x00'); |
| fprintf (fp,"\x7f%s_NULL_THUNK_DATA%c", base_name, '\x00'); |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| fprintf (fp,"%s%c",exp->name,'\x00'); |
| fprintf (fp,"__imp_%s%c",exp->name,'\x00'); |
| } |
| } |
| |
| /* dump image archive linker member 2 */ |
| static void |
| dump_ialm2 (FILE *fp, uint32_t id, uint32_t nid, uint32_t ntd) |
| { |
| export_type *exp; |
| uint32_t i; |
| uint16_t dummy = 0x0000; |
| uint32_t d_nmembers = d_nfuncs + 3; |
| uint32_t d_nsymbols = (d_nfuncs*2) + 3; |
| |
| /* OFFSET TABLE */ |
| fwrite (&d_nmembers, sizeof(uint32_t), 1, fp); |
| |
| fwrite (&id, sizeof(uint32_t), 1, fp); |
| fwrite (&nid, sizeof(uint32_t), 1, fp); |
| fwrite (&ntd, sizeof(uint32_t), 1, fp); |
| |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| fwrite (&exp->data, sizeof(uint32_t), 1, fp); |
| } |
| |
| /* INDEX TABLE */ |
| fwrite (&d_nsymbols, sizeof(uint32_t), 1, fp); |
| |
| for (i = 0;i < 3; i++) |
| { |
| dummy++; |
| fwrite (&dummy, sizeof(uint16_t), 1, fp); |
| } |
| |
| for (i = 0;i < (uint32_t)d_nfuncs; i++) |
| { |
| dummy++; |
| fwrite (&dummy, sizeof(uint16_t), 1, fp); |
| fwrite (&dummy, sizeof(uint16_t), 1, fp); |
| } |
| /* SYMBOL TABLE */ |
| fprintf (fp,"__IMPORT_DESCRIPTOR_%s%c", base_name, '\x00'); |
| fprintf (fp,"__NULL_IMPORT_DESCRIPTOR%c", '\x00'); |
| fprintf (fp,"\x7f%s_NULL_THUNK_DATA%c", base_name, '\x00'); |
| for (exp = d_exports; exp; exp = exp->next) |
| { |
| fprintf (fp,"%s%c",exp->name,'\x00'); |
| fprintf (fp,"__imp_%s%c",exp->name,'\x00'); |
| } |
| |
| } |
| |
| |
| /* dump short library import function */ |
| static void |
| dump_slif (FILE *fp, export_type *exp, uint16_t count) |
| { |
| uint16_t dummy1 = 0x0000; |
| uint16_t dummy2 = 0xffff; |
| uint32_t d_imp_size = strlen(exp->name) + strlen(dll_name) + 2; |
| uint32_t oddname = 0; |
| // dont forget to handle odd obj |
| if (d_imp_size % 2 != 0) |
| oddname++; |
| |
| d_imp_size+=oddname; |
| |
| uint32_t sizeslif = 20; // header size is 20 |
| sizeslif += strlen(exp->name) + strlen(dll_name) + 2 + oddname; |
| /* IMAGE_ARCHIVE_MEMBER_HEADER */ |
| dump_iamh(fp, sizeslif, dll_name); |
| // Sig1, Sig2, Version |
| fwrite (&dummy1, sizeof(uint16_t), 1, fp); |
| fwrite (&dummy2, sizeof(uint16_t), 1, fp); |
| fwrite (&dummy1, sizeof(uint16_t), 1, fp); |
| // Machine |
| fwrite (&machine_type, sizeof(uint16_t), 1, fp); |
| // Date |
| fwrite (&time_now, sizeof(uint32_t), 1, fp); |
| |
| fwrite (&d_imp_size, sizeof(uint32_t), 1, fp); |
| // Hint |
| fwrite (&count, sizeof(uint16_t), 1, fp); |
| // Type |
| fprintf (fp,"\x04%c",'\x00'); |
| // Our Import :) |
| fprintf (fp,"%s%c",exp->name,'\x00'); |
| fprintf (fp,"%s%c",dll_name,'\x00'); |
| |
| if(oddname) |
| fprintf (fp,"\x0A"); |
| } |