下面是我一个从网上找到无模块注入代码的方法.
具体是先自身载入DLL, 然后修复.reloc section后写入到目标进程。测试过,如果注入的是C++ DLL可以正常运行,但如果是DELPHI的DLL,调用ShowMessage函数就会出错。
例如下面的代码,使用ShowMessage不行,但用MessageBox就可以。
有谁知道是什么原因吗?
procedure showDlg; stdcall; export;
begin
    ShowMessage('Delphi Dialog');
    //MessageBox(0, 'Win32 Dialog', 'Win32 Dialog', MB_OK);
end;
LPVOID GetRelocBase(LPVOID lpModuleBaseAddr)
{
    PIMAGE_DOS_HEADER pImg_DOS_Header = (PIMAGE_DOS_HEADER)lpModuleBaseAddr;
    PIMAGE_NT_HEADERS pImg_NT_Header = (PIMAGE_NT_HEADERS)((ULONG)pImg_DOS_Header + pImg_DOS_Header->e_lfanew);    _IMAGE_FILE_HEADER FileHeader = pImg_NT_Header->FileHeader;
    WORD NumberOfSections = FileHeader.NumberOfSections;
    IMAGE_SECTION_HEADER* pIMAGE_SECTION_HEADER = (IMAGE_SECTION_HEADER*)((DWORD)pImg_NT_Header + sizeof(IMAGE_NT_HEADERS));
    for (WORD i=0; i<NumberOfSections; i++)
    {
        if (!lstrcmpiA((CHAR*)(pIMAGE_SECTION_HEADER->Name), ".reloc"))
        {
            return (LPVOID)((DWORD)lpModuleBaseAddr + pIMAGE_SECTION_HEADER->VirtualAddress);
        }
        pIMAGE_SECTION_HEADER += 1;
    }
    return 0;
}
BOOL CWar::DoWork()
{
    HMODULE hMod = LoadLibrary(TEXT("Project1.DLL"));
    typedef BOOL (*FUNC)();
    FUNC HaveFun = (FUNC)GetProcAddress(hMod, "showDlg");

    MODULEINFO info;
    GetModuleInformation(GetCurrentProcess(), hMod, &info, sizeof(info));
    LPVOID lpAlloc = VirtualAlloc(NULL, info.SizeOfImage, MEM_COMMIT, PAGE_READWRITE);
    memcpy(lpAlloc, info.lpBaseOfDll, info.SizeOfImage);
    LPVOID lpReloc = GetRelocBase(lpAlloc);
    
    LPVOID lpTargAddr = VirtualAllocEx(m_handle, NULL, info.SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    DWORD dwX = (DWORD)lpTargAddr - (DWORD)info.lpBaseOfDll; // 差值
    char* pcurReloc = (char*)lpReloc;
    DWORD pBlockRVA;
    DWORD dwBlockSize, dwCurSize;
    WORD itemRVA;
    do
    {
        pBlockRVA = *(DWORD *)pcurReloc;
        dwBlockSize = *(DWORD *)(pcurReloc + 4);
        dwCurSize = 8;
        pcurReloc += 8;
        if ( dwBlockSize > 8 )
        {
            do
            {
                itemRVA = *(WORD *)pcurReloc;
                pcurReloc += 2;
                dwCurSize += 2;
                if ( itemRVA >> 12 )
                {
                    if ( itemRVA >> 12 != 3 )
                        return 4;
                    *(DWORD *)((char *)lpAlloc + pBlockRVA + (itemRVA & 0xFFF)) += dwX;
                }
            }
            while ( dwCurSize < dwBlockSize );
        }
    }
    while ( dwBlockSize );    DWORD dwTid;
    WriteProcessMemory(m_handle, lpTargAddr, lpAlloc, info.SizeOfImage, &dwTid);
    HANDLE hThread = CreateRemoteThread(m_handle, NULL, 0, LPTHREAD_START_ROUTINE((char*)HaveFun - (char*)info.lpBaseOfDll + (char*)lpTargAddr), 0, CREATE_DEFAULT_ERROR_MODE, &dwTid);
    //WaitForSingleObject(hThread, 10*1000);
    VirtualFree(lpAlloc, 0, MEM_RELEASE);
    //VirtualFreeEx(m_handle, lpTargAddr, 0, MEM_RELEASE);
    return TRUE;
}

解决方案 »

  1.   

    可能是句柄问题, 即DLL的APPLICATION的句柄.
      

  2.   

    有谁知道是什么原因? 是不是因为DELPHI的API没有重定位到?
      

  3.   

    可能是调用约定不一样啊,改为_stdcall 试试
      

  4.   

    启动远程线程时被拦截了..发现是DELPHI DLL初始化没运行
      

  5.   

    delphi的dll,通常是要把主程式的TApplication,THandle等都要傳入
    例:
    procedure Technology_Form(ConStr,FormCaption,TitleKey,Ucode,Uname:string;AP:TApplication;HD:THandle;Fw:TScreen);stdcall;而且調用dll中,還需要注意當退出dll時
    例:
    procedure DLLUnloadProc(Reason: Integer); register;
    begin
      if (Reason = DLL_PROCESS_DETACH) or (Reason = DLL_THREAD_DETACH) then
        begin
          Application := DllApplication;
          Application.Handle := DllHandle;
          Screen := DllScreen;
        end;
    end;exports ***_dll;begin
      DllApplication := Application;
      DllHandle := Application.Handle;
      DllScreen := Screen;
      DLLProc := @DLLUnloadProc;
    end.
      

  6.   

    已经解决, 要在DELPHI DLL未初始化之前将映像注入到目标进程,然后再调用DLLMAIN
      

  7.   

    只要有统一的调用方式,dll就可以通用,要是用com来编程的,就不要考虑什么语言了,都ok
      

  8.   

    可能是句柄问题, 即DLL的APPLICATION的句柄.
      

  9.   

    procedure showDlg; stdcall; export;
    begin
        ShowMessage('Delphi Dialog');
        //MessageBox(0, 'Win32 Dialog', 'Win32 Dialog', MB_OK);
    end;