手搓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 支持