手搓obj,补充safeseh支持

#define _CRT_SECURE_NO_WARNINGS

#include <windows.h>

#include <assert.h>
#include <stdio.h>
#include <time.h>

#include <pshpack1.h>
struct JmpThunk {
  BYTE Jmp;
  DWORD Dir;
  DWORD Rel;
};
#include <poppack.h>

void StoreName(PCCH sz, PIMAGE_SYMBOL psym, PULONG pcbStrings) {
  memset((void*)&psym->N.Name, 0, (size_t)sizeof(psym->N.Name));
  if (strlen(sz) <= IMAGE_SIZEOF_SHORT_NAME) {
    strncpy((char*)psym->N.ShortName, (char*)sz, IMAGE_SIZEOF_SHORT_NAME);
  } else {
    psym->N.Name.Long = *pcbStrings;
    *pcbStrings += strlen(sz) + 1;
  }
}

void WriteThunkObj(PCHAR szFrom, PCHAR szTo, PCHAR szToImp, PCHAR szFilename) {
  FILE* pfile;
  IMAGE_FILE_HEADER hdr;
  IMAGE_SYMBOL sym;
  ULONG cbStrings, foStringTable;
  IMAGE_SECTION_HEADER sec;
  IMAGE_RELOCATION reloc = {0};

  if ((pfile = fopen(szFilename, "wb")) == NULL) {
    printf("can't open file \"%s\"\n", szFilename);
    exit(1);
  }

  hdr.Machine = IMAGE_FILE_MACHINE_I386;
  hdr.NumberOfSections = 1;
  hdr.TimeDateStamp = (DWORD)time(NULL);
  hdr.PointerToSymbolTable = sizeof(IMAGE_FILE_HEADER) +
                             sizeof(IMAGE_SECTION_HEADER) +
                             sizeof(JmpThunk) + sizeof(IMAGE_RELOCATION) * 2;
  hdr.NumberOfSymbols = 4;
  hdr.SizeOfOptionalHeader = 0;
  hdr.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED;

  fwrite(&hdr, sizeof(hdr), 1, pfile);

  // Generate one section header.  This is necessary because of a link bug
  // (vce:182) which fails for .obj's with 0 sections and unknown machine type.
  //
  memset(&sec, 0, sizeof(sec));
  strcpy((char*)sec.Name, ".text$mn");
  sec.Characteristics = IMAGE_SCN_ALIGN_4BYTES |
                        IMAGE_SCN_CNT_CODE |IMAGE_SCN_MEM_READ |
                        IMAGE_SCN_MEM_EXECUTE;
  sec.NumberOfRelocations = 2;
  sec.SizeOfRawData = sizeof(JmpThunk);
  sec.PointerToRawData =
      sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_SECTION_HEADER);
  sec.PointerToRelocations =
      sec.PointerToRawData + sec.SizeOfRawData;
  fwrite(&sec, sizeof(sec), 1, pfile);

  // jmp xxxxxx
  JmpThunk jmp_thunk{
      .Jmp = 0xE9,
      .Dir = 0,
      .Rel = 0,
  };
  fwrite(&jmp_thunk, sizeof(jmp_thunk), 1, pfile);

  reloc.VirtualAddress = 1;     // Skip JMP opcode
  reloc.SymbolTableIndex = 1;   // Points to szTo
  reloc.Type = IMAGE_REL_I386_REL32;
  fwrite(&reloc, sizeof(reloc), 1, pfile);

  reloc.VirtualAddress = 5;
  reloc.SymbolTableIndex = 1; // Points to szTo
  reloc.Type = IMAGE_REL_I386_DIR32;
  fwrite(&reloc, sizeof(reloc), 1, pfile);

  cbStrings = sizeof(ULONG);  // make room for stringtab size

  StoreName("@feat.00", &sym, &cbStrings);  
  sym.Value = 0x00000011;
  sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
  sym.Type = IMAGE_SYM_TYPE_NULL;
  sym.StorageClass = IMAGE_SYM_CLASS_STATIC;
  sym.NumberOfAuxSymbols = 0;
  fwrite(&sym, sizeof(sym), 1, pfile);

  StoreName(szTo, &sym, &cbStrings);
  sym.Value = 0;
  sym.SectionNumber = IMAGE_SYM_UNDEFINED;
  sym.Type = IMAGE_SYM_TYPE_NULL;
  sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  sym.NumberOfAuxSymbols = 0;
  fwrite(&sym, sizeof(sym), 1, pfile);

  StoreName(szFrom, &sym, &cbStrings);
  sym.Value = 0;
  sym.SectionNumber = 1;
  sym.Type = IMAGE_SYM_TYPE_NULL | (IMAGE_SYM_DTYPE_FUNCTION << 4);
  sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  sym.NumberOfAuxSymbols = 0;
  fwrite(&sym, sizeof(sym), 1, pfile);

  StoreName(szToImp, &sym, &cbStrings);
  sym.Value = 5;
  sym.SectionNumber = 1;
  sym.Type = IMAGE_SYM_TYPE_NULL;
  sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
  sym.NumberOfAuxSymbols = 0;
  fwrite(&sym, sizeof(sym), 1, pfile);

  // Write the string table.
  //
  foStringTable = ftell(pfile);
  fwrite(&cbStrings, sizeof(cbStrings), 1, pfile);
  if (strlen(szTo) > IMAGE_SIZEOF_SHORT_NAME) {
    fputs(szTo, pfile);
    fputc(0, pfile);
  }
  if (strlen(szFrom) > IMAGE_SIZEOF_SHORT_NAME) {
    fputs(szFrom, pfile);
    fputc(0, pfile);
  }
  if (strlen(szToImp) > IMAGE_SIZEOF_SHORT_NAME) {
    fputs(szToImp, pfile);
    fputc(0, pfile);
  }
  assert(ftell(pfile) - foStringTable == cbStrings);

  fclose(pfile);
}

// Undefined               // IMAGE_SYM_UNDEFINED
// External                // IMAGE_SYM_CLASS_EXTERNAL
// WeakExternal            // IMAGE_SYM_CLASS_WEAK_EXTERNAL
int main(int argc, char** argv) {
  PCHAR szFrom, szTo, szToImp, szFilename; 

  if (argc != 5) {
    printf("usage: thunkobj.exe from-name to-name to-imp-name output-filename\n");
    exit(1);
  }
  szFrom = argv[1];
  szTo = argv[2];
  szToImp = argv[3];
  szFilename = argv[4];

  WriteThunkObj(szFrom, szTo, szToImp, szFilename);

  return 0;
}

添加 SAFESEH 支持

posted @ 2025-06-25 14:30  吱吱的笔记  阅读(2)  评论(0)    收藏  举报