4

I found a tool to repair import table here, but how are PE executable without import table built in the first place in c/c++?

ollydbg
  • 3,475
  • 7
  • 28
  • 29

2 Answers2

7

Just don't use CRT, and don't use any imported functions.

#pragma comment(linker, "/entry:start")
int start()
{
   return 42; 
}

To use WinAPI functions, find kernel32 base, parse it's export directory and find LoadLibrary() function (you should already have something like GetProcAddress() to find LoadLibrary())

This may looks like this:

// compile as console application, "release" configuration with /MT /GS-
#include <Windows.h>
#pragma comment(linker, "/entry:start")
void start()
{
    HMODULE kernel32base = *(HMODULE*)(*(DWORD*)(*(DWORD*)(*(DWORD*)(*(DWORD*)(__readfsdword(0x30) + 0x0C) + 0x14))) + 0x10);

    DWORD base = (DWORD)kernel32base;
    IMAGE_NT_HEADERS* pe = PIMAGE_NT_HEADERS(base + PIMAGE_DOS_HEADER(base)->e_lfanew);
    IMAGE_EXPORT_DIRECTORY* exportDir = PIMAGE_EXPORT_DIRECTORY(base + pe->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    DWORD* namePtr = (DWORD*)(base + exportDir->AddressOfNames);
    WORD* ordPtr = (WORD*)(base + exportDir->AddressOfNameOrdinals);
    for(; strcmp((const char*)(base + *namePtr), "GetProcAddress"); ++namePtr, ++ordPtr)
        ;
    DWORD funcRVA = *(DWORD*)(base + exportDir->AddressOfFunctions + *ordPtr * 4);

    typedef FARPROC (WINAPI *GetProcAddress_t)(HMODULE, const char*);
    GetProcAddress_t GetProcAddress = (GetProcAddress_t)(base + funcRVA);

    HANDLE (WINAPI *GetStdHandle)(DWORD);
    *(FARPROC*)&GetStdHandle = GetProcAddress(kernel32base, "GetStdHandle");

    HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);

    BOOL (WINAPI *WriteFile)(HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED);
    *(FARPROC*)&WriteFile = GetProcAddress(kernel32base, "WriteFile");

    const char* greeting = "Hello world!\n";

    DWORD written;
    WriteFile(stdout, greeting, strlen(greeting), &written, NULL);
}
Abyx
  • 12,345
  • 5
  • 44
  • 76
  • Can you provide a hello world example in its entirety? – ollydbg Oct 11 '10 at 11:59
  • @ollydbg It' rather complete for MSVC. Compile it as "release" with /MT /GS- and it won't have any imports. – Abyx Oct 11 '10 at 14:24
  • You managed to create an executable without import table that can run without problem,don't you?What I was expecting was one that will report a run time error due to lack of import table. – ollydbg Oct 13 '10 at 13:09
  • @ollydbg: "managed"? I just wrote it. And I know that it works because I know how it works, why it works and I tested it. Did you **expect** that it don't work? First test it, and find out why it works or don't works, if you don't understand it. Use google, there is answers to all your questions. – Abyx Oct 13 '10 at 14:51
  • It's probably easier to use interrupts to write a "hello world" program without any imports – 小太郎 Jan 17 '12 at 02:46
  • strcmp is unresolved symbol, Do I still need strcmp from a dll ? –  Nov 10 '20 at 19:27
0

To strip imports from existing executable module, you should parse it's imports directory to get its imports, then generate and add a code to get those imports, then remove imports directory.

Abyx
  • 12,345
  • 5
  • 44
  • 76